예제 #1
0
 public void Equals()
 {
     var c1 = new Coordinate<int>(13, 14);
       var c2 = new Coordinate<int>(c1);
       var c3 = new Coordinate<int>(23, 24);
       Assert.IsTrue(c1.Equals(c2));
       Assert.IsFalse(c1.Equals(c3));
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        public override void ComputeIntersection(Coordinate p, Coordinate p1, Coordinate 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 = NoIntersection;
                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 = NoIntersection;
                return;
            }

            IsProper = true;
            if (p.Equals(p1) || p.Equals(p2))             
                IsProper = false;
            
            Result = PointIntersection;
        }
예제 #3
0
        public void DifferentTypes()
        {
            var c1 = new Coordinate<int>(13, 14);
              var c2 = new Coordinate<double>(13, 14);

              Assert.IsFalse(c1.Equals(c2));
        }
        /// <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(Coordinate p, Coordinate p0, Coordinate p1)
        {
            var dx = Math.Abs(p1.X - p0.X);
            var dy = Math.Abs(p1.Y - p0.Y);

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

                // <FIX>: hack to ensure that non-endpoints always have a non-zero distance
                if (dist == 0.0 && ! p.Equals2D(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(Coordinate p, Coordinate p1, Coordinate 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 = IntersectionTypes.PointIntersection;
             return;
         }
     }
     Result = IntersectionTypes.NoIntersection;
 }
 /// <summary>
 /// Automatically closes the ring (if it not alread is).
 /// </summary>
 public void CloseRing()
 {
     if (_ptList.Count < 1) return;
     var startPt = new Coordinate(_ptList[0]);
     var lastPt = _ptList[_ptList.Count - 1];
     /*Coordinate last2Pt = null;
       if (ptList.Count >= 2)
           last2Pt = (Coordinate)ptList[ptList.Count - 2];*/
     if (startPt.Equals(lastPt)) return;
     _ptList.Add(startPt);
 }
예제 #7
0
        public void TestEquals()
        {
            Coordinate c1 = new Coordinate(1, 2, 3);
            const string s = "Not a coordinate";
            Assert.IsFalse(c1.Equals(s));

            Coordinate c2 = new Coordinate(1, 2, 3);
            Assert.IsTrue(c1.Equals2D(c2));

            Coordinate c3 = new Coordinate(1, 22, 3);
            Assert.IsFalse(c1.Equals2D(c3));
        }
예제 #8
0
        public void DiffCoordinateNotEquals()
        {
            //arrange
            Coordinate first = new Coordinate(1, 1);
            Coordinate second = new Coordinate(2, 2);
            bool expected = false;

            //act
            bool actual = first.Equals(second);

            //assert
            Assert.AreEqual(expected, actual);
        }
 /// <summary>
 /// This function is non-robust, since it may compute the square of large numbers.
 /// Currently not sure how to improve this.
 /// </summary>
 public static double NonRobustComputeEdgeDistance(Coordinate p, Coordinate p1, Coordinate 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;
 }
예제 #10
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(Coordinate p0, Coordinate 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;
        }
 private void doTestCoordinateHash(bool equal, Coordinate a, Coordinate b) {
     Assert.AreEqual(equal, a.Equals(b));
     Assert.AreEqual(equal, a.GetHashCode() == b.GetHashCode());
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <param name="p4"></param>
        /// <returns></returns>
        public override IntersectionTypes ComputeIntersect(Coordinate p1, Coordinate p2, Coordinate p3, Coordinate p4) 
        {
            /*
            *  Coefficients of line eqns.
            */

            /*
            *  'Sign' values
            */
            
            IsProper = false;

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

            /*
            *  Compute r3 and r4.
            */
            double r3 = a1 * p3.X + b1 * p3.Y + c1;
            double r4 = a1 * p4.X + b1 * p4.Y + c1;

            /*
            *  Check signs of r3 and r4.  If both point 3 and point 4 lie on
            *  same side of line 1, the line segments do not intersect.
            */
            if (r3 != 0 && r4 != 0 && IsSameSignAndNonZero(r3, r4))
            {
                return IntersectionTypes.NoIntersection;
            }

            /*
            *  Compute a2, b2, c2
            */
            double a2 = p4.Y - p3.Y;
            double b2 = p3.X - p4.X;
            double c2 = p4.X * p3.Y - p3.X * p4.Y;

            /*
            *  Compute r1 and r2
            */
            double r1 = a2 * p1.X + b2 * p1.Y + c2;
            double r2 = a2 * p2.X + b2 * p2.Y + c2;

            /*
            *  Check signs of r1 and r2.  If both point 1 and point 2 lie
            *  on same side of second line segment, the line segments do
            *  not intersect.
            */
            if (r1 != 0 && r2 != 0 && IsSameSignAndNonZero(r1, r2))
            {
                return IntersectionTypes.NoIntersection;
            }

            /*
            *  Line segments intersect: compute intersection point.
            */
            double denom = a1 * b2 - a2 * b1;
            if (denom == 0) 
                return ComputeCollinearIntersection(p1, p2, p3, p4);
            
            double numX = b1 * c2 - b2 * c1;
            double x = numX / denom;

            double numY = a2 * c1 - a1 * c2;
            double y = numY / denom;

            PointA = new Coordinate(x, y);

            // check if this is a proper intersection BEFORE truncating values,
            // to avoid spurious equality comparisons with endpoints
            IsProper = true;
            if (PointA.Equals(p1) || PointA.Equals(p2) || PointA.Equals(p3) || PointA.Equals(p4))             
                IsProper = false;            

            // truncate computed point to precision grid            
            if (PrecisionModel != null)
                PrecisionModel.MakePrecise(PointA);
            
            return IntersectionTypes.PointIntersection;
        }
예제 #13
0
        /// <summary>Computes the Projection Factor for the projection of the point p
        /// onto this LineSegment.  The Projection Factor is the constant r
        /// by which the vector for this segment must be multiplied to
        /// equal the vector for the projection of <tt>p</tt> on the line
        /// defined by this segment.
        /// <para/>
        /// The projection factor will lie in the range <tt>(-inf, +inf)</tt>,
        /// or be <c>NaN</c> if the line segment has zero length.
        /// </summary>
        /// <param name="p">The point to compute the factor for</param>
        /// <returns>The projection factor for the point</returns>
        public double ProjectionFactor(Coordinate 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
            */
            var dx = _p1.X - _p0.X;
            var dy = _p1.Y - _p0.Y;
            var len = dx * dx + dy * dy;

            // handle zero-length segments
            if (len <= 0.0) return Double.NaN;

            double r = ((p.X - _p0.X) * dx + (p.Y - _p0.Y) * dy)
                      / len;
            return r;
        }
예제 #14
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 virtual double ProjectionFactor(Coordinate 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;
        }
예제 #15
0
 public static bool IsInList(Coordinate pt, Coordinate[] pts)
 {
     foreach (Coordinate p in pts)
         if (pt.Equals(p))
             return true;
     return true;
 }
예제 #16
0
 private static void CheckCollapse(Coordinate p0, Coordinate p1, Coordinate p2)
 {
     if (p0.Equals(p2))
         throw new ApplicationException(String.Format(
             "found non-noded collapse at: {0}, {1} {2}", p0, p1, p2));
 }
예제 #17
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="p0"></param>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 private static void CheckCollapse(Coordinate p0, Coordinate p1, Coordinate p2)
 {
     if (p0.Equals(p2))
         throw new Exception("found non-noded collapse at: " + p0 + ", " + p1 + " " + p2);
 }
예제 #18
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(Coordinate A, Coordinate B, Coordinate C, Coordinate 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
        }
예제 #19
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)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="q1"></param>
        /// <param name="q2"></param>
        /// <returns></returns>
        private IntersectionTypes ComputeCollinearIntersection(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate 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) 
            {
                IntersectionPoints[0] = q1;
                IntersectionPoints[1] = q2;
                return IntersectionTypes.Collinear;
            }
            if(q1p1q2 && q1p2q2) 
            {
                IntersectionPoints[0] = p1;
                IntersectionPoints[1] = p2;
                return IntersectionTypes.Collinear;
            }
            if(p1q1p2 && q1p1q2)
            {
                IntersectionPoints[0] = q1;
                IntersectionPoints[1] = p1;
                return q1.Equals(p1) && !p1q2p2 && !q1p2q2 ? IntersectionTypes.PointIntersection : IntersectionTypes.Collinear;
            }
            if(p1q1p2 && q1p2q2) 
            {
                IntersectionPoints[0] = q1;
                IntersectionPoints[1] = p2;
                return q1.Equals(p2) && !p1q2p2 && !q1p1q2 ? IntersectionTypes.PointIntersection : IntersectionTypes.Collinear;
            }
            if(p1q2p2 && q1p1q2) 
            {
                IntersectionPoints[0] = q2;
                IntersectionPoints[1] = p1;
                return q2.Equals(p1) && !p1q1p2 && !q1p2q2 ? IntersectionTypes.PointIntersection : IntersectionTypes.Collinear;
            }
            if(p1q2p2 && q1p2q2) 
            {
                IntersectionPoints[0] = q2;
                IntersectionPoints[1] = p2;
                return q2.Equals(p2) && !p1q1p2 && !q1p1q2 ? IntersectionTypes.PointIntersection : IntersectionTypes.Collinear;
            }
            return IntersectionTypes.NoIntersection;
        }
예제 #21
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="pt"></param>
 private void AddPt(Coordinate pt)
 {
     Coordinate bufPt = new Coordinate(pt);
     _precisionModel.MakePrecise(bufPt);
     // don't add duplicate points
     Coordinate lastPt = null;
     if (_ptList.Count >= 1)
         lastPt = _ptList.Last();
     if (lastPt != null && bufPt.Equals(lastPt)) return;
     _ptList.Add(bufPt);
 }
예제 #22
0
 /// <summary>
 ///
 /// </summary>
 private void ClosePts()
 {
     if (_ptList.Count < 1) return;
     Coordinate startPt = new Coordinate(_ptList[0]);
     Coordinate lastPt = _ptList[_ptList.Count - 1];
     if (startPt.Equals(lastPt)) return;
     _ptList.Add(startPt);
 }
예제 #23
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;
        }
예제 #24
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        /// <param name="l"></param>
        /// <returns></returns>
        private static Location Locate(Coordinate p, ILineString l)
        {
            // bounding-box check
            if (!l.EnvelopeInternal.Intersects(p)) 
                return Location.Exterior;
  	

            Coordinate[] pt = l.Coordinates;
            if(!l.IsClosed)
                if(p.Equals(pt[0]) || p.Equals(pt[pt.Length - 1]))
                    return Location.Boundary;                            
            if (CGAlgorithms.IsOnLine(p, pt))
                return Location.Interior;
            return Location.Exterior;
        }
예제 #25
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(Coordinate A, Coordinate B, Coordinate C, Coordinate 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 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.
	         */
            var noIntersection = false;
            if (!Envelope.Intersects(A, B, C, D))
            {
                noIntersection = true;
            }
            else
            {
                var denom = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X);

                if (denom == 0)
                {
                    noIntersection = true;
                }
                else
                {
                    var r_num = (A.Y - C.Y) * (D.X - C.X) - (A.X - C.X) * (D.Y - C.Y);
                    var s_num = (A.Y - C.Y) * (B.X - A.X) - (A.X - C.X) * (B.Y - A.Y);

                    var s = s_num / denom;
                    var r = r_num / denom;

                    if ((r < 0) || (r > 1) || (s < 0) || (s > 1))
                    {
                        noIntersection = true;
                    }
                }
            }
            if (noIntersection)
            {
                return MathUtil.Min(
                      DistancePointLine(A, C, D),
                      DistancePointLine(B, C, D),
                      DistancePointLine(C, A, B),
                      DistancePointLine(D, A, B));
            }
            // segments intersect
            return 0.0;
        }
예제 #26
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 the hot pixel edges
        /// do not lie on the coordinate grid. 
        /// It is sufficient to check if any of the following occur:
        ///  - a proper intersection between the segment and any hot pixel edge.
        ///  - an intersection between the segment and BOTH the left and bottom hot pixel edges
        /// (which detects the case where the segment intersects the bottom left hot pixel corner).
        ///  - 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(Coordinate p0, Coordinate p1)
        {
            var intersectsLeft = false;
            var intersectsBottom = false;
            //Console.WriteLine("Hot Pixel: " + WKTWriter.ToLineString(corner));
            //Console.WriteLine("Line: " + WKTWriter.ToLineString(p0, p1));

            _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;
        }
예제 #27
0
        /// <summary>
        /// Compute the projection of a point onto the line determined
        /// by this line segment.
        /// Notice 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 virtual Coordinate Project(Coordinate p)
        {
            if (p.Equals(P0) || p.Equals(P1))
                return new Coordinate(p);

            double r = ProjectionFactor(p);
            Coordinate coord = new Coordinate();
            coord.X = P0.X + r * (P1.X - P0.X);
            coord.Y = P0.Y + r * (P1.Y - P0.Y);
            return coord;
        }
        private void Move(Coordinate currentCoordinate, Coordinate target, int step)
        {
            //reached target
            if (currentCoordinate.Equals(target))
            {
                //_pathFound = true;
                return;
            }

            //try up
            if(IsCellInsideLabyrinth(currentCoordinate.X, currentCoordinate.Y - 1) && CanMoveTo(currentCoordinate, MoveDirection.Up) && !HasBeenThere(new Coordinate(currentCoordinate.X, currentCoordinate.Y - 1)))
            {
                _tempLabirynth[currentCoordinate.X, currentCoordinate.Y - 1] = step;
                //Move(new Coordinate(currentCoordinate.X, currentCoordinate.Y - 1), target, step + 1);
            }

            //try down
            if (IsCellInsideLabyrinth(currentCoordinate.X, currentCoordinate.Y + 1) && CanMoveTo(currentCoordinate, MoveDirection.Down) && !HasBeenThere(new Coordinate(currentCoordinate.X, currentCoordinate.Y + 1)))
            {
                _tempLabirynth[currentCoordinate.X, currentCoordinate.Y + 1] = step;
                //Move(new Coordinate(currentCoordinate.X, currentCoordinate.Y + 1), target, step + 1);
            }

            //try left
            if(IsCellInsideLabyrinth(currentCoordinate.X - 1, currentCoordinate.Y) && CanMoveTo(currentCoordinate, MoveDirection.Left) && !HasBeenThere(new Coordinate(currentCoordinate.X - 1, currentCoordinate.Y)))
            {
                _tempLabirynth[currentCoordinate.X - 1, currentCoordinate.Y] = step;
                //Move(new Coordinate(currentCoordinate.X - 1, currentCoordinate.Y), target, step + 1);
            }

            //try right
            if (IsCellInsideLabyrinth(currentCoordinate.X + 1, currentCoordinate.Y) && CanMoveTo(currentCoordinate, MoveDirection.Right) && !HasBeenThere(new Coordinate(currentCoordinate.X + 1, currentCoordinate.Y)))
            {
                _tempLabirynth[currentCoordinate.X + 1, currentCoordinate.Y] = step;
                //Move(new Coordinate(currentCoordinate.X + 1, currentCoordinate.Y), target, step + 1);
            }
        }
예제 #29
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 Coordinate Project(Coordinate p)
        {
            if (p.Equals(_p0) || p.Equals(_p1))
                return new Coordinate(p);

            var r = ProjectionFactor(p);
            var coord = new Coordinate { X = _p0.X + r * (_p1.X - _p0.X), Y = _p0.Y + r * (_p1.Y - _p0.Y) };
            return coord;
        }
예제 #30
0
        public void SameCoordinateEquals()
        {
            //arrange
            Coordinate first = new Coordinate(1, 1);
            Coordinate second = new Coordinate(1, 1);
            bool expected = true;

            //act
            bool actual = first.Equals(second);

            //assert
            Assert.AreEqual(expected, actual);
        }