Skip to content

Commit

Permalink
Added FromGeographicCoordinateSystem function to Geohash.
Browse files Browse the repository at this point in the history
  • Loading branch information
amsga committed Jan 21, 2024
1 parent 1bf5379 commit bbbf223
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CoordinateSystems/CoordinateSystems.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageId>TensionDev.CoordinateSystems</PackageId>
<Version>0.1.0-alpha</Version>
<Version>0.1.0</Version>
<Authors>TensionDev amsga</Authors>
<Company>TensionDev</Company>
<Product>TensionDev.CoordinateSystems</Product>
Expand Down
79 changes: 77 additions & 2 deletions CoordinateSystems/Geohash.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,40 @@ public String Hash
}
}

public static Geohash FromGeographicCoordinateSystem(GeographicCoordinateSystem geographicCoordinateSystem, Int32 length)
{
if (length < 0) throw new ArgumentOutOfRangeException($"GeoHash of length {length} is not supported!", nameof(length));
if (length > 12) throw new ArgumentOutOfRangeException($"GeoHash of length {length} is not supported!", nameof(length));

Int32 bitLength = length * 5;
UInt64 bitNotation = 0;
Boolean bit;

Double latitudeMin = -90;
Double latitudeMax = 90;
Double longitudeMin = -180;
Double longitudeMax = 180;

for (Int32 i = 0; i < bitLength; ++i)
{
if (i % 2 == 0)
{
(longitudeMin, longitudeMax, bit) = BitNotationMultiplication(longitudeMin, longitudeMax, geographicCoordinateSystem.LongitudeDecimalDegrees);
}
else
{
(latitudeMin, latitudeMax, bit) = BitNotationMultiplication(latitudeMin, latitudeMax, geographicCoordinateSystem.LatitudeDecimalDegrees);
}

bitNotation <<= 1;
bitNotation += bit ? 1u : 0u;
}

String hash = FromBitNotationToHash(bitNotation, length);

return new Geohash(hash);
}

public GeographicCoordinateSystem ToGeographicCoordinateSystem()
{
(BitArray bitNotation, UInt32 length) = ToBitNotation();
Expand Down Expand Up @@ -96,7 +130,7 @@ public GeographicCoordinateSystem ToGeographicCoordinateSystem()

BitArray bitNotation = new BitArray(BitConverter.GetBytes(bitStream))
{
Length = (int)length
Length = (Int32)length
};

return (bitNotation, length);
Expand All @@ -117,7 +151,7 @@ private static GeographicCoordinateSystem BitNotationDivisions(BitArray bitNotat

for (Int32 i = 0; i < length; ++i)
{
Int32 index = (int)(length - i - 1);
Int32 index = (Int32)(length - i - 1);
if (i % 2 == 0)
{
(longitudeMin, longitudeMax) = BitNotationDivision(bitNotation[index], longitudeMin, longitudeMax);
Expand Down Expand Up @@ -149,5 +183,46 @@ private static (Double min, Double max) BitNotationDivision(Boolean bit, Double
return (min, mean);
}
}

private static (Double min, Double max, Boolean bit) BitNotationMultiplication(Double min, Double max, Double value)
{
Double mean = (min + max) / 2.0;

if (value >= mean)
{
return (mean, max, true);
}
else
{
return (min, mean, false);
}
}

private static String FromBitNotationToHash(UInt64 bitNotation, Int32 hashLength)
{
StringBuilder sb = new StringBuilder();

for (Int32 i = 0; i < hashLength; ++i)
{
UInt64 value = bitNotation % 32;
bitNotation >>= 5;

Char c = (Char)48;
if (value < 10)
c += (Char)value;
else if (value < 17)
c += (Char)(value + 40);
else if (value < 19)
c += (Char)(value + 41);
else if (value < 21)
c += (Char)(value + 42);
else
c += (Char)(value + 43);

sb.Insert(0, c);
}

return sb.ToString();
}
}
}
20 changes: 19 additions & 1 deletion XUnitTestProjectCoordinateSystems/UnitTestGeohash.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public void TestConstructorLimits()
}

[Fact]
public void TestConversion()
public void TestToGeographicCoordinateSystem()
{
GeographicCoordinateSystem expected = new GeographicCoordinateSystem()
{
Expand All @@ -107,5 +107,23 @@ public void TestConversion()
Assert.Equal(expected.LongitudeDecimalDegrees, actual.LongitudeDecimalDegrees, LongitudeError5);
Assert.Equal(expected.AltitudeMetres, actual.AltitudeMetres);
}

[Fact]
public void TestFromGeographicCoordinateSystem()
{
String geohashString = "u4pruydqqvj";
Geohash expected = new Geohash(geohashString);

GeographicCoordinateSystem value = new GeographicCoordinateSystem()
{
LatitudeDecimalDegrees = 57.64911,
LongitudeDecimalDegrees = 10.40744,
AltitudeMetres = 0,
};

Geohash actual = Geohash.FromGeographicCoordinateSystem(value, 11);

Assert.Equal(expected.Hash, actual.Hash);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.6.5" />
<PackageReference Include="xunit" Version="2.6.6" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand Down

0 comments on commit bbbf223

Please sign in to comment.