Esempio n. 1
0
        /// <summary>
        /// Compute the projection factor for the projection of the point p
        /// onto this <c>LineSegment</c>. The projection factor is the constant k
        /// by which the vector for this segment must be multiplied to
        /// equal the vector for the projection of p.
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public double ProjectionFactor(ICoordinate p)
        {
            if (p.Equals(P0))
            {
                return(0.0);
            }
            if (p.Equals(P1))
            {
                return(1.0);
            }

            // Otherwise, use comp.graphics.algorithms Frequently Asked Questions method

            /*                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 dx   = P1.X - P0.X;
            double dy   = P1.Y - P0.Y;
            double len2 = dx * dx + dy * dy;
            double r    = ((p.X - P0.X) * dx + (p.Y - P0.Y) * dy) / len2;

            return(r);
        }
Esempio n. 2
0
        /// <summary> 
        /// Computes the "edge distance" of an intersection point p along a segment.
        /// The edge distance is a metric of the point along the edge.
        /// The metric used is a robust and easy to compute metric function.
        /// It is not equivalent to the usual Euclidean metric.
        /// It relies on the fact that either the x or the y ordinates of the
        /// points in the edge are unique, depending on whether the edge is longer in
        /// the horizontal or vertical direction.
        /// NOTE: This function may produce incorrect distances
        /// for inputs where p is not precisely on p1-p2
        /// (E.g. p = (139,9) p1 = (139,10), p2 = (280,1) produces distanct 0.0, which is incorrect.
        /// My hypothesis is that the function is safe to use for points which are the
        /// result of rounding points which lie on the line, but not safe to use for truncated points.
        /// </summary>
        public static double ComputeEdgeDistance(ICoordinate p, ICoordinate p0, ICoordinate p1)
        {
            double dx = Math.Abs(p1.X - p0.X);
            double dy = Math.Abs(p1.Y - p0.Y);

            double dist = -1.0;   // sentinel value
            if (p.Equals(p0)) 
                dist = 0.0;            
            else if (p.Equals(p1)) 
            {
                if (dx > dy)
                     dist = dx;
                else dist = dy;
            }
            else 
            {
                double pdx = Math.Abs(p.X - p0.X);
                double pdy = Math.Abs(p.Y - p0.Y);
                if (dx > dy)
                     dist = pdx;
                else dist = pdy;

                // <FIX>: hack to ensure that non-endpoints always have a non-zero distance
                if (dist == 0.0 && ! p.Equals(p0))                
                    dist = Math.Max(pdx, pdy);
                
            }
            Assert.IsTrue(!(dist == 0.0 && ! p.Equals(p0)), "Bad distance calculation");
            return dist;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="p"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        public override void ComputeIntersection(ICoordinate p, ICoordinate p1, ICoordinate p2)
        {
            double a1;
            double b1;
            double c1;

            /*
             *  Coefficients of line eqns.
             */

            double r;

            /*
             *  'Sign' values
             */

            isProper = false;

            /*
             *  Compute a1, b1, c1, where line joining points 1 and 2
             *  is "a1 x  +  b1 y  +  c1  =  0".
             */
            a1 = p2.Y - p1.Y;
            b1 = p1.X - p2.X;
            c1 = p2.X * p1.Y - p1.X * p2.Y;

            /*
             *  Compute r3 and r4.
             */
            r = a1 * p.X + b1 * p.Y + c1;

            // if r != 0 the point does not lie on the line
            if (r != 0)
            {
                result = DontIntersect;
                return;
            }

            // Point lies on line - check to see whether it lies in line segment.

            double dist = RParameter(p1, p2, p);

            if (dist < 0.0 || dist > 1.0)
            {
                result = DontIntersect;
                return;
            }

            isProper = true;
            if (p.Equals(p1) || p.Equals(p2))
            {
                isProper = false;
            }

            result = DoIntersect;
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="li"></param>
 /// <param name="p0"></param>
 /// <param name="p1"></param>
 /// <returns><c>true</c> if there is an intersection point which is not an endpoint of the segment p0-p1.</returns>
 private bool HasInteriorIntersection(LineIntersector li, ICoordinate p0, ICoordinate p1)
 {
     for (int i = 0; i < li.IntersectionNum; i++)
     {
         ICoordinate intPt = li.GetIntersection(i);
         if (!(intPt.Equals(p0) || intPt.Equals(p1)))
         {
             return(true);
         }
     }
     return(false);
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        public override void ComputeIntersection(ICoordinate p, ICoordinate p1, ICoordinate p2) 
        {
            double a1;
            double b1;
            double c1;
            /*
            *  Coefficients of line eqns.
            */

            double r;
            /*
            *  'Sign' values
            */

            isProper = false;

            /*
            *  Compute a1, b1, c1, where line joining points 1 and 2
            *  is "a1 x  +  b1 y  +  c1  =  0".
            */
            a1 = p2.Y - p1.Y;
            b1 = p1.X - p2.X;
            c1 = p2.X * p1.Y - p1.X * p2.Y;

            /*
            *  Compute r3 and r4.
            */
            r = a1 * p.X + b1 * p.Y + c1;

            // if r != 0 the point does not lie on the line
            if (r != 0) 
            {
                result = DontIntersect;
                return;
            }

            // Point lies on line - check to see whether it lies in line segment.

            double dist = RParameter(p1, p2, p);
            if (dist < 0.0 || dist > 1.0)
            {
                result = DontIntersect;
                return;
            }

            isProper = true;
            if (p.Equals(p1) || p.Equals(p2))             
                isProper = false;
            
            result = DoIntersect;
        }
Esempio n. 6
0
        /// <summary>
        /// Compute the projection of a point onto the line determined
        /// by this line segment.
        /// Note that the projected point  may lie outside the line segment.
        /// If this is the case,  the projection factor will lie outside the range [0.0, 1.0].
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public ICoordinate Project(ICoordinate p)
        {
            if (p.Equals(P0) || p.Equals(P1))
            {
                return(new Coordinate(p));
            }

            var         r     = ProjectionFactor(p);
            ICoordinate coord = new Coordinate {
                X = P0.X + r * (P1.X - P0.X), Y = P0.Y + r * (P1.Y - P0.Y)
            };

            return(coord);
        }
Esempio n. 7
0
        /// <summary>
        /// Compute the projection of a point onto the line determined
        /// by this line segment.
        /// Note that the projected point
        /// may lie outside the line segment.  If this is the case,
        /// the projection factor will lie outside the range [0.0, 1.0].
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public ICoordinate Project(ICoordinate p)
        {
            if (p.Equals(P0) || p.Equals(P1))
            {
                return(new Coordinate(p));
            }

            double      r     = ProjectionFactor(p);
            ICoordinate coord = new Coordinate();

            coord.X = P0.X + r * (P1.X - P0.X);
            coord.Y = P0.Y + r * (P1.Y - P0.Y);
            return(coord);
        }
Esempio n. 8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="original">The vertices of a linear ring, which may or may not be flattened (i.e. vertices collinear).</param>
        /// <returns>The coordinates with unnecessary (collinear) vertices removed.</returns>
        private ICoordinate[] CleanRing(ICoordinate[] original)
        {
            Equals(original[0], original[original.Length - 1]);
            List <ICoordinate> cleanedRing = new List <ICoordinate>();
            ICoordinate        previousDistinctCoordinate = null;

            for (int i = 0; i <= original.Length - 2; i++)
            {
                ICoordinate currentCoordinate = original[i];
                ICoordinate nextCoordinate    = original[i + 1];
                if (currentCoordinate.Equals(nextCoordinate))
                {
                    continue;
                }
                if (previousDistinctCoordinate != null &&
                    IsBetween(previousDistinctCoordinate, currentCoordinate, nextCoordinate))
                {
                    continue;
                }
                cleanedRing.Add(currentCoordinate);
                previousDistinctCoordinate = currentCoordinate;
            }
            cleanedRing.Add(original[original.Length - 1]);
            return(cleanedRing.ToArray());
        }
Esempio n. 9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <returns></returns>
        private bool IsLineSegmentContainedInBoundary(ICoordinate p0, ICoordinate p1)
        {
            if (p0.Equals(p1))
            {
                return(IsPointContainedInBoundary(p0));
            }
            // we already know that the segment is contained in the rectangle envelope
            if (p0.X == p1.X)
            {
                if (p0.X == rectEnv.MinX ||
                    p0.X == rectEnv.MaxX)
                {
                    return(true);
                }
            }
            else if (p0.Y == p1.Y)
            {
                if (p0.Y == rectEnv.MinY ||
                    p0.Y == rectEnv.MaxY)
                {
                    return(true);
                }
            }

            /*
             * Either both x and y values are different
             * or one of x and y are the same, but the other ordinate is not the same as a boundary ordinate
             * In either case, the segment is not wholely in the boundary
             */
            return(false);
        }
Esempio n. 10
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="p"></param>
 /// <param name="l"></param>
 /// <returns></returns>
 private Locations Locate(ICoordinate p, ILineString l)
 {
     ICoordinate[] pt = l.Coordinates;
     if (!l.IsClosed)
     {
         if (p.Equals(pt[0]) || p.Equals(pt[pt.Length - 1]))
         {
             return(Locations.Boundary);
         }
     }
     if (CGAlgorithms.IsOnLine(p, pt))
     {
         return(Locations.Interior);
     }
     return(Locations.Exterior);
 }
Esempio n. 11
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="p0"></param>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 private void CheckCollapse(ICoordinate p0, ICoordinate p1, ICoordinate p2)
 {
     if (p0.Equals(p2))
     {
         throw new Exception("found non-noded collapse at: " + p0 + ", " + p1 + " " + p2);
     }
 }
Esempio n. 12
0
 /// <summary>
 /// Tests whether a given point is in an array of points.
 /// Uses a value-based test.
 /// </summary>
 /// <param name="pt">A <c>Coordinate</c> for the test point.</param>
 /// <param name="pts">An array of <c>Coordinate</c>s to test,</param>
 /// <returns><c>true</c> if the point is in the array.</returns>
 public static bool IsInList(ICoordinate pt, ICoordinate[] pts)
 {
     foreach (ICoordinate p in pts)
         if (pt.Equals(p))
             return true;
     return true;
 }
Esempio n. 13
0
 private void CheckCollapse(ICoordinate p0, ICoordinate p1, ICoordinate p2)
 {
     if (p0.Equals(p2))
     {
         throw new ApplicationException(String.Format(
                                            "found non-noded collapse at: {0}, {1} {2}", p0, p1, p2));
     }
 }
        /// <summary>
        ///
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="q1"></param>
        /// <param name="q2"></param>
        /// <returns></returns>
        private int ComputeCollinearIntersection(ICoordinate p1, ICoordinate p2, ICoordinate q1, ICoordinate q2)
        {
            bool p1q1p2 = Envelope.Intersects(p1, p2, q1);
            bool p1q2p2 = Envelope.Intersects(p1, p2, q2);
            bool q1p1q2 = Envelope.Intersects(q1, q2, p1);
            bool q1p2q2 = Envelope.Intersects(q1, q2, p2);

            if (p1q1p2 && p1q2p2)
            {
                intPt[0] = q1;
                intPt[1] = q2;
                return(Collinear);
            }
            if (q1p1q2 && q1p2q2)
            {
                intPt[0] = p1;
                intPt[1] = p2;
                return(Collinear);
            }
            if (p1q1p2 && q1p1q2)
            {
                intPt[0] = q1;
                intPt[1] = p1;
                return(q1.Equals(p1) && !p1q2p2 && !q1p2q2 ? DoIntersect : Collinear);
            }
            if (p1q1p2 && q1p2q2)
            {
                intPt[0] = q1;
                intPt[1] = p2;
                return(q1.Equals(p2) && !p1q2p2 && !q1p1q2 ? DoIntersect : Collinear);
            }
            if (p1q2p2 && q1p1q2)
            {
                intPt[0] = q2;
                intPt[1] = p1;
                return(q2.Equals(p1) && !p1q1p2 && !q1p2q2 ? DoIntersect : Collinear);
            }
            if (p1q2p2 && q1p2q2)
            {
                intPt[0] = q2;
                intPt[1] = p2;
                return(q2.Equals(p2) && !p1q1p2 && !q1p1q2 ? DoIntersect : Collinear);
            }
            return(DontIntersect);
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="p"></param>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 public override void ComputeIntersection(ICoordinate p, ICoordinate p1, ICoordinate p2) 
 {
     isProper = false;
     // do between check first, since it is faster than the orientation test
     if(Envelope.Intersects(p1, p2, p)) 
     {
         if( (CGAlgorithms.OrientationIndex(p1, p2, p) == 0) && 
             (CGAlgorithms.OrientationIndex(p2, p1, p) == 0) ) 
         {
             isProper = true;
             if (p.Equals(p1) || p.Equals(p2)) 
                 isProper = false;                    
             result = DoIntersect;
             return;
         }
     }
     result = DontIntersect;
 }
Esempio n. 16
0
        /// <summary>
        /// This function is non-robust, since it may compute the square of large numbers.
        /// Currently not sure how to improve this.
        /// </summary>
        /// <param name="p"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        public static double NonRobustComputeEdgeDistance(ICoordinate p, ICoordinate p1, ICoordinate p2)
        {
            double dx   = p.X - p1.X;
            double dy   = p.Y - p1.Y;
            double dist = Math.Sqrt(dx * dx + dy * dy);   // dummy value

            Assert.IsTrue(!(dist == 0.0 && !p.Equals(p1)), "Invalid distance calculation");
            return(dist);
        }
Esempio n. 17
0
        /// <summary>
        /// Computes the "edge distance" of an intersection point p along a segment.
        /// The edge distance is a metric of the point along the edge.
        /// The metric used is a robust and easy to compute metric function.
        /// It is not equivalent to the usual Euclidean metric.
        /// It relies on the fact that either the x or the y ordinates of the
        /// points in the edge are unique, depending on whether the edge is longer in
        /// the horizontal or vertical direction.
        /// NOTE: This function may produce incorrect distances
        /// for inputs where p is not precisely on p1-p2
        /// (E.g. p = (139,9) p1 = (139,10), p2 = (280,1) produces distanct 0.0, which is incorrect.
        /// My hypothesis is that the function is safe to use for points which are the
        /// result of rounding points which lie on the line, but not safe to use for truncated points.
        /// </summary>
        public static double ComputeEdgeDistance(ICoordinate p, ICoordinate p0, ICoordinate p1)
        {
            double dx = Math.Abs(p1.X - p0.X);
            double dy = Math.Abs(p1.Y - p0.Y);

            double dist = -1.0;   // sentinel value

            if (p.Equals(p0))
            {
                dist = 0.0;
            }
            else if (p.Equals(p1))
            {
                if (dx > dy)
                {
                    dist = dx;
                }
                else
                {
                    dist = dy;
                }
            }
            else
            {
                double pdx = Math.Abs(p.X - p0.X);
                double pdy = Math.Abs(p.Y - p0.Y);
                if (dx > dy)
                {
                    dist = pdx;
                }
                else
                {
                    dist = pdy;
                }

                // <FIX>: hack to ensure that non-endpoints always have a non-zero distance
                if (dist == 0.0 && !p.Equals(p0))
                {
                    dist = Math.Max(pdx, pdy);
                }
            }
            Assert.IsTrue(!(dist == 0.0 && !p.Equals(p0)), "Bad distance calculation");
            return(dist);
        }
Esempio n. 18
0
        /// <summary>
        /// Reads and parses the header of the .shp index file
        /// </summary>
        /// <remarks>
        /// From ESRI ShapeFile Technical Description document
        ///
        /// http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf
        ///
        /// Byte
        /// Position    Field           Value       Type    Order
        /// -----------------------------------------------------
        /// Byte 0      File Code       9994        Integer Big
        /// Byte 4      Unused          0           Integer Big
        /// Byte 8      Unused          0           Integer Big
        /// Byte 12     Unused          0           Integer Big
        /// Byte 16     Unused          0           Integer Big
        /// Byte 20     Unused          0           Integer Big
        /// Byte 24     File Length     File Length Integer Big
        /// Byte 28     Version         1000        Integer Little
        /// Byte 32     Shape Type      Shape Type  Integer Little
        /// Byte 36     Bounding Box    Xmin        Double  Little
        /// Byte 44     Bounding Box    Ymin        Double  Little
        /// Byte 52     Bounding Box    Xmax        Double  Little
        /// Byte 60     Bounding Box    Ymax        Double  Little
        /// Byte 68*    Bounding Box    Zmin        Double  Little
        /// Byte 76*    Bounding Box    Zmax        Double  Little
        /// Byte 84*    Bounding Box    Mmin        Double  Little
        /// Byte 92*    Bounding Box    Mmax        Double  Little
        ///
        /// * Unused, with value 0.0, if not Measured or Z type
        ///
        /// The "Integer" type corresponds to the CLS Int32 type, and "Double" to CLS Double (IEEE 754).
        /// </remarks>
        private void parseHeader(BinaryReader reader)
        {
            reader.BaseStream.Seek(0, SeekOrigin.Begin);

            // Check file header
            if (ByteEncoder.GetBigEndian(reader.ReadInt32()) != ShapeFileConstants.HeaderStartCode)
            {
                throw new ShapeFileIsInvalidException("Invalid ShapeFile (.shp)");
            }

            // Seek to File Length
            reader.BaseStream.Seek(24, 0);

            // Read filelength as big-endian. The length is number of 16-bit words in file
            FileLengthInWords = ByteEncoder.GetBigEndian(reader.ReadInt32());

            // Seek to ShapeType
            reader.BaseStream.Seek(32, 0);
            ShapeType = (ShapeType)reader.ReadInt32();

            // Seek to bounding box of shapefile
            reader.BaseStream.Seek(36, 0);

            // Read the spatial bounding box of the contents
            Double xMin = ByteEncoder.GetLittleEndian(reader.ReadDouble());
            Double yMin = ByteEncoder.GetLittleEndian(reader.ReadDouble());
            Double xMax = ByteEncoder.GetLittleEndian(reader.ReadDouble());
            Double yMax = ByteEncoder.GetLittleEndian(reader.ReadDouble());

            ICoordinate min = _geoFactory.CoordinateFactory.Create(xMin, yMin);
            ICoordinate max = _geoFactory.CoordinateFactory.Create(xMax, yMax);

            Extents = min.Equals(max) && min.Equals(_geoFactory.CoordinateFactory.Create(0, 0)) //jd: if the shapefile has just been created the box wil be 0,0,0,0 in this case create an empty extents
                ? _geoFactory.CreateExtents()
                : _geoFactory.CreateExtents(min, max);


            //jd:allow exmpty extents
            //if (Extents.IsEmpty)
            //{
            //    Extents = null;
            //}
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="p"></param>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 public override void ComputeIntersection(ICoordinate p, ICoordinate p1, ICoordinate p2)
 {
     isProper = false;
     // do between check first, since it is faster than the orientation test
     if (Envelope.Intersects(p1, p2, p))
     {
         if ((CGAlgorithms.OrientationIndex(p1, p2, p) == 0) && (CGAlgorithms.OrientationIndex(p2, p1, p) == 0))
         {
             isProper = true;
             if (p.Equals(p1) || p.Equals(p2))
             {
                 isProper = false;
             }
             result = DoIntersect;
             return;
         }
     }
     result = DontIntersect;
 }
Esempio n. 20
0
        /// <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(ICoordinate A, ICoordinate B, ICoordinate C, ICoordinate D)
        {
            // check for zero-length segments
            if (A.Equals(B))
                return DistancePointLine(A,C,D);
            if (C.Equals(D))
                return DistancePointLine(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 Point be the position vector of the intersection point, then
                    Point=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(DistancePointLine(A,C,D),
                        Math.Min(DistancePointLine(B,C,D),
                        Math.Min(DistancePointLine(C,A,B),
                        DistancePointLine(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(DistancePointLine(A,C,D),
                        Math.Min(DistancePointLine(B,C,D),
                        Math.Min(DistancePointLine(C,A,B),
                        DistancePointLine(D,A,B) ) ) );

            return 0.0; //intersection exists
        }
Esempio n. 21
0
 /// <summary>
 /// Tests whether a given point is in an array of points.
 /// Uses a value-based test.
 /// </summary>
 /// <param name="pt">A <c>Coordinate</c> for the test point.</param>
 /// <param name="pts">An array of <c>Coordinate</c>s to test,</param>
 /// <returns><c>true</c> if the point is in the array.</returns>
 public static bool IsInList(ICoordinate pt, ICoordinate[] pts)
 {
     for (int i = 0; i < pts.Length; i++)
     {
         if (pt.Equals(pts[i]))
         {
             return(false);
         }
     }
     return(true);
 }
Esempio n. 22
0
 /// <summary>
 /// Tests whether a given point is in an array of points.
 /// Uses a value-based test.
 /// </summary>
 /// <param name="pt">A <c>Coordinate</c> for the test point.</param>
 /// <param name="pts">An array of <c>Coordinate</c>s to test,</param>
 /// <returns><c>true</c> if the point is in the array.</returns>
 public static bool IsInList(ICoordinate pt, ICoordinate[] pts)
 {
     foreach (ICoordinate p in pts)
     {
         if (pt.Equals(p))
         {
             return(true);
         }
     }
     return(true);
 }
Esempio n. 23
0
 /// <summary>
 /// Returns the index of <paramref name="coordinate" /> in <paramref name="coordinates" />.
 /// The first position is 0; the second is 1; etc.
 /// </summary>
 /// <param name="coordinate">A <see cref="Coordinate" /> to search for.</param>
 /// <param name="coordinates">A <see cref="Coordinate" /> array to search.</param>
 /// <returns>The position of <c>coordinate</c>, or -1 if it is not found.</returns>
 public static int IndexOf(ICoordinate coordinate, ICoordinate[] coordinates)
 {
     for (int i = 0; i < coordinates.Length; i++)
     {
         if (coordinate.Equals(coordinates[i]))
         {
             return(i);
         }
     }
     return(-1);
 }
Esempio n. 24
0
        /// <summary>
        /// Tests whether the segment p0-p1 intersects the hot pixel tolerance square.
        /// Because the tolerance square point set is partially open (along the
        /// top and right) the test needs to be more sophisticated than
        /// simply checking for any intersection.  However, it
        /// can take advantage of the fact that because the hot pixel edges
        /// do not lie on the coordinate grid.  It is sufficient to check
        /// if there is at least one of:
        ///  - a proper intersection with the segment and any hot pixel edge.
        ///  - an intersection between the segment and both the left and bottom edges.
        ///  - an intersection between a segment endpoint and the hot pixel coordinate.
        /// </summary>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <returns></returns>
        private bool IntersectsToleranceSquare(ICoordinate p0, ICoordinate p1)
        {
            bool intersectsLeft   = false;
            bool intersectsBottom = false;

            li.ComputeIntersection(p0, p1, corner[0], corner[1]);
            if (li.IsProper)
            {
                return(true);
            }

            li.ComputeIntersection(p0, p1, corner[1], corner[2]);
            if (li.IsProper)
            {
                return(true);
            }
            if (li.HasIntersection)
            {
                intersectsLeft = true;
            }

            li.ComputeIntersection(p0, p1, corner[2], corner[3]);
            if (li.IsProper)
            {
                return(true);
            }
            if (li.HasIntersection)
            {
                intersectsBottom = true;
            }

            li.ComputeIntersection(p0, p1, corner[3], corner[0]);
            if (li.IsProper)
            {
                return(true);
            }

            if (intersectsLeft && intersectsBottom)
            {
                return(true);
            }

            if (p0.Equals(pt))
            {
                return(true);
            }
            if (p1.Equals(pt))
            {
                return(true);
            }

            return(false);
        }
Esempio n. 25
0
 /// <summary>
 /// Returns the edge whose first two coordinates are p0 and p1.
 /// </summary>
 /// <param name="p0"></param>
 /// <param name="p1"></param>
 /// <returns> The edge, if found <c>null</c> if the edge was not found.</returns>
 public Edge FindEdge(ICoordinate p0, ICoordinate p1)
 {
     for (int i = 0; i < edges.Count; i++)
     {
         Edge          e      = (Edge)edges[i];
         ICoordinate[] eCoord = e.Coordinates;
         if (p0.Equals(eCoord[0]) && p1.Equals(eCoord[1]))
         {
             return(e);
         }
     }
     return(null);
 }
Esempio n. 26
0
 /// <summary>
 /// The coordinate pairs match if they define line segments lying in the same direction.
 /// E.g. the segments are parallel and in the same quadrant
 /// (as opposed to parallel and opposite!).
 /// </summary>
 /// <param name="p0"></param>
 /// <param name="p1"></param>
 /// <param name="ep0"></param>
 /// <param name="ep1"></param>
 private bool MatchInSameDirection(ICoordinate p0, ICoordinate p1, ICoordinate ep0, ICoordinate ep1)
 {
     if (!p0.Equals(ep0))
     {
         return(false);
     }
     if (CGAlgorithms.ComputeOrientation(p0, p1, ep1) == CGAlgorithms.Collinear &&
         QuadrantOp.Quadrant(p0, p1) == QuadrantOp.Quadrant(ep0, ep1))
     {
         return(true);
     }
     return(false);
 }
Esempio n. 27
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(ICoordinate p, ICoordinate A, ICoordinate 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))));
        }
Esempio n. 28
0
        /// <summary>
        /// Returns <c>true</c> if <c>o</c> has the same values for its points.
        /// </summary>
        /// <param name="o">A <c>LineSegment</c> with which to do the comparison.</param>
        /// <returns>
        /// <c>true</c> if <c>o</c> is a <c>LineSegment</c>
        /// with the same values for the x and y ordinates.
        /// </returns>
        public override bool Equals(object o)
        {
            if (o == null)
            {
                return(false);
            }
            if (!(o is LineSegment))
            {
                return(false);
            }
            LineSegment other = (LineSegment)o;

            return(p0.Equals(other.p0) && p1.Equals(other.p1));
        }
Esempio n. 29
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="dirEdgeList"></param>
        public void FindEdge(IList dirEdgeList)
        {
            /*
             * Check all forward DirectedEdges only.  This is still general,
             * because each edge has a forward DirectedEdge.
             */
            for (IEnumerator i = dirEdgeList.GetEnumerator(); i.MoveNext();)
            {
                DirectedEdge de = (DirectedEdge)i.Current;
                if (!de.IsForward)
                {
                    continue;
                }
                CheckForRightmostCoordinate(de);
            }

            /*
             * If the rightmost point is a node, we need to identify which of
             * the incident edges is rightmost.
             */
            Assert.IsTrue(minIndex != 0 || minCoord.Equals(minDe.Coordinate), "inconsistency in rightmost processing");
            if (minIndex == 0)
            {
                FindRightmostEdgeAtNode();
            }
            else
            {
                FindRightmostEdgeAtVertex();
            }

            /*
             * now check that the extreme side is the R side.
             * If not, use the sym instead.
             */
            orientedDe = minDe;
            Positions rightmostSide = GetRightmostSide(minDe, minIndex);

            if (rightmostSide == Positions.Left)
            {
                orientedDe = minDe.Sym;
            }
        }
Esempio n. 30
0
        /// <summary>
        /// Calculates the dyad product.
        /// </summary>
        /// <typeparam name="T">The type of coordinate values.</typeparam>
        /// <param name="point1">The point1.</param>
        /// <param name="point2">The point2.</param>
        /// <returns>The result of dyad product operation.</returns>
        public static BaseDyadCoordinate <T> DyadProduct <T>(this ICoordinate <T> point1, ICoordinate <T> point2) where T : struct
        {
            if (point1.Equals(point2))
            {
                return(new SymmetricDyadCoordinate <T>(
                           (dynamic)point1.X * point2.X,
                           (dynamic)point1.X * point2.Y,
                           (dynamic)point1.X * point2.Z,
                           (dynamic)point1.Y * point2.Y,
                           (dynamic)point1.Y * point2.Z,
                           (dynamic)point1.Z * point2.Z));
            }

            return(new DyadCoordinate <T>(
                       (dynamic)point1.X * point2.X,
                       (dynamic)point1.X * point2.Y,
                       (dynamic)point1.X * point2.Z,
                       (dynamic)point1.Y * point2.X,
                       (dynamic)point1.Y * point2.Y,
                       (dynamic)point1.Y * point2.Z,
                       (dynamic)point1.Z * point2.X,
                       (dynamic)point1.Z * point2.Y,
                       (dynamic)point1.Z * point2.Z));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="q1"></param>
        /// <param name="q2"></param>
        /// <returns></returns>
        private int ComputeCollinearIntersection(ICoordinate p1, ICoordinate p2, ICoordinate q1, ICoordinate q2) 
        {
            bool p1q1p2 = Envelope.Intersects(p1, p2, q1);
            bool p1q2p2 = Envelope.Intersects(p1, p2, q2);
            bool q1p1q2 = Envelope.Intersects(q1, q2, p1);
            bool q1p2q2 = Envelope.Intersects(q1, q2, p2);

            if (p1q1p2 && p1q2p2) 
            {
                intPt[0] = q1;
                intPt[1] = q2;
                return Collinear;
            }
            if (q1p1q2 && q1p2q2) 
            {
                intPt[0] = p1;
                intPt[1] = p2;
                return Collinear;
            }
            if (p1q1p2 && q1p1q2)
            {
                intPt[0] = q1;
                intPt[1] = p1;
                return q1.Equals(p1) && !p1q2p2 && !q1p2q2 ? DoIntersect : Collinear;
            }
            if (p1q1p2 && q1p2q2) 
            {
                intPt[0] = q1;
                intPt[1] = p2;
                return q1.Equals(p2) && !p1q2p2 && !q1p1q2 ? DoIntersect : Collinear;
            }
            if (p1q2p2 && q1p1q2) 
            {
                intPt[0] = q2;
                intPt[1] = p1;
                return q2.Equals(p1) && !p1q1p2 && !q1p2q2 ? DoIntersect : Collinear;
            }
            if (p1q2p2 && q1p2q2) 
            {
                intPt[0] = q2;
                intPt[1] = p2;
                return q2.Equals(p2) && !p1q1p2 && !q1p1q2 ? DoIntersect : Collinear;
            }
            return DontIntersect;
        }
Esempio n. 32
0
        /// <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(ICoordinate A, ICoordinate B, ICoordinate C, ICoordinate D)
        {
            // check for zero-length segments
            if (A.Equals(B))
            {
                return(DistancePointLine(A, C, D));
            }
            if (C.Equals(D))
            {
                return(DistancePointLine(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 Point be the position vector of the intersection point, then
             *              Point=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(DistancePointLine(A, C, D),
                                Math.Min(DistancePointLine(B, C, D),
                                         Math.Min(DistancePointLine(C, A, B),
                                                  DistancePointLine(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(DistancePointLine(A, C, D),
                                Math.Min(DistancePointLine(B, C, D),
                                         Math.Min(DistancePointLine(C, A, B),
                                                  DistancePointLine(D, A, B)))));
            }

            return(0.0); //intersection exists
        }
Esempio n. 33
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="p0"></param>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 private void CheckCollapse(ICoordinate p0, ICoordinate p1, ICoordinate p2)
 {
     if (p0.Equals(p2))
         throw new Exception("found non-noded collapse at: " + p0 + ", " + p1 + " " + p2);
 }
Esempio n. 34
0
 private void CheckCollapse(ICoordinate p0, ICoordinate p1, ICoordinate p2)
 {
     if (p0.Equals(p2))
         throw new ApplicationException(String.Format(
             "found non-noded collapse at: {0}, {1} {2}", p0, p1, p2));
 }
Esempio n. 35
0
        /// <summary>
        /// Computes whether a ring defined by an array of <c>Coordinate</c> is
        /// oriented counter-clockwise.
        /// This will handle coordinate lists which contain repeated points.
        /// </summary>
        /// <param name="ring">an array of coordinates forming a ring.</param>
        /// <returns>
        /// <c>true</c> if the ring is oriented counter-clockwise.
        /// throws <c>ArgumentException</c> if the ring is degenerate (does not contain 3 different points)
        /// </returns>
        public static bool IsCCW(ICoordinate[] ring)
        {
            // # of points without closing endpoint
            int nPts = ring.Length - 1;

            // check that this is a valid ring - if not, simply return a dummy value
            if (nPts < 4)
            {
                return(false);
            }

            // algorithm to check if a Ring is stored in CCW order
            // find highest point
            ICoordinate hip = ring[0];
            int         hii = 0;

            for (int i = 1; i <= nPts; i++)
            {
                ICoordinate p = ring[i];
                if (p.Y > hip.Y)
                {
                    hip = p;
                    hii = i;
                }
            }

            // find different point before highest point
            int iPrev = hii;

            do
            {
                iPrev = (iPrev - 1) % nPts;
            }while(ring[iPrev].Equals(hip) && iPrev != hii);

            // find different point after highest point
            int iNext = hii;

            do
            {
                iNext = (iNext + 1) % nPts;
            }while (ring[iNext].Equals(hip) && iNext != hii);

            ICoordinate prev = ring[iPrev];
            ICoordinate next = ring[iNext];

            if (prev.Equals(hip) || next.Equals(hip) || prev.Equals(next))
            {
                throw new ArgumentException("degenerate ring (does not contain 3 different points)");
            }

            // translate so that hip is at the origin.
            // This will not affect the area calculation, and will avoid
            // finite-accuracy errors (i.e very small vectors with very large coordinates)
            // This also simplifies the discriminant calculation.
            double prev2x = prev.X - hip.X;
            double prev2y = prev.Y - hip.Y;
            double next2x = next.X - hip.X;
            double next2y = next.Y - hip.Y;

            // compute cross-product of vectors hip->next and hip->prev
            // (e.g. area of parallelogram they enclose)
            double disc = next2x * prev2y - next2y * prev2x;

            /* If disc is exactly 0, lines are collinear.  There are two possible cases:
             *      (1) the lines lie along the x axis in opposite directions
             *      (2) the line lie on top of one another
             *
             *      (2) should never happen, so we're going to ignore it!
             *          (Might want to assert this)
             *
             *      (1) is handled by checking if next is left of prev ==> CCW
             */
            if (disc == 0.0)
            {
                return(prev.X > next.X);   // poly is CCW if prev x is right of next x
            }
            else
            {
                return(disc > 0.0);        // if area is positive, points are ordered CCW
            }
        }
Esempio n. 36
0
        /// <summary> 
        /// Compute the projection of a point onto the line determined
        /// by this line segment.
        /// Note that the projected point
        /// may lie outside the line segment.  If this is the case,
        /// the projection factor will lie outside the range [0.0, 1.0].
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public ICoordinate Project(ICoordinate p)
        {
            if (p.Equals(P0) || p.Equals(P1)) 
                return new Coordinate(p);

            double r = ProjectionFactor(p);
            ICoordinate coord = new Coordinate();
            coord.X = P0.X + r * (P1.X - P0.X);
            coord.Y = P0.Y + r * (P1.Y - P0.Y);
            return coord;
        }
Esempio n. 37
0
 /// <summary>
 /// This function is non-robust, since it may compute the square of large numbers.
 /// Currently not sure how to improve this.
 /// </summary>
 /// <param name="p"></param>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 /// <returns></returns>
 public static double NonRobustComputeEdgeDistance(ICoordinate p, ICoordinate p1, ICoordinate p2)
 {
     double dx = p.X - p1.X;
     double dy = p.Y - p1.Y;
     double dist = Math.Sqrt(dx * dx + dy * dy);   // dummy value
     Assert.IsTrue(! (dist == 0.0 && ! p.Equals(p1)), "Invalid distance calculation");
     return dist;
 }
Esempio n. 38
0
 /// <summary>
 /// The coordinate pairs match if they define line segments lying in the same direction.
 /// E.g. the segments are parallel and in the same quadrant
 /// (as opposed to parallel and opposite!).
 /// </summary>
 /// <param name="p0"></param>
 /// <param name="p1"></param>
 /// <param name="ep0"></param>
 /// <param name="ep1"></param>
 private bool MatchInSameDirection(ICoordinate p0, ICoordinate p1, ICoordinate ep0, ICoordinate ep1)
 {
     if (! p0.Equals(ep0))
         return false;
     if (CGAlgorithms.ComputeOrientation(p0, p1, ep1) == CGAlgorithms.Collinear && 
         QuadrantOp.Quadrant(p0, p1) == QuadrantOp.Quadrant(ep0, ep1) )
         return true;
     return false;
 }
Esempio n. 39
0
        /// <summary>
        /// Tests whether the segment p0-p1 intersects the hot pixel tolerance square.
        /// Because the tolerance square point set is partially open (along the
        /// top and right) the test needs to be more sophisticated than
        /// simply checking for any intersection.  However, it
        /// can take advantage of the fact that because the hot pixel edges
        /// do not lie on the coordinate grid.  It is sufficient to check
        /// if there is at least one of:
        ///  - a proper intersection with the segment and any hot pixel edge.
        ///  - an intersection between the segment and both the left and bottom edges.
        ///  - an intersection between a segment endpoint and the hot pixel coordinate.
        /// </summary>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <returns></returns>
        private bool IntersectsToleranceSquare(ICoordinate p0, ICoordinate p1)
        {
            bool intersectsLeft = false;
            bool intersectsBottom = false;

            li.ComputeIntersection(p0, p1, corner[0], corner[1]);
            if(li.IsProper) return true;

            li.ComputeIntersection(p0, p1, corner[1], corner[2]);
            if(li.IsProper) return true;
            if(li.HasIntersection) intersectsLeft = true;

            li.ComputeIntersection(p0, p1, corner[2], corner[3]);
            if(li.IsProper) return true;
            if(li.HasIntersection) intersectsBottom = true;

            li.ComputeIntersection(p0, p1, corner[3], corner[0]);
            if(li.IsProper) return true;

            if(intersectsLeft && intersectsBottom) return true;

            if(p0.Equals(pt)) return true;
            if(p1.Equals(pt)) return true;

            return false;
        }
Esempio n. 40
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="p"></param>
 /// <param name="l"></param>
 /// <returns></returns>
 private Locations Locate(ICoordinate p, ILineString l)
 {
     ICoordinate[] pt = l.Coordinates;
     if(!l.IsClosed)
         if(p.Equals(pt[0]) || p.Equals(pt[pt.Length - 1]))
             return Locations.Boundary;                            
     if (CGAlgorithms.IsOnLine(p, pt))
         return Locations.Interior;
     return Locations.Exterior;
 }
Esempio n. 41
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="p0"></param>
 /// <param name="p1"></param>
 /// <returns></returns>
 private bool IsLineSegmentContainedInBoundary(ICoordinate p0, ICoordinate p1)
 {
     if (p0.Equals(p1))
         return IsPointContainedInBoundary(p0);
     // we already know that the segment is contained in the rectangle envelope
     if (p0.X == p1.X)
     {
         if (p0.X == rectEnv.MinX ||
             p0.X == rectEnv.MaxX)
                 return true;
     }
     else if (p0.Y == p1.Y)
     {
         if (p0.Y == rectEnv.MinY ||
             p0.Y == rectEnv.MaxY)
                 return true;
     }
     /*
      * Either both x and y values are different
      * or one of x and y are the same, but the other ordinate is not the same as a boundary ordinate
      * In either case, the segment is not wholely in the boundary
      */
     return false;
 }
Esempio n. 42
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        protected bool Equal(ICoordinate a, ICoordinate b, double tolerance)
        {
            if (tolerance == 0)
                return a.Equals(b);

            return a.Distance(b) <= tolerance;
        }
Esempio n. 43
0
 /// <summary>
 /// Tests whether a given point is in an array of points.
 /// Uses a value-based test.
 /// </summary>
 /// <param name="pt">A <c>Coordinate</c> for the test point.</param>
 /// <param name="pts">An array of <c>Coordinate</c>s to test,</param>
 /// <returns><c>true</c> if the point is in the array.</returns>
 public static bool IsInList(ICoordinate pt, ICoordinate[] pts)
 {
     for (int i = 0; i < pts.Length; i++)
         if (pt.Equals(pts[i]))
             return false;
     return true;
 }
Esempio n. 44
0
        /// <summary> 
        /// Compute the projection of a point onto the line determined
        /// by this line segment.
        /// Note that the projected point  may lie outside the line segment.  
        /// If this is the case,  the projection factor will lie outside the range [0.0, 1.0].
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public ICoordinate Project(ICoordinate p)
        {
            if (p.Equals(P0) || p.Equals(P1)) 
                return new Coordinate(p);

            var r = ProjectionFactor(p);
            ICoordinate coord = new Coordinate {X = P0.X + r*(P1.X - P0.X), Y = P0.Y + r*(P1.Y - P0.Y)};
            return coord;
        }
Esempio n. 45
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(ICoordinate p, ICoordinate A, ICoordinate 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)));
        }
Esempio n. 46
0
 /// <summary>
 /// Returns the edge whose first two coordinates are p0 and p1.
 /// </summary>
 /// <param name="p0"></param>
 /// <param name="p1"></param>
 /// <returns> The edge, if found <c>null</c> if the edge was not found.</returns>
 public Edge FindEdge(ICoordinate p0, ICoordinate p1)
 {
     for (int i = 0; i < edges.Count; i++) 
     {
         Edge e = (Edge) edges[i];
         ICoordinate[] eCoord = e.Coordinates;
         if (p0.Equals(eCoord[0]) && p1.Equals(eCoord[1]))
             return e;
     }
     return null;
 }
Esempio n. 47
0
        /// <summary>
        /// Compute the projection factor for the projection of the point p
        /// onto this <c>LineSegment</c>. The projection factor is the constant k
        /// by which the vector for this segment must be multiplied to
        /// equal the vector for the projection of p.
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public double ProjectionFactor(ICoordinate p)
        {
            if (p.Equals(P0)) return 0.0;
            if (p.Equals(P1)) return 1.0;

            // Otherwise, use comp.graphics.algorithms Frequently Asked Questions method
            /*     	          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 dx = P1.X - P0.X;
            double dy = P1.Y - P0.Y;
            double len2 = dx * dx + dy * dy;
            double r = ((p.X - P0.X) * dx + (p.Y - P0.Y) * dy) / len2;
            return r;
        }