/// <summary> /// Computes the closest points on a line segment. /// </summary> /// <param name="line"></param> /// <returns> /// A pair of Coordinates which are the closest points on the line segments. /// </returns> public virtual ICoordinate[] ClosestPoints(ILineSegmentBase line) { LineSegment myLine = new LineSegment(line); // test for intersection Coordinate intPt = new Coordinate(Intersection(line)); if (intPt != null) { return new Coordinate[] { intPt, intPt } } ; /* * if no intersection closest pair contains at least one endpoint. * Test each endpoint in turn. */ Coordinate[] closestPt = new Coordinate[2]; double minDistance = Double.MaxValue; double dist; Coordinate close00 = new Coordinate(ClosestPoint(line.P0)); minDistance = close00.Distance(line.P0); closestPt[0] = close00; closestPt[1] = new Coordinate(line.P0); Coordinate close01 = new Coordinate(ClosestPoint(line.P1)); dist = close01.Distance(line.P1); if (dist < minDistance) { minDistance = dist; closestPt[0] = close01; closestPt[1] = new Coordinate(line.P1); } Coordinate close10 = new Coordinate(myLine.ClosestPoint(P0)); dist = close10.Distance(P0); if (dist < minDistance) { minDistance = dist; closestPt[0] = new Coordinate(P0); closestPt[1] = close10; } Coordinate close11 = new Coordinate(myLine.ClosestPoint(P1)); dist = close11.Distance(P1); if (dist < minDistance) { minDistance = dist; closestPt[0] = new Coordinate(P1); closestPt[1] = close11; } return(closestPt); }
/// <summary> /// /// </summary> /// <param name="p"></param> /// <param name="seg"></param> private void TestLineSegment(Coordinate p, ILineSegmentBase seg) { /* * Test if segment crosses ray from test point in positive x direction. */ Coordinate p1 = seg.P0; Coordinate p2 = seg.P1; double x1 = p1.X - p.X; double y1 = p1.Y - p.Y; double x2 = p2.X - p.X; double y2 = p2.Y - p.Y; if (((y1 > 0) && (y2 <= 0)) || ((y2 > 0) && (y1 <= 0))) { /* * segment straddles x axis, so compute intersection. */ double xInt = RobustDeterminant.SignOfDet2X2(x1, y1, x2, y2) / (y2 - y1); // x intersection of segment with ray /* * crosses ray if strictly positive intersection. */ if (0.0 < xInt) { _crossings++; } } }
/// <summary> /// Computes an intersection point between two segments, if there is one. /// There may be 0, 1 or many intersection points between two segments. /// If there are 0, null is returned. If there is 1 or more, a single one /// is returned (chosen at the discretion of the algorithm). If /// more information is required about the details of the intersection, /// the {RobustLineIntersector} class should be used. /// </summary> /// <param name="line"></param> /// <returns> An intersection point, or <c>null</c> if there is none.</returns> public virtual Coordinate Intersection(ILineSegmentBase line) { LineIntersector li = new RobustLineIntersector(); li.ComputeIntersection(P0, P1, new Coordinate(line.P0), new Coordinate(line.P1)); if (li.HasIntersection) { return(li.GetIntersection(0)); } return(null); }
/// <summary> /// Compares this object with the specified object for order. /// Uses the standard lexicographic ordering for the points in the LineSegment. /// </summary> /// <param name="o"> /// The <c>LineSegment</c> with which this <c>LineSegment</c> /// is being compared. /// </param> /// <returns> /// A negative integer, zero, or a positive integer as this <c>LineSegment</c> /// is less than, equal to, or greater than the specified <c>LineSegment</c>. /// </returns> public virtual int CompareTo(object o) { ILineSegmentBase other = (ILineSegmentBase)o; int comp0 = new Coordinate(_p0).CompareTo(other.P0); if (comp0 != 0) { return(comp0); } return(new Coordinate(_p1).CompareTo(other.P1)); }
/// <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 ILineSegmentBase)) { return(false); } ILineSegmentBase other = (ILineSegmentBase)o; return(_p0.X == other.P0.X && _p0.Y == other.P0.Y && _p1.X == other.P1.X && _p1.Y == other.P1.Y); }
/// <summary> /// Compute an offset segment for an input segment on a given side and at a given distance. /// The offset points are computed in full double precision, for accuracy. /// </summary> /// <param name="seg">The segment to offset.</param> /// <param name="side">The side of the segment the offset lies on.</param> /// <param name="distance">The offset distance.</param> /// <param name="offset">The points computed for the offset segment.</param> private static void ComputeOffsetSegment(ILineSegmentBase seg, PositionType side, double distance, ILineSegmentBase offset) { int sideSign = side == PositionType.Left ? 1 : -1; double dx = seg.P1.X - seg.P0.X; double dy = seg.P1.Y - seg.P0.Y; double len = Math.Sqrt(dx * dx + dy * dy); // u is the vector that is the length of the offset, in the direction of the segment double ux = sideSign * distance * dx / len; double uy = sideSign * distance * dy / len; offset.P0.X = seg.P0.X - uy; offset.P0.Y = seg.P0.Y + ux; offset.P1.X = seg.P1.X - uy; offset.P1.Y = seg.P1.Y + ux; }
/// <summary> /// Determines the orientation of a LineSegment relative to this segment. /// The concept of orientation is specified as follows: /// Given two line segments A and L, /// A is to the left of a segment L if A lies wholly in the /// closed half-plane lying to the left of L /// A is to the right of a segment L if A lies wholly in the /// closed half-plane lying to the right of L /// otherwise, A has indeterminate orientation relative to L. This /// happens if A is collinear with L or if A crosses the line determined by L. /// </summary> /// <param name="seg">The <c>LineSegment</c> to compare.</param> /// <returns> /// 1 if <c>seg</c> is to the left of this segment, /// -1 if <c>seg</c> is to the right of this segment, /// 0 if <c>seg</c> has indeterminate orientation relative to this segment. /// </returns> public virtual int OrientationIndex(ILineSegmentBase seg) { int orient0 = CgAlgorithms.OrientationIndex(P0, P1, seg.P0); int orient1 = CgAlgorithms.OrientationIndex(P0, P1, seg.P1); // this handles the case where the points are Curve or collinear if (orient0 >= 0 && orient1 >= 0) { return(Math.Max(orient0, orient1)); } // this handles the case where the points are R or collinear if (orient0 <= 0 && orient1 <= 0) { return(Math.Max(orient0, orient1)); } // points lie on opposite sides ==> indeterminate orientation return(0); }
/// <summary> /// Project a line segment onto this line segment and return the resulting /// line segment. The returned line segment will be a subset of /// the target line line segment. This subset may be null, if /// the segments are oriented in such a way that there is no projection. /// Notice that the returned line may have zero length (i.e. the same endpoints). /// This can happen for instance if the lines are perpendicular to one another. /// </summary> /// <param name="seg">The line segment to project.</param> /// <returns>The projected line segment, or <c>null</c> if there is no overlap.</returns> public virtual ILineSegment Project(ILineSegmentBase seg) { double pf0 = ProjectionFactor(seg.P0); double pf1 = ProjectionFactor(seg.P1); // check if segment projects at all if (pf0 >= 1.0 && pf1 >= 1.0) { return(null); } if (pf0 <= 0.0 && pf1 <= 0.0) { return(null); } Coordinate newp0 = Project(seg.P0); if (pf0 < 0.0) { newp0 = P0; } if (pf0 > 1.0) { newp0 = P1; } Coordinate newp1 = Project(seg.P1); if (pf1 < 0.0) { newp1 = P0; } if (pf1 > 1.0) { newp1 = P1; } return(new LineSegment(newp0, newp1)); }
/// <summary> /// Computes the distance between this line segment and another one. /// </summary> /// <param name="ls"></param> /// <returns></returns> public virtual double Distance(ILineSegmentBase ls) { return CgAlgorithms.DistanceLineLine(P0, P1, new Coordinate(ls.P0), new Coordinate(ls.P1)); }
/// <summary> /// Defines a new LineSegment based on the previous line segment /// </summary> /// <param name="ls">The ILineSegmentBase</param> public virtual void SetCoordinates(ILineSegmentBase ls) { SetCoordinates(ls.P0, ls.P1); }
/// <summary> /// Determines the orientation of a LineSegment relative to this segment. /// The concept of orientation is specified as follows: /// Given two line segments A and L, /// A is to the left of a segment L if A lies wholly in the /// closed half-plane lying to the left of L /// A is to the right of a segment L if A lies wholly in the /// closed half-plane lying to the right of L /// otherwise, A has indeterminate orientation relative to L. This /// happens if A is collinear with L or if A crosses the line determined by L. /// </summary> /// <param name="seg">The <c>LineSegment</c> to compare.</param> /// <returns> /// 1 if <c>seg</c> is to the left of this segment, /// -1 if <c>seg</c> is to the right of this segment, /// 0 if <c>seg</c> has indeterminate orientation relative to this segment. /// </returns> public virtual int OrientationIndex(ILineSegmentBase seg) { int orient0 = CgAlgorithms.OrientationIndex(P0, P1, seg.P0); int orient1 = CgAlgorithms.OrientationIndex(P0, P1, seg.P1); // this handles the case where the points are Curve or collinear if (orient0 >= 0 && orient1 >= 0) return Math.Max(orient0, orient1); // this handles the case where the points are R or collinear if (orient0 <= 0 && orient1 <= 0) return Math.Max(orient0, orient1); // points lie on opposite sides ==> indeterminate orientation return 0; }
/// <summary> /// Compare two collinear segments for left-most ordering. /// If segs are vertical, use vertical ordering for comparison. /// If segs are equal, return 0. /// Segments are assumed to be directed so that the second coordinate is >= to the first /// (e.g. up and to the right). /// </summary> /// <param name="seg0">The left hand side segment to compare.</param> /// <param name="seg1">The riht hand side segment to compare.</param> /// <returns>An integer, -1 if seg0 is less, 0 if they are the same, and 1 if seg0 is greater.</returns> private static int CompareX(ILineSegmentBase seg0, ILineSegmentBase seg1) { int compare0 = seg0.P0.CompareTo(seg1.P0); return(compare0 != 0 ? compare0 : seg0.P1.CompareTo(seg1.P1)); }
/// <summary> /// Creates a new instance of a LineSegment which implements /// ILineSegment and ILineSegmentBase from an ILineSegmentBase /// </summary> /// <param name="ls"></param> public LineSegment(ILineSegmentBase ls) : this(ls.P0, ls.P1) { }
/// <summary> /// Computes an intersection point between two segments, if there is one. /// There may be 0, 1 or many intersection points between two segments. /// If there are 0, null is returned. If there is 1 or more, a single one /// is returned (chosen at the discretion of the algorithm). If /// more information is required about the details of the intersection, /// the {RobustLineIntersector} class should be used. /// </summary> /// <param name="line"></param> /// <returns> An intersection point, or <c>null</c> if there is none.</returns> public virtual Coordinate Intersection(ILineSegmentBase line) { LineIntersector li = new RobustLineIntersector(); li.ComputeIntersection(P0, P1, new Coordinate(line.P0), new Coordinate(line.P1)); if (li.HasIntersection) return li.GetIntersection(0); return null; }
/// <summary> /// Creates a new vector from a line segment, assuming that the direction is from the start point to the end point /// </summary> /// <param name="inLineSegment">A Topology.LineSegment object to turn into a vector</param> public Vector(ILineSegmentBase inLineSegment) { X = inLineSegment.P1.X - inLineSegment.P0.X; Y = inLineSegment.P1.Y - inLineSegment.P0.Y; Z = inLineSegment.P1.Z - inLineSegment.P0.Z; }
/// <summary> /// Computes the distance between this line segment and another one. /// </summary> /// <param name="ls"></param> /// <returns></returns> public virtual double Distance(ILineSegmentBase ls) { return(CgAlgorithms.DistanceLineLine(P0, P1, new Coordinate(ls.P0), new Coordinate(ls.P1))); }
/// <summary> /// Compare two collinear segments for left-most ordering. /// If segs are vertical, use vertical ordering for comparison. /// If segs are equal, return 0. /// Segments are assumed to be directed so that the second coordinate is >= to the first /// (e.g. up and to the right). /// </summary> /// <param name="seg0">The left hand side segment to compare.</param> /// <param name="seg1">The riht hand side segment to compare.</param> /// <returns>An integer, -1 if seg0 is less, 0 if they are the same, and 1 if seg0 is greater.</returns> private static int CompareX(ILineSegmentBase seg0, ILineSegmentBase seg1) { int compare0 = seg0.P0.CompareTo(seg1.P0); return compare0 != 0 ? compare0 : seg0.P1.CompareTo(seg1.P1); }
/// <summary> /// /// </summary> /// <param name="seg"></param> /// <param name="depth"></param> public DepthSegment(ILineSegmentBase seg, int depth) { // input seg is assumed to be normalized _upwardSeg = new LineSegment(seg); _leftDepth = depth; }
/// <summary> /// Project a line segment onto this line segment and return the resulting /// line segment. The returned line segment will be a subset of /// the target line line segment. This subset may be null, if /// the segments are oriented in such a way that there is no projection. /// Notice that the returned line may have zero length (i.e. the same endpoints). /// This can happen for instance if the lines are perpendicular to one another. /// </summary> /// <param name="seg">The line segment to project.</param> /// <returns>The projected line segment, or <c>null</c> if there is no overlap.</returns> public virtual ILineSegment Project(ILineSegmentBase seg) { double pf0 = ProjectionFactor(seg.P0); double pf1 = ProjectionFactor(seg.P1); // check if segment projects at all if (pf0 >= 1.0 && pf1 >= 1.0) return null; if (pf0 <= 0.0 && pf1 <= 0.0) return null; Coordinate newp0 = Project(seg.P0); if (pf0 < 0.0) newp0 = P0; if (pf0 > 1.0) newp0 = P1; Coordinate newp1 = Project(seg.P1); if (pf1 < 0.0) newp1 = P0; if (pf1 > 1.0) newp1 = P1; return new LineSegment(newp0, newp1); }
public RoadSegment(ILineSegmentBase ls, long id) : base(ls) { m_ParentRoadID = id; }
/// <summary> /// Computes the closest points on a line segment. /// </summary> /// <param name="line"></param> /// <returns> /// A pair of Coordinates which are the closest points on the line segments. /// </returns> public virtual Coordinate[] ClosestPoints(ILineSegmentBase line) { LineSegment myLine = new LineSegment(line); // test for intersection Coordinate intPt = Intersection(line); if (intPt != null) return new[] { intPt, intPt }; /* * if no intersection closest pair contains at least one endpoint. * Test each endpoint in turn. */ Coordinate[] closestPt = new Coordinate[2]; Coordinate close00 = new Coordinate(ClosestPoint(line.P0)); double minDistance = close00.Distance(line.P0); closestPt[0] = close00; closestPt[1] = new Coordinate(line.P0); Coordinate close01 = new Coordinate(ClosestPoint(line.P1)); double dist = close01.Distance(line.P1); if (dist < minDistance) { minDistance = dist; closestPt[0] = close01; closestPt[1] = new Coordinate(line.P1); } Coordinate close10 = new Coordinate(myLine.ClosestPoint(P0)); dist = close10.Distance(P0); if (dist < minDistance) { minDistance = dist; closestPt[0] = new Coordinate(P0); closestPt[1] = close10; } Coordinate close11 = new Coordinate(myLine.ClosestPoint(P1)); dist = close11.Distance(P1); if (dist < minDistance) { closestPt[0] = new Coordinate(P1); closestPt[1] = close11; } return closestPt; }
/// <summary> /// Returns <c>true</c> if <c>other</c> is /// topologically equal to this LineSegment (e.g. irrespective /// of orientation). /// </summary> /// <param name="other"> /// A <c>LineSegment</c> with which to do the comparison. /// </param> /// <returns> /// <c>true</c> if <c>other</c> is a <c>LineSegment</c> /// with the same values for the x and y ordinates. /// </returns> public virtual bool EqualsTopologically(ILineSegmentBase other) { return ((new Coordinate(_p0).Equals(other.P0) && new Coordinate(_p1).Equals(other.P1)) || (new Coordinate(_p0).Equals(other.P1) && new Coordinate(_p1).Equals(other.P0))); }
/// <summary> /// Returns <c>true</c> if <c>other</c> is /// topologically equal to this LineSegment (e.g. irrespective /// of orientation). /// </summary> /// <param name="other"> /// A <c>LineSegment</c> with which to do the comparison. /// </param> /// <returns> /// <c>true</c> if <c>other</c> is a <c>LineSegment</c> /// with the same values for the x and y ordinates. /// </returns> public virtual bool EqualsTopologically(ILineSegmentBase other) { return (new Coordinate(_p0).Equals(other.P0) && new Coordinate(_p1).Equals(other.P1)) || (new Coordinate(_p0).Equals(other.P1) && new Coordinate(_p1).Equals(other.P0)); }
/// <summary> /// Compare two collinear segments for left-most ordering. /// If segs are vertical, use vertical ordering for comparison. /// If segs are equal, return 0. /// Segments are assumed to be directed so that the second coordinate is >= to the first /// (e.g. up and to the right). /// </summary> /// <param name="seg0">A segment to compare.</param> /// <param name="seg1">A segment to compare.</param> /// <returns></returns> private static int CompareX(LineSegment seg0, ILineSegmentBase seg1) { int compare0 = seg0.CP0.CompareTo(seg1.P0); if (compare0 != 0) return compare0; return seg0.cP1.CompareTo(seg1.P1); }
/// <summary> /// /// </summary> /// <param name="seg0"></param> /// <param name="seg1"></param> /// <returns></returns> private static bool HasInteriorIntersection(ILineSegmentBase seg0, ILineSegmentBase seg1) { Li.ComputeIntersection(seg0.P0, seg0.P1, seg1.P0, seg1.P1); return Li.IsInteriorIntersection(); }
/// <summary> /// /// </summary> /// <param name="p"></param> /// <param name="seg"></param> private void TestLineSegment(Coordinate p, ILineSegmentBase seg) { /* * Test if segment crosses ray from test point in positive x direction. */ Coordinate p1 = seg.P0; Coordinate p2 = seg.P1; double x1 = p1.X - p.X; double y1 = p1.Y - p.Y; double x2 = p2.X - p.X; double y2 = p2.Y - p.Y; if (((y1 > 0) && (y2 <= 0)) || ((y2 > 0) && (y1 <= 0))) { /* * segment straddles x axis, so compute intersection. */ double xInt = RobustDeterminant.SignOfDet2X2(x1, y1, x2, y2) / (y2 - y1); // x intersection of segment with ray /* * crosses ray if strictly positive intersection. */ if (0.0 < xInt) _crossings++; } }
/// <summary> /// /// </summary> /// <param name="seg0"></param> /// <param name="seg1"></param> /// <returns></returns> private static bool HasInteriorIntersection(ILineSegmentBase seg0, ILineSegmentBase seg1) { Li.ComputeIntersection(seg0.P0, seg0.P1, seg1.P0, seg1.P1); return(Li.IsInteriorIntersection()); }