Skip to content

Commit 60ffbc0

Browse files
author
Hannes Pavelka
committed
refactored polygon hasher, added unit-tests & upgrade to .NET 8
1 parent f0ffd1f commit 60ffbc0

File tree

4 files changed

+147
-87
lines changed

4 files changed

+147
-87
lines changed

src/Geohash.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net7.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<GenerateDocumentationFile>true</GenerateDocumentationFile>
66
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
77
<PackageId>geohash-dotnet</PackageId>
@@ -13,15 +13,15 @@
1313
<PackageProjectUrl>https://github.com/postlagerkarte/geohash-dotnet</PackageProjectUrl>
1414
<PackageIconUrl>https://github.com/postlagerkarte/geohash-dotnet/raw/master/icon.png</PackageIconUrl>
1515
<PackageTags>geohash dotnet core csharp c#</PackageTags>
16-
<Version>2.0.0</Version>
16+
<Version>2.1.0</Version>
1717
</PropertyGroup>
1818

1919
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
2020
<DocumentationFile></DocumentationFile>
2121
</PropertyGroup>
2222

2323
<ItemGroup>
24-
<PackageReference Include="NetTopologySuite" Version="2.0.0" />
24+
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
2525
</ItemGroup>
2626

2727
</Project>

src/PolygonHasher.cs

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.ComponentModel;
77
using System.Diagnostics;
88
using System.Linq;
9+
using System.Threading;
910
using System.Threading.Tasks;
1011

1112
namespace Geohash
@@ -40,26 +41,28 @@ public enum GeohashInclusionCriteria
4041
/// <param name="polygon">The input polygon.</param>
4142
/// <param name="geohashPrecision">The desired geohash precision.</param>
4243
/// <param name="geohashInclusionCriteria">The criteria for including geohashes in the result set.</param>
44+
/// <param name="progress">Allows to report progress</param>
4345
/// <returns>A HashSet containing the geohashes that meet the specified inclusion criteria with the input polygon.</returns>
44-
public HashSet<string> GetHashes(Polygon polygon, int geohashPrecision, GeohashInclusionCriteria geohashInclusionCriteria = GeohashInclusionCriteria.Intersects)
46+
47+
public HashSet<string> GetHashes(Polygon polygon, int geohashPrecision, GeohashInclusionCriteria geohashInclusionCriteria = GeohashInclusionCriteria.Contains, IProgress<double> progress = null)
4548
{
46-
// Determine the envelope of the polygon.
4749
var envelope = polygon.EnvelopeInternal;
48-
49-
// Calculate step size based on geohash precision.
5050
double latStep = 180.0 / Math.Pow(2, (5 * geohashPrecision - geohashPrecision % 2) / 2);
51-
double lngStep = 180.0 / Math.Pow(2, (5 * geohashPrecision + geohashPrecision % 2) / 2 - 1);
52-
53-
// Expand envelope by half the step size to ensure boundary geohashes are considered.
51+
double lngStep = 360.0 / Math.Pow(2, (5 * geohashPrecision + geohashPrecision % 2) / 2);
5452
envelope.ExpandBy(latStep / 2, lngStep / 2);
5553

56-
var geohashes = new ConcurrentBag<string>();
57-
54+
HashSet<string> geohashes = new HashSet<string>();
5855
bool checkContains = geohashInclusionCriteria == GeohashInclusionCriteria.Contains;
5956
bool checkIntersects = geohashInclusionCriteria == GeohashInclusionCriteria.Intersects;
6057

61-
// Parallelize the outer latitude loop.
62-
Parallel.For((int)(envelope.MinY / latStep), (int)(envelope.MaxY / latStep) + 1, (latIdx) =>
58+
int totalSteps = (int)Math.Ceiling((envelope.MaxY - envelope.MinY) / latStep);
59+
int stepsCompleted = 0;
60+
61+
// Calculate the size of the work batch for progress reporting
62+
int progressBatchSize = Math.Max(1, totalSteps / 100);
63+
64+
Parallel.For((int)(envelope.MinY / latStep), (int)(envelope.MaxY / latStep) + 1, () => new HashSet<string>(),
65+
(latIdx, state, localGeohashes) =>
6366
{
6467
double lat = latIdx * latStep;
6568
Coordinate[] coords = new Coordinate[5];
@@ -79,27 +82,37 @@ public HashSet<string> GetHashes(Polygon polygon, int geohashPrecision, GeohashI
7982

8083
var geohashPoly = new Polygon(new LinearRing(coords));
8184

82-
// Check inclusion criteria.
85+
8386
if ((checkContains && polygon.Contains(geohashPoly)) ||
8487
(checkIntersects && polygon.Intersects(geohashPoly)))
8588
{
86-
geohashes.Add(curGeohash);
89+
localGeohashes.Add(curGeohash);
8790
}
8891
}
89-
});
90-
91-
return geohashes.ToHashSet();
92-
}
93-
94-
95-
96-
97-
98-
9992

93+
if ((latIdx + 1) % progressBatchSize == 0)
94+
{
95+
progress?.Report(Math.Min(1.0, (double)latIdx / totalSteps));
96+
}
10097

98+
return localGeohashes;
99+
},
100+
(localGeohashes) =>
101+
{
102+
lock (geohashes)
103+
{
104+
foreach (var geohash in localGeohashes)
105+
{
106+
geohashes.Add(geohash);
107+
}
108+
}
109+
});
101110

111+
// Final progress update to ensure we reach 100% when done
112+
progress?.Report(1.0);
102113

114+
return geohashes;
115+
}
103116

104117
}
105118
}

tests/Geohash.Tests.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net7.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55

66
<IsPackable>false</IsPackable>
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
11-
<PackageReference Include="xunit" Version="2.4.1" />
12-
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
11+
<PackageReference Include="xunit" Version="2.6.2" />
12+
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
1313
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1414
<PrivateAssets>all</PrivateAssets>
1515
</PackageReference>
16-
<PackageReference Include="coverlet.collector" Version="1.3.0">
16+
<PackageReference Include="coverlet.collector" Version="6.0.0">
1717
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1818
<PrivateAssets>all</PrivateAssets>
1919
</PackageReference>

tests/PolygonHasherTests.cs

Lines changed: 103 additions & 56 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)