Пример #1
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))));
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        private LinearLocation GetLocationForward(double length)
        {
            if (length <= 0.0)
            {
                return(new LinearLocation());
            }

            double totalLength = 0.0;

            foreach (LinearIterator.LinearElement element in new LinearIterator(linearGeom))
            {
                if (!element.IsEndOfLine)
                {
                    ICoordinate p0     = element.SegmentStart;
                    ICoordinate p1     = element.SegmentEnd;
                    double      segLen = p1.Distance(p0);
                    // length falls in this segment
                    if (totalLength + segLen > length)
                    {
                        double frac      = (length - totalLength) / segLen;
                        int    compIndex = element.ComponentIndex;
                        int    segIndex  = element.VertexIndex;
                        return(new LinearLocation(compIndex, segIndex, frac));
                    }
                    totalLength += segLen;
                }
            }
            // length is longer than line - return end location
            return(LinearLocation.GetEndLocation(linearGeom));
        }
Пример #3
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 ICoordinate[] ClosestPoints(LineSegment line)
        {
            // test for intersection
            ICoordinate intPt = Intersection(line);

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

            /*
             *  if no intersection closest pair contains at least one endpoint.
             * Test each endpoint in turn.
             */
            ICoordinate[] closestPt   = new ICoordinate[2];
            double        minDistance = Double.MaxValue;
            double        dist;

            ICoordinate close00 = ClosestPoint(line.P0);

            minDistance  = close00.Distance(line.P0);
            closestPt[0] = close00;
            closestPt[1] = line.P0;

            ICoordinate close01 = ClosestPoint(line.P1);

            dist = close01.Distance(line.P1);
            if (dist < minDistance)
            {
                minDistance = dist;

                closestPt[0] = close01;
                closestPt[1] = line.P1;
            }

            ICoordinate close10 = line.ClosestPoint(P0);

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

            ICoordinate close11 = line.ClosestPoint(P1);

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

            return(closestPt);
        }
Пример #4
0
 /// <summary>
 /// 比较。与原点的距离。
 /// </summary>
 /// <param name="obj"></param>
 /// <returns></returns>
 public int CompareTo(object obj)
 {
     if (obj is ICoordinate)
     {
         ICoordinate other = obj as ICoordinate;
         return((int)((Distance(Zero) - other.Distance(Zero)) * 1000000));
     }
     return(0);
 }
Пример #5
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="point"></param>
 private void Add(ICoordinate point)
 {
     double dist = point.Distance(centroid);
     if (dist < minDistance)
     {
         interiorPoint = new Coordinate(point);
         minDistance = dist;
     }
 }
Пример #6
0
        private void AppendCoordinate(ILineString lineString, ICoordinate worldPosition)
        {
            double worldDistance = MapControlHelper.ImageToWorld(Map, (int)ActualMinDistance);

            ICoordinate coordinate;

            if (TemporalEnd)
            {
                coordinate = lineString.Coordinates[lineString.Coordinates.Length - 2];
            }
            else
            {
                coordinate = lineString.Coordinates[lineString.Coordinates.Length - 1];
            }
            if (worldPosition.Distance(coordinate) > worldDistance)
            {
                // if distance is larger than marge add new coordinate at exact location. During drawing line
                // you do not want to snap. For example a line should be able to pass very near a node.

                // HACK: not nice to solve here. If autocurve do not add snapped point when dragging. If not auto
                // curve use the actualSnapping value (=Snap)
                ICoordinate SnapLocation = worldPosition;
                if (!AutoCurve)
                {
                    SnapLocation = Snap(worldPosition).Location;
                }
                if (TemporalEnd)
                {
                    GeometryHelper.SetCoordinate(lineString, lineString.Coordinates.Length - 1, SnapLocation);
                }
                else
                {
                    lineString = AppendCurvePoint(lineString, SnapLocation);
                }
                TemporalEnd = false;
            }
            else
            {
                ICoordinate SnapLocation = worldPosition;
                if (!SupportShorties)
                {
                    SnapLocation = Snap(worldPosition).Location;
                }
                if (TemporalEnd)
                {
                    GeometryHelper.SetCoordinate(lineString, lineString.Coordinates.Length - 1, SnapLocation);
                }
                else
                {
                    lineString = AppendCurvePoint(lineString, SnapLocation);
                }
                TemporalEnd = true;
            }
            newLineGeometry.Clear();
            newLineGeometry.Add(lineString);
        }
Пример #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="point"></param>
        private void Add(ICoordinate point)
        {
            double dist = point.Distance(centroid);

            if (dist < minDistance)
            {
                interiorPoint = new Coordinate(point);
                minDistance   = dist;
            }
        }
Пример #8
0
        /**
         * @param co
         *            input coordinate in the neighbourhood of the MLineString
         * @param tolerance
         *            max. distance that co may be from this MLineString
         * @return an MCoordinate on this MLineString with appropriate M-value
         */
        public MCoordinate GetClosestPoint(ICoordinate co, double tolerance)
        {
            if (!this.IsMonotone(false))
            {
                throw new ApplicationException("MGeometryException.OPERATION_REQUIRES_MONOTONE");
            }

            if (!this.IsEmpty)
            {
                LineSegment   seg  = new LineSegment();
                ICoordinate[] coAr = this.Coordinates;
                seg.P0 = coAr[0];
                double      d        = 0.0;
                double      projfact = 0.0;
                double      minDist  = Double.PositiveInfinity;
                MCoordinate mincp    = null;
                for (int i = 1; i < coAr.Length; i++)
                {
                    seg.P1 = coAr[i];
                    ICoordinate cp = seg.ClosestPoint(co);
                    d = cp.Distance(co);
                    if (d <= tolerance && d <= minDist)
                    {
                        MCoordinate testcp = new MCoordinate(cp);
                        projfact = seg.ProjectionFactor(cp);
                        testcp.M = ((MCoordinate)coAr[i - 1]).M
                                   + projfact
                                   * (((MCoordinate)coAr[i]).M - ((MCoordinate)coAr[i - 1]).M);
                        if (d < minDist || testcp.M < mincp.M)
                        {
                            mincp   = testcp;
                            minDist = d;
                        }
                    }
                    seg.P0 = seg.P1;
                }
                if (minDist > tolerance)
                {
                    return(null);
                }
                else
                {
                    return(mincp);
                }
            }
            else
            {
                return(null);
            }
        }
Пример #9
0
        public static double TotalDistance(this IEnumerable <ICoordinate> source)
        {
            double      distance = 0.0;
            ICoordinate last     = null;

            foreach (var i in source)
            {
                if (last != null)
                {
                    distance += last.Distance(i);
                }
                last = i;
            }

            return(distance);
        }
Пример #10
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="pt"></param>
 /// <param name="snapPts"></param>
 /// <returns></returns>
 private ICoordinate FindSnapForVertex(ICoordinate pt, ICoordinate[] snapPts)
 {
     foreach (ICoordinate 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);
 }
Пример #11
0
        /// <summary>
        /// Gets the length of the segment in the given
        /// Geometry containing this location.
        /// </summary>
        /// <param name="linearGeom">A linear geometry.</param>
        /// <returns>The length of the segment.</returns>
        public double GetSegmentLength(IGeometry linearGeom)
        {
            ILineString lineComp = (ILineString)linearGeom.GetGeometryN(componentIndex);

            // ensure segment index is valid
            int segIndex = segmentIndex;

            if (segmentIndex >= lineComp.NumPoints - 1)
            {
                segIndex = lineComp.NumPoints - 2;
            }

            ICoordinate p0 = lineComp.GetCoordinateN(segIndex);
            ICoordinate p1 = lineComp.GetCoordinateN(segIndex + 1);

            return(p0.Distance(p1));
        }
Пример #12
0
        private INetworkLocation GetNearestNetworkLocation(ICoordinate coordinate)
        {
            //TODO: speed up. this sucks when we have 100000 locations (write performance test!).
            //TODO add a maximal distance otherwise return null
            double           minDistance = double.MaxValue;
            INetworkLocation minLocation = null;

            foreach (INetworkLocation location in Locations.Values)
            {
                double distance = coordinate.Distance(location.Geometry.Coordinate);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    minLocation = location;
                }
            }
            return(minLocation);
        }
Пример #13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="loc"></param>
        /// <returns></returns>
        public double GetLength(LinearLocation loc)
        {
            double totalLength = 0.0;

            foreach (LinearIterator.LinearElement element in new LinearIterator(linearGeom))
            {
                if (!element.IsEndOfLine)
                {
                    ICoordinate p0     = element.SegmentStart;
                    ICoordinate p1     = element.SegmentEnd;
                    double      segLen = p1.Distance(p0);
                    // length falls in this segment
                    if (loc.ComponentIndex == element.ComponentIndex && loc.SegmentIndex == element.VertexIndex)
                    {
                        return(totalLength + segLen * loc.SegmentFraction);
                    }
                    totalLength += segLen;
                }
            }
            return(totalLength);
        }
Пример #14
0
        private void AppendCoordinate(ILineString lineString, ICoordinate worldPosition)
        {
            double worldDistance = MapControlHelper.ImageToWorld(Map, (int)ActualMinDistance);

            ICoordinate coordinate;
            if (TemporalEnd)
                coordinate = lineString.Coordinates[lineString.Coordinates.Length - 2];
            else
                coordinate = lineString.Coordinates[lineString.Coordinates.Length - 1];
            if (worldPosition.Distance(coordinate) > worldDistance)
            {
                // if distance is larger than marge add new coordinate at exact location. During drawing line
                // you do not want to snap. For example a line should be able to pass very near a node.

                // HACK: not nice to solve here. If autocurve do not add snapped point when dragging. If not auto
                // curve use the actualSnapping value (=Snap)
                ICoordinate SnapLocation = worldPosition;
                if (!AutoCurve)
                    SnapLocation = Snap(worldPosition).Location;
                if (TemporalEnd)
                    GeometryHelper.SetCoordinate(lineString, lineString.Coordinates.Length - 1, SnapLocation);
                else
                    lineString = AppendCurvePoint(lineString, SnapLocation);
                TemporalEnd = false;
            }
            else
            {
                ICoordinate SnapLocation = worldPosition;
                if (!SupportShorties)
                    SnapLocation = Snap(worldPosition).Location;
                if (TemporalEnd)
                    GeometryHelper.SetCoordinate(lineString, lineString.Coordinates.Length - 1, SnapLocation);
                else
                    lineString = AppendCurvePoint(lineString, SnapLocation);
                TemporalEnd = true;
            }
            newLineGeometry.Clear();
            newLineGeometry.Add(lineString);
        }
Пример #15
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)));
        }
Пример #16
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="pt"></param>
 /// <param name="snapPts"></param>
 /// <returns></returns>
 private ICoordinate FindSnapForVertex(ICoordinate pt, ICoordinate[] snapPts)
 {
     foreach (ICoordinate 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;
 }
Пример #17
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;
        }