///<summary>
 /// Initializes the points.
 ///</summary>
 /// <param name="p0">1st coordinate</param>
 /// <param name="p1">2nd coordinate</param>
 public void Initialize(Coordinate p0, Coordinate p1)
 {
     _pt[0].CoordinateValue = p0;
     _pt[1].CoordinateValue = p1;
     _distance = p0.Distance(p1);
     _isNull = false;
 }
 /// <summary>
 /// Computes the inCircle test using distance from the circumcentre. 
 /// Uses standard double-precision arithmetic.
 /// </summary>
 /// <remarks>
 /// In general this doesn't
 /// appear to be any more robust than the standard calculation. However, there
 /// is at least one case where the test point is far enough from the
 /// circumcircle that this test gives the correct answer. 
 /// <pre>
 /// LINESTRING (1507029.9878 518325.7547, 1507022.1120341457 518332.8225183258,
 /// 1507029.9833 518325.7458, 1507029.9896965567 518325.744909031)
 /// </pre>
 /// </remarks>
 /// <param name="a">A vertex of the triangle</param>
 /// <param name="b">A vertex of the triangle</param>
 /// <param name="c">A vertex of the triangle</param>
 /// <param name="p">The point to test</param>
 /// <returns>The area of a triangle defined by the points a, b and c</returns>
 public static bool IsInCircleCC(Coordinate a, Coordinate b, Coordinate c,
     Coordinate p)
 {
     Coordinate cc = Triangle.Circumcentre(a, b, c);
     double ccRadius = a.Distance(cc);
     double pRadiusDiff = p.Distance(cc) - ccRadius;
     return pRadiusDiff <= 0;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="point"></param>
 private void Add(Coordinate point)
 {
     double dist = point.Distance(_centroid);
     if (dist < _minDistance)
     {
         _interiorPoint = new Coordinate(point);
         _minDistance = dist;
     }
 }
 private void checkWithinCircle(Coordinate[] pts, Coordinate centre, double radius, double tolerance)
 {
     for (int i = 0; i < pts.Length; i++)
     {
         Coordinate p = pts[i];
         double ptRadius = centre.Distance(p);
         double error = ptRadius - radius;
         Assert.LessOrEqual(error, tolerance);
     }
 }
 /// <summary>
 /// Tests whether the given point is redundant
 /// relative to the previous
 /// point in the list (up to tolerance).
 /// </summary>
 /// <param name="pt"></param>
 /// <returns>true if the point is redundant</returns>
 private bool IsRedundant(Coordinate pt)
 {
     if (_ptList.Count < 1)
         return false;
     var lastPt = _ptList[_ptList.Count - 1];
     double ptDist = pt.Distance(lastPt);
     if (ptDist < _minimimVertexDistance)
         return true;
     return false;
 }
 ///<summary>
 /// Tests whether the given point duplicates the previous point in the list (up to tolerance)
 ///</summary>
 /// <param name="pt">The point to test</param>
 /// <returns>true if the point duplicates the previous point</returns>
 private bool IsDuplicate(Coordinate pt)
 {
     if (_ptList.Count < 1)
         return false;
     var lastPt = _ptList[_ptList.Count - 1];
     var ptDist = pt.Distance(lastPt);
     if (ptDist < _minimimVertexDistance)
         return true;
     return false;
 }
예제 #7
0
        public static double Distance(Coordinate p0, Coordinate p1)
        {
            // default to 2D distance if either Z is not set
            if (Double.IsNaN(p0.Z) || Double.IsNaN(p1.Z))
                return p0.Distance(p1);

            var dx = p0.X - p1.X;
            var dy = p0.Y - p1.Y;
            var dz = p0.Z - p1.Z;
            return Math.Sqrt(dx * dx + dy * dy + dz * dz);
        }
 public void SetMaximum(Coordinate p0, Coordinate p1)
 {
     if (_isNull)
     {
         Initialize(p0, p1);
         return;
     }
     double dist = p0.Distance(p1);
     if (dist > _distance)
         Initialize(p0, p1, dist);
 }
        private void Densify(Coordinate p0, Coordinate p1, double segLength)
        {
            double origLen = p1.Distance(p0);
            int nPtsToAdd = (int)Math.Floor(origLen / segLength);

            double delx = p1.X - p0.X;
            double dely = p1.Y - p0.Y;

            double segLenFrac = segLength / origLen;
            for (int i = 0; i <= nPtsToAdd; i++)
            {
                double addedPtFrac = i * segLenFrac;
                Coordinate pt = new Coordinate(p0.X + addedPtFrac * delx,
                                                p0.Y + addedPtFrac * dely);
                newCoords.Add(pt, false);
            }
            newCoords.Add(new Coordinate(p1), false);
        }
        /// <summary>
        /// Creates an AffineTransformation defined by a pair of control vectors. A
        /// control vector consists of a source point and a destination point, which is
        /// the image of the source point under the desired transformation. The
        /// computed transformation is a combination of one or more of a uniform scale,
        /// a rotation, and a translation (i.e. there is no shear component and no
        /// reflection)
        /// </summary>
        /// <param name="src0"></param>
        /// <param name="src1"></param>
        /// <param name="dest0"></param>
        /// <param name="dest1"></param>
        /// <returns>The computed transformation</returns>
        /// <returns><c>null</c> if the control vectors do not determine a well-defined transformation</returns>
        public static AffineTransformation CreateFromControlVectors(Coordinate src0,
                Coordinate src1, Coordinate dest0, Coordinate dest1)
        {
            Coordinate rotPt = new Coordinate(dest1.X - dest0.X, dest1.Y - dest0.Y);

            double ang = AngleUtility.AngleBetweenOriented(src1, src0, rotPt);

            double srcDist = src1.Distance(src0);
            double destDist = dest1.Distance(dest0);

            if (srcDist == 0.0)
                return null;

            double scale = destDist / srcDist;

            AffineTransformation trans = AffineTransformation.TranslationInstance(
                    -src0.X, -src0.Y);
            trans.Rotate(ang);
            trans.Scale(scale, scale);
            trans.Translate(dest0.X, dest0.Y);
            return trans;
        }
예제 #11
0
        /// <summary>
        /// Computes the closest points on a line segment.
        /// </summary>
        /// <param name="line"></param>
        /// <returns>
        /// A pair of Coordinates which are the closest points on the line segments.
        /// </returns>
        public virtual Coordinate[] ClosestPoints(ILineSegmentBase line)
        {
            LineSegment myLine = new LineSegment(line);

            // test for intersection
            Coordinate intPt = Intersection(line);

            if (intPt != null)
                return new[] { intPt, intPt };

            /*
            *  if no intersection closest pair contains at least one endpoint.
            * Test each endpoint in turn.
            */
            Coordinate[] closestPt = new Coordinate[2];

            Coordinate close00 = new Coordinate(ClosestPoint(line.P0));
            double minDistance = close00.Distance(line.P0);
            closestPt[0] = close00;
            closestPt[1] = new Coordinate(line.P0);

            Coordinate close01 = new Coordinate(ClosestPoint(line.P1));
            double dist = close01.Distance(line.P1);
            if (dist < minDistance)
            {
                minDistance = dist;
                closestPt[0] = close01;
                closestPt[1] = new Coordinate(line.P1);
            }

            Coordinate close10 = new Coordinate(myLine.ClosestPoint(P0));
            dist = close10.Distance(P0);
            if (dist < minDistance)
            {
                minDistance = dist;
                closestPt[0] = new Coordinate(P0);
                closestPt[1] = close10;
            }

            Coordinate close11 = new Coordinate(myLine.ClosestPoint(P1));
            dist = close11.Distance(P1);
            if (dist < minDistance)
            {
                closestPt[0] = new Coordinate(P1);
                closestPt[1] = close11;
            }

            return closestPt;
        }
예제 #12
0
        /// <summary> 
        /// Computes the distance from a point p to a line segment AB.
        /// Note: NON-ROBUST!
        /// </summary>
        /// <param name="p">The point to compute the distance for.</param>
        /// <param name="A">One point of the line.</param>
        /// <param name="B">Another point of the line (must be different to A).</param>
        /// <returns> The distance from p to line segment AB.</returns>
        public static double DistancePointLine(Coordinate p, Coordinate A, Coordinate B)
        {
            // if start = end, then just compute distance to one of the endpoints
            if (A.X == B.X && A.Y == B.Y) 
                return p.Distance(A);

            // otherwise use comp.graphics.algorithms Frequently Asked Questions method
            /*(1)     	      AC dot AB
                        r =   ---------
                              ||AB||^2
             
		                r has the following meaning:
		                r=0 Point = A
		                r=1 Point = B
		                r<0 Point is on the backward extension of AB
		                r>1 Point is on the forward extension of AB
		                0<r<1 Point is interior to AB
	        */

            var len2 = ((B.X - A.X)*(B.X - A.X) + (B.Y - A.Y)*(B.Y - A.Y));
            var r = ((p.X - A.X)*(B.X - A.X) + (p.Y - A.Y)*(B.Y - A.Y))/len2;

            if (r <= 0.0) 
                return p.Distance(A);
            if (r >= 1.0) 
                return p.Distance(B);


            /*(2)
		                    (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
		                s = -----------------------------
		             	                Curve^2

		                Then the distance from C to Point = |s|*Curve.
      
                        This is the same calculation as {@link #distancePointLinePerpendicular}.
                        Unrolled here for performance.
	        */

            var s = ((A.Y - p.Y)*(B.X - A.X) - (A.X - p.X)*(B.Y - A.Y))/len2;

            return Math.Abs(s) * Math.Sqrt(len2);
        }
예제 #13
0
        /// <summary>
        /// Computes the distance from a point to a sequence of line segments.
        /// </summary>
        /// <param name="p">A point</param>
        /// <param name="line">A sequence of contiguous line segments defined by their vertices</param>
        /// <returns>The minimum distance between the point and the line segments</returns>
        /// <exception cref="ArgumentException">If there are too few points to make up a line (at least one?)</exception>
        public static double DistancePointLine(Coordinate p, Coordinate[] line)
        {
            if (line.Length == 0)
                throw new ArgumentException("Line array must contain at least one vertex");

            // this handles the case of length = 1
            double minDistance = p.Distance(line[0]);
            for (int i = 0; i < line.Length - 1; i++)
            {
                double dist = CGAlgorithms.DistancePointLine(p, line[i], line[i + 1]);
                if (dist < minDistance)
                {
                    minDistance = dist;
                }
            }
            return minDistance;
        }
예제 #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        protected virtual bool Equal(Coordinate a, Coordinate b, double tolerance)
        {
            if (tolerance == 0)
                return a.Equals(b);

            return a.Distance(b) <= tolerance;
        }
 public bool Equals(Coordinate p0, Coordinate p1, double distanceTolerance)
 {
     return p0.Distance(p1) <= distanceTolerance;
 }
예제 #16
0
        /// <summary>
        /// Checks if the computed value for isInCircle is correct, using
        /// double-double precision arithmetic.
        /// </summary>
        /// <param name="a">A vertex of the triangle</param>
        /// <param name="b">A vertex of the triangle</param>
        /// <param name="c">A vertex of the triangle</param>
        /// <param name="p">The point to test</param>
        private static void CheckRobustInCircle(Coordinate a, Coordinate b, Coordinate c,
            Coordinate p)
        {
            bool nonRobustInCircle = IsInCircleNonRobust(a, b, c, p);
            bool isInCircleDD = IsInCircleDDSlow(a, b, c, p);
            bool isInCircleCC = IsInCircleCC(a, b, c, p);

            Coordinate circumCentre = Triangle.Circumcentre(a, b, c);
            #if !PCL
            // ReSharper disable RedundantStringFormatCall
            // String.Format needed to build 2.0 release!
            Debug.WriteLine(String.Format("p radius diff a = {0}", Math.Abs(p.Distance(circumCentre) - a.Distance(circumCentre))/a.Distance(circumCentre)));
            if (nonRobustInCircle != isInCircleDD || nonRobustInCircle != isInCircleCC)
            {
                Debug.WriteLine(String.Format("inCircle robustness failure (double result = {0}, DD result = {1}, CC result = {2})", nonRobustInCircle, isInCircleDD, isInCircleCC));
                Debug.WriteLine(WKTWriter.ToLineString(new CoordinateArraySequence(new[] { a, b, c, p })));
                Debug.WriteLine(String.Format("Circumcentre = {0} radius = {1}", WKTWriter.ToPoint(circumCentre), a.Distance(circumCentre)));
                Debug.WriteLine(String.Format("p radius diff a = {0}", Math.Abs(p.Distance(circumCentre)/a.Distance(circumCentre) - 1)));
                Debug.WriteLine(String.Format("p radius diff b = {0}", Math.Abs(p.Distance(circumCentre)/b.Distance(circumCentre) - 1)));
                Debug.WriteLine(String.Format("p radius diff c = {0}", Math.Abs(p.Distance(circumCentre)/c.Distance(circumCentre) - 1)));
                Debug.WriteLine("");
            }
            // ReSharper restore RedundantStringFormatCall
            #endif
        }
예제 #17
0
        /// <summary> 
        /// Computes the distance from a point p to a line segment AB.
        /// Note: NON-ROBUST!
        /// </summary>
        /// <param name="p">The point to compute the distance for.</param>
        /// <param name="A">One point of the line.</param>
        /// <param name="B">Another point of the line (must be different to A).</param>
        /// <returns> The distance from p to line segment AB.</returns>
        public static double DistancePointLine(Coordinate p, Coordinate A, Coordinate B)
        {
            // if start == end, then use pt distance
            if (A.Equals(B)) 
                return p.Distance(A);

            // otherwise use comp.graphics.algorithms Frequently Asked Questions method
            /*(1)     	      AC dot AB
                        r =   ---------
                              ||AB||^2
             
		                r has the following meaning:
		                r=0 Point = A
		                r=1 Point = B
		                r<0 Point is on the backward extension of AB
		                r>1 Point is on the forward extension of AB
		                0<r<1 Point is interior to AB
	        */

            double r =  ( (p.X - A.X) * (B.X - A.X) + (p.Y - A.Y) * (B.Y - A.Y) )
                        /
                        ( (B.X - A.X) * (B.X - A.X) + (B.Y - A.Y) * (B.Y - A.Y) );

            if (r <= 0.0) return p.Distance(A);
            if (r >= 1.0) return p.Distance(B);


            /*(2)
		                    (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
		                s = -----------------------------
		             	                Curve^2

		                Then the distance from C to Point = |s|*Curve.
	        */

            double s =  ( (A.Y - p.Y) * (B.X - A.X) - (A.X - p.X) * (B.Y - A.Y) )
                        /
                        ( (B.X - A.X) * (B.X - A.X) + (B.Y - A.Y) * (B.Y - A.Y) );

            return Math.Abs(s) * Math.Sqrt(((B.X - A.X) * (B.X - A.X) + (B.Y - A.Y) * (B.Y - A.Y)));
        }
예제 #18
0
        ///<summary>Computes the point at which the bisector of the angle ABC cuts the segment AC.</summary>
        /// <param name="a">A vertex of the triangle</param>
        /// <param name="b">A vertex of the triangle</param>
        /// <param name="c">A vertex of the triangle</param>
        /// <returns>The angle bisector cut point</returns>
        public static Coordinate AngleBisector(Coordinate a, Coordinate b, Coordinate c)
        {
            /*
             * Uses the fact that the lengths of the parts of the split segment
             * are proportional to the lengths of the adjacent triangle sides
             */
            double len0 = b.Distance(a);
            double len2 = b.Distance(c);
            double frac = len0 / (len0 + len2);
            double dx = c.X - a.X;
            double dy = c.Y - a.Y;

            Coordinate splitPt = new Coordinate(a.X + frac * dx,
                                                a.Y + frac * dy);
            return splitPt;
        }
예제 #19
0
 /// <summary>
 /// Given the specified test point, this checks each segment, and will
 /// return the closest point on the specified segment.
 /// </summary>
 /// <param name="testPoint">The point to test.</param>
 /// <returns></returns>
 public override Coordinate ClosestPoint(Coordinate testPoint)
 {
     // For a point outside the polygon, it must be closer to the shell than
     // any holes.
     Coordinate closest = null;
     double dist = double.MaxValue;
     foreach (IGeometry geometry in Geometries)
     {
         Coordinate temp = geometry.ClosestPoint(testPoint);
         double tempDist = testPoint.Distance(temp);
         if (tempDist >= dist) continue;
         dist = tempDist;
         closest = temp;
     }
     return closest;
 }
        /// <summary>
        /// Creates an AffineTransformation defined by a maping between two baselines.
        /// The computed transformation consists of:
        /// <list type="Bullet">
        /// <item>a translation from the start point of the source baseline to the start point of the destination baseline,</item>
        /// <item>a rotation through the angle between the baselines about the destination start point,</item>
        /// <item>and a scaling equal to the ratio of the baseline lengths.</item>
        /// </list>
        /// If the source baseline has zero length, an identity transformation is returned.
        /// </summary>
        /// <param name="src0">The start point of the source baseline</param>
        /// <param name="src1">The end point of the source baseline</param>
        /// <param name="dest0">The start point of the destination baseline</param>
        /// <param name="dest1">The end point of the destination baseline</param>
        /// <returns></returns>
        public static AffineTransformation CreateFromBaseLines(
                Coordinate src0, Coordinate src1,
                Coordinate dest0, Coordinate dest1)
        {
            Coordinate rotPt = new Coordinate(src0.X + dest1.X - dest0.X, src0.Y + dest1.Y - dest0.Y);

            double ang = AngleUtility.AngleBetweenOriented(src1, src0, rotPt);

            double srcDist = src1.Distance(src0);
            double destDist = dest1.Distance(dest0);

            // return identity if transformation would be degenerate
            if (srcDist == 0.0)
                return new AffineTransformation();

            double scale = destDist / srcDist;

            AffineTransformation trans = AffineTransformation.TranslationInstance(
                    -src0.X, -src0.Y);
            trans.Rotate(ang);
            trans.Scale(scale, scale);
            trans.Translate(dest0.X, dest0.Y);
            return trans;
        }
 private void CheckVertexDistance(Coordinate vertex)
 {
     double vertexDist = vertex.Distance(_queryPt);
     if (vertexDist > 0)
     {
         _smc.UpdateClearance(vertexDist, _queryPt, vertex);
     }
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="pt"></param>
 /// <param name="snapPts"></param>
 /// <returns></returns>
 private Coordinate FindSnapForVertex(Coordinate pt, Coordinate[] snapPts)
 {
     foreach (Coordinate coord in snapPts)
     {
         // if point is already equal to a src pt, don't snap
         if (pt.Equals2D(coord))
             return null;
         if (pt.Distance(coord) < _snapTolerance)
             return coord;
     }
     return null;
 }
        private void DoMinimumBoundingCircleTest(String wkt, String expectedWKT, Coordinate expectedCentre, double expectedRadius)
        {
            MinimumBoundingCircle mbc = new MinimumBoundingCircle(reader.Read(wkt));
            Coordinate[] exPts = mbc.GetExtremalPoints();
            IGeometry actual = geometryFactory.CreateMultiPoint(exPts);
            double actualRadius = mbc.GetRadius();
            Coordinate actualCentre = mbc.GetCentre();
            Console.WriteLine("   Centre = " + actualCentre + "   Radius = " + actualRadius);

            IGeometry expected = reader.Read(expectedWKT);
            bool isEqual = actual.Equals(expected);
            // need this hack because apparently equals does not work for MULTIPOINT EMPTY
            if (actual.IsEmpty && expected.IsEmpty)
                isEqual = true;
  	        if (!isEqual)
  	        {
  	            Console.WriteLine("Actual = " + actual + ", Expected = " + expected);
  	        }
            Assert.IsTrue(isEqual);

            if (expectedCentre != null)
            {
                Assert.IsTrue(expectedCentre.Distance(actualCentre) < TOLERANCE);
            }
            if (expectedRadius >= 0)
            {
                Assert.IsTrue(Math.Abs(expectedRadius - actualRadius) < TOLERANCE);
            }
        }
예제 #24
0
        /// <summary>
        /// The original algorithm simply allows edges that have one defined point and 
        /// another "NAN" point.  Simply excluding the not a number coordinates fails
        /// to preserve the known direction of the ray.  We only need to extend this
        /// long enough to encounter the bounding box, not infinity.
        /// </summary>
        /// <param name="graph">The VoronoiGraph with the edge list</param>
        /// <param name="bounds">The polygon bounding the datapoints</param>
        private static void HandleBoundaries(VoronoiGraph graph, IEnvelope bounds)
        {
            
            List<ILineString> boundSegments = new List<ILineString>();
            List<VoronoiEdge> unboundEdges = new List<VoronoiEdge>();
            // Identify bound edges for intersection testing
            foreach (VoronoiEdge edge in graph.Edges)
            {
                if(edge.VVertexA.ContainsNan() || edge.VVertexB.ContainsNan())
                {
                    unboundEdges.Add(edge);
                    continue;
                }
                boundSegments.Add(new LineString(new List<Coordinate>{edge.VVertexA.ToCoordinate(), edge.VVertexB.ToCoordinate()}));
            }

            // calculate a length to extend a ray to look for intersections
            IEnvelope env = bounds;
            double h = env.Height;
            double w = env.Width;
            double len = Math.Sqrt(w * w + h * h);  // len is now long enough to pass entirely through the dataset no matter where it starts

            foreach (VoronoiEdge edge in unboundEdges)
            {
                // the unbound line passes thorugh start
                Coordinate start = (edge.VVertexB.ContainsNan())
                                        ? edge.VVertexA.ToCoordinate()
                                        : edge.VVertexB.ToCoordinate();

                // the unbound line should have a direction normal to the line joining the left and right source points
                double dx = edge.LeftData.X - edge.RightData.X;
                double dy = edge.LeftData.Y - edge.RightData.Y;
                double l = Math.Sqrt(dx*dx + dy*dy);

                

                // the slope of the bisector between left and right
                double sx = -dy/l;
                double sy = dx/l;

                Coordinate center = bounds.Center();
                if((start.X > center.X && start.Y > center.Y) || (start.X < center.X && start.Y < center.Y))
                {
                    sx = dy/l;
                    sy = -dx/l;
                }

                Coordinate end1 = new Coordinate(start.X + len*sx, start.Y + len * sy);
                Coordinate end2 = new Coordinate(start.X - sx * len, start.Y - sy * len);
                
                Coordinate end = (end1.Distance(center) < end2.Distance(center)) ? end2 : end1;
                if(bounds.Contains(end))
                {
                    end = new Coordinate(start.X - sx * len, start.Y - sy * len);
                }
                if (edge.VVertexA.ContainsNan())
                {
                    edge.VVertexA = new Vector2(end.ToArray());
                }
                else
                {
                    edge.VVertexB = new Vector2(end.ToArray());
                }
                
                
                
                
            }
            
        }
예제 #25
0
 /// <summary>
 /// Given the specified test point, this checks each segment, and will
 /// return the closest point on the specified segment.
 /// </summary>
 /// <param name="testPoint">The point to test.</param>
 /// <returns></returns>
 public override Coordinate ClosestPoint(Coordinate testPoint)
 {
     Coordinate closest = Coordinate;
     double dist = double.MaxValue;
     for (int i = 0; i < _points.Count - 1; i++)
     {
         LineSegment s = new LineSegment(_points[i], _points[i + 1]);
         Coordinate temp = s.ClosestPoint(testPoint);
         double tempDist = testPoint.Distance(temp);
         if (tempDist < dist)
         {
             dist = tempDist;
             closest = temp;
         }
     }
     return closest;
 }
예제 #26
0
        /// <summary>
        /// Checks if the computed value for isInCircle is correct, using
        /// double-double precision arithmetic.
        /// </summary>
        /// <param name="a">A vertex of the triangle</param>
        /// <param name="b">A vertex of the triangle</param>
        /// <param name="c">A vertex of the triangle</param>
        /// <param name="p">The point to test</param>
        private static void CheckRobustInCircle(Coordinate a, Coordinate b, Coordinate c,
                                                Coordinate p)
        {
            bool nonRobustInCircle = IsInCircleNonRobust(a, b, c, p);
            bool isInCircleDD = IsInCircleDDSlow(a, b, c, p);
            bool isInCircleCC = IsInCircleCC(a, b, c, p);

            Coordinate circumCentre = Triangle.Circumcentre(a, b, c);
            System.Diagnostics.Debug.WriteLine("p radius diff a = "
                              + Math.Abs(p.Distance(circumCentre) - a.Distance(circumCentre))
                              /a.Distance(circumCentre));

            if (nonRobustInCircle != isInCircleDD || nonRobustInCircle != isInCircleCC)
            {
                System.Diagnostics.Debug.WriteLine("inCircle robustness failure (double result = "
                                  + nonRobustInCircle
                                  + ", DD result = " + isInCircleDD
                                  + ", CC result = " + isInCircleCC + ")");
                System.Diagnostics.Debug.WriteLine(WKTWriter.ToLineString(new CoordinateArraySequence(new[] { a, b, c, p })));

                System.Diagnostics.Debug.WriteLine("Circumcentre = " + WKTWriter.ToPoint(circumCentre)
                                  + " radius = " + a.Distance(circumCentre));
                System.Diagnostics.Debug.WriteLine("p radius diff a = "
                                  + Math.Abs(p.Distance(circumCentre)/a.Distance(circumCentre) - 1));
                System.Diagnostics.Debug.WriteLine("p radius diff b = "
                                  + Math.Abs(p.Distance(circumCentre)/b.Distance(circumCentre) - 1));
                System.Diagnostics.Debug.WriteLine("p radius diff c = "
                                  + Math.Abs(p.Distance(circumCentre)/c.Distance(circumCentre) - 1));
                System.Diagnostics.Debug.WriteLine("");
            }
        }
예제 #27
0
 ///<summary>Computes the length of the longest side of a triangle</summary>
 /// <param name="a">A vertex of the triangle</param>
 /// <param name="b">A vertex of the triangle</param>
 /// <param name="c">A vertex of the triangle</param>
 /// <returns>The length of the longest side of the triangle</returns>
 public static double LongestSideLength(Coordinate a, Coordinate b, Coordinate c)
 {
     // ReSharper disable InconsistentNaming
     double lenAB = a.Distance(b);
     double lenBC = b.Distance(c);
     double lenCA = c.Distance(a);
     // ReSharper restore InconsistentNaming
     double maxLen = lenAB;
     if (lenBC > maxLen)
         maxLen = lenBC;
     if (lenCA > maxLen)
         maxLen = lenCA;
     return maxLen;
 }
예제 #28
0
        /// <summary>
        /// Given the specified test point, this checks each segment, and will
        /// return the closest point on the specified segment.
        /// </summary>
        /// <param name="testPoint">The point to test.</param>
        /// <returns></returns>
        public override Coordinate ClosestPoint(Coordinate testPoint)
        {
            // For a point outside the polygon, it must be closer to the shell than
            // any holes.
            if (Intersects(new Point(testPoint)) == false)
            {
                return _shell.ClosestPoint(testPoint);
            }

            Coordinate closest = _shell.ClosestPoint(testPoint);
            double dist = testPoint.Distance(closest);
            foreach (ILinearRing ring in Holes)
            {
                Coordinate temp = ring.ClosestPoint(testPoint);
                double tempDist = testPoint.Distance(temp);
                if (tempDist >= dist) continue;
                dist = tempDist;
                closest = temp;
            }
            return closest;
        }
        //    public static final String DEBUG_SEG_SPLIT = "C:\\proj\\CWB\\test\\segSplit.jml";
        /// <summary>
        /// Given a set of points stored in the kd-tree and a line segment defined by
        /// two points in this set, finds a <see cref="Coordinate"/> in the circumcircle of
        /// the line segment, if one exists. This is called the Gabriel point - if none
        /// exists then the segment is said to have the Gabriel condition. Uses the
        /// heuristic of finding the non-Gabriel point closest to the midpoint of the
        /// segment.
        /// </summary>
        /// <param name="seg">the line segment</param>
        /// <returns>
        /// A point which is non-Gabriel,
        /// or null if no point is non-Gabriel
        /// </returns>
        private Coordinate FindNonGabrielPoint(Segment seg)
        {
            Coordinate p = seg.Start;
            Coordinate q = seg.End;
            // Find the mid point on the line and compute the radius of enclosing circle
            Coordinate midPt = new Coordinate((p.X + q.X) / 2.0, (p.Y + q.Y) / 2.0);
            double segRadius = p.Distance(midPt);

            // compute envelope of circumcircle
            Envelope env = new Envelope(midPt);
            env.ExpandBy(segRadius);
            // Find all points in envelope
            ICollection<KdNode<Vertex>> result = _kdt.Query(env);

            // For each point found, test if it falls strictly in the circle
            // find closest point
            Coordinate closestNonGabriel = null;
            double minDist = Double.MaxValue;
            foreach (KdNode<Vertex> nextNode in result)
            {
                Coordinate testPt = nextNode.Coordinate;
                // ignore segment endpoints
                if (testPt.Equals2D(p) || testPt.Equals2D(q))
                    continue;

                double testRadius = midPt.Distance(testPt);
                if (testRadius < segRadius)
                {
                    // double testDist = seg.distance(testPt);
                    double testDist = testRadius;
                    if (closestNonGabriel == null || testDist < minDist)
                    {
                        closestNonGabriel = testPt;
                        minDist = testDist;
                    }
                }
            }
            return closestNonGabriel;
        }
예제 #30
0
        ///<summary>
        /// Computes the incentre of a triangle.
        ///</summary>
        /// <remarks>
        /// The <c>InCentre</c> of a triangle is the point which is equidistant
        /// from the sides of the triangle.
        /// It is also the point at which the bisectors of the triangle's angles meet.
        /// It is the centre of the triangle's <c>InCircle</c>, which is the unique circle 
        /// that is tangent to each of the triangle's three sides.
        /// </remarks>
        /// <param name="a">A vertex of the triangle</param>
        /// <param name="b">A vertex of the triangle</param>
        /// <param name="c">A vertex of the triangle</param>
        /// <returns>The point which is the incentre of the triangle</returns>
        public static Coordinate InCentre(Coordinate a, Coordinate b, Coordinate c)
        {
            // the lengths of the sides, labelled by their opposite vertex
            double len0 = b.Distance(c);
            double len1 = a.Distance(c);
            double len2 = a.Distance(b);
            double circum = len0 + len1 + len2;

            double inCentreX = (len0 * a.X + len1 * b.X + len2 * c.X) / circum;
            double inCentreY = (len0 * a.Y + len1 * b.Y + len2 * c.Y) / circum;
            return new Coordinate(inCentreX, inCentreY);
        }