Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions .idea/.idea.ResPlan/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 63 additions & 0 deletions ResPlan.Tests/GeometryVerificationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System.Linq;
using NetTopologySuite.Geometries;
using Xunit;
using ResPlan.Library;

namespace ResPlan.Tests
{
public class GeometryVerificationTests
{
[Fact]
public void VerifyAllGeometriesAreValidAndClosed()
{
string jsonPath = "resplan_samples.json";
Assert.True(System.IO.File.Exists(jsonPath), $"Test data {jsonPath} not found.");

var plans = PlanLoader.LoadPlans(jsonPath);
Assert.NotEmpty(plans);

foreach (var plan in plans)
{
foreach (var kvp in plan.Geometries)
{
var layerName = kvp.Key;
var geometries = kvp.Value;

foreach (var geometry in geometries)
{
// 1. Check validity
Assert.True(geometry.IsValid, $"Invalid geometry found in plan {plan.Id}, layer {layerName}. Reason: {geometry.IsValid}");

// 2. Check for closed rings if it's a polygon or multipolygon
if (geometry is Polygon polygon)
{
ValidatePolygon(polygon, plan.Id, layerName);
}
else if (geometry is MultiPolygon multiPolygon)
{
foreach (var g in multiPolygon.Geometries)
{
if (g is Polygon p)
ValidatePolygon(p, plan.Id, layerName);
}
}

// 3. Ensure non-empty
Assert.False(geometry.IsEmpty, $"Empty geometry found in plan {plan.Id}, layer {layerName}");
}
}
}
}

private void ValidatePolygon(Polygon polygon, int planId, string layerName)
{
// shell
Assert.True(polygon.ExteriorRing.IsClosed, $"Polygon exterior ring not closed in plan {planId}, layer {layerName}");
// holes
foreach (var hole in polygon.InteriorRings)
{
Assert.True(hole.IsClosed, $"Polygon interior ring not closed in plan {planId}, layer {layerName}");
}
}
}
}
16 changes: 13 additions & 3 deletions ResPlan.Tests/ImageComparisonTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@
using System.Linq;
using SkiaSharp;
using Xunit;
using Xunit.Abstractions;
using ResPlan.Library;

namespace ResPlan.Tests
{
public class ImageComparisonTests
{
private readonly ITestOutputHelper _output;

public ImageComparisonTests(ITestOutputHelper output)
{
_output = output;
}

[Fact]
public void VerifyImageGenerationAgainstReference()
{
Expand All @@ -27,11 +35,11 @@ public void VerifyImageGenerationAgainstReference()
Assert.True(File.Exists(refPath), $"Reference image {refPath} not found.");

// Compare
CompareImages(refPath, actualPath);
CompareImages(refPath, actualPath, plan.Id);
}
}

private void CompareImages(string refPath, string actualPath)
private void CompareImages(string refPath, string actualPath, int planId)
{
using var refImg = SKBitmap.Decode(refPath);
using var actImg = SKBitmap.Decode(actualPath);
Expand Down Expand Up @@ -62,6 +70,8 @@ private void CompareImages(string refPath, string actualPath)
double mse = diffSum / (double)(pixelCount * 3);
double rmse = Math.Sqrt(mse);

_output.WriteLine($"Plan {planId} Comparison: RMSE = {rmse:F2}");

// Define a tolerance. 0 is perfect.
// Given font rendering, anti-aliasing differences, etc.
// 255 is max difference.
Expand All @@ -86,7 +96,7 @@ private void CompareImages(string refPath, string actualPath)
// So axes are off. Background should be white.

// Let's assert RMSE < 20.
Assert.True(rmse < 50, $"Image mismatch for {refPath}. RMSE: {rmse}");
Assert.True(rmse < 20, $"Image mismatch for {refPath}. RMSE: {rmse}");
}

private long Sq(int x) => x * x;
Expand Down
Loading