/// <summary> /// Returns the minimum distance between this Geometry <paramref name="g0"/> and another Geometry <paramref name="g1"/>, by calculating the nearest /// points in NTS and then asking (Sharp)Proj to get the actual distance in meters. /// </summary> /// <param name="g0">Geometry 1</param> /// <param name="g1">Geometry 2</param> /// <returns>The distance in meters between g0 and g1, or null if unable to calculate</returns> /// <exception cref="ArgumentNullException">g0 or g1 is null</exception> /// <exception cref="ArgumentOutOfRangeException">The SRID of g0 and g1 don't match, are 0 or can't be resolved using <see cref="SridRegister"/></exception> /// <exception cref="ArgumentException"></exception> public static double?MeterDistance(this Geometry g0, Geometry g1) { if (g0 == null) { throw new ArgumentNullException(nameof(g0)); } else if (g1 == null) { throw new ArgumentNullException(nameof(g1)); } int srid = g0.SRID; if (srid == 0 || g1.SRID != g0.SRID) { throw new ArgumentOutOfRangeException("SRID is 0 or doesn't match"); } SridItem sridItem; try { sridItem = SridRegister.GetByValue(srid); } catch (IndexOutOfRangeException sridExcepton) { throw new ArgumentOutOfRangeException("SRID not resolveable", sridExcepton); } using (var dt = sridItem.CRS.DistanceTransform.Clone()) // Thread safe with clone { return(g0.MeterDistance(g1, dt)); } }
/// <summary> /// /// </summary> /// <typeparam name="TGeometry"></typeparam> /// <param name="geometry"></param> /// <param name="toSrid"></param> /// <returns></returns> public static TGeometry Reproject <TGeometry>(this TGeometry geometry, SridItem toSrid) where TGeometry : Geometry { if (geometry == null) { return(null); } if (toSrid == null) { throw new ArgumentNullException(nameof(toSrid)); } int srcSRID = geometry.SRID; if (srcSRID == 0) { throw new ArgumentOutOfRangeException(nameof(geometry), "Geometry doesn't have valid srid"); } SridItem srcItem = SridRegister.GetByValue(srcSRID); using (ProjContext pc = toSrid.CRS.Context.Clone()) // Make thread-safe. Use settings from crs using (CoordinateTransform ct = CoordinateTransform.Create(srcItem, toSrid, pc)) { return(Reproject(geometry, ct, toSrid.Factory)); } }
/// <summary> /// /// </summary> /// <typeparam name="TGeometry"></typeparam> /// <param name="geometry"></param> /// <param name="toSRID"></param> /// <returns></returns> public static TGeometry Reproject <TGeometry>(this TGeometry geometry, int toSRID) where TGeometry : Geometry { if (geometry == null) { return(null); } SridItem toSridItem = SridRegister.GetByValue(toSRID); return(Reproject(geometry, toSridItem)); }
/// <summary> /// Returns a boolean indicating whether this Geometry <paramref name="g0"/> is within <paramref name="distanceInMeter"/> meters /// of Geometry <paramref name="g1"/>. /// </summary> /// <param name="g0">Geometry 1</param> /// <param name="g1">Geometry 2</param> /// <param name="distanceInMeter">The distance limit</param> /// <returns>true if the geometries are within distance, false if not and NULL if unable to calculate</returns> /// <exception cref="ArgumentNullException">g0 or g1 is null</exception> /// <exception cref="ArgumentOutOfRangeException">The SRID of g0 and g1 don't match, are 0 or can't be resolved using <see cref="SridRegister"/></exception> /// <exception cref="ArgumentException"></exception> public static bool?IsWithinMeterDistance(this Geometry g0, Geometry g1, double distanceInMeter) { if (g0 == null) { throw new ArgumentNullException(nameof(g0)); } else if (g1 == null) { throw new ArgumentNullException(nameof(g1)); } int srid = g0.SRID; if (srid == 0 || g1.SRID != g0.SRID) { throw new ArgumentOutOfRangeException("SRID is 0 or doesn't match"); } DistanceOp distanceOp = new DistanceOp(g0, g1); Coordinate[] nearestPoints = distanceOp.NearestPoints(); SridItem sridItem; try { sridItem = SridRegister.GetByValue(srid); } catch (IndexOutOfRangeException sridExcepton) { throw new ArgumentOutOfRangeException("SRID not resolveable", sridExcepton); } // TODO: There should be possible optimizations now, with knowledg of the CRS // Maybe we can assume that this is always false if the NTS cut-off thinks it's false // Not 100% sure and we want correctness using (var dt = sridItem.CRS.DistanceTransform.Clone()) // Thread safe with clone { double d = dt.GeoDistance(nearestPoints[0].ToPPoint(), nearestPoints[1].ToPPoint()); if (double.IsInfinity(d) || double.IsNaN(d)) { return(null); } else { return(d <= distanceInMeter); } } }
/// <summary> /// Generic low-level reprojection. Used by the other methods /// </summary> /// <typeparam name="TGeometry"></typeparam> /// <param name="geometry"></param> /// <param name="operation"></param> /// <param name="factory"></param> /// <returns></returns> public static TGeometry Reproject <TGeometry>(this TGeometry geometry, CoordinateTransform operation, GeometryFactory factory) where TGeometry : Geometry { if (geometry is null) { throw new ArgumentNullException(nameof(geometry)); } else if (operation is null) { throw new ArgumentNullException(nameof(operation)); } else if (factory is null) { throw new ArgumentNullException(nameof(factory)); } return(SridRegister.ReProject(geometry, factory, sq => factory.CoordinateSequenceFactory.Create(sq.ToPPoints().Select(x => operation.Apply(x)).ToCoordinates().ToArray()))); }
public void EpsgEnumTests() { var r = SridRegister.GetById(Epsg.Netherlands); var factory = r.Factory; //SharpProj. Assert.AreEqual((int)Epsg.Netherlands, r.SRID); Assert.AreEqual((int)Epsg.Netherlands, factory.SRID); Assert.AreEqual((int)Epsg.BelgiumLambert, SridRegister.GetById(Epsg.BelgiumLambert).SRID); Assert.AreEqual(2, r.CRS.CoordinateSystem.Axis.Count); Point p = factory.CreatePoint(new Coordinate(155000, 463000)); Point pp = p.Reproject(SridRegister.GetById(Epsg.BelgiumLambert)); Assert.IsNotNull(pp); Assert.IsNotNull(p.Reproject <Geometry>(SridRegister.GetById(Epsg.BelgiumLambert))); Assert.AreEqual((int)Epsg.BelgiumLambert, pp.SRID); Assert.AreEqual(new Point(719706, 816781), new Point(pp.Coordinate.RoundAll(0))); using (CoordinateTransform t = CoordinateTransform.Create(SridRegister.GetByValue(p.SRID), SridRegister.GetById(Epsg.BelgiumLambert), new CoordinateTransformOptions { NoBallparkConversions = true })) { if (t is CoordinateTransformList mc) { Assert.AreEqual(3, mc.Count); Assert.AreEqual(5, mc[0].Parameters.Count); Assert.AreEqual(7, mc[1].Parameters.Count); Assert.AreEqual(6, mc[2].Parameters.Count); } else { Assert.Fail(); } var rr = t.Apply(new PPoint(155000, 463000)); } }
public void NtsMeterDistance() { PPoint amersfoortRD = new PPoint(155000, 463000); var srid = SridRegister.GetById(Epsg.Netherlands); var t1 = CreateTriangle(srid.Factory, amersfoortRD.Offset(-50000, 0).ToCoordinate(), 5000); var t2 = CreateTriangle(srid.Factory, amersfoortRD.Offset(20, 50000).ToCoordinate(), 5000); var t3 = CreateTriangle(srid.Factory, amersfoortRD.ToCoordinate(), 100000); Assert.AreEqual(300000, Math.Round(t3.ExteriorRing.Length, 5)); // Pythagoras. By definition Assert.AreEqual(65908.18, Math.Round(t1.Distance(t2), 2), "Distance pythagoras"); // Pythagoras Assert.AreEqual(65913.62, Math.Round(t1.MeterDistance(t2).Value, 2), "Geo distance"); // Via NL CRS Assert.AreEqual(300024.180, Math.Round(t3.ExteriorRing.MeterLength().Value, 3)); Assert.IsTrue(t1.IsWithinMeterDistance(t2, 70000).Value); Assert.IsFalse(t2.IsWithinMeterDistance(t1, 64000).Value); Assert.IsTrue(t1.Centroid.Coordinate.Equals3D(t1.Centroid.Coordinate)); Assert.AreEqual(4330127018.92, Math.Round(t3.Area, 2)); // Test the raw (signed) operations to return the same thing. On polygon the value is taken absolute (unsigned) Assert.AreEqual(4330127018.92, Math.Round(NetTopologySuite.Algorithm.Area.OfRingSigned(t3.ExteriorRing.Coordinates), 2)); Assert.AreEqual(4330957964.64, Math.Round(srid.CRS.DistanceTransform.GeoArea(t3.Coordinates), 2)); Assert.AreEqual(4330957964.64, Math.Round(t3.MeterArea().Value, 2)); // Not using backing data yet }
public void NotSameTwice() { CoordinateReferenceSystem crs = SridRegister.GetById(Epsg.Netherlands); SridRegister.Ensure((Epsg)(-1), () => crs, -1); }
public void Init() { SridRegister.Ensure(Epsg.Netherlands, () => CoordinateReferenceSystem.Create("EPSG:28992"), (int)Epsg.Netherlands); SridRegister.Ensure(Epsg.BelgiumLambert, () => CoordinateReferenceSystem.Create("EPSG:3812"), (int)Epsg.BelgiumLambert); SridRegister.Ensure(Epsg.AnotherNL, () => CoordinateReferenceSystem.Create("EPSG:28992"), (int)Epsg.AnotherNL); // Different EPSG, same definition. Ok. But can't use same CRS instance }