-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from JonMcPherson/float-handling
Fix floating point precision issues with new algorithm for Encode() and Decode()
Showing
15 changed files
with
679 additions
and
455 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Google.OpenLocationCode; | ||
using NUnit.Framework; | ||
|
||
public static class DecodingTest { | ||
|
||
private const double Precision = 1e-10; | ||
|
||
// Test cases for decoding valid codes into code areas | ||
// https://github.com/google/open-location-code/blob/master/test_data/decoding.csv | ||
private static readonly IEnumerable<TestData> DecodingTestCases = TestDataUtils.ReadTestData<TestData>("decoding.csv"); | ||
|
||
|
||
public class TheDecodeMethod { | ||
[Test] | ||
public void ShouldDecodeFullCodesToExpectedCodeArea() { | ||
foreach (var testData in DecodingTestCases) { | ||
AssertExpectedDecodedArea(testData, OpenLocationCode.Decode(testData.Code)); | ||
} | ||
} | ||
|
||
[Test] | ||
public void ShouldDecodeFullCodesWithLowercaseCharactersToExpectedCodeArea() { | ||
foreach (var testData in DecodingTestCases) { | ||
AssertExpectedDecodedArea(testData, OpenLocationCode.Decode(testData.Code.ToLower())); | ||
} | ||
} | ||
|
||
[Test] | ||
public void ShouldDecodeToCodeAreaWithValidContainmentRelation() { | ||
foreach (var testData in DecodingTestCases) { | ||
var olc = new OpenLocationCode(testData.Code); | ||
var decoded = olc.Decode(); | ||
Assert.True(decoded.Contains(decoded.CenterLatitude, decoded.CenterLongitude), | ||
$"Containment relation is broken for the decoded middle point of code {testData.Code}"); | ||
Assert.True(decoded.Contains(decoded.SouthLatitude, decoded.WestLongitude), | ||
$"Containment relation is broken for the decoded bottom left corner of code {testData.Code}"); | ||
Assert.False(decoded.Contains(decoded.NorthLatitude, decoded.EastLongitude), | ||
$"Containment relation is broken for the decoded top right corner of code {testData.Code}"); | ||
Assert.False(decoded.Contains(decoded.SouthLatitude, decoded.EastLongitude), | ||
$"Containment relation is broken for the decoded bottom right corner of code {testData.Code}"); | ||
Assert.False(decoded.Contains(decoded.NorthLatitude, decoded.WestLongitude), | ||
$"Containment relation is broken for the decoded top left corner of code {testData.Code}"); | ||
} | ||
} | ||
|
||
[Test] | ||
public void ShouldDecodeToCodeAreaWithExpectedDimensions() { | ||
Assert.AreEqual(20.0, OpenLocationCode.Decode("67000000+").LongitudeWidth, 0); | ||
Assert.AreEqual(20.0, OpenLocationCode.Decode("67000000+").LatitudeHeight, 0); | ||
Assert.AreEqual(1.0, OpenLocationCode.Decode("67890000+").LongitudeWidth, 0); | ||
Assert.AreEqual(1.0, OpenLocationCode.Decode("67890000+").LatitudeHeight, 0); | ||
Assert.AreEqual(0.05, OpenLocationCode.Decode("6789CF00+").LongitudeWidth, 0); | ||
Assert.AreEqual(0.05, OpenLocationCode.Decode("6789CF00+").LatitudeHeight, 0); | ||
Assert.AreEqual(0.0025, OpenLocationCode.Decode("6789CFGH+").LongitudeWidth, 0); | ||
Assert.AreEqual(0.0025, OpenLocationCode.Decode("6789CFGH+").LatitudeHeight, 0); | ||
Assert.AreEqual(0.000125, OpenLocationCode.Decode("6789CFGH+JM").LongitudeWidth, 0); | ||
Assert.AreEqual(0.000125, OpenLocationCode.Decode("6789CFGH+JM").LatitudeHeight, 0); | ||
Assert.AreEqual(0.00003125, OpenLocationCode.Decode("6789CFGH+JMP").LongitudeWidth, 0); | ||
Assert.AreEqual(0.000025, OpenLocationCode.Decode("6789CFGH+JMP").LatitudeHeight, 0); | ||
} | ||
|
||
[Test] | ||
public void ShouldThrowArgumentExceptionForInvalidOrShortCodes() { | ||
foreach (string code in new[] { null, "INVALID", "9QCJ+2VX" }) { | ||
Assert.Throws<ArgumentException>(() => OpenLocationCode.Decode(code), | ||
$"Expected exception was not thrown for code {code}"); | ||
} | ||
} | ||
|
||
} | ||
|
||
public class TheDecodeConstructor { | ||
[Test] | ||
public void ShouldAcceptFullCodesAndDecodeToExpectedCodeArea() { | ||
foreach (var testData in DecodingTestCases) { | ||
AssertExpectedDecodedArea(testData, new OpenLocationCode(testData.Code).Decode()); | ||
} | ||
} | ||
|
||
[Test] | ||
public void ShouldNormalizeFullCodeDigitsToExpectedCode() { | ||
foreach (var testData in DecodingTestCases) { | ||
string codeDigits = OpenLocationCode.TrimCode(testData.Code); | ||
Assert.AreEqual(testData.Code, new OpenLocationCode(codeDigits).Code, | ||
$"Wrong code normalized from code digits {codeDigits}"); | ||
} | ||
} | ||
|
||
[Test] | ||
public void ShouldTrimCodesIntoToExpectedCodeDigits() { | ||
foreach (var testData in DecodingTestCases) { | ||
Assert.AreEqual(OpenLocationCode.TrimCode(testData.Code), new OpenLocationCode(testData.Code).CodeDigits, | ||
$"Wrong digits trimmed from code {testData.Code}."); | ||
} | ||
} | ||
|
||
[Test] | ||
public void ShouldThrowArgumentExceptionForInvalidOrShortCodes() { | ||
foreach (string code in new[] { null, "INVALID", "9QCJ+2VX" }) { | ||
Assert.Throws<ArgumentException>(() => new OpenLocationCode(code), | ||
$"Expected exception was not thrown for code {code}"); | ||
} | ||
} | ||
} | ||
|
||
private static void AssertExpectedDecodedArea(TestData testData, CodeArea decoded) { | ||
Assert.AreEqual(testData.Length, decoded.CodeLength, $"Wrong length for code {testData.Code}"); | ||
Assert.AreEqual(testData.LatLo, decoded.SouthLatitude, Precision, $"Wrong low latitude for code {testData.Code}"); | ||
Assert.AreEqual(testData.LatHi, decoded.NorthLatitude, Precision, $"Wrong high latitude for code {testData.Code}"); | ||
Assert.AreEqual(testData.LngLo, decoded.WestLongitude, Precision, $"Wrong low longitude for code {testData.Code}"); | ||
Assert.AreEqual(testData.LngHi, decoded.EastLongitude, Precision, $"Wrong high longitude for code {testData.Code}"); | ||
} | ||
|
||
|
||
public class TestData { | ||
|
||
public string Code { get; set; } | ||
public int Length { get; set; } | ||
public double LatLo { get; set; } | ||
public double LngLo { get; set; } | ||
public double LatHi { get; set; } | ||
public double LngHi { get; set; } | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Test decoding Open Location Codes. | ||
# | ||
# Provides test cases for decoding valid codes. | ||
# | ||
# Format: | ||
# code,length,latLo,lngLo,latHi,lngHi | ||
7FG49Q00+,6,20.35,2.75,20.4,2.8 | ||
7FG49QCJ+2V,10,20.37,2.782125,20.370125,2.78225 | ||
7FG49QCJ+2VX,11,20.3701,2.78221875,20.370125,2.78225 | ||
7FG49QCJ+2VXGJ,13,20.370113,2.782234375,20.370114,2.78223632813 | ||
8FVC2222+22,10,47.0,8.0,47.000125,8.000125 | ||
4VCPPQGP+Q9,10,-41.273125,174.785875,-41.273,174.786 | ||
62G20000+,4,0.0,-180.0,1,-179 | ||
22220000+,4,-90,-180,-89,-179 | ||
7FG40000+,4,20.0,2.0,21.0,3.0 | ||
22222222+22,10,-90.0,-180.0,-89.999875,-179.999875 | ||
6VGX0000+,4,0,179,1,180 | ||
6FH32222+222,11,1,1,1.000025,1.00003125 | ||
# Special cases over 90 latitude and 180 longitude | ||
CFX30000+,4,89,1,90,2 | ||
CFX30000+,4,89,1,90,2 | ||
62H20000+,4,1,-180,2,-179 | ||
62H30000+,4,1,-179,2,-178 | ||
CFX3X2X2+X2,10,89.9998750,1,90,1.0001250 | ||
# Test non-precise latitude/longitude value | ||
6FH56C22+22,10,1.2000000000000028,3.4000000000000057,1.2001249999999999,3.4001250000000027 | ||
# Validate that digits after the first 15 are ignored when decoding | ||
849VGJQF+VX7QR3J,15,37.5396691200,-122.3750698242,37.5396691600,-122.3750697021 | ||
849VGJQF+VX7QR3J7QR3J,15,37.5396691200,-122.3750698242,37.5396691600,-122.3750697021 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# Test encoding Open Location Codes. | ||
# | ||
# Provides test cases for encoding latitude and longitude to codes. | ||
# | ||
# Format: | ||
# latitude,longitude,length,expected code (empty if the input should cause an error) | ||
20.375,2.775,6,7FG49Q00+ | ||
20.3700625,2.7821875,10,7FG49QCJ+2V | ||
20.3701125,2.782234375,11,7FG49QCJ+2VX | ||
20.3701135,2.78223535156,13,7FG49QCJ+2VXGJ | ||
47.0000625,8.0000625,10,8FVC2222+22 | ||
-41.2730625,174.7859375,10,4VCPPQGP+Q9 | ||
0.5,-179.5,4,62G20000+ | ||
-89.5,-179.5,4,22220000+ | ||
20.5,2.5,4,7FG40000+ | ||
-89.9999375,-179.9999375,10,22222222+22 | ||
0.5,179.5,4,6VGX0000+ | ||
1,1,11,6FH32222+222 | ||
################################################################################ | ||
# | ||
# Special cases over 90 latitude and 180 longitude | ||
# | ||
################################################################################ | ||
90,1,4,CFX30000+ | ||
92,1,4,CFX30000+ | ||
1,180,4,62H20000+ | ||
1,181,4,62H30000+ | ||
90,1,10,CFX3X2X2+X2 | ||
################################################################################ | ||
# | ||
# Test non-precise latitude/longitude value | ||
# | ||
################################################################################ | ||
1.2,3.4,10,6FH56C22+22 | ||
################################################################################ | ||
# | ||
# Validate that codes generated with a length exceeding 15 significant digits | ||
# return a 15-digit code | ||
# | ||
################################################################################ | ||
37.539669125,-122.375069724,15,849VGJQF+VX7QR3J | ||
37.539669125,-122.375069724,16,849VGJQF+VX7QR3J | ||
37.539669125,-122.375069724,100,849VGJQF+VX7QR3J | ||
################################################################################ | ||
# | ||
# Test floating point representation/rounding errors. | ||
# | ||
################################################################################ | ||
35.6,3.033,10,8F75J22M+26 | ||
-48.71,142.78,8,4R347QRJ+ | ||
-70,163.7,8,3V252P22+ | ||
-2.804,7.003,13,6F9952W3+C6222 | ||
13.9,164.88,12,7V56WV2J+2222 | ||
-13.23,172.77,8,5VRJQQCC+ | ||
40.6,129.7,8,8QGFJP22+ | ||
-52.166,13.694,14,3FVMRMMV+JJ2222 | ||
-14,106.9,6,5PR82W00+ | ||
70.3,-87.64,13,C62J8926+22222 | ||
66.89,-106,10,95RPV2R2+22 | ||
2.5,-64.23,11,67JQGQ2C+222 | ||
-56.7,-47.2,14,38MJ8R22+222222 | ||
-34.45,-93.719,6,46Q8H700+ | ||
-35.849,-93.75,12,46P85722+C222 | ||
65.748,24.316,12,9GQ6P8X8+6C22 | ||
-57.32,130.43,12,3QJGMCJJ+2222 | ||
17.6,-44.4,6,789QJJ00+ | ||
-27.6,-104.8,6,554QC600+ | ||
41.87,-145.59,13,83HPVCC6+22222 | ||
-4.542,148.638,13,6R7CFJ5Q+66222 | ||
-37.014,-159.936,10,43J2X3P7+CJ | ||
-57.25,125.49,15,3QJ7QF2R+2222222 | ||
48.89,-80.52,13,86WXVFRJ+22222 | ||
53.66,170.97,14,9V5GMX6C+222222 | ||
0.49,-76.97,15,67G5F2RJ+2222222 | ||
40.44,-36.7,12,89G5C8R2+2222 | ||
58.73,69.95,8,9JCFPXJ2+ | ||
16.179,150.075,12,7R8G53HG+J222 | ||
-55.574,-70.061,12,37PFCWGQ+CJ22 | ||
76.1,-82.5,15,C68V4G22+2222222 | ||
58.66,149.17,10,9RCFM56C+22 | ||
-67.2,48.6,6,3H4CRJ00+ | ||
-5.6,-54.5,14,6867CG22+222222 | ||
-34,145.5,14,4RR72G22+222222 | ||
-34.2,66.4,12,4JQ8RC22+2222 | ||
17.8,-108.5,6,759HRG00+ | ||
10.734,-168.294,10,722HPPM4+JC | ||
-28.732,54.32,8,5H3P789C+ | ||
64.1,107.9,12,9PP94W22+2222 | ||
79.7525,6.9623,8,CFF8QX36+ | ||
-63.6449,-25.1475,8,398P9V43+ | ||
35.019,148.827,11,8R7C2R9G+JR2 | ||
71.132,-98.584,15,C6334CJ8+RC22222 | ||
53.38,-51.34,12,985C9MJ6+2222 | ||
-1.2,170.2,12,6VCGR622+2222 | ||
50.2,-162.8,11,922V6622+222 | ||
-25.798,-59.812,10,5862652Q+R6 | ||
81.654,-162.422,14,C2HVMH3H+J62222 | ||
-75.7,-35.4,8,29P68J22+ | ||
-80.01,58.57,15,2HFWXHRC+2222222 | ||
67.2,115.1,11,9PVQ6422+222 | ||
-78.137,-42.995,12,28HVV274+6222 | ||
-56.3,114.5,11,3PMPPG22+222 | ||
10.767,-62.787,13,772VQ687+R6222 | ||
-19.212,107.423,10,5PG9QCQF+66 | ||
21.192,-45.145,15,78HP5VR4+R222222 | ||
16.701,148.648,14,7R8CPJ2X+C62222 | ||
52.25,-77.45,15,97447H22+2222222 | ||
-68.54504,-62.81725,11,373VF53M+X4J | ||
76.7,-86.172,12,C68MPR2H+2622 | ||
-6.2,96.6,13,6M5RRJ22+22222 | ||
59.32,-157.21,12,93F48QCR+2222 | ||
29.7,39.6,12,7GXXPJ22+2222 | ||
-18.32,96.397,10,5MHRM9JW+2R | ||
-30.3,76.5,11,4JXRPG22+222 | ||
50.342,-112.534,15,95298FR8+RC22222 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Test shortening and extending codes. | ||
# | ||
# Format: | ||
# full code,lat,lng,shortcode,test_type | ||
# test_type is R for recovery only, S for shorten only, or B for both. | ||
9C3W9QCJ+2VX,51.3701125,-1.217765625,+2VX,B | ||
# Adjust so we can't trim by 8 (+/- .000755) | ||
9C3W9QCJ+2VX,51.3708675,-1.217765625,CJ+2VX,B | ||
9C3W9QCJ+2VX,51.3693575,-1.217765625,CJ+2VX,B | ||
9C3W9QCJ+2VX,51.3701125,-1.218520625,CJ+2VX,B | ||
9C3W9QCJ+2VX,51.3701125,-1.217010625,CJ+2VX,B | ||
# Adjust so we can't trim by 6 (+/- .0151) | ||
9C3W9QCJ+2VX,51.3852125,-1.217765625,9QCJ+2VX,B | ||
9C3W9QCJ+2VX,51.3550125,-1.217765625,9QCJ+2VX,B | ||
9C3W9QCJ+2VX,51.3701125,-1.232865625,9QCJ+2VX,B | ||
9C3W9QCJ+2VX,51.3701125,-1.202665625,9QCJ+2VX,B | ||
# Added to detect error in recoverNearest functionality | ||
8FJFW222+,42.899,9.012,22+,B | ||
796RXG22+,14.95125,-23.5001,22+,B | ||
# Reference location is in the 4 digit cell to the south. | ||
8FVC2GGG+GG,46.976,8.526,2GGG+GG,B | ||
# Reference location is in the 4 digit cell to the north. | ||
8FRCXGGG+GG,47.026,8.526,XGGG+GG,B | ||
# Reference location is in the 4 digit cell to the east. | ||
8FR9GXGG+GG,46.526,8.026,GXGG+GG,B | ||
# Reference location is in the 4 digit cell to the west. | ||
8FRCG2GG+GG,46.526,7.976,G2GG+GG,B | ||
# Added to detect errors recovering codes near the poles. | ||
# This tests recovery function, but these codes won't shorten. | ||
CFX22222+22,89.6,0.0,2222+22,R | ||
2CXXXXXX+XX,-81.0,0.0,XXXXXX+XX,R | ||
# Recovered full codes should be the full code | ||
8FRCG2GG+GG,46.526,7.976,8FRCG2GG+GG,R | ||
# Recovered full codes should be the uppercased full code | ||
8FRCG2GG+GG,46.526,7.976,8frCG2GG+gG,R |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Test data for validity tests. | ||
# Format of each line is: | ||
# code,isValid,isShort,isFull,isPadded | ||
# Valid full codes: | ||
8FWC2345+G6,true,false,true,false | ||
8FWC2345+G6G,true,false,true,false | ||
8fwc2345+,true,false,true,false | ||
8FWCX400+,true,false,true,true | ||
8FWC0000+,true,false,true,true | ||
8F000000+,true,false,true,true | ||
# Valid short codes: | ||
WC2345+G6g,true,true,false,false | ||
2345+G6,true,true,false,false | ||
45+G6,true,true,false,false | ||
+G6,true,true,false,false | ||
# Invalid codes | ||
G+,false,false,false,false | ||
+,false,false,false,false | ||
8FWC2345+G,false,false,false,false | ||
8FWC2_45+G6,false,false,false,false | ||
8FWC2η45+G6,false,false,false,false | ||
8FWC2345+G6+,false,false,false,false | ||
8FWC2345G6+,false,false,false,false | ||
8FWC2300+G6,false,false,false,false | ||
WC2300+G6g,false,false,false,false | ||
WC2345+G,false,false,false,false | ||
WC2300+,false,false,false,false | ||
# Validate that codes at and exceeding 15 digits are still valid when all their | ||
# digits are valid, and invalid when not. | ||
849VGJQF+VX7QR3J,true,false,true,false | ||
849VGJQF+VX7QR3U,false,false,false,false | ||
849VGJQF+VX7QR3JW,true,false,true,false | ||
849VGJQF+VX7QR3JU,false,false,false,false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System.Collections.Immutable; | ||
using System.IO; | ||
using CsvHelper; | ||
using CsvHelper.Configuration; | ||
|
||
|
||
public static class TestDataUtils { | ||
|
||
public static ImmutableList<T> ReadTestData<T>(string fileName) { | ||
using (var reader = new StreamReader($"..\\..\\..\\TestData\\{fileName}")) { | ||
using (var csv = new CsvReader(reader, new Configuration { HasHeaderRecord = false, AllowComments = true })) { | ||
return csv.GetRecords<T>().ToImmutableList(); | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
using System; | ||
|
||
namespace Google.OpenLocationCode { | ||
/// <summary> | ||
/// A rectangular area on the geographic coordinate system specified by the minimum and maximum <see cref="GeoPoint"/> coordinates. | ||
/// The coordinates include the latitude and longitude of the lower left (south west) and upper right (north east) corners. | ||
/// <para> | ||
/// Additional properties exist to calculate the <see cref="Center"/> of the bounding box, | ||
/// and the <see cref="LatitudeHeight"/> or <see cref="LongitudeWidth"/> area dimensions in degrees. | ||
/// </para> | ||
/// </summary> | ||
public class GeoArea { | ||
|
||
/// <summary> | ||
/// Create a new rectangular GeoArea of the provided min and max geo points. | ||
/// </summary> | ||
/// <param name="min">The minimum GeoPoint</param> | ||
/// <param name="max">The maximum GeoPoint</param> | ||
/// <exception cref="ArgumentException">If min is greater than or equal to max.</exception> | ||
public GeoArea(GeoPoint min, GeoPoint max) { | ||
if (min.Latitude >= max.Latitude || min.Longitude >= max.Longitude) { | ||
throw new ArgumentException("min must be less than max"); | ||
} | ||
Min = min; | ||
Max = max; | ||
} | ||
|
||
/// <summary> | ||
/// Create a new rectangular GeoArea of the provided min and max geo coordinates. | ||
/// </summary> | ||
/// <param name="southLatitude">The minimum south latitude</param> | ||
/// <param name="westLongitude">The minimum west longitude</param> | ||
/// <param name="northLatitude">The maximum north latitude</param> | ||
/// <param name="eastLongitude">The maximum east longitude</param> | ||
public GeoArea(double southLatitude, double westLongitude, double northLatitude, double eastLongitude) : | ||
this(new GeoPoint(southLatitude, westLongitude), new GeoPoint(northLatitude, eastLongitude)) { } | ||
|
||
/// <summary> | ||
/// The min (south west) point coordinates of the area bounds. | ||
/// </summary> | ||
public GeoPoint Min { get; } | ||
|
||
/// <summary> | ||
/// The max (north east) point coordinates of the area bounds. | ||
/// </summary> | ||
public GeoPoint Max { get; } | ||
|
||
/// <summary> | ||
/// The center point of the area which is equidistant between <see cref="Min"/> and <see cref="Max"/>. | ||
/// </summary> | ||
public GeoPoint Center => new GeoPoint(CenterLatitude, CenterLongitude); | ||
|
||
|
||
/// <summary> | ||
/// The width of the area in longitude degrees. | ||
/// </summary> | ||
public double LongitudeWidth => (double)((decimal)Max.Longitude - (decimal)Min.Longitude); | ||
|
||
/// <summary> | ||
/// The height of the area in latitude degrees. | ||
/// </summary> | ||
public double LatitudeHeight => (double)((decimal)Max.Latitude - (decimal)Min.Latitude); | ||
|
||
|
||
/// <summary>The south (min) latitude coordinate in decimal degrees.</summary> | ||
/// <remarks>Alias to <see cref="Min"/>.<see cref="GeoPoint.Latitude">Latitude</see></remarks> | ||
public double SouthLatitude => Min.Latitude; | ||
|
||
/// <summary>The west (min) longitude coordinate in decimal degrees.</summary> | ||
/// <remarks>Alias to <see cref="Min"/>.<see cref="GeoPoint.Longitude">Longitude</see></remarks> | ||
public double WestLongitude => Min.Longitude; | ||
|
||
/// <summary>The north (max) latitude coordinate in decimal degrees.</summary> | ||
/// <remarks>Alias to <see cref="Max"/>.<see cref="GeoPoint.Latitude">Latitude</see></remarks> | ||
public double NorthLatitude => Max.Latitude; | ||
|
||
/// <summary>The east (max) longitude coordinate in decimal degrees.</summary> | ||
/// <remarks>Alias to <see cref="Max"/>.<see cref="GeoPoint.Longitude">Longitude</see></remarks> | ||
public double EastLongitude => Max.Longitude; | ||
|
||
/// <summary>The center latitude coordinate in decimal degrees.</summary> | ||
/// <remarks>Alias to <see cref="Center"/>.<see cref="GeoPoint.Latitude">Latitude</see></remarks> | ||
public double CenterLatitude => (Min.Latitude + Max.Latitude) / 2; | ||
|
||
/// <summary>The center longitude coordinate in decimal degrees.</summary> | ||
/// <remarks>Alias to <see cref="Center"/>.<see cref="GeoPoint.Longitude">Longitude</see></remarks> | ||
public double CenterLongitude => (Min.Longitude + Max.Longitude) / 2; | ||
|
||
|
||
/// <returns><c>true</c> if this geo area contains the provided point, <c>false</c> otherwise.</returns> | ||
/// <param name="point">The point coordinates to check.</param> | ||
public bool Contains(GeoPoint point) { | ||
return Contains(point.Latitude, point.Longitude); | ||
} | ||
|
||
/// <returns><c>true</c> if this geo area contains the provided point, <c>false</c> otherwise.</returns> | ||
/// <param name="latitude">The latitude coordinate of the point to check.</param> | ||
/// <param name="longitude">The longitude coordinate of the point to check.</param> | ||
public bool Contains(double latitude, double longitude) { | ||
return Min.Latitude <= latitude && latitude < Max.Latitude | ||
&& Min.Longitude <= longitude && longitude < Max.Longitude; | ||
} | ||
|
||
} | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,20 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<package> | ||
<?xml version="1.0"?> | ||
<package > | ||
<metadata> | ||
<id>OpenLocationCode</id> | ||
<version>2.0.0</version> | ||
<title>OpenLocationCode</title> | ||
<authors>Jon McPherson</authors> | ||
<owners>JonMcPherson</owners> | ||
<id>$id$</id> | ||
<version>$version$</version> | ||
<title>$title$</title> | ||
<authors>$author$</authors> | ||
<owners>$owner$</owners> | ||
<licenseUrl>https://github.com/google/open-location-code/blob/master/LICENSE</licenseUrl> | ||
<projectUrl>https://plus.codes/</projectUrl> | ||
<repository type="git" url="https://github.com/JonMcPherson/open-location-code" /> | ||
<requireLicenseAcceptance>false</requireLicenseAcceptance> | ||
<description>The C# (.NET Standard) implementation of the Google Open Location Code API.</description> | ||
<tags>OLC google open location code plus codes latitude longitude encode decode</tags> | ||
<description>$description$</description> | ||
<releaseNotes>$packageReleaseNotes$</releaseNotes> | ||
<tags>$packageTags$</tags> | ||
<dependencies> | ||
<group targetFramework=".NETStandard2.0" /> | ||
</dependencies> | ||
</metadata> | ||
<files> | ||
<file src="bin\$configuration$\netstandard2.0\OpenLocationCode.dll" target="lib\netstandard2.0\OpenLocationCode.dll" /> | ||
</files> | ||
</package> |