Skip to content

Commit

Permalink
GDAL Processing (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
tschumpr authored Apr 30, 2024
2 parents 1874257 + 809457d commit 9f49dee
Show file tree
Hide file tree
Showing 25 changed files with 1,090 additions and 5 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ dotnet_diagnostic.CA2227.severity = none
dotnet_diagnostic.CA1303.severity = none
dotnet_diagnostic.CS8602.severity = none
dotnet_diagnostic.SA0000.severity = warning
dotnet_diagnostic.SA1010.severity = none
dotnet_diagnostic.SA1101.severity = none
dotnet_diagnostic.SA1116.severity = warning
dotnet_diagnostic.SA1118.severity = warning
Expand Down
121 changes: 121 additions & 0 deletions Geodatenbezug.Test/GdalAssert.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System.Globalization;
using MaxRev.Gdal.Core;
using OSGeo.OGR;

namespace Geodatenbezug;

/// <summary>
/// Provides methods to assert the results of GDAL operations.
/// </summary>
internal static class GdalAssert
{
/// <summary>
/// Asserts that the result layer has the expected fields.
/// </summary>
internal static void AssertLayerFields(Layer resultLayer, List<string> expectedLayerFields)
{
var resultLayerFields = new List<string>();
var resultLayerDefn = resultLayer.GetLayerDefn();
for (var i = 0; i < resultLayerDefn.GetFieldCount(); i++)
{
resultLayerFields.Add(resultLayerDefn.GetFieldDefn(i).GetName());
}

CollectionAssert.AreEqual(expectedLayerFields, resultLayerFields);
}

/// <summary>
/// Asserts that the field has the expected type.
/// </summary>
internal static void AssertFieldType(Layer resultLayer, string fieldName, FieldType expectedFieldType)
{
var resultLayerDefn = resultLayer.GetLayerDefn();
var fieldIndex = resultLayerDefn.GetFieldIndex(fieldName);
Assert.AreEqual(resultLayerDefn.GetFieldDefn(fieldIndex).GetFieldType(), expectedFieldType);
}

/// <summary>
/// Asserts that the field has the expected type and subtype.
/// </summary>
internal static void AssertFieldType(Layer resultLayer, string fieldName, FieldType expectedFieldType, FieldSubType expectedFieldSubType)
{
var resultLayerDefn = resultLayer.GetLayerDefn();
var fieldIndex = resultLayerDefn.GetFieldIndex(fieldName);
Assert.AreEqual(resultLayerDefn.GetFieldDefn(fieldIndex).GetFieldType(), expectedFieldType);
Assert.AreEqual(resultLayerDefn.GetFieldDefn(fieldIndex).GetSubType(), expectedFieldSubType);
}

/// <summary>
/// Asserts that the result layer contains only single-part geometries.
/// </summary>
internal static void AssertOnlySinglePartGeometries(Layer resultLayer)
{
var hasOnlySinglePartGeometries = true;
resultLayer.ResetReading();
for (var i = 0; i < resultLayer.GetFeatureCount(1); i++)
{
var feature = resultLayer.GetNextFeature();
if (feature.GetGeometryRef().GetGeometryCount() > 1)
{
hasOnlySinglePartGeometries = false;
break;
}
}

Assert.IsTrue(hasOnlySinglePartGeometries);
}

/// <summary>
/// Asserts that the result layer contains only valid LNF codes.
/// </summary>
internal static void AssertOnlyValidLnfCodes(Layer resultLayer)
{
var hasOnlyValidLnfCodes = true;
resultLayer.ResetReading();
for (var i = 0; i < resultLayer.GetFeatureCount(1); i++)
{
var feature = resultLayer.GetNextFeature();
var lnfCode = feature.GetFieldAsInteger("lnf_code");
if ((lnfCode >= 921 && lnfCode <= 928) || lnfCode == 950 || lnfCode == 951)
{
hasOnlyValidLnfCodes = false;
break;
}
}

Assert.IsTrue(hasOnlyValidLnfCodes);
}

/// <summary>
/// Asserts that the result feature has the same datetime as the input feature.
/// </summary>
internal static void AssertDateTime(Feature inputFeature, Feature resultFeature, string fieldName)
{
var inputValue = inputFeature.GetFieldAsString(fieldName);
if (!DateTime.TryParse(inputValue, out var inputDate))
{
if (string.IsNullOrEmpty(inputValue))
{
Assert.IsTrue(resultFeature.IsFieldNull(fieldName));
return;
}

var inputYear = int.Parse(inputValue, CultureInfo.InvariantCulture);
inputDate = new DateTime(inputYear, 1, 1);
}

resultFeature.GetFieldAsDateTime(fieldName, out var year, out var month, out var day, out var hour, out var minute, out var second, out var tzFlag);
Assert.AreEqual(inputDate, new DateTime(year, month, day));
}

/// <summary>
/// Asserts that the result feature has the same geometry as the input feature.
/// </summary>
internal static void AssertGeometry(Feature inputFeature, Feature resultFeature)
{
var inputCentroid = inputFeature.GetGeometryRef().Centroid();
var resultCentroid = resultFeature.GetGeometryRef().Centroid();
Assert.AreEqual(inputCentroid.GetX(0), resultCentroid.GetX(0), 0.0001);
Assert.AreEqual(inputCentroid.GetY(0), resultCentroid.GetY(0), 0.0001);
}
}
20 changes: 20 additions & 0 deletions Geodatenbezug.Test/Geodatenbezug.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="MaxRev.Gdal.Core" Version="3.8.3.286" />
<PackageReference Include="MaxRev.Gdal.WindowsRuntime.Minimal" Version="3.8.3.259" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
Expand All @@ -34,6 +36,24 @@
<None Include="testdata\lwb_perimeter_terrassenreben_lv95_no_gpkg.zip">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="testdata\lwb_bewirtschaftungseinheit_v2_0_lv95_NE_202404191123.gpkg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="testdata\lwb_biodiversitaetsfoerderflaechen_v2_0_lv95_NE_202404191123.gpkg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="testdata\lwb_nutzungsflaechen_v2_0_lv95_NE_202404191123.gpkg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="testdata\lwb_perimeter_ln_sf_v2_0_lv95_NE_202404191123.gpkg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="testdata\lwb_perimeter_terrassenreben_v2_0_lv95_NE_202404191123.gpkg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="testdata\lwb_rebbaukataster_v2_0_lv95_NE_202404191123.gpkg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions Geodatenbezug.Test/Initialize.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using MaxRev.Gdal.Core;
using OSGeo.OGR;

namespace Geodatenbezug;

[TestClass]
public sealed class Initialize
{
[AssemblyInitialize]
public static void AssemblyInitialize(TestContext testContext)
{
GdalBase.ConfigureAll();
Ogr.RegisterAll();
Ogr.UseExceptions();
}
}
155 changes: 155 additions & 0 deletions Geodatenbezug.Test/Processors/BewirtschaftungseinheitProcessorTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
using Geodatenbezug.Models;
using Microsoft.Extensions.Logging;
using Moq;
using OSGeo.OGR;

namespace Geodatenbezug.Processors;

[TestClass]
[DeploymentItem("testdata/lwb_bewirtschaftungseinheit_v2_0_lv95_NE_202404191123.gpkg", "testdata")]
public class BewirtschaftungseinheitProcessorTest
{
private readonly Topic topic = new ()
{
TopicTitle = BaseTopic.lwb_bewirtschaftungseinheit.GetDescription(),
Canton = Canton.NE,
BaseTopic = BaseTopic.lwb_bewirtschaftungseinheit,
UpdatedAt = DateTime.Now,
};

private Mock<ILogger<Processor>> loggerMock;
private Mock<IGeodiensteApi> geodiensteApiMock;
private Mock<IAzureStorage> azureStorageMock;
private BewirtschaftungseinheitProcessor processor;

[TestInitialize]
public void Initialize()
{
loggerMock = new Mock<ILogger<Processor>>(MockBehavior.Strict);
geodiensteApiMock = new Mock<IGeodiensteApi>(MockBehavior.Strict);
azureStorageMock = new Mock<IAzureStorage>(MockBehavior.Strict);
processor = new BewirtschaftungseinheitProcessor(geodiensteApiMock.Object, azureStorageMock.Object, loggerMock.Object, topic);
}

[TestCleanup]
public void Cleanup()
{
loggerMock.VerifyAll();
}

[TestMethod]
public async Task RunGdalProcessingAsync()
{
loggerMock.Setup(LogLevel.Information, $"Starte GDAL-Prozessierung von Thema {topic.TopicTitle} ({topic.Canton})...");

processor.InputDataPath = "testdata\\lwb_bewirtschaftungseinheit_v2_0_lv95_NE_202404191123.gpkg";
await processor.RunGdalProcessingAsync();

var inputSource = Ogr.Open(processor.InputDataPath, 0);
var resultSource = Ogr.Open(processor.InputDataPath.Replace(".gpkg", ".gdb", StringComparison.InvariantCulture), 0);

var betriebLayerName = "betrieb";
var betriebInputLayer = inputSource.GetLayerByName(betriebLayerName);
var betriebResultLayer = resultSource.GetLayerByName(betriebLayerName);

var expectedBetriebLayerFields = new List<string>
{
"t_id",
"bezugsjahr",
"betriebsnummer",
"betriebsname",
"bur_nr",
"kanton",
};
GdalAssert.AssertLayerFields(betriebResultLayer, expectedBetriebLayerFields);

GdalAssert.AssertFieldType(betriebResultLayer, "t_id", FieldType.OFTInteger);
GdalAssert.AssertFieldType(betriebResultLayer, "bezugsjahr", FieldType.OFTDateTime);

GdalAssert.AssertOnlySinglePartGeometries(betriebResultLayer);

var firstBetriebInputFeature = betriebInputLayer.GetNextFeature();
betriebResultLayer.ResetReading();
var firstBetriebResultFeature = betriebResultLayer.GetNextFeature();
Assert.AreEqual(firstBetriebInputFeature.GetFID(), firstBetriebResultFeature.GetFieldAsInteger("t_id"));
GdalAssert.AssertDateTime(firstBetriebInputFeature, firstBetriebResultFeature, "bezugsjahr");
Assert.AreEqual(firstBetriebInputFeature.GetFieldAsString("betriebsnummer"), firstBetriebResultFeature.GetFieldAsString("betriebsnummer"));
Assert.AreEqual(firstBetriebInputFeature.GetFieldAsString("betriebsname"), firstBetriebResultFeature.GetFieldAsString("betriebsname"));
Assert.AreEqual(firstBetriebInputFeature.GetFieldAsString("bur_nr"), firstBetriebResultFeature.GetFieldAsString("bur_nr"));
Assert.AreEqual(firstBetriebInputFeature.GetFieldAsString("kanton"), firstBetriebResultFeature.GetFieldAsString("kanton"));
GdalAssert.AssertGeometry(firstBetriebInputFeature, firstBetriebResultFeature);

var bewirtschaftungseinheitLayerName = "bewirtschaftungseinheit";
var bewirtschaftungseinheitInputLayer = inputSource.GetLayerByName(bewirtschaftungseinheitLayerName);
var bewirtschaftungseinheitResultLayer = resultSource.GetLayerByName(bewirtschaftungseinheitLayerName);

var expectedBewirtschaftungseinheitLayerFields = new List<string>
{
"t_id",
"bezugsjahr",
"ist_definitiv",
"betriebsnummer",
"ps_nr",
"bur_nr",
"gemeinde",
"zone_ausland",
"flaeche_m2",
"kanton",
};
GdalAssert.AssertLayerFields(bewirtschaftungseinheitResultLayer, expectedBewirtschaftungseinheitLayerFields);

GdalAssert.AssertFieldType(bewirtschaftungseinheitResultLayer, "t_id", FieldType.OFTInteger);
GdalAssert.AssertFieldType(bewirtschaftungseinheitResultLayer, "bezugsjahr", FieldType.OFTDateTime);
GdalAssert.AssertFieldType(bewirtschaftungseinheitResultLayer, "ist_definitiv", FieldType.OFTInteger, FieldSubType.OFSTInt16);

GdalAssert.AssertOnlySinglePartGeometries(bewirtschaftungseinheitResultLayer);

var firstBewirtschaftungseinheitInputFeature = bewirtschaftungseinheitInputLayer.GetNextFeature();
bewirtschaftungseinheitResultLayer.ResetReading();
var firstBewirtschaftungseinheitResultFeature = bewirtschaftungseinheitResultLayer.GetNextFeature();
Assert.AreEqual(firstBewirtschaftungseinheitInputFeature.GetFID(), firstBewirtschaftungseinheitResultFeature.GetFieldAsInteger("t_id"));
GdalAssert.AssertDateTime(firstBewirtschaftungseinheitInputFeature, firstBewirtschaftungseinheitResultFeature, "bezugsjahr");
Assert.AreEqual(firstBewirtschaftungseinheitInputFeature.GetFieldAsInteger("ist_definitiv"), firstBewirtschaftungseinheitResultFeature.GetFieldAsInteger("ist_definitiv"));
Assert.AreEqual(firstBewirtschaftungseinheitInputFeature.GetFieldAsString("betriebsnummer"), firstBewirtschaftungseinheitResultFeature.GetFieldAsString("betriebsnummer"));
Assert.AreEqual(firstBewirtschaftungseinheitInputFeature.GetFieldAsString("ps_nr"), firstBewirtschaftungseinheitResultFeature.GetFieldAsString("ps_nr"));
Assert.AreEqual(firstBewirtschaftungseinheitInputFeature.GetFieldAsString("bur_nr"), firstBewirtschaftungseinheitResultFeature.GetFieldAsString("bur_nr"));
Assert.AreEqual(firstBewirtschaftungseinheitInputFeature.GetFieldAsString("gemeinde"), firstBewirtschaftungseinheitResultFeature.GetFieldAsString("gemeinde"));
Assert.AreEqual(firstBewirtschaftungseinheitInputFeature.GetFieldAsString("zone_ausland"), firstBewirtschaftungseinheitResultFeature.GetFieldAsString("zone_ausland"));
Assert.AreEqual(firstBewirtschaftungseinheitInputFeature.GetFieldAsInteger("flaeche_m2"), firstBewirtschaftungseinheitResultFeature.GetFieldAsInteger("flaeche_m2"));
Assert.AreEqual(firstBewirtschaftungseinheitInputFeature.GetFieldAsString("kanton"), firstBewirtschaftungseinheitResultFeature.GetFieldAsString("kanton"));
GdalAssert.AssertGeometry(firstBewirtschaftungseinheitInputFeature, firstBewirtschaftungseinheitResultFeature);

var produktionsstaetteLayerName = "produktionsstaette";
var produktionsstaetteInputLayer = inputSource.GetLayerByName(produktionsstaetteLayerName);
var produktionsstaetteResultLayer = resultSource.GetLayerByName(produktionsstaetteLayerName);

var expectedProduktionsstaetteLayerFields = new List<string>
{
"t_id",
"bezugsjahr",
"ps_nr",
"ps_name",
"betriebsnummer",
"bur_nr",
"kanton",
};
GdalAssert.AssertLayerFields(produktionsstaetteResultLayer, expectedProduktionsstaetteLayerFields);

GdalAssert.AssertFieldType(produktionsstaetteResultLayer, "t_id", FieldType.OFTInteger);
GdalAssert.AssertFieldType(produktionsstaetteResultLayer, "bezugsjahr", FieldType.OFTDateTime);

GdalAssert.AssertOnlySinglePartGeometries(produktionsstaetteResultLayer);

var firstProduktionsstaetteInputFeature = produktionsstaetteInputLayer.GetNextFeature();
produktionsstaetteResultLayer.ResetReading();
var firstProduktionsstaetteResultFeature = produktionsstaetteResultLayer.GetNextFeature();
Assert.AreEqual(firstProduktionsstaetteInputFeature.GetFID(), firstProduktionsstaetteResultFeature.GetFieldAsInteger("t_id"));
GdalAssert.AssertDateTime(firstProduktionsstaetteInputFeature, firstProduktionsstaetteResultFeature, "bezugsjahr");
Assert.AreEqual(firstProduktionsstaetteInputFeature.GetFieldAsString("ps_nr"), firstProduktionsstaetteResultFeature.GetFieldAsString("ps_nr"));
Assert.AreEqual(firstProduktionsstaetteInputFeature.GetFieldAsString("ps_name"), firstProduktionsstaetteResultFeature.GetFieldAsString("ps_name"));
Assert.AreEqual(firstProduktionsstaetteInputFeature.GetFieldAsString("betriebsnummer"), firstProduktionsstaetteResultFeature.GetFieldAsString("betriebsnummer"));
Assert.AreEqual(firstProduktionsstaetteInputFeature.GetFieldAsString("bur_nr"), firstProduktionsstaetteResultFeature.GetFieldAsString("bur_nr"));
Assert.AreEqual(firstProduktionsstaetteInputFeature.GetFieldAsString("kanton"), firstProduktionsstaetteResultFeature.GetFieldAsString("kanton"));
GdalAssert.AssertGeometry(firstProduktionsstaetteInputFeature, firstProduktionsstaetteResultFeature);
}
}
Loading

0 comments on commit 9f49dee

Please sign in to comment.