public bool HasNearNeighbourUntested(Point p, double epsilon) { double[,] bounds = CalculateBoundEpsilon(p, epsilon); if (EpsilonboundIntersectsCellBounds(bounds)) { if (HasChildren()) { foreach (Cell cell in c) { if (cell.HasNearNeighbourUntested(p, epsilon)) { return(true); } } } else { foreach (Point point in Elements) { if (p != point) { if (DistanceComputer.ComputeSquaredDistance(p, point) <= epsilon * epsilon) { return(true); } } } } } return(false); }
//// temporary Coordinates to materialize points from the CoordinateSequence //private readonly Coordinate _p0 = new Coordinate(); //private readonly Coordinate _p1 = new Coordinate(); //private readonly Coordinate _q0 = new Coordinate(); //private readonly Coordinate _q1 = new Coordinate(); private double ComputeLineLineDistance(FacetSequence facetSeq) { // both linear - compute minimum segment-segment distance var minDistance = Double.MaxValue; var p0 = new Coordinate(); var p1 = new Coordinate(); var q0 = new Coordinate(); var q1 = new Coordinate(); for (int i = _start; i < _end - 1; i++) { for (int j = facetSeq._start; j < facetSeq._end - 1; j++) { _pts.GetCoordinate(i, p0); _pts.GetCoordinate(i + 1, p1); facetSeq._pts.GetCoordinate(j, q0); facetSeq._pts.GetCoordinate(j + 1, q1); double dist = DistanceComputer.SegmentToSegment(p0, p1, q0, q1); if (dist == 0.0) { return(0.0); } if (dist < minDistance) { minDistance = dist; } } } return(minDistance); }
private double SegmentDistance(FacetSequence fs1, FacetSequence fs2) { for (var i1 = 0; i1 < fs1.Count; i1++) { for (var i2 = 1; i2 < fs2.Count; i2++) { var p = fs1.GetCoordinate(i1); var seg0 = fs2.GetCoordinate(i2 - 1); var seg1 = fs2.GetCoordinate(i2); if (!(p.Equals2D(seg0) || p.Equals2D(seg1))) { var d = DistanceComputer.PointToSegment(p, seg0, seg1); if (d < _minDist) { _minDist = d; UpdatePts(p, seg0, seg1); if (d == 0.0) { return(d); } } } } } return(_minDist); }
public void TestDistancePointLine() { Assert.AreEqual(0.5, DistanceComputer.PointToSegment( new Coordinate(0.5, 0.5), new Coordinate(0, 0), new Coordinate(1, 0)), 0.000001); Assert.AreEqual(1.0, DistanceComputer.PointToSegment( new Coordinate(2, 0), new Coordinate(0, 0), new Coordinate(1, 0)), 0.000001); }
/// <summary> /// If an endpoint of one segment is near /// the <i>interior</i> of the other segment, add it as an intersection. /// EXCEPT if the endpoint is also close to a segment endpoint /// (since this can introduce "zigs" in the linework). /// <para/> /// This resolves situations where /// a segment A endpoint is extremely close to another segment B, /// but is not quite crossing. Due to robustness issues /// in orientation detection, this can /// result in the snapped segment A crossing segment B /// without a node being introduced. /// </summary> private void ProcessNearVertex(ISegmentString srcSS, int srcIndex, Coordinate p, ISegmentString ss, int segIndex, Coordinate p0, Coordinate p1) { /* * Don't add intersection if candidate vertex is near endpoints of segment. * This avoids creating "zig-zag" linework * (since the vertex could actually be outside the segment envelope). * Also, this should have already been snapped. */ if (p.Distance(p0) < _snapTolerance) { return; } if (p.Distance(p1) < _snapTolerance) { return; } double distSeg = DistanceComputer.PointToSegment(p, p0, p1); if (distSeg < _snapTolerance) { // add vertex to target segment ((NodedSegmentString)ss).AddIntersection(p, segIndex); // add node at vertex to source SS ((NodedSegmentString)srcSS).AddIntersection(p, srcIndex); } }
/// <summary> /// /// </summary> /// <param name="line0"></param> /// <param name="line1"></param> /// <param name="locGeom"></param> private void ComputeMinDistance(ILineString line0, ILineString line1, GeometryLocation[] locGeom) { if (line0.EnvelopeInternal.Distance(line1.EnvelopeInternal) > _minDistance) { return; } var coord0 = line0.Coordinates; var coord1 = line1.Coordinates; // brute force approach! for (int i = 0; i < coord0.Length - 1; i++) { for (int j = 0; j < coord1.Length - 1; j++) { double dist = DistanceComputer.SegmentToSegment( coord0[i], coord0[i + 1], coord1[j], coord1[j + 1]); if (dist < _minDistance) { _minDistance = dist; var seg0 = new LineSegment(coord0[i], coord0[i + 1]); var seg1 = new LineSegment(coord1[j], coord1[j + 1]); var closestPt = seg0.ClosestPoints(seg1); locGeom[0] = new GeometryLocation(line0, i, closestPt[0]); locGeom[1] = new GeometryLocation(line1, j, closestPt[1]); } if (_minDistance <= _terminateDistance) { return; } } } }
/// <summary> /// /// </summary> /// <param name="line"></param> /// <param name="pt"></param> /// <param name="locGeom"></param> private void ComputeMinDistance(ILineString line, IPoint pt, GeometryLocation[] locGeom) { if (line.EnvelopeInternal.Distance(pt.EnvelopeInternal) > _minDistance) { return; } var coord0 = line.Coordinates; var coord = pt.Coordinate; // brute force approach! for (int i = 0; i < coord0.Length - 1; i++) { double dist = DistanceComputer.PointToSegment(coord, coord0[i], coord0[i + 1]); if (dist < _minDistance) { _minDistance = dist; var seg = new LineSegment(coord0[i], coord0[i + 1]); var segClosestPoint = seg.ClosestPoint(coord); locGeom[0] = new GeometryLocation(line, i, segClosestPoint); locGeom[1] = new GeometryLocation(pt, 0, coord); } if (_minDistance <= _terminateDistance) { return; } } }
private double ComputeDistancePointLine(Coordinate pt, FacetSequence facetSeq, GeometryLocation[] locs) { double minDistance = double.MaxValue; for (int i = facetSeq._start; i < facetSeq._end - 1; i++) { var q0 = facetSeq._pts.GetCoordinate(i); var q1 = facetSeq._pts.GetCoordinate(i + 1); double dist = DistanceComputer.PointToSegment(pt, q0, q1); if (dist < minDistance) { minDistance = dist; if (locs != null) { UpdateNearestLocationsPointLine(pt, facetSeq, i, q0, q1, locs); } if (minDistance <= 0) { return(minDistance); } } } return(minDistance); }
private double ComputeDistanceLineLine(FacetSequence facetSeq, GeometryLocation[] locs) { // both linear - compute minimum segment-segment distance double minDistance = double.MaxValue; for (int i = _start; i < _end - 1; i++) { var p0 = _pts.GetCoordinate(i); var p1 = _pts.GetCoordinate(i + 1); for (int j = facetSeq._start; j < facetSeq._end - 1; j++) { var q0 = facetSeq._pts.GetCoordinate(j); var q1 = facetSeq._pts.GetCoordinate(j + 1); double dist = DistanceComputer.SegmentToSegment(p0, p1, q0, q1); if (dist < minDistance) { minDistance = dist; if (locs != null) { UpdateNearestLocationsLineLine(i, p0, p1, facetSeq, j, q0, q1, locs); } if (minDistance <= 0) { return(minDistance); } } } } return(minDistance); }
private void CheckSegmentDistance(Coordinate seg0, Coordinate seg1) { if (_queryPt.Equals2D(seg0) || _queryPt.Equals2D(seg1)) return; double segDist = DistanceComputer.PointToSegment(_queryPt, seg1, seg0); if (segDist > 0) _smc.UpdateClearance(segDist, _queryPt, seg1, seg0); }
/// <summary> /// Tests whether a triangular ring would be eroded completely by the given /// buffer distance. /// This is a precise test. It uses the fact that the inner buffer of a /// triangle converges on the inCentre of the triangle (the point /// equidistant from all sides). If the buffer distance is greater than the /// distance of the inCentre from a side, the triangle will be eroded completely. /// This test is important, since it removes a problematic case where /// the buffer distance is slightly larger than the inCentre distance. /// In this case the triangle buffer curve "inverts" with incorrect topology, /// producing an incorrect hole in the buffer. /// </summary> /// <param name="triangleCoord"></param> /// <param name="bufferDistance"></param> /// <returns></returns> private static bool IsTriangleErodedCompletely(Coordinate[] triangleCoord, double bufferDistance) { var tri = new Triangle(triangleCoord[0], triangleCoord[1], triangleCoord[2]); var inCentre = tri.InCentre(); double distToCentre = DistanceComputer.PointToSegment(inCentre, tri.P0, tri.P1); return(distToCentre < Math.Abs(bufferDistance)); }
public void EqualPointsHaveDistanceZero() { Point p1 = new Point(0, 0); Point p2 = new Point(0, 0); double expected = 0; double actual = DistanceComputer.ComputeSquaredDistance(p1, p2); Assert.AreEqual(expected, actual); }
public void TestDistancePointLinePerpendicular() { Assert.AreEqual(0.5, DistanceComputer.PointToLinePerpendicular( new Coordinate(0.5, 0.5), new Coordinate(0, 0), new Coordinate(1, 0)), 0.000001); Assert.AreEqual(0.5, DistanceComputer.PointToLinePerpendicular( new Coordinate(3.5, 0.5), new Coordinate(0, 0), new Coordinate(1, 0)), 0.000001); Assert.AreEqual(0.707106, DistanceComputer.PointToLinePerpendicular( new Coordinate(1, 0), new Coordinate(0, 0), new Coordinate(1, 1)), 0.000001); }
public void XandYareDifferent() { Point p1 = new Point(3, 5); Point p2 = new Point(7, 2); double expected = 25; double actual = DistanceComputer.ComputeSquaredDistance(p1, p2); Assert.AreEqual(expected, actual); }
public void YareEqualXareDifferent() { Point p1 = new Point(0, 0); Point p2 = new Point(4, 0); double expected = 16; double actual = DistanceComputer.ComputeSquaredDistance(p1, p2); Assert.AreEqual(expected, actual); }
private static double GetDistance(LineString line, Point point) { //var x0 = point.X; //var y0 = point.Y; //var x1 = line.StartPoint.X; //var x2 = line.EndPoint.X; //var y1 = line.StartPoint.Y; //var y2 = line.EndPoint.Y; //return Math.Abs((((y2 - y1) * point.X) - ((x2 - x1) * point.Y) + (x2 * y1) - (y2 * x1))) / (Math.Sqrt(Math.Pow(y2 - y1, 2) + Math.Pow(x2 - x1, 2))); return(DistanceComputer.PointToSegment(point.Coordinate, line.StartPoint.Coordinate, line.EndPoint.Coordinate)); }
private void PrintStats(string tag, Coordinate intPt, Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2) { double distP = DistanceComputer.PointToLinePerpendicular(intPt, p1, p2); double distQ = DistanceComputer.PointToLinePerpendicular(intPt, q1, q2); AddStat(tag, distP); AddStat(tag, distQ); if (Verbose) { Console.WriteLine(tag + " : " + WKTWriter.ToPoint(intPt) + " -- Dist P = " + distP + " Dist Q = " + distQ); } }
/// <summary> /// /// </summary> /// <param name="line0"></param> /// <param name="line1"></param> /// <param name="locGeom"></param> private void ComputeMinDistance(LineString line0, LineString line1, GeometryLocation[] locGeom) { if (line0.EnvelopeInternal.Distance(line1.EnvelopeInternal) > _minDistance) { return; } var coord0 = line0.Coordinates; var coord1 = line1.Coordinates; // brute force approach! for (int i = 0; i < coord0.Length - 1; i++) { // short-circuit if line segment is far from line var segEnv0 = new Envelope(coord0[i], coord0[i + 1]); if (segEnv0.Distance(line1.EnvelopeInternal) > _minDistance) { continue; } for (int j = 0; j < coord1.Length - 1; j++) { // short-circuit if line segments are far apart var segEnv1 = new Envelope(coord1[j], coord1[j + 1]); if (segEnv0.Distance(segEnv1) > _minDistance) { continue; } double dist = DistanceComputer.SegmentToSegment( coord0[i], coord0[i + 1], coord1[j], coord1[j + 1]); if (dist < _minDistance) { _minDistance = dist; var seg0 = new LineSegment(coord0[i], coord0[i + 1]); var seg1 = new LineSegment(coord1[j], coord1[j + 1]); var closestPt = seg0.ClosestPoints(seg1); locGeom[0] = new GeometryLocation(line0, i, closestPt[0]); locGeom[1] = new GeometryLocation(line1, j, closestPt[1]); } if (_minDistance <= _terminateDistance) { return; } } } }
public void TestDistancePointToSegmentStringConsistency() { Coordinate[] coords = { new Coordinate(24824.045318333192, 38536.15071012041), new Coordinate(26157.378651666528, 37567.42733944659), new Coordinate(26666.666666666668, 36000.0), new Coordinate(26157.378651666528, 34432.57266055341), new Coordinate(24824.045318333192, 33463.84928987959), new Coordinate(23175.954681666804, 33463.84928987959), }; var pt = new Coordinate(21842.621348333472, 34432.57266055341); double dist1 = DistanceComputer.PointToSegmentString(pt, coords); double dist2 = DistanceComputer.PointToSegmentString(pt, new CoordinateArraySequence(coords)); Assert.That(dist1, Is.EqualTo(dist2)); }
private static Coordinate IntersectionDDFilter(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2) { // Compute using DP math var intPt = IntersectionBasic(p1, p2, q1, q2); if (intPt == null) { return(null); } if (DistanceComputer.PointToLinePerpendicular(intPt, p1, p2) > FILTER_TOL) { return(null); } if (DistanceComputer.PointToLinePerpendicular(intPt, q1, q2) > FILTER_TOL) { return(null); } return(intPt); }
public void TestRandomDisjointCollinearSegments() { int n = 1000000; int failCount = 0; for (int i = 0; i < n; i++) { //System.out.println(i); var seg = RandomDisjointCollinearSegments(); if (0 == DistanceComputer.SegmentToSegment(seg[0], seg[1], seg[2], seg[3])) { /* * System.out.println("FAILED! - " + WKTWriter.toLineString(seg[0], seg[1]) + " - " + WKTWriter.toLineString(seg[2], seg[3])); */ failCount++; } } Console.WriteLine("# failed = " + failCount + " out of " + n); }
private static double ComputePointLineDistance(Coordinate pt, FacetSequence facetSeq) { var minDistance = Double.MaxValue; var q0 = new Coordinate(); var q1 = new Coordinate(); for (var i = facetSeq._start; i < facetSeq._end - 1; i++) { facetSeq._pts.GetCoordinate(i, q0); facetSeq._pts.GetCoordinate(i + 1, q1); var dist = DistanceComputer.PointToSegment(pt, q0, q1); if (dist == 0.0) { return(0.0); } if (dist < minDistance) { minDistance = dist; } } return(minDistance); }
/// <summary> /// If an endpoint of one segment is near /// the <i>interior</i> of the other segment, add it as an intersection. /// EXCEPT if the endpoint is also close to a segment endpoint /// (since this can introduce "zigs" in the linework). /// <para/> /// This resolves situations where /// a segment A endpoint is extremely close to another segment B, /// but is not quite crossing.Due to robustness issues /// in orientation detection, this can /// result in the snapped segment A crossing segment B /// without a node being introduced. /// </summary> private void ProcessNearVertex(Coordinate p, ISegmentString edge, int segIndex, Coordinate p0, Coordinate p1) { /* * Don't add intersection if candidate vertex is near endpoints of segment. * This avoids creating "zig-zag" linework * (since the vertex could actually be outside the segment envelope). */ if (p.Distance(p0) < _nearnessTol) { return; } if (p.Distance(p1) < _nearnessTol) { return; } double distSeg = DistanceComputer.PointToSegment(p, p0, p1); if (distSeg < _nearnessTol) { Intersections.Add(p); ((NodedSegmentString)edge).AddIntersection(p, segIndex); } }
/// <summary> /// Computes the distance from a line segment AB to a line segment CD. /// Note: NON-ROBUST! /// </summary> /// <param name="A">A point of one line.</param> /// <param name="B">The second point of the line (must be different to A).</param> /// <param name="C">One point of the line.</param> /// <param name="D">Another point of the line (must be different to A).</param> /// <returns>The distance from line segment AB to line segment CD.</returns> public static double DistanceLineLine(Coordinate A, Coordinate B, Coordinate C, Coordinate D) { // check for zero-length segments if (A.Equals(B)) { return(DistanceComputer.PointToSegment(A, C, D)); } if (C.Equals(D)) { return(DistanceComputer.PointToSegment(D, A, B)); } // AB and CD are line segments /* * from comp.graphics.algo * * Solving the above for r and s yields * (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy) * r = ----------------------------- (eqn 1) * (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) * * (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) * s = ----------------------------- (eqn 2) * (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) * * Let P be the position vector of the * intersection point, then * P=A+r(B-A) or * Px=Ax+r(Bx-Ax) * Py=Ay+r(By-Ay) * By examining the values of r & s, you can also determine some other limiting * conditions: * If 0<=r<=1 & 0<=s<=1, intersection exists * r<0 or r>1 or s<0 or s>1 line segments do not intersect * If the denominator in eqn 1 is zero, AB & CD are parallel * If the numerator in eqn 1 is also zero, AB & CD are collinear. */ double r_top = (A.Y - C.Y) * (D.X - C.X) - (A.X - C.X) * (D.Y - C.Y); double r_bot = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X); double s_top = (A.Y - C.Y) * (B.X - A.X) - (A.X - C.X) * (B.Y - A.Y); double s_bot = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X); if ((r_bot == 0) || (s_bot == 0)) { return(Math .Min( DistanceComputer.PointToSegment(A, C, D), Math.Min( DistanceComputer.PointToSegment(B, C, D), Math.Min(DistanceComputer.PointToSegment(C, A, B), DistanceComputer.PointToSegment(D, A, B))))); } double s = s_top / s_bot; double r = r_top / r_bot; if ((r < 0) || (r > 1) || (s < 0) || (s > 1)) { // no intersection return(Math .Min( DistanceComputer.PointToSegment(A, C, D), Math.Min( DistanceComputer.PointToSegment(B, C, D), Math.Min(DistanceComputer.PointToSegment(C, A, B), DistanceComputer.PointToSegment(D, A, B))))); } return(0.0); // intersection exists }
private static bool IsShallow(Coordinate p0, Coordinate p1, Coordinate p2, double distanceTol) { double dist = DistanceComputer.PointToSegment(p1, p0, p2); return(dist < distanceTol); }
/// <summary> /// Computes the perpendicular distance between the (infinite) line defined /// by this line segment and a point. /// </summary> /// <param name="p"></param> /// <returns></returns> public double DistancePerpendicular(Coordinate p) { return(DistanceComputer.PointToLinePerpendicular(p, _p0, _p1)); }
/// <summary> /// Computes the distance between this line segment and a point. /// </summary> public double Distance(Coordinate p) { return(DistanceComputer.PointToSegment(p, _p0, _p1)); }
public void TestDistanceLineLineDisjointCollinear() { Assert.AreEqual(1.999699, DistanceComputer.SegmentToSegment( new Coordinate(0, 0), new Coordinate(9.9, 1.4), new Coordinate(11.88, 1.68), new Coordinate(21.78, 3.08)), 0.000001); }
/// <summary> /// Computes the distance between this line segment and another one. /// </summary> /// <param name="ls"></param> /// <returns></returns> public double Distance(LineSegment ls) { return(DistanceComputer.SegmentToSegment(_p0, _p1, ls._p0, ls._p1)); }