/// <summary>
        /// 
        /// </summary>
        /// <param name="querySeg"></param>
        /// <returns></returns>
        public virtual 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;
        }
 /// <summary>
 /// 
 /// </summary>
 private void BuildIndex()
 {
     _sirTree = new SIRtree();
     IList<Coordinate> pts = _ring.Coordinates;
     for (int i = 1; i < pts.Count; 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);
     }
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="pts"></param>
 /// <param name="i"></param>
 /// <param name="j"></param>
 /// <param name="maxDistance"></param>
 /// <returns></returns>
 private static int FindFurthestPoint(IList<Coordinate> pts, int i, int j, double[] maxDistance)
 {
     LineSegment seg = new LineSegment();
     seg.P0 = pts[i];
     seg.P1 = pts[j];
     double maxDist = -1.0;
     int maxIndex = i;
     for (int k = i + 1; k < j; k++) 
     {
         Coordinate midPt = pts[k];
         double distance = seg.Distance(midPt);
         if (distance > maxDist) 
         {
             maxDist = distance;
             maxIndex = k;
         }
     }
     maxDistance[0] = maxDist;
     return maxIndex;
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        /// <param name="seg"></param>
        private void TestLineSegment(Coordinate p, LineSegment seg) 
        {
            /*
            *  Test if segment crosses ray from test point in positive x direction.
            */
            Coordinate p1 = seg.CP0;
            Coordinate p2 = seg.cP1;
            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="seg"></param>
 public virtual void AddToResult(LineSegment seg)
 {
     _resultSegs.Add(seg);
 }
 /// <summary>
 /// Given the specified test point, this checks each segment, and will
 /// return the closest point on the specified segment.
 /// </summary>
 /// <param name="testPoint">The point to test.</param>
 /// <returns></returns>
 public override Coordinate ClosestPoint(Coordinate testPoint)
 {
     Coordinate closest = Coordinate;
     double dist = double.MaxValue;
     for(int i = 0; i < _points.Count - 1; i++)
     {
         LineSegment s = new LineSegment(_points[i], _points[i+1]);
         Coordinate temp = s.ClosestPoint(testPoint);
         double tempDist = testPoint.Distance(temp);
         if(tempDist < dist)
         {
             dist = tempDist;
             closest = temp;
         }
     }
     return closest;
 }
 /// <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;
     IList<Coordinate> coord0 = line0.Coordinates;
     IList<Coordinate> coord1 = line1.Coordinates;
     // brute force approach!
     for (int i = 0; i < coord0.Count - 1; i++)
     {
         for (int j = 0; j < coord1.Count - 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]);
                 Coordinate[] closestPt = seg0.ClosestPoints(seg1);
                 locGeom[0] = new GeometryLocation(line0, i, new Coordinate(closestPt[0]));
                 locGeom[1] = new GeometryLocation(line1, j, new Coordinate(closestPt[1]));
             }
             if (_minDistance <= _terminateDistance) return;
         }
     }
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg0"></param>
 /// <param name="seg1"></param>
 /// <returns></returns>
 private static bool HasInteriorIntersection(LineSegment seg0, LineSegment seg1)
 {
     Li.ComputeIntersection(seg0.CP0, seg0.cP1, seg1.CP0, seg1.cP1);
     return Li.IsInteriorIntersection();
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="candidateSeg"></param>
 /// <returns></returns>
 private bool HasBadOutputIntersection(LineSegment candidateSeg)
 {
     IList querySegs = _outputIndex.Query(candidateSeg);
     for (IEnumerator i = querySegs.GetEnumerator(); i.MoveNext(); ) 
     {
         LineSegment querySeg = (LineSegment) i.Current;
         if (HasInteriorIntersection(querySeg, candidateSeg)) 
             return true;                
     }
     return false;
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="geom"></param>
        private void ComputeWidthConvex(IGeometry geom)
        {
            IList<Coordinate> pts;
            if (geom is Polygon)
                pts = ((Polygon)geom).Shell.Coordinates;
            else pts = geom.Coordinates;

            // special cases for lines or points or degenerate rings
            if (pts.Count == 0) 
            {
                _minWidth = 0.0;
                _minWidthPt = Coordinate.Empty;
                _minBaseSeg = null;
            }
            else if (pts.Count == 1) 
            {
                _minWidth = 0.0;
                _minWidthPt = pts[0];
                _minBaseSeg.P0 = pts[0];
                _minBaseSeg.P1 = pts[0];
            }
            else if (pts.Count == 2 || pts.Count == 3) 
            {
                _minWidth = 0.0;
                _minWidthPt = pts[0];
                _minBaseSeg.P0 = pts[0];
                _minBaseSeg.P1 = pts[1];
            }
            else ComputeConvexRingMinDiameter(pts);
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="querySeg"></param>
 public LineSegmentVisitor(LineSegment querySeg) 
 {
     this.querySeg = querySeg;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 public virtual void Remove(LineSegment seg)
 {
     index.Remove(new Envelope(seg.P0, seg.P1), seg);
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 public virtual void Add(LineSegment seg)
 {
     index.Insert(new Envelope(seg.P0, seg.P1), seg);
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="index"></param>
 /// <param name="ls"></param>
 public virtual void GetLineSegment(int index, ref LineSegment ls)
 {
     ls.P0 = _pts[index];
     ls.P1 = _pts[index + 1];
 }
 /// <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) { }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="start"></param>
 /// <param name="end"></param>
 /// <returns></returns>
 private LineSegment Flatten(int start, int end)
 {
     // make a new segment for the simplified point
     Coordinate p0 = _linePts[start];
     Coordinate p1 = _linePts[end];
     LineSegment newSeg = new LineSegment(p0, p1);
     // update the indexes
     Remove(_line, start, end);
     _outputIndex.Add(newSeg);
     return newSeg;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="parentLine"></param>
 /// <param name="sectionIndex"></param>
 /// <param name="candidateSeg"></param>
 /// <returns></returns>
 private bool HasBadIntersection(TaggedLineString parentLine, int[] sectionIndex, LineSegment candidateSeg)
 {
     if (HasBadOutputIntersection(candidateSeg)) 
         return true;
     if (HasBadInputIntersection(parentLine, sectionIndex, candidateSeg)) 
         return true;
     return false;
 }
        /// <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(IList<Coordinate> 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.Count - 1; i++) 
            {
                seg.P0 = pts[i];
                seg.P1 = pts[i + 1];
                currMaxIndex = FindMaxPerpDistance(pts, seg, currMaxIndex);
            }
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="parentLine"></param>
 /// <param name="sectionIndex"></param>
 /// <param name="candidateSeg"></param>
 /// <returns></returns>
 private bool HasBadInputIntersection(TaggedLineString parentLine, int[] sectionIndex, LineSegment candidateSeg)
 {
     IList querySegs = _inputIndex.Query(candidateSeg);
     for (IEnumerator i = querySegs.GetEnumerator(); i.MoveNext(); ) 
     {
         TaggedLineSegment querySeg = (TaggedLineSegment) i.Current;
         if (HasInteriorIntersection(querySeg, candidateSeg)) 
         {
             if (IsInLineSection(parentLine, sectionIndex, querySeg))
                 continue;
             return true;
         }
     }
     return false;
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pts"></param>
        /// <param name="seg"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        private int FindMaxPerpDistance(IList<Coordinate> pts, ILineSegment 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;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="i"></param>
        /// <param name="j"></param>
        /// <param name="depth"></param>
        private void SimplifySection(int i, int j, int depth)
        {
            depth += 1;
            int[] sectionIndex = new int[2];
            if((i+1) == j)
            {
                LineSegment newSeg = _line.GetSegment(i);
                _line.AddToResult(newSeg);
                // leave this segment in the input index, for efficiency
                return;
            }

            double[] distance = new double[1];
            int furthestPtIndex = FindFurthestPoint(_linePts, i, j, distance);
            bool isValidToFlatten = true;

            // must have enough points in the output line
            if (_line.ResultSize < _line.MinimumSize && depth < 2)  isValidToFlatten = false;
            // flattening must be less than distanceTolerance
            if (distance[0] > DistanceTolerance) isValidToFlatten = false;
            // test if flattened section would cause intersection
            LineSegment candidateSeg = new LineSegment();
            candidateSeg.P0 = _linePts[i];
            candidateSeg.P1 = _linePts[j];
            sectionIndex[0] = i;
            sectionIndex[1] = j;
            if (HasBadIntersection(_line, sectionIndex, candidateSeg)) isValidToFlatten = false;

            if (isValidToFlatten)
            {
                LineSegment newSeg = Flatten(i, j);
                _line.AddToResult(newSeg);
                return;
            }
            SimplifySection(i, furthestPtIndex, depth);
            SimplifySection(furthestPtIndex, j, depth);
        }
 /// <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>
 /// 
 /// </summary>
 /// <param name="line"></param>
 /// <param name="pt"></param>
 /// <param name="locGeom"></param>
 private void ComputeMinDistance(ILineString line, Point pt, GeometryLocation[] locGeom)
 {
     if (line.EnvelopeInternal.Distance(pt.EnvelopeInternal) > _minDistance) return;
     IList<Coordinate> coord0 = line.Coordinates;
     Coordinate coord = pt.Coordinate;
     // brute force approach!
     for (int i = 0; i < coord0.Count - 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]);
             Coordinate segClosestPoint = new Coordinate(seg.ClosestPoint(coord));
             locGeom[0] = new GeometryLocation(line, i, segClosestPoint);
             locGeom[1] = new GeometryLocation(pt, 0, coord);
         }
         if (_minDistance <= _terminateDistance) return;
     }
 }
            /// <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>
        /// 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> 
 /// 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) { }
Beispiel #27
0
 /// <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(LineSegment inLineSegment)
 {
     X = inLineSegment.P1.X - inLineSegment.P0.X;
     Y = inLineSegment.P1.Y - inLineSegment.P0.Y;
     Z = inLineSegment.P1.Z - inLineSegment.P0.Z;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ls"></param>
 public override void Select(LineSegment ls)
 {
     _container.TestLineSegment(_p, ls);
 }