/// <summary> /// Is loop clockwise oriented? /// </summary> /// <param name="loop"></param> /// <param name="isTransmeridian"></param> /// <returns></returns> internal static bool IsClockwiseNormalized(this GeoFence loop, bool isTransmeridian) { decimal sum = 0m; GeoCoord a; GeoCoord b; // INIT_ITERATION; int loopIndex = -1; while (true) { if (++loopIndex >= loop.NumVerts) { break; } a = loop.Verts[loopIndex]; b = loop.Verts[(loopIndex + 1) % loop.NumVerts]; // If we identify a transmeridian arc (> 180 degrees longitude), // start over with the transmeridian flag set if (!isTransmeridian && Math.Abs(a.Longitude - b.Longitude) > Constants.H3.M_PI) { return(loop.IsClockwiseNormalized(true)); } sum += (b.Longitude.NormalizeLongitude(isTransmeridian) - a.Longitude.NormalizeLongitude(isTransmeridian)) * (b.Latitude + a.Latitude); } return(sum > 0); }
/// <summary> /// Get hexagons along edge of lines of a polygon /// </summary> /// <param name="geofence"></param> /// <param name="res"></param> /// <returns></returns> internal static HashSet <H3Index> GetEdgeHexagons(this GeoFence geofence, int res) { var found = new List <H3Index>(); for (var i = 0; i < geofence.NumVerts; i++) { var origin = geofence.Verts[i]; var destination = i == geofence.NumVerts - 1 ? geofence.Verts[0] : geofence.Verts[i + 1]; int numHexesEstimate = origin.LineHexEstimate(destination, res); for (var j = 0; j < numHexesEstimate; j++) { var interpolate = new GeoCoord ( origin.Latitude * (numHexesEstimate - j) / numHexesEstimate + destination.Latitude * j / numHexesEstimate, origin.Longitude * (numHexesEstimate - j) / numHexesEstimate + destination.Longitude * j / numHexesEstimate ); var pointHex = interpolate.ToH3Index(res); found.Add(pointHex); } } return(new HashSet <H3Index>(found)); }
public void PointInsideGeofenceTransmeridian() { var verts = new[] { new GeoCoord(0.01m, -Constants.H3.M_PI + 0.01m), new GeoCoord(0.01m, Constants.H3.M_PI - 0.01m), new GeoCoord(-0.01m, Constants.H3.M_PI - 0.01m), new GeoCoord(-0.01m, -Constants.H3.M_PI + 0.01m) }; var transMeridianGeofence = new GeoFence { NumVerts = 4, Verts = verts }; var eastPoint = new GeoCoord(0.001m, -Constants.H3.M_PI + 0.001m); var eastPointOutside = new GeoCoord(0.001m, -Constants.H3.M_PI + 0.1m); var westPoint = new GeoCoord(0.001m, Constants.H3.M_PI - 0.001m); var westPointOutside = new GeoCoord(0.001m, Constants.H3.M_PI - 0.1m); var bbox = transMeridianGeofence.ToBBox(); Assert.IsTrue(transMeridianGeofence.PointInside(bbox, westPoint)); Assert.IsTrue(transMeridianGeofence.PointInside(bbox, eastPoint)); Assert.IsFalse(transMeridianGeofence.PointInside(bbox, westPointOutside)); Assert.IsFalse(transMeridianGeofence.PointInside(bbox, eastPointOutside)); }
public void PolyfillTransmeridianComplex() { // This polygon is "complex" in that it has > 4 vertices - this // tests for a bug that was taking the max and min longitude as // the bounds for transmeridian polygons var verts = new[] { new GeoCoord(0.1m, -Constants.H3.M_PI + 0.00001m), new GeoCoord(0.1m, Constants.H3.M_PI - 0.00001m), new GeoCoord(0.05m, Constants.H3.M_PI - 0.2m), new GeoCoord(-0.1m, Constants.H3.M_PI - 0.00001m), new GeoCoord(-0.1m, -Constants.H3.M_PI + 0.00001m), new GeoCoord(-0.05m, -Constants.H3.M_PI + 0.2m), }; var geofence = new GeoFence { NumVerts = 6, Verts = verts }; var polygon = new GeoPolygon { GeoFence = geofence, NumHoles = 0 }; var hexagons = polygon.Polyfill(4); int actualNumHexagons = Utility.CountActualHexagons(hexagons); Assert.AreEqual(1204, actualNumHexagons); }
public void h3js_67() { decimal east = (-56.25m).DegreesToRadians(); decimal north = (-33.13755119234615m).DegreesToRadians(); decimal south = (-34.30714385628804m).DegreesToRadians(); decimal west = (-57.65625m).DegreesToRadians(); var testVerts = new[] { new GeoCoord(north, east), new GeoCoord(south, east), new GeoCoord(south, west), new GeoCoord(north, west), }; var testGeoFence = new GeoFence { NumVerts = 4, Verts = testVerts }; var testPolygon = new GeoPolygon { GeoFence = testGeoFence, NumHoles = 0 }; const int res = 7; var hexagons = testPolygon.Polyfill(res); int actualNumHexagons = Utility.CountActualHexagons(hexagons); Assert.AreEqual(4499, actualNumHexagons); }
public void PolyfillExact() { var somewhere = new GeoCoord(1, 2); var origin = somewhere.ToH3Index(9); var boundary = origin.ToGeoBoundary(); var verts = new List <GeoCoord>(); verts.AddRange(boundary.Verts.Take(boundary.NumVerts)); verts.Add(boundary.Verts[0]); var someGeofence = new GeoFence { NumVerts = boundary.NumVerts + 1, Verts = verts.ToArray() }; var someHexagon = new GeoPolygon { GeoFence = someGeofence, NumHoles = 0 }; var hexagons = someHexagon.Polyfill(9); var actualNumHexagons = Utility.CountActualHexagons(hexagons); Assert.AreEqual(1, actualNumHexagons); }
// https://github.com/uber/h3-js/issues/76#issuecomment-561204505 public void entireWorld() { // TODO: Fails for a single worldwide polygon var worldVerts = new List <GeoCoord> { new GeoCoord(-Constants.H3.M_PI_2, -Constants.H3.M_PI), new GeoCoord(Constants.H3.M_PI_2, -Constants.H3.M_PI), new GeoCoord(Constants.H3.M_PI_2, 0), new GeoCoord(-Constants.H3.M_PI_2, 0), }; var worldGeofence = new GeoFence { NumVerts = 4, Verts = worldVerts.ToArray() }; var worldGeoPolygon = new GeoPolygon { GeoFence = worldGeofence, NumHoles = 0 }; var worldVerts2 = new List <GeoCoord> { new GeoCoord(-Constants.H3.M_PI_2, 0), new GeoCoord(Constants.H3.M_PI_2, 0), new GeoCoord(Constants.H3.M_PI_2, -Constants.H3.M_PI), new GeoCoord(-Constants.H3.M_PI_2, -Constants.H3.M_PI), }; var worldGeofence2 = new GeoFence { NumVerts = 4, Verts = worldVerts2.ToArray() }; var worldGeoPolygon2 = new GeoPolygon { GeoFence = worldGeofence2, NumHoles = 0 }; for (int res = 0; res < 3; res++) { var polyfillOut = worldGeoPolygon.Polyfill(res); var actualNumHexagons = Utility.CountActualHexagons(polyfillOut); var polyfillOut2 = worldGeoPolygon2.Polyfill(res); var actualNumHexagons2 = Utility.CountActualHexagons(polyfillOut2); Assert.AreEqual(res.NumHexagons(), actualNumHexagons + actualNumHexagons2); // Sets should be disjoint foreach (var fill1 in polyfillOut) { if (fill1 == 0) { continue; } bool found = polyfillOut2.Any(fill2 => fill1 == fill2); Assert.IsFalse(found); } polyfillOut.Clear(); polyfillOut2.Clear(); } }
private static void RepeatBoxTest(GeoFence geofence, BBox expected, GeoCoord inside, GeoCoord outside) { var result = geofence.ToBBox(); Assert.AreEqual(result, expected); Assert.IsTrue(result.Contains(inside)); Assert.IsFalse(result.Contains(outside)); }
public bool IsPointInFence(ILocation point, IGeoFence fence) { var points = (from p in fence.Fence select new GeoFence.Point(p.Lat.Point, p.Lon.Point)).ToList(); var f = new GeoFence(points); var coord = new Coordinate(point.Lat.Point, point.Lon.Point); return(f.IsPointInPolygon(coord)); }
/// <summary> /// _getEdgeHexagons takes a given geofence ring (either the main geofence or /// one of the holes) and traces it with hexagons and updates the search and /// found memory blocks. This is used for determining the initial hexagon set /// for the polyfill algorithm to execute on. /// </summary> /// <param name="geofence">The geofence (or hole) to be traced</param> /// <param name="numHexagons"> /// The maximum number of hexagons possible for the geofence /// (also the bounds of the search and found arrays) /// </param> /// <param name="res">The hexagon resolution (0-15)</param> /// <param name="numSearchHexagons">The number of hexagons found so far to be searched</param> /// <param name="search">The block of memory containing the hexagons to search from</param> /// <param name="found">The block of memory containing the hexagons found from the search</param> /// <returns> ///An error code if the hash function cannot insert a found hexagon into the found array. /// </returns> /// <!-- /// algos.c /// int _getEdgeHexagons /// --> public static int GetEdgeHexagons2(this GeoFence geofence, int numHexagons, int res, ref int numSearchHexagons, ref List <H3Index> search, ref List <H3Index> found) { for (int i = 0; i < geofence.NumVerts; i++) { var origin = geofence.Verts[i]; var destination = i == geofence.NumVerts - 1 ? geofence.Verts[0] : geofence.Verts[i + 1]; int numHexesEstimate = origin.LineHexEstimate(destination, res); for (var j = 0; j < numHexesEstimate; j++) { var interpolate = new GeoCoord( origin.Latitude * (numHexesEstimate - j) / numHexesEstimate + destination.Latitude * j / numHexesEstimate, origin.Longitude * (numHexesEstimate - j) / numHexesEstimate + destination.Longitude * j / numHexesEstimate ); var pointHex = interpolate.ToH3Index(res); // A simple hash to store the hexagon, or move to another place if // needed var loc = (int)(pointHex % (ulong)numHexagons); var loopCount = 0; while (found[loc] != 0) { // If this conditional is reached, the `found` memory block is // too small for the given polygon. This should not happen. if (loopCount > numHexagons) { return(Constants.Algos.HexHashOverflow); // LCOV_EXCL_LINE } if (found[loc] == pointHex) { break; // At least two points of the geofence index to the same cell } loc = (loc + 1) % numHexagons; loopCount++; } if (found[loc] == pointHex) { continue; // Skip this hex, already exists in the found hash } // Otherwise, set it in the found hash for now found[loc] = pointHex; search[numSearchHexagons] = pointHex; numSearchHexagons++; } } return(0); }
public void AddLocationMessage(GTSLocationMessage msg, GeoFence geoFence) { base.SetTrackerInfo(msg); Time = msg.ClientRecordedDateTime; _entryTime = msg.ClientRecordedDateTime; _locationMessage = msg; _locMsgID = _locationMessage.Id; _geoFence = geoFence; _geoFenceId = geoFence.Id; }
public void BboxFromGeofenceNoVertices() { var geofence = new GeoFence(); var expected = new BBox(0.0m, 0.0m, 0.0m, 0.0m); var result = geofence.ToBBox(); Assert.AreEqual(result, expected); }
public static void Save(GeoFence geoFence) { if (geoFence.FencesId == 0) { geoFence.CreatedDate = DateTime.Now; db.GeoFences.AddObject(geoFence); } geoFence.UpdatedDate = DateTime.Now; db.SaveChanges(); }
public void IsClockwiseGeofence() { var verts = new[] { new GeoCoord(0m, 0m), new GeoCoord(0.1m, 0.1m), new GeoCoord(0m, 0.1m) }; var geofence = new GeoFence { NumVerts = 3, Verts = verts }; Assert.IsTrue(geofence.IsClockwise()); }
public void PointInsideGeofence() { var geofence = new GeoFence { NumVerts = 6, Verts = SfVerts }; var inside = new GeoCoord(0.659m, -2.136m); var somewhere = new GeoCoord(1, 2); BBox bbox = geofence.ToBBox(); Assert.IsFalse(geofence.PointInside(bbox, SfVerts[0])); Assert.IsTrue(geofence.PointInside(bbox, SfVerts[4])); Assert.IsTrue(geofence.PointInside(bbox, inside)); Assert.IsFalse(geofence.PointInside(bbox, somewhere)); }
public void IsClockwiseGeofenceTransmeridian() { decimal[,] raw = { { 0.4m, Constants.H3.M_PI - 0.1m }, { 0.4m, -Constants.H3.M_PI + 0.1m }, { -0.4m, -Constants.H3.M_PI + 0.1m }, { -0.4m, Constants.H3.M_PI - 0.1m } }; var verts = MakeGeoCoordArray(raw); var geofence = new GeoFence { NumVerts = 4, Verts = verts }; Assert.IsTrue(geofence.IsClockwise()); }
private static void Main() { var sfVerts = Enumerable.Range(0, SfVerts.GetLength(0)) .Select(s => new GeoCoord(SfVerts[s, 0], SfVerts[s, 1])) .ToArray(); var sfGeoFence = new GeoFence() { NumVerts = sfVerts.Length, Verts = sfVerts }; var sfGeoPolygon = new GeoPolygon() { GeoFence = sfGeoFence }; var alamedaVerts = Enumerable.Range(0, AlamedaVerts.GetLength(0)) .Select(s => new GeoCoord(AlamedaVerts[s, 0], AlamedaVerts[s, 1])) .ToArray(); var alamedaGeoFence = new GeoFence() { NumVerts = alamedaVerts.Length, Verts = alamedaVerts }; var alamedaGeoPolygon = new GeoPolygon() { GeoFence = alamedaGeoFence }; var southernVerts = Enumerable.Range(0, SouthernVerts.GetLength(0)) .Select(s => new GeoCoord(SouthernVerts[s, 0], SouthernVerts[s, 1])) .ToArray(); var southernGeoFence = new GeoFence() { NumVerts = southernVerts.Length, Verts = southernVerts }; var southernGeoPolygon = new GeoPolygon() { GeoFence = southernGeoFence }; Console.WriteLine("Starting..."); Console.WriteLine(); Benchmark("polyfill SF", 500, sfGeoPolygon, 9, DoPolyFill); Benchmark("polyfill Alameda", 500, alamedaGeoPolygon, 9, DoPolyFill); Benchmark("polyfill Southern", 10, southernGeoPolygon, 9, DoPolyFill); }
public void AroundZeroZero() { var verts = new[] { new GeoCoord(0.4m, -0.4m), new GeoCoord(0.4m, 0.4m), new GeoCoord(-0.4m, 0.4m), new GeoCoord(-0.4m, -0.4m) }; var geofence = new GeoFence { NumVerts = 4, Verts = verts }; var expected = new BBox(0.4m, -0.4m, 0.4m, -0.4m); var inside = new GeoCoord(-0.1m, -0.1m); var outside = new GeoCoord(1.0m, -1.0m); RepeatBoxTest(geofence, expected, inside, outside); }
public void PosLatNegLan() { var verts = new[] { new GeoCoord(0.7m, -1.4m), new GeoCoord(0.8m, -0.9m), new GeoCoord(1.0m, -0.8m), new GeoCoord(1.1m, -1.3m) }; var geofence = new GeoFence { NumVerts = 4, Verts = verts }; var expected = new BBox(1.1m, 0.7m, -0.8m, -1.4m); var inside = new GeoCoord(0.9m, -1.0m); var outside = new GeoCoord(0.0m, 0.0m); RepeatBoxTest(geofence, expected, inside, outside); }
public void PosLatPosLon() { var verts = new[] { new GeoCoord(0.8m, 0.3m), new GeoCoord(0.7m, 0.6m), new GeoCoord(1.1m, 0.7m), new GeoCoord(1.0m, 0.2m) }; var geofence = new GeoFence { Verts = verts, NumVerts = 4 }; var expected = new BBox(1.1m, 0.7m, 0.7m, 0.2m); var inside = new GeoCoord(0.9m, 0.4m); var outside = new GeoCoord(0.0m, 0.0m); RepeatBoxTest(geofence, expected, inside, outside); }
public void NegLatNegLon() { var verts = new[] { new GeoCoord(-0.4m, -1.4m), new GeoCoord(-0.3m, -1.1m), new GeoCoord(-0.1m, -1.2m), new GeoCoord(-0.2m, -1.4m) }; var geofence = new GeoFence { NumVerts = 4, Verts = verts }; var expected = new BBox(-0.1m, -0.4m, -1.1m, -1.4m); var inside = new GeoCoord(-0.3m, -1.2m); var outside = new GeoCoord(0.0m, 0.0m); RepeatBoxTest(geofence, expected, inside, outside); }
public void BboxFromGeofence() { var verts = new[] { new GeoCoord(0.8m, 0.3m), new GeoCoord(0.7m, 0.6m), new GeoCoord(1.1m, 0.7m), new GeoCoord(1.0m, 0.2m) }; var geofence = new GeoFence { NumVerts = 4, Verts = verts }; var expected = new BBox(1.1m, 0.7m, 0.7m, 0.2m); BBox result = geofence.ToBBox(); Assert.AreEqual(result, expected); }
public void Polyline_Out_Range() { Coordinate c1 = new Coordinate(31.67, -106.51, new EagerLoad(false)); List <GeoFence.Point> points = new List <GeoFence.Point>(); points.Add(new GeoFence.Point(31.65, -106.52)); points.Add(new GeoFence.Point(31.65, -84.02)); points.Add(new GeoFence.Point(42.03, -84.02)); points.Add(new GeoFence.Point(42.03, -106.52)); points.Add(new GeoFence.Point(31.65, -106.52)); GeoFence gf = new GeoFence(points); Distance d = new Distance(900, DistanceType.Meters); Assert.IsFalse(gf.IsPointInRangeOfLine(c1, 900)); Assert.IsFalse(gf.IsPointInRangeOfLine(c1, d)); }
public void EdgeOnNorthPole() { var verts = new[] { new GeoCoord(Constants.H3.M_PI_2 - 0.1m, 0.1m), new GeoCoord(Constants.H3.M_PI_2 - 0.1m, 0.8m), new GeoCoord(Constants.H3.M_PI_2, 0.8m), new GeoCoord(Constants.H3.M_PI_2, 0.1m) }; var geofence = new GeoFence { NumVerts = 4, Verts = verts }; var expected = new BBox(Constants.H3.M_PI_2, Constants.H3.M_PI_2 - 0.1m, 0.8m, 0.1m); var inside = new GeoCoord(Constants.H3.M_PI_2 - 0.01m, 0.4m); var outside = new GeoCoord(Constants.H3.M_PI_2, 0.9m); RepeatBoxTest(geofence, expected, inside, outside); }
public void PolyfillPentagon() { H3Index pentagon = new H3Index(9, 24, 0); var coord = pentagon.ToGeoCoord(); // Length of half an edge of the polygon, in radians decimal edgeLength2 = (0.001m).DegreesToRadians(); var boundingTopRight = coord .SetLatitude(coord.Latitude + edgeLength2) .SetLongitude(coord.Longitude + edgeLength2); var boundingTopLeft = coord .SetLatitude(coord.Latitude + edgeLength2) .SetLongitude(coord.Longitude - edgeLength2); var boundingBottomRight = coord .SetLatitude(coord.Latitude - edgeLength2) .SetLongitude(coord.Longitude + edgeLength2); var boundingBottomLeft = coord .SetLatitude(coord.Latitude - edgeLength2) .SetLongitude(coord.Longitude - edgeLength2); var verts = new[] { boundingBottomLeft, boundingTopLeft, boundingTopRight, boundingBottomRight }; var geofence = new GeoFence { Verts = verts, NumVerts = 4 }; var polygon = new GeoPolygon { GeoFence = geofence, NumHoles = 0 }; var hexagons = polygon.Polyfill(9); Assert.AreEqual(1, hexagons.Count); Assert.IsTrue(hexagons.First().IsPentagon()); }
public void BboxFromGeofenceTransmeridian() { var verts = new[] { new GeoCoord(0.1m, -Constants.H3.M_PI + 0.1m), new GeoCoord(0.1m, Constants.H3.M_PI - 0.1m), new GeoCoord(0.05m, Constants.H3.M_PI - 0.2m), new GeoCoord(-0.1m, Constants.H3.M_PI - 0.1m), new GeoCoord(-0.1m, -Constants.H3.M_PI + 0.1m), new GeoCoord(-0.05m, -Constants.H3.M_PI + 0.2m) }; var geofence = new GeoFence { NumVerts = 6, Verts = verts }; var expected = new BBox(0.1m, -0.1m, -Constants.H3.M_PI + 0.2m, Constants.H3.M_PI - 0.2m); var result = geofence.ToBBox(); Assert.AreEqual(result, expected); }
public void BboxesFromGeoPolygonHole() { var verts = new[] { new GeoCoord(0.8m, 0.3m), new GeoCoord(0.7m, 0.6m), new GeoCoord(1.1m, 0.7m), new GeoCoord(1.0m, 0.2m) }; var geofence = new GeoFence { NumVerts = 4, Verts = verts }; // not a real hole, but doesn't matter for the test var holeVerts = new[] { new GeoCoord(0.9m, 0.3m), new GeoCoord(0.9m, 0.5m), new GeoCoord(1.0m, 0.7m), new GeoCoord(0.9m, 0.3m) }; var holeGeofence = new GeoFence { NumVerts = 4, Verts = holeVerts }; var polygon = new GeoPolygon { GeoFence = geofence, NumHoles = 1, Holes = new List <GeoFence> { holeGeofence } }; var expected = new BBox(1.1m, 0.7m, 0.7m, 0.2m); var expectedHole = new BBox(1.0m, 0.9m, 0.7m, 0.3m); var result = polygon.ToBBoxes(); Assert.AreEqual(result[0], expected); Assert.AreEqual(result[1], expectedHole); }
public int AddFence(GeoFence fence) { var f = FencesManager.GetById(fence.FencesId); f.FencesName = fence.FencesName; f.FencesCoordinate = fence.FencesCoordinate; //f.GeoFenceTypes = FencesManager.GetFencesTypeById(Convert.ToInt32(fence.TempTypeId)) ; f.Details = fence.Details; f.IsPublic = fence.IsPublic; f.Zoom = fence.Zoom; if (f.FencesId == 0) { f.CreatedBy = Membership.GetUser().ProviderUserKey.ToString(); f.Status = true; } f.UpdatedBy = Membership.GetUser().ProviderUserKey.ToString(); FencesManager.Save(f); return(f.FencesId); //???? }
public void BboxesFromGeoPolygon() { var verts = new[] { new GeoCoord(0.8m, 0.3m), new GeoCoord(0.7m, 0.6m), new GeoCoord(1.1m, 0.7m), new GeoCoord(1.0m, 0.2m) }; var geofence = new GeoFence { NumVerts = 4, Verts = verts }; var polygon = new GeoPolygon { GeoFence = geofence, NumHoles = 0 }; var expected = new BBox(1.1m, 0.7m, 0.7m, 0.2m); var result = polygon.ToBBoxes(); Assert.AreEqual(result[0], expected); }
public void Inside_Polygon() { Coordinate c1 = new Coordinate(31.67, -106.51, new EagerLoad(false)); Coordinate c2 = new Coordinate(31.67, -84.03, new EagerLoad(false)); Coordinate c3 = new Coordinate(42.01, -106.51, new EagerLoad(false)); Coordinate c4 = new Coordinate(42.01, -84.03, new EagerLoad(false)); List <GeoFence.Point> points = new List <GeoFence.Point>(); points.Add(new GeoFence.Point(31.65, -106.52)); points.Add(new GeoFence.Point(31.65, -84.02)); points.Add(new GeoFence.Point(42.03, -84.02)); points.Add(new GeoFence.Point(42.03, -106.52)); points.Add(new GeoFence.Point(31.65, -106.52)); GeoFence gf = new GeoFence(points); Assert.IsTrue(gf.IsPointInPolygon(c1)); Assert.IsTrue(gf.IsPointInPolygon(c2)); Assert.IsTrue(gf.IsPointInPolygon(c3)); Assert.IsTrue(gf.IsPointInPolygon(c4)); }