/// <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++;            
            }
        }
        /// <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;
        }
        /// <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);
            }
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="querySeg"></param>
 public LineSegmentVisitor(LineSegment querySeg) 
 {
     this.querySeg = querySeg;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 public void Remove(LineSegment seg)
 {
     index.Remove(new Envelope(seg.P0, seg.P1), seg);
 }
示例#6
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ls"></param>
 public override void Select(LineSegment ls)
 {
     container.TestLineSegment(p, ls);
 }
示例#7
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;
     }
 }
示例#8
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];
 }
示例#9
0
        /// <summary>
        /// Add an end cap around point p1, terminating a line segment coming from p0.
        /// </summary>
        private void AddLineEndCap(ICoordinate p0, ICoordinate p1)
        {
            var seg = new LineSegment(p0, p1);

            var offsetL = new LineSegment();
            ComputeOffsetSegment(seg, Positions.Left, distance, offsetL);
            var offsetR = new LineSegment();
            ComputeOffsetSegment(seg, Positions.Right, distance, offsetR);

            var dx = p1.X - p0.X;
            var dy = p1.Y - p0.Y;
            var angle = Math.Atan2(dy, dx);

            switch (endCapStyle)
            {
                case BufferStyle.CapRound:
                    // add offset seg points with a fillet between them
                    AddPt(offsetL.P1);
                    AddFillet(p1, angle + Math.PI / 2, angle - Math.PI / 2, CGAlgorithms.Clockwise, distance);
                    AddPt(offsetR.P1);
                    break;

                case BufferStyle.CapButt:
                    // only offset segment points are added
                    AddPt(offsetL.P1);
                    AddPt(offsetR.P1);
                    break;

                case BufferStyle.CapSquare:
                    // add a square defined by extensions of the offset segment endpoints
                    ICoordinate squareCapSideOffset = new Coordinate();
                    squareCapSideOffset.X = Math.Abs(distance) * Math.Cos(angle);
                    squareCapSideOffset.Y = Math.Abs(distance) * Math.Sin(angle);

                    ICoordinate squareCapLOffset = new Coordinate(
                        offsetL.P1.X + squareCapSideOffset.X,
                        offsetL.P1.Y + squareCapSideOffset.Y);
                    ICoordinate squareCapROffset = new Coordinate(
                        offsetR.P1.X + squareCapSideOffset.X,
                        offsetR.P1.Y + squareCapSideOffset.Y);
                    AddPt(squareCapLOffset);
                    AddPt(squareCapROffset);
                    break;

                default:
                    break;
            }
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg0"></param>
 /// <param name="seg1"></param>
 /// <returns></returns>
 private bool HasInteriorIntersection(LineSegment seg0, LineSegment seg1)
 {
     li.ComputeIntersection(seg0.P0, seg0.P1, seg1.P0, seg1.P1);
     return li.IsInteriorIntersection();
 }
示例#11
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ls"></param>
 public void SetCoordinates(LineSegment ls)
 {
     SetCoordinates(ls.P0, ls.P1);
 }
示例#12
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ls"></param>
 public LineSegment(LineSegment ls) : this(ls.p0, ls.p1) { }
示例#13
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);
 }
示例#14
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="ls"></param>
 public void SetCoordinates(LineSegment ls)
 {
     SetCoordinates(ls.P0, ls.P1);
 }
示例#15
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="ls"></param>
 public LineSegment(LineSegment ls) : this(ls.p0, ls.p1)
 {
 }
 /// <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) { }
示例#17
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));
 }
示例#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);
        }
        /// <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);
        }
示例#20
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);
            }
        }
示例#21
0
 /// <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 void ComputeOffsetSegment(LineSegment seg, Positions side, double distance, LineSegment offset)
 {
     var sideSign = side == Positions.Left ? 1 : -1;
     var dx = seg.P1.X - seg.P0.X;
     var dy = seg.P1.Y - seg.P0.Y;
     var len = Math.Sqrt(dx * dx + dy * dy);
     // u is the vector that is the length of the offset, in the direction of the segment
     var ux = sideSign * distance * dx / len;
     var 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;
 }
示例#22
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;
        }
示例#23
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;
         }
     }
 }
示例#24
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;
            }
        }
 /// <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) { }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="pts"></param>
 /// <param name="i"></param>
 /// <param name="j"></param>
 /// <param name="maxDistance"></param>
 /// <returns></returns>
 private int FindFurthestPoint(ICoordinate[] 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++) 
     {
         ICoordinate midPt = pts[k];
         double distance = seg.Distance(midPt);
         if (distance > maxDist) 
         {
             maxDist = distance;
             maxIndex = k;
         }
     }
     maxDistance[0] = maxDist;
     return maxIndex;
 }
示例#27
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 public void Add(LineSegment seg)
 {
     index.Insert(new Envelope(seg.P0, seg.P1), 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
     ICoordinate p0 = linePts[start];
     ICoordinate 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>
 /// 
 /// </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>
		/// Create a rectangle containing the study area and dividible by the desired grid size
		/// </summary>
		/// <param name="pol"></param>
		/// <param name="widthDivBy"></param>
		/// <param name="heightDivBy"></param>
		private void roundedRectangle(IPolygon pol, int widthDivBy, int heightDivBy)
		{
			try {
				double width = new  LineSegment(pol.Coordinates[0],pol.Coordinates[1]).Length;
				double height = new LineSegment(pol.Coordinates[1],pol.Coordinates[2]).Length;
				
				var roundedWidth = (int) Math.Sign(width) * Math.Ceiling(Math.Abs(width)/widthDivBy) * widthDivBy;
				var roundedHeight= (int) Math.Sign(height) * Math.Ceiling(Math.Abs(height)/heightDivBy) * heightDivBy;
				
				//get the total num of cols and rows
				_gridCols=(int)roundedWidth/widthDivBy;
				_gridRows=(int)roundedHeight/heightDivBy;
				
				
				ICoordinate origin =(ICoordinate)pol.Coordinates[0];
				
				ICoordinate[] coords=new ICoordinate[5];
				coords[0]= origin;
				coords[1]= new Coordinate(origin.X+roundedWidth, origin.Y);
				coords[2]= new Coordinate(origin.X+roundedWidth,origin.Y+roundedHeight);
				coords[3]= new Coordinate(origin.X,origin.Y+roundedHeight);
				coords[4]= origin;
				
				ILinearRing lr=new LinearRing(coords);
				
				_roundedRectangle=new Polygon(lr);
				
			} catch (Exception ex) {
				throw ex;
			}
			
			
		}
 /// <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;
 }
示例#33
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="seg"></param>
 public void AddToResult(LineSegment seg)
 {
     resultSegs.Add(seg);
 }
示例#34
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));
 }