Skip to content

Commit ee453aa

Browse files
Update benchmarks
1 parent 0de9052 commit ee453aa

File tree

10 files changed

+32783
-182
lines changed

10 files changed

+32783
-182
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
#nullable disable
5+
6+
using BenchmarkDotNet.Attributes;
7+
using GeoJSON.Text.Feature;
8+
using PolygonClipper.Tests;
9+
using PolygonClipper.Tests.TestCases;
10+
11+
namespace PolygonClipper.Benchmarks;
12+
13+
/// <summary>
14+
/// Benchmarks the performance of <c>PolygonClipper</c> for polygon union operations using a fixed input dataset.
15+
/// </summary>
16+
[MemoryDiagnoser]
17+
[OperationsPerSecond]
18+
public class Benches
19+
{
20+
private Polygon subject;
21+
private Polygon clipping;
22+
23+
[Params("hole_hole.geojson", "states_source.geojson", "asia.geojson")]
24+
public string File { get; set; }
25+
26+
[GlobalSetup]
27+
public void Setup()
28+
{
29+
FeatureCollection collection = TestData.Benchmarks.GetFeatureCollection(this.File);
30+
(Polygon subject, Polygon clipping) = TestPolygonUtilities.BuildPolygon(collection);
31+
this.subject = subject;
32+
this.clipping = clipping;
33+
}
34+
35+
[Benchmark]
36+
public Polygon PolygonClipper() => global::PolygonClipper.PolygonClipper.Union(this.subject, this.clipping);
37+
}

tests/PolygonClipper.Benchmarks/ClippingLibraryComparison.cs

Lines changed: 0 additions & 61 deletions
This file was deleted.

tests/PolygonClipper.Benchmarks/PolygonClipper.Benchmarks.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
@@ -36,7 +36,6 @@
3636

3737
<ItemGroup>
3838
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
39-
<PackageReference Include="Clipper2" Version="1.5.4" />
4039
</ItemGroup>
4140

4241
<ItemGroup>

tests/PolygonClipper.Tests/PolygonClipper.Tests.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<CodeAnalysisRuleSet>..\sixlabors.tests.ruleset</CodeAnalysisRuleSet>
@@ -23,7 +23,6 @@
2323
<PackageReference Include="xunit" Version="2.4.0" />
2424
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
2525
<PackageReference Include="coverlet.collector" Version="1.2.0" />
26-
<PackageReference Include="Clipper2" Version="1.5.4" />
2726
</ItemGroup>
2827

2928
<ItemGroup>

tests/PolygonClipper.Tests/TestData.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,27 @@ private static string GetGeoJsonPath(string fileName)
4040
=> GetFullPath(nameof(Generic), fileName);
4141
}
4242

43+
public static class Benchmarks
44+
{
45+
public static IEnumerable<string> GetFileNames()
46+
{
47+
DirectoryInfo info = new(Path.Combine(TestEnvironment.GeoJsonTestDataFullPath, nameof(Benchmarks)));
48+
foreach (FileInfo file in info.EnumerateFiles("*.geojson"))
49+
{
50+
yield return file.Name;
51+
}
52+
}
53+
54+
public static FeatureCollection GetFeatureCollection(string fileName)
55+
{
56+
string path = GetGeoJsonPath(fileName);
57+
return JsonSerializer.Deserialize<FeatureCollection>(File.ReadAllText(path))!;
58+
}
59+
60+
private static string GetGeoJsonPath(string fileName)
61+
=> GetFullPath(nameof(Benchmarks), fileName);
62+
}
63+
4364
private static string GetFullPath(string folder, string fileName)
4465
=> Path.Combine(TestEnvironment.GeoJsonTestDataFullPath, folder, fileName);
4566
}

tests/PolygonClipper.Tests/TestPolygonUtilities.cs

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the Six Labors Split License.
33

44
using System;
5-
using Clipper2Lib;
65
using GeoJSON.Text.Feature;
76
using GeoJSON.Text.Geometry;
87

@@ -23,17 +22,6 @@ public static (Polygon Subject, Polygon Clipping) BuildPolygon(FeatureCollection
2322
return (subject, clipping);
2423
}
2524

26-
public static (PathsD Subject, PathsD Clipping) BuildClipper2Polygon(FeatureCollection data)
27-
{
28-
IGeometryObject subjectGeometry = data.Features[0].Geometry;
29-
IGeometryObject clippingGeometry = data.Features[1].Geometry;
30-
31-
PathsD subject = ConvertToClipper2Polygon(subjectGeometry);
32-
PathsD clipping = ConvertToClipper2Polygon(clippingGeometry);
33-
34-
return (subject, clipping);
35-
}
36-
3725
private static Polygon ConvertToPolygon(IGeometryObject geometry)
3826
{
3927
if (geometry is GeoPolygon geoJsonPolygon)
@@ -86,69 +74,4 @@ private static Polygon ConvertToPolygon(IGeometryObject geometry)
8674

8775
throw new InvalidOperationException("Unsupported geometry type.");
8876
}
89-
90-
private static PathsD ConvertToClipper2Polygon(IGeometryObject geometry)
91-
{
92-
if (geometry is GeoPolygon geoJsonPolygon)
93-
{
94-
// Convert GeoJSON Polygon to our Polygon type
95-
PathsD polygon = [];
96-
foreach (LineString ring in geoJsonPolygon.Coordinates)
97-
{
98-
PathD contour = [];
99-
foreach (IPosition xy in ring.Coordinates)
100-
{
101-
contour.Add(new PointD(xy.Longitude, xy.Latitude));
102-
}
103-
104-
if (!ring.IsClosed())
105-
{
106-
contour.Add(contour[0]);
107-
}
108-
109-
polygon.Add(contour);
110-
}
111-
112-
return polygon;
113-
}
114-
else if (geometry is MultiPolygon geoJsonMultiPolygon)
115-
{
116-
// Convert GeoJSON MultiPolygon to our Polygon type
117-
PathsD polygon = [];
118-
119-
// Clipper2 expects holes run in the opposite direction
120-
// to the outer ring, so we need to reverse holes if they are clockwise.
121-
int i = 0;
122-
foreach (GeoPolygon geoPolygon in geoJsonMultiPolygon.Coordinates)
123-
{
124-
foreach (LineString ring in geoPolygon.Coordinates)
125-
{
126-
PathD contour = [];
127-
foreach (IPosition xy in ring.Coordinates)
128-
{
129-
contour.Add(new PointD(xy.Longitude, xy.Latitude));
130-
}
131-
132-
if (!ring.IsClosed())
133-
{
134-
contour.Add(contour[0]);
135-
}
136-
137-
// Assume all polygons following the initial one are holes.
138-
// If the area of the contour is positive, we must reverse it.
139-
if (i > 0 && Clipper.Area(contour) > 0)
140-
{
141-
contour.Reverse();
142-
}
143-
144-
polygon.Add(contour);
145-
i++;
146-
}
147-
}
148-
149-
return polygon;
150-
}
151-
152-
throw new InvalidOperationException("Unsupported geometry type.");
153-
}
15477
}
Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4-
using Clipper2Lib;
54
using GeoJSON.Text.Feature;
65
using PolygonClipper.Tests.TestCases;
76
using Xunit;
@@ -12,6 +11,9 @@ public class TestPolygonUtilitiesTests
1211
{
1312
private static readonly FeatureCollection Data = TestData.Generic.GetFeatureCollection("issue71.geojson");
1413

14+
/// <summary>
15+
/// Static to allow profiling in Rider.
16+
/// </summary>
1517
private static readonly (Polygon subject, Polygon clipping) Polygons = TestPolygonUtilities.BuildPolygon(Data);
1618

1719
[Fact]
@@ -33,51 +35,13 @@ public void ConvertToPolygon_ValidGeometry_ReturnsPolygon()
3335
}
3436

3537
[Fact]
36-
public void ConvertToClipper2Polygon_ValidGeometry_ReturnsPathsD()
38+
public void PolygonClipper_Union_Profile_Test()
3739
{
38-
(PathsD subject, PathsD clipping) = TestPolygonUtilities.BuildClipper2Polygon(Data);
39-
40-
Assert.NotNull(subject);
41-
Assert.NotNull(clipping);
42-
Assert.IsType<PathsD>(subject);
43-
Assert.IsType<PathsD>(clipping);
44-
45-
Assert.Equal(2, subject.Count);
46-
Assert.Equal(122, subject[0].Count);
47-
Assert.Equal(9, subject[1].Count);
48-
49-
Assert.Single(clipping);
50-
Assert.Equal(12, clipping[0].Count);
51-
}
52-
53-
[Fact]
54-
public void PolygonClipper_Union_ValidPolygons_ReturnsCorrectResult()
55-
{
56-
//(Polygon subject, Polygon clipping) = TestPolygonUtilities.BuildPolygon(Data);
57-
5840
Polygon solution = PolygonClipper.Union(Polygons.subject, Polygons.clipping);
5941
Assert.NotNull(solution);
6042

6143
Assert.Equal(2, solution.ContourCount);
6244
Assert.Equal(122, solution[0].VertexCount);
6345
Assert.Equal(9, solution[1].VertexCount);
6446
}
65-
66-
[Fact]
67-
public void Clipper2_Union_ValidPolygons_ReturnsCorrectResult()
68-
{
69-
(PathsD subject, PathsD clipping) = TestPolygonUtilities.BuildClipper2Polygon(Data);
70-
71-
PathsD solution = [];
72-
ClipperD clipper2 = new();
73-
clipper2.AddSubject(subject);
74-
clipper2.AddClip(clipping);
75-
Assert.True(clipper2.Execute(ClipType.Union, FillRule.Positive, solution));
76-
77-
// Clipper2 does not duplicate the first vertex of the each contour
78-
// for closed polygons, so we need to adjust the expected counts.
79-
Assert.Equal(2, solution.Count);
80-
Assert.Equal(121, solution[0].Count);
81-
Assert.Equal(8, solution[1].Count);
82-
}
8347
}

0 commit comments

Comments
 (0)