Example #1
0
 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);
 }
Example #2
0
        //// 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);
        }
Example #3
0
            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);
            }
Example #4
0
 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);
            }
        }
Example #6
0
        /// <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;
                    }
                }
            }
        }
Example #7
0
        /// <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;
                }
            }
        }
Example #8
0
        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);
        }
Example #9
0
        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);
        }
Example #10
0
 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));
        }
Example #12
0
        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);
        }
Example #13
0
 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);
 }
Example #14
0
        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);
        }
Example #15
0
        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);
        }
Example #16
0
 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));
 }
Example #17
0
        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);
            }
        }
Example #18
0
        /// <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;
                    }
                }
            }
        }
Example #19
0
        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);
        }
Example #22
0
        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);
        }
Example #23
0
        /// <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);
        }
Example #26
0
 /// <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));
 }
Example #27
0
 /// <summary>
 /// Computes the distance between this line segment and a point.
 /// </summary>
 public double Distance(Coordinate p)
 {
     return(DistanceComputer.PointToSegment(p, _p0, _p1));
 }
Example #28
0
 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);
 }
Example #29
0
 /// <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));
 }