/// <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)))); }
/// <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)); }
/// <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); }
/// <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); }
/// <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; } }
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); }
/// <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; } }
/** * @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); } }
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); }
/// <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); }
/// <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)); }
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); }
/// <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); }
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); }
/// <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))); }
/// <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; }
/// <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; }