Skip to content

Commit

Permalink
Apply filter and geometry convertion on copy
Browse files Browse the repository at this point in the history
Layer.DeleteFeature is successful but the feature still exists so we
have to use a different approach.
  • Loading branch information
tschumpr committed May 28, 2024
1 parent f423dee commit d126699
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,13 @@ public async Task RunGdalProcessingAsync()
{
loggerMock.Setup(LogLevel.Information, $"Starte GDAL-Prozessierung");
loggerMock.Setup(LogLevel.Information, $"Kopiere Features aus dem GPKG in die GDB");
loggerMock.Setup(LogLevel.Information, $"Filtere LNF-Codes");
loggerMock.Setup(LogLevel.Information, $"Lade Nutzungsart-Katalog von https://models.geo.admin.ch/BLW/LWB_Nutzungsflaechen_Kataloge_V2_0.xml");
loggerMock.Setup(LogLevel.Information, $"Erstelle temporären Nutzungsartlayer");
loggerMock.Setup(LogLevel.Information, $"Erstelle temporären Bewirtschaftungslayer");
loggerMock.Setup(LogLevel.Information, $"Führe Join mit Nutzungsart und Bewirtschaftungseinheit aus");
loggerMock.Setup(LogLevel.Information, $"Lösche initialen Nutzungsflächenlayer");
loggerMock.Setup(LogLevel.Information, $"Erstelle neuen Nutzungsflächenlayer");
loggerMock.Setup(LogLevel.Information, $"Kopiere Features vom Joined Layer zum neuen Nutzungsflächenlayer");
loggerMock.Setup(LogLevel.Information, $"Konvertiere Multi- zu Singlepart-Geometrien");
loggerMock.Setup(LogLevel.Information, $"Lösche temporäre Layer");

processor.InputDataPath = "testdata\\lwb_nutzungsflaechen_v2_0_lv95_NE_202404191123.gpkg";
Expand Down
9 changes: 3 additions & 6 deletions Geodatenbezug/Processors/BewirtschaftungseinheitProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,17 @@ protected override Task ProcessTopicAsync()
{ bezugsjahrFieldDefinition.GetName(), bezugsjahrFieldDefinition },
};

var betriebLayer = CreateGdalLayer("betrieb", fieldTypeConversions);
var betriebLayer = CreateGdalLayer("betrieb", fieldTypeConversions, false, true);
betriebLayer.CopyFeatures();
betriebLayer.ConvertMultiPartToSinglePartGeometry();

var produktionsstaetteLayer = CreateGdalLayer("produktionsstaette", fieldTypeConversions);
var produktionsstaetteLayer = CreateGdalLayer("produktionsstaette", fieldTypeConversions, false, true);
produktionsstaetteLayer.CopyFeatures();
produktionsstaetteLayer.ConvertMultiPartToSinglePartGeometry();

using var isDefinitivFieldDefinition = new FieldDefn("ist_definitiv", FieldType.OFTInteger);
isDefinitivFieldDefinition.SetSubType(FieldSubType.OFSTInt16);
fieldTypeConversions.Add(isDefinitivFieldDefinition.GetName(), isDefinitivFieldDefinition);
var bewirtschaftungseinheitLayer = CreateGdalLayer("bewirtschaftungseinheit", fieldTypeConversions, ["identifikator_be"]);
var bewirtschaftungseinheitLayer = CreateGdalLayer("bewirtschaftungseinheit", fieldTypeConversions, ["identifikator_be"], false, true);
bewirtschaftungseinheitLayer.CopyFeatures();
bewirtschaftungseinheitLayer.ConvertMultiPartToSinglePartGeometry();

return Task.CompletedTask;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,14 @@ protected override Task ProcessTopicAsync()
{ beitragsberechtigtFieldDefinition.GetName(), beitragsberechtigtFieldDefinition },
};

var bffVernetzungFlaechenLayer = CreateGdalLayer("bff_vernetzung_flaechen", fieldTypeConversions);
var bffVernetzungFlaechenLayer = CreateGdalLayer("bff_vernetzung_flaechen", fieldTypeConversions, true, true);
bffVernetzungFlaechenLayer.CopyFeatures();
bffVernetzungFlaechenLayer.FilterLnfCodes();
bffVernetzungFlaechenLayer.ConvertMultiPartToSinglePartGeometry();

using var nhgFieldDefinition = new FieldDefn("nhg", FieldType.OFTInteger);
nhgFieldDefinition.SetSubType(FieldSubType.OFSTInt16);
fieldTypeConversions.Add(nhgFieldDefinition.GetName(), nhgFieldDefinition);
var bffQualitaet2FlaechenLayer = CreateGdalLayer("bff_qualitaet_2_flaechen", fieldTypeConversions);
var bffQualitaet2FlaechenLayer = CreateGdalLayer("bff_qualitaet_2_flaechen", fieldTypeConversions, true, true);
bffQualitaet2FlaechenLayer.CopyFeatures();
bffQualitaet2FlaechenLayer.FilterLnfCodes();
bffQualitaet2FlaechenLayer.ConvertMultiPartToSinglePartGeometry();

return Task.CompletedTask;
}
Expand Down
62 changes: 44 additions & 18 deletions Geodatenbezug/Processors/GdalLayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public class GdalLayer
private readonly Layer inputLayer;
private readonly Layer processingLayer;

private readonly bool filterLnfCodes;
private readonly bool convertMultiToSinglePartGeometries;

/// <summary>
/// The <see cref="Layer"/> for the input data.
/// </summary>
Expand All @@ -21,11 +24,14 @@ public class GdalLayer
/// <summary>
/// Initializes a new instance of the <see cref="GdalLayer"/> class.
/// </summary>
public GdalLayer(Layer inputLayer, Layer processingLayer, Dictionary<string, FieldDefn> fieldTypeConversions, List<string> fieldsToDrop)
public GdalLayer(Layer inputLayer, Layer processingLayer, Dictionary<string, FieldDefn> fieldTypeConversions, List<string> fieldsToDrop, bool filterLnfCodes, bool convertMultiToSinglePartGeometries)
{
this.inputLayer = inputLayer;
this.processingLayer = processingLayer;

this.filterLnfCodes = filterLnfCodes;
this.convertMultiToSinglePartGeometries = convertMultiToSinglePartGeometries;

var inputLayerDefinition = inputLayer.GetLayerDefn();

using var tIdFieldDefinition = new FieldDefn(TIdFieldName, FieldType.OFTString);
Expand Down Expand Up @@ -63,6 +69,16 @@ public void CopyFeatures()
for (var i = 0; i < inputLayer.GetFeatureCount(1); i++)
{
var inputFeature = inputLayer.GetNextFeature();

if (filterLnfCodes)
{
var lnfCode = inputFeature.GetFieldAsInteger("lnf_code");
if ((lnfCode >= 921 && lnfCode <= 928) || lnfCode == 950 || lnfCode == 951)
{
continue;
}
}

var processingLayerDefinition = processingLayer.GetLayerDefn();
using var newFeature = new Feature(processingLayerDefinition);
newFeature.SetGeometry(inputFeature.GetGeometryRef());
Expand Down Expand Up @@ -119,23 +135,33 @@ public void CopyFeatures()
}
}

processingLayer.CreateFeature(newFeature);
if (convertMultiToSinglePartGeometries)
{
var geometry = newFeature.GetGeometryRef();
if (geometry.GetGeometryCount() > 1)
{
for (var j = 0; j < geometry.GetGeometryCount(); j++)
{
var singlePartGeometry = geometry.GetGeometryRef(j);
var singlePartGeometryType = singlePartGeometry.GetGeometryType();
if (singlePartGeometryType == wkbGeometryType.wkbPolygon || singlePartGeometryType == wkbGeometryType.wkbCurvePolygon)
{
using var newSinglePartFeature = newFeature.Clone();
newSinglePartFeature.SetFID(-1);
newSinglePartFeature.SetGeometry(singlePartGeometry);
processingLayer.CreateFeature(newSinglePartFeature);
}
}
}
else
{
processingLayer.CreateFeature(newFeature);
}
}
else
{
processingLayer.CreateFeature(newFeature);
}
}
}

/// <summary>
/// Remove features from the layer that have a specific LNF code (921-928, 950, 951).
/// </summary>
public void FilterLnfCodes()
{
processingLayer.FilterLnfCodes();
}

/// <summary>
/// Convert multipart geometries to singlepart geometries.
/// </summary>
public void ConvertMultiPartToSinglePartGeometry()
{
processingLayer.ConvertMultiPartToSinglePartGeometry();
}
}
52 changes: 0 additions & 52 deletions Geodatenbezug/Processors/LayerExtensions.cs

This file was deleted.

7 changes: 1 addition & 6 deletions Geodatenbezug/Processors/NutzungsflaechenProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,9 @@ protected async override Task ProcessTopicAsync()
"schnittzeitpunkt",
};

var nutzungsflaechenTempLayer = CreateGdalLayer(NutzungsflaechenLayerName, fieldTypeConversions, fieldsToDrop);
var nutzungsflaechenTempLayer = CreateGdalLayer(NutzungsflaechenLayerName, fieldTypeConversions, fieldsToDrop, true, true);
Logger.LogInformation($"{Topic.TopicTitle} ({Topic.Canton}): Kopiere Features aus dem GPKG in die GDB");
nutzungsflaechenTempLayer.CopyFeatures();
Logger.LogInformation($"{Topic.TopicTitle} ({Topic.Canton}): Filtere LNF-Codes");
nutzungsflaechenTempLayer.FilterLnfCodes();

// Create a temporary layer with data from the nutzungsart catalog
await CreateNutzungsartLayerAsync().ConfigureAwait(false);
Expand Down Expand Up @@ -176,9 +174,6 @@ protected async override Task ProcessTopicAsync()
nutzungsflaechenLayer.CreateFeature(newFeature);
}

Logger.LogInformation($"{Topic.TopicTitle} ({Topic.Canton}): Konvertiere Multi- zu Singlepart-Geometrien");
nutzungsflaechenLayer.ConvertMultiPartToSinglePartGeometry();

Logger.LogInformation($"{Topic.TopicTitle} ({Topic.Canton}): Lösche temporäre Layer");

// Delete the temporary work layers
Expand Down
3 changes: 1 addition & 2 deletions Geodatenbezug/Processors/PerimeterLnSfProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ protected override Task ProcessTopicAsync()
{
{ bezugsJahrFieldDefinition.GetName(), bezugsJahrFieldDefinition },
};
var perimeterLnSfLayer = CreateGdalLayer("perimeter_ln_sf", fieldTypeConversions);
var perimeterLnSfLayer = CreateGdalLayer("perimeter_ln_sf", fieldTypeConversions, false, true);
perimeterLnSfLayer.CopyFeatures();
perimeterLnSfLayer.ConvertMultiPartToSinglePartGeometry();

return Task.CompletedTask;
}
Expand Down
3 changes: 1 addition & 2 deletions Geodatenbezug/Processors/PerimeterTerrassenrebenProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ protected override Task ProcessTopicAsync()
{ aenderungsdatumFieldDefinition.GetName(), aenderungsdatumFieldDefinition },
};

var perimeterTerrassenrebenLayer = CreateGdalLayer("perimeter_terrassenreben", fieldTypeConversions);
var perimeterTerrassenrebenLayer = CreateGdalLayer("perimeter_terrassenreben", fieldTypeConversions, false, true);
perimeterTerrassenrebenLayer.CopyFeatures();
perimeterTerrassenrebenLayer.ConvertMultiPartToSinglePartGeometry();

return Task.CompletedTask;
}
Expand Down
3 changes: 1 addition & 2 deletions Geodatenbezug/Processors/RebbaukatasterProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ protected override Task ProcessTopicAsync()
{ aenderungsdatumFieldDefinition.GetName(), aenderungsdatumFieldDefinition },
};

var rebbaukatasterLayer = CreateGdalLayer("rebbaukataster", fieldTypeConversions);
var rebbaukatasterLayer = CreateGdalLayer("rebbaukataster", fieldTypeConversions, false, true);
rebbaukatasterLayer.CopyFeatures();
rebbaukatasterLayer.ConvertMultiPartToSinglePartGeometry();

return Task.CompletedTask;
}
Expand Down
8 changes: 4 additions & 4 deletions Geodatenbezug/Processors/TopicProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,15 +211,15 @@ protected internal async Task RunGdalProcessingAsync()
/// <summary>
/// Creates a new GDAL layer for processing.
/// </summary>
public GdalLayer CreateGdalLayer(string layerName, Dictionary<string, FieldDefn>? fieldTypeConversions)
public GdalLayer CreateGdalLayer(string layerName, Dictionary<string, FieldDefn>? fieldTypeConversions, bool filterLnfCodes, bool convertMultiToSinglePartGeometries)
{
return CreateGdalLayer(layerName, fieldTypeConversions, []);
return CreateGdalLayer(layerName, fieldTypeConversions, [], filterLnfCodes, convertMultiToSinglePartGeometries);
}

/// <summary>
/// Creates a new GDAL layer for processing.
/// </summary>
public GdalLayer CreateGdalLayer(string layerName, Dictionary<string, FieldDefn>? fieldTypeConversions, List<string> fieldsToDrop)
public GdalLayer CreateGdalLayer(string layerName, Dictionary<string, FieldDefn>? fieldTypeConversions, List<string> fieldsToDrop, bool filterLnfCodes, bool convertMultiToSinglePartGeometries)
{
var inputLayer = InputDataSource.GetLayerByName(layerName);

Expand All @@ -229,7 +229,7 @@ public GdalLayer CreateGdalLayer(string layerName, Dictionary<string, FieldDefn>
var processingLayer = ProcessingDataSource.CreateLayer(layerName, inputLayer.GetSpatialRef(), geometryType, []);
fieldTypeConversions ??= [];

return new GdalLayer(inputLayer, processingLayer, fieldTypeConversions, fieldsToDrop);
return new GdalLayer(inputLayer, processingLayer, fieldTypeConversions, fieldsToDrop, filterLnfCodes, convertMultiToSinglePartGeometries);
}

/// <summary>
Expand Down

0 comments on commit d126699

Please sign in to comment.