예제 #1
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        /// <param name="seg"></param>
        private void TestLineSegment(ICoordinate p, LineSegment seg)
        {
            double xInt;  // x intersection of segment with ray
            double x1;    // translated coordinates
            double y1;
            double x2;
            double y2;

            /*
            *  Test if segment crosses ray from test point in positive x direction.
            */
            ICoordinate p1 = seg.P0;
            ICoordinate p2 = seg.P1;
            x1 = p1.X - p.X;
            y1 = p1.Y - p.Y;
            x2 = p2.X - p.X;
            y2 = p2.Y - p.Y;

            if (((y1 > 0) && (y2 <= 0)) || ((y2 > 0) && (y1 <= 0)))
            {
                /*
                *  segment straddles x axis, so compute intersection.
                */
                xInt = RobustDeterminant.SignOfDet2x2(x1, y1, x2, y2) / (y2 - y1);

                /*
                *  crosses ray if strictly positive intersection.
                */
                if (0.0 < xInt)
                    crossings++;
            }
        }
예제 #2
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 /// <param name="inputPt"></param>
 /// <returns></returns>
 public static double SegmentFraction(LineSegment seg, ICoordinate inputPt)
 {
     double segFrac = seg.ProjectionFactor(inputPt);
     if (segFrac < 0.0)
         segFrac = 0.0;
     else if (segFrac > 1.0)
         segFrac = 1.0;
     return segFrac;
 }
예제 #3
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="querySeg"></param>
        /// <returns></returns>
        public IList Query(LineSegment querySeg)
        {
            Envelope env = new Envelope(querySeg.P0, querySeg.P1);

            LineSegmentVisitor visitor = new LineSegmentVisitor(querySeg);
            index.Query(env, visitor);
            IList itemsFound = visitor.Items;

            return itemsFound;
        }
예제 #4
0
        /// <summary>
        /// 
        /// </summary>
        private void BuildIndex()
        {
            sirTree = new SIRtree();
            ICoordinate[] pts = ring.Coordinates;
            for (int i = 1; i < pts.Length; i++)
            {
                if (pts[i - 1].Equals(pts[i]))
                    continue;

                LineSegment seg = new LineSegment(pts[i - 1], pts[i]);
                sirTree.Insert(seg.P0.Y, seg.P1.Y, seg);
            }
        }
예제 #5
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">A segment to compare.</param>
 /// <param name="seg1">A segment to compare.</param>
 /// <returns></returns>
 private int CompareX(LineSegment seg0, LineSegment seg1)
 {
     int compare0 = seg0.P0.CompareTo(seg1.P0);
     if (compare0 != 0) return compare0;
     return seg0.P1.CompareTo(seg1.P1);
 }
예제 #6
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 /// <param name="depth"></param>
 public DepthSegment(LineSegment seg, int depth)
 {
     // input seg is assumed to be normalized
     upwardSeg = new LineSegment(seg);
     this.leftDepth = depth;
 }
예제 #7
0
 /// <summary> 
 /// Computes the distance between this line segment and another one.
 /// </summary>
 /// <param name="ls"></param>
 /// <returns></returns>
 public double Distance(LineSegment ls)
 {
     return CGAlgorithms.DistanceLineLine(P0, P1, ls.P0, ls.P1);
 }
예제 #8
0
 /// <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 bool EqualsTopologically(LineSegment other)
 {
     return
         P0.Equals(other.P0) && P1.Equals(other.P1) ||
         P0.Equals(other.P1) && P1.Equals(other.P0);
 }
예제 #9
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="line"></param>
 /// <param name="pt"></param>
 /// <param name="locGeom"></param>
 private void ComputeMinDistance(ILineString line, IPoint pt, GeometryLocation[] locGeom)
 {
     if (line.EnvelopeInternal.Distance(pt.EnvelopeInternal) > minDistance) return;
     ICoordinate[] coord0 = line.Coordinates;
     ICoordinate coord = pt.Coordinate;
     // brute force approach!
     for (int i = 0; i < coord0.Length - 1; i++)
     {
         double dist = CGAlgorithms.DistancePointLine(coord, coord0[i], coord0[i + 1]);
         if (dist < minDistance)
         {
             minDistance = dist;
             LineSegment seg = new LineSegment(coord0[i], coord0[i + 1]);
             ICoordinate segClosestPoint = seg.ClosestPoint(coord);
             locGeom[0] = new GeometryLocation(line, i, segClosestPoint);
             locGeom[1] = new GeometryLocation(pt, 0, coord);
         }
         if (minDistance <= terminateDistance)
             return;
     }
 }
예제 #10
0
 /// <summary> 
 /// This is a convenience function which can be overridden to obtain the actual
 /// line segments which overlap.
 /// </summary>
 /// <param name="seg1"></param>
 /// <param name="seg2"></param>
 public virtual void Overlap(LineSegment seg1, LineSegment seg2)
 {
 }
예제 #11
0
 /// <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 int OrientationIndex(LineSegment 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;
 }
예제 #12
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ls"></param>
 public override void Select(LineSegment ls)
 {
     container.TestLineSegment(p, ls);
 }
예제 #13
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="inputPt"></param>
        /// <param name="minIndex"></param>
        /// <returns></returns>
        private double IndexOfFromStart(ICoordinate inputPt, double minIndex)
        {
            double minDistance = Double.MaxValue;

            double ptMeasure = minIndex;
            double segmentStartMeasure = 0.0;

            LineSegment seg = new LineSegment();
            foreach(LinearIterator.LinearElement element in new LinearIterator(linearGeom))
            {
                if (!element.IsEndOfLine)
                {
                    seg.P0 = element.SegmentStart;
                    seg.P1 = element.SegmentEnd;
                    double segDistance = seg.Distance(inputPt);
                    double segMeasureToPt = SegmentNearestMeasure(seg, inputPt, segmentStartMeasure);
                    if (segDistance < minDistance && segMeasureToPt > minIndex)
                    {
                        ptMeasure = segMeasureToPt;
                        minDistance = segDistance;
                    }
                    segmentStartMeasure += seg.Length;
                }
            }
            return ptMeasure;
        }
예제 #14
0
 /// <summary>
 /// This is a convenience function which can be overridden to obtain the actual
 /// line segment which is selected.
 /// </summary>
 /// <param name="seg"></param>
 public virtual void Select(LineSegment seg)
 {
 }
예제 #15
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ls"></param>
 public void SetCoordinates(LineSegment ls)
 {
     SetCoordinates(ls.P0, ls.P1);
 }
예제 #16
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ls"></param>
 public LineSegment(LineSegment ls)
     : this(ls.p0, ls.p1)
 {
 }
예제 #17
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.
        /// Note 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 LineSegment Project(LineSegment 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;

            ICoordinate newp0 = Project(seg.P0);
            if (pf0 < 0.0) newp0 = P0;
            if (pf0 > 1.0) newp0 = P1;

            ICoordinate newp1 = Project(seg.P1);
            if (pf1 < 0.0) newp1 = P0;
            if (pf1 > 1.0) newp1 = P1;

            return new LineSegment(newp0, newp1);
        }
예제 #18
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="geom"></param>
        private void ComputeWidthConvex(IGeometry geom)
        {
            ICoordinate[] pts = null;
            if (geom is IPolygon)
                 pts = ((IPolygon) geom).ExteriorRing.Coordinates;
            else pts = geom.Coordinates;

            // special cases for lines or points or degenerate rings
            if (pts.Length == 0)
            {
                minWidth = 0.0;
                minWidthPt = null;
                minBaseSeg = null;
            }
            else if (pts.Length == 1)
            {
                minWidth = 0.0;
                minWidthPt = pts[0];
                minBaseSeg.P0 = pts[0];
                minBaseSeg.P1 = pts[0];
            }
            else if (pts.Length == 2 || pts.Length == 3)
            {
                minWidth = 0.0;
                minWidthPt = pts[0];
                minBaseSeg.P0 = pts[0];
                minBaseSeg.P1 = pts[1];
            }
            else ComputeConvexRingMinDiameter(pts);
        }
예제 #19
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 /// <param name="inputPt"></param>
 /// <param name="segmentStartMeasure"></param>
 /// <returns></returns>
 private double SegmentNearestMeasure(LineSegment seg, ICoordinate inputPt, double segmentStartMeasure)
 {
     // found new minimum, so compute location distance of point
     double projFactor = seg.ProjectionFactor(inputPt);
     if (projFactor <= 0.0)
         return segmentStartMeasure;
     if (projFactor <= 1.0)
         return segmentStartMeasure + projFactor * seg.Length;
     // ASSERT: projFactor > 1.0
     return segmentStartMeasure + seg.Length;
 }
예제 #20
0
 /// <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 ICoordinate Intersection(LineSegment line)
 {
     LineIntersector li = new RobustLineIntersector();
     li.ComputeIntersection(P0, P1, line.P0, line.P1);
     if (li.HasIntersection)
     return li.GetIntersection(0);
     return null;
 }
예제 #21
0
        /// <summary> 
        /// Compute the width information for a ring of <c>Coordinate</c>s.
        /// Leaves the width information in the instance variables.
        /// </summary>
        /// <param name="pts"></param>
        private void ComputeConvexRingMinDiameter(ICoordinate[] pts)
        {
            // for each segment in the ring
            minWidth = Double.MaxValue;
            int currMaxIndex = 1;

            LineSegment seg = new LineSegment();
            // compute the max distance for all segments in the ring, and pick the minimum
            for (int i = 0; i < pts.Length - 1; i++)
            {
                seg.P0 = pts[i];
                seg.P1 = pts[i + 1];
                currMaxIndex = FindMaxPerpDistance(pts, seg, currMaxIndex);
            }
        }
예제 #22
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 public void AddToResult(LineSegment seg)
 {
     resultSegs.Add(seg);
 }
예제 #23
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pts"></param>
        /// <param name="seg"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        private int FindMaxPerpDistance(ICoordinate[] pts, LineSegment seg, int startIndex)
        {
            double maxPerpDistance = seg.DistancePerpendicular(pts[startIndex]);
            double nextPerpDistance = maxPerpDistance;
            int maxIndex = startIndex;
            int nextIndex = maxIndex;
            while (nextPerpDistance >= maxPerpDistance)
            {
                maxPerpDistance = nextPerpDistance;
                maxIndex = nextIndex;

                nextIndex = NextIndex(pts, maxIndex);
                nextPerpDistance = seg.DistancePerpendicular(pts[nextIndex]);
            }

            // found maximum width for this segment - update global min dist if appropriate
            if (maxPerpDistance < minWidth)
            {
                minPtIndex = maxIndex;
                minWidth = maxPerpDistance;
                minWidthPt = pts[minPtIndex];
                minBaseSeg = new LineSegment(seg);
            }
            return maxIndex;
        }
예제 #24
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="querySeg"></param>
 public LineSegmentVisitor(LineSegment querySeg)
 {
     this.querySeg = querySeg;
 }
예제 #25
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="line0"></param>
 /// <param name="line1"></param>
 /// <param name="locGeom"></param>
 private void ComputeMinDistance(ILineString line0, ILineString line1, GeometryLocation[] locGeom)
 {
     if (line0.EnvelopeInternal.Distance(line1.EnvelopeInternal) > minDistance)
         return;
     ICoordinate[] coord0 = line0.Coordinates;
     ICoordinate[] coord1 = line1.Coordinates;
     // brute force approach!
     for (int i = 0; i < coord0.Length - 1; i++)
     {
         for (int j = 0; j < coord1.Length - 1; j++)
         {
             double dist = CGAlgorithms.DistanceLineLine(
                                             coord0[i], coord0[i + 1],
                                             coord1[j], coord1[j + 1]);
             if (dist < minDistance)
             {
                 minDistance = dist;
                 LineSegment seg0 = new LineSegment(coord0[i], coord0[i + 1]);
                 LineSegment seg1 = new LineSegment(coord1[j], coord1[j + 1]);
                 ICoordinate[] closestPt = seg0.ClosestPoints(seg1);
                 locGeom[0] = new GeometryLocation(line0, i, closestPt[0]);
                 locGeom[1] = new GeometryLocation(line1, j, closestPt[1]);
             }
             if (minDistance <= terminateDistance) return;
         }
     }
 }
예제 #26
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 public void Add(LineSegment seg)
 {
     index.Insert(new Envelope(seg.P0, seg.P1), seg);
 }
예제 #27
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="inputPt"></param>
        /// <param name="minIndex"></param>
        /// <returns></returns>
        private LinearLocation IndexOfFromStart(ICoordinate inputPt, LinearLocation minIndex)
        {
            double minDistance = Double.MaxValue;
            int minComponentIndex = 0;
            int minSegmentIndex = 0;
            double minFrac = -1.0;

            LineSegment seg = new LineSegment();
            foreach (LinearIterator.LinearElement element in new LinearIterator(linearGeom))
            {
                if (!element.IsEndOfLine)
                {
                    seg.P0 = element.SegmentStart;
                    seg.P1 = element.SegmentEnd;
                    double segDistance = seg.Distance(inputPt);
                    double segFrac = SegmentFraction(seg, inputPt);

                    int candidateComponentIndex = element.ComponentIndex;
                    int candidateSegmentIndex = element.VertexIndex;
                    if (segDistance < minDistance)
                    {
                        // ensure after minLocation, if any
                        if (minIndex == null ||
                            minIndex.CompareLocationValues(candidateComponentIndex, candidateSegmentIndex, segFrac) < 0)
                        {
                            // otherwise, save this as new minimum
                            minComponentIndex = candidateComponentIndex;
                            minSegmentIndex = candidateSegmentIndex;
                            minFrac = segFrac;
                            minDistance = segDistance;
                        }
                    }
                }
            }

            LinearLocation loc = new LinearLocation(minComponentIndex, minSegmentIndex, minFrac);
            return loc;
        }
예제 #28
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 public void Remove(LineSegment seg)
 {
     index.Remove(new Envelope(seg.P0, seg.P1), seg);
 }
예제 #29
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="index"></param>
 /// <param name="ls"></param>
 public void GetLineSegment(int index, ref LineSegment ls)
 {
     ls.P0 = pts[index];
     ls.P1 = pts[index + 1];
 }
예제 #30
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;
        }