public LocateFailureException(LineSegment seg)
     : base("Locate failed to converge (at edge: "
         + seg
         + ").  Possible causes include invalid Subdivision topology or very close sites")
 {
     this.Segment = new LineSegment(seg);
 }
示例#2
0
 /// <summary>
 /// Densifies a coordinate sequence.
 /// </summary>
 /// <param name="pts">The coordinate sequence to densify</param>
 /// <param name="distanceTolerance">The distance tolerance (<see cref="DistanceTolerance"/>)</param>
 /// <param name="precModel">The precision model to apply on the new coordinates</param>
 /// <returns>The densified coordinate sequence</returns>
 private static Coordinate[] DensifyPoints(Coordinate[] pts,
                                            double distanceTolerance, IPrecisionModel precModel)
 {
     var seg = new LineSegment();
     var coordList = new CoordinateList();
     for (int i = 0; i < pts.Length - 1; i++)
     {
         seg.P0 = pts[i];
         seg.P1 = pts[i + 1];
         coordList.Add(seg.P0, false);
         double len = seg.Length;
         int densifiedSegCount = (int) (len/distanceTolerance) + 1;
         if (densifiedSegCount > 1)
         {
             double densifiedSegLen = len/densifiedSegCount;
             for (int j = 1; j < densifiedSegCount; j++)
             {
                 double segFract = (j*densifiedSegLen)/len;
                 var p = seg.PointAlong(segFract);
                 precModel.MakePrecise(p);
                 coordList.Add(p, false);
             }
         }
     }
     coordList.Add(pts[pts.Length - 1], false);
     return coordList.ToCoordinateArray();
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        /// <param name="seg"></param>
        private void TestLineSegment(Coordinate 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.
            */
            Coordinate p1 = seg.P0;
            Coordinate 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++;            
            }
        }
        void CheckOffset(double x0, double y0, double x1, double y1, double segFrac, double offset,
            double expectedX, double expectedY)
        {
            LineSegment seg = new LineSegment(x0, y0, x1, y1);
            Coordinate p = seg.PointAlongOffset(segFrac, offset);

            Assert.IsTrue(EqualsTolerance(new Coordinate(expectedX, expectedY), p, 0.000001));
        }
 private Coordinate computePoint(LineSegment seg, double dist)
 {
     double dx = seg.P1.X - seg.P0.X;
     double dy = seg.P1.Y - seg.P0.Y;
     double len = seg.Length;
     Coordinate pt = new Coordinate(dist * dx / len, dist * dy / len);
     pm.MakePrecise(pt);
     return pt;
 }
        public void TestProjectionFactor()
        {
            // zero-length line
            var seg = new LineSegment(10, 0, 10, 0);
            Assert.IsTrue(Double.IsNaN(seg.ProjectionFactor(new Coordinate(11, 0))));

            var seg2 = new LineSegment(10, 0, 20, 0);
            Assert.IsTrue(seg2.ProjectionFactor(new Coordinate(11, 0)) == 0.1);

        }
 private void UpdateClearance(double candidateValue, Coordinate p,
                              Coordinate seg0, Coordinate seg1)
 {
     if (candidateValue < _minClearance)
     {
         _minClearance = candidateValue;
         _minClearancePts[0] = new Coordinate(p);
         var seg = new LineSegment(seg0, seg1);
         _minClearancePts[1] = new Coordinate(seg.ClosestPoint(p));
     }
 }
 public static void ComputeDistance(ILineString line, Coordinate pt, PointPairDistance ptDist)
 {
     var coords = line.Coordinates;
     var tempSegment = new LineSegment();
     for (var i = 0; i < coords.Length - 1; i++)
     {
         tempSegment.SetCoordinates(coords[i], coords[i + 1]);
         // this is somewhat inefficient - could do better
         var closestPt = tempSegment.ClosestPoint(pt);
         ptDist.SetMinimum(closestPt, pt);
     }
 }
        /// <summary>
        /// 
        /// </summary>
        private void BuildIndex()
        {
            _sirTree = new SIRtree<LineSegment>();
            Coordinate[] 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);
            }
        }
 private void CheckPointsAtDistance(LineSegment seg, double dist0, double dist1)
 {
     Coordinate p0 = computePoint(seg, dist0);
     Coordinate p1 = computePoint(seg, dist1);
     if (p0.Equals(p1))
     {
         CheckNodePosition(seg, p0, p1, 0);
     }
     else
     {
         CheckNodePosition(seg, p0, p1, -1);
         CheckNodePosition(seg, p1, p0, 1);
     }
 }
        public void TestOrientationIndexCoordinate()
        {
            LineSegment seg = new LineSegment(0, 0, 10, 10);
            CheckOrientationIndex(seg, 10, 11, 1);
            CheckOrientationIndex(seg, 10, 9, -1);

            CheckOrientationIndex(seg, 11, 11, 0);

            CheckOrientationIndex(seg, 11, 11.0000001, 1);
            CheckOrientationIndex(seg, 11, 10.9999999, -1);

            CheckOrientationIndex(seg, -2, -1.9999999, 1);
            CheckOrientationIndex(seg, -2, -2.0000001, -1);
        }
        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;
            }

            bool isValidToSimplify = true;

            /**
             * Following logic ensures that there is enough points in the output line.
             * If there is already more points than the minimum, there's nothing to check.
             * Otherwise, if in the worst case there wouldn't be enough points,
             * don't flatten this segment (which avoids the worst case scenario)
             */
            if (_line.ResultSize < _line.MinimumSize)
            {
                int worstCaseSize = depth + 1;
                if (worstCaseSize < _line.MinimumSize)
                    isValidToSimplify = false;
            }

            double[] distance = new double[1];
            int furthestPtIndex = FindFurthestPoint(_linePts, i, j, distance);
            // flattening must be less than distanceTolerance
            if (distance[0] > _distanceTolerance)
                isValidToSimplify = 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))
                isValidToSimplify = false;

            if (isValidToSimplify)
            {
                LineSegment newSeg = Flatten(i, j);
                _line.AddToResult(newSeg);
                return;
            }
            SimplifySection(i, furthestPtIndex, depth);
            SimplifySection(furthestPtIndex, j, depth);
        }
        private void CheckSegment(double x, double y)
        {
            Coordinate seg0 = new Coordinate(0, 0);
            Coordinate seg1 = new Coordinate(x, y);
            LineSegment seg = new LineSegment(seg0, seg1);

            for (int i = 0; i < 4; i++)
            {
                double dist = i;

                double gridSize = 1 / pm.Scale;

                CheckPointsAtDistance(seg, dist, dist + 1.0 * gridSize);
                CheckPointsAtDistance(seg, dist, dist + 2.0 * gridSize);
                CheckPointsAtDistance(seg, dist, dist + 3.0 * gridSize);
                CheckPointsAtDistance(seg, dist, dist + 4.0 * gridSize);
            }
        }
示例#14
0
 /// <summary>
 /// Gets the line segment starting at <paramref name="index"/>
 /// </summary>
 /// <param name="index">The index of the segment</param>
 /// <param name="ls">The line segment to extract to</param>
 public 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 segments which overlap.
 /// </summary>
 /// <param name="seg1"></param>
 /// <param name="seg2"></param>
 public virtual void Overlap(LineSegment seg1, LineSegment seg2)
 {
 }
示例#16
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ls"></param>
 public override void Select(LineSegment ls)
 {
     _container.TestLineSegment(_p, ls);
 }
示例#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="ls"></param>
 public void SetCoordinates(LineSegment ls)
 {
     SetCoordinates(ls._p0, ls._p1);
 }
示例#19
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);
 }
示例#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">A line segment</param>
 /// <returns> An intersection point, or <c>null</c> if there is none.</returns>
 /// <see cref="RobustLineIntersector"/>
 public Coordinate 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>
        /// 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)
        {
            var pf0 = ProjectionFactor(seg._p0);
            var 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;

            var newp0 = Project(seg._p0);
            if (pf0 < 0.0) newp0 = _p0;
            if (pf0 > 1.0) newp0 = _p1;

            var newp1 = Project(seg._p1);
            if (pf1 < 0.0) newp1 = _p0;
            if (pf1 > 1.0) newp1 = _p1;

            return new LineSegment(newp0, newp1);
        }
示例#22
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));
 }
示例#23
0
 /// <summary>
 /// Creates an instance of this class using another instance
 /// </summary>
 /// <param name="ls"></param>
 public LineSegment(LineSegment ls) : this(ls._p0, ls._p1)
 {
 }
示例#24
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)
 {
     var orient0 = CGAlgorithms.OrientationIndex(_p0, _p1, seg._p0);
     var 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;
 }
示例#25
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);
 }
示例#26
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="ls"></param>
 public void SetCoordinates(LineSegment ls)
 {
     SetCoordinates(ls._p0, ls._p1);
 }
示例#27
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 Coordinate[] ClosestPoints(LineSegment line)
        {
            // test for intersection
            var 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.
            */
            var closestPt = new Coordinate[2];

            var close00 = ClosestPoint(line._p0);
            double minDistance = close00.Distance(line._p0);
            closestPt[0] = close00;
            closestPt[1] = line._p0;

            var close01 = ClosestPoint(line._p1);
            double dist = close01.Distance(line._p1);
            if (dist < minDistance)
            {
                minDistance = dist;
                closestPt[0] = close01;
                closestPt[1] = line._p1;
            }

            var close10 = line.ClosestPoint(_p0);
            dist = close10.Distance(_p0);
            if (dist < minDistance)
            {
                minDistance = dist;
                closestPt[0] = _p0;
                closestPt[1] = close10;
            }

            var close11 = line.ClosestPoint(_p1);
            dist = close11.Distance(_p1);
            if (dist < minDistance)
            {
                minDistance = dist;
                closestPt[0] = _p1;
                closestPt[1] = close11;
            }

            return closestPt;
        }
        /// <summary>
        /// Adds a mitre join connecting the two reflex offset segments.
        /// The mitre will be beveled if it exceeds the mitre ratio limit.
        /// </summary>
        /// <param name="p"></param>
        /// <param name="offset0">The first offset segment</param>
        /// <param name="offset1">The second offset segment</param>
        /// <param name="distance">The offset distance</param>
        private void AddMitreJoin(Coordinate p,
            LineSegment offset0,
            LineSegment offset1,
            double distance)
        {
            var isMitreWithinLimit = true;
            Coordinate intPt;

            /**
             * This computation is unstable if the offset segments are nearly collinear.
             * Howver, this situation should have been eliminated earlier by the check for
             * whether the offset segment endpoints are almost coincident
             */
            try
            {
                intPt = HCoordinate.Intersection(offset0.P0,
                   offset0.P1, offset1.P0, offset1.P1);

                var mitreRatio = distance <= 0.0 ? 1.0
                    : intPt.Distance(p) / Math.Abs(distance);

                if (mitreRatio > _bufParams.MitreLimit)
                    isMitreWithinLimit = false;
            }
            catch (NotRepresentableException ex)
            {
                intPt = new Coordinate(0, 0);
                isMitreWithinLimit = false;
            }

            if (isMitreWithinLimit)
            {
                _segList.AddPt(intPt);
            }
            else
            {
                AddLimitedMitreJoin(offset0, offset1, distance, _bufParams.MitreLimit);
                //      addBevelJoin(offset0, offset1);
            }
        }
示例#29
0
 /// <summary>
 /// Computes the intersection point of the lines defined by two segments, if there is one.
 /// </summary>
 /// <remarks>
 /// There may be 0, 1 or an infinite number of intersection points between two lines.
 /// If there is a unique intersection point, it is returned.
 /// Otherwise, <c>null</c> is returned.
 /// If more information is required about the details of the intersection,
 /// the <see cref="RobustLineIntersector"/> class should be used.
 /// </remarks>
 /// <param name="line">A line segment defining a straight line</param>
 /// <returns>An intersection point, or <c>null</c> if there is none or an infinite number</returns>
 /// <seealso cref="RobustLineIntersector"/>
 public Coordinate LineIntersection(LineSegment line)
 {
     try
     {
         var intPt = HCoordinate.Intersection(_p0, _p1, line._p0, line._p1);
         return intPt;
     }
     catch (NotRepresentableException ex)
     {
         // eat this exception, and return null;
     }
     return null;
 }
        /// <summary>
        /// Adds a limited mitre join connecting the two reflex offset segments.
        /// A limited mitre is a mitre which is beveled at the distance
        /// determined by the mitre ratio limit.
        /// </summary>
        /// <param name="offset0">The first offset segment</param>
        /// <param name="offset1">The second offset segment</param>
        /// <param name="distance">The offset distance</param>
        /// <param name="mitreLimit">The mitre limit ratio</param>
        private void AddLimitedMitreJoin(
            LineSegment offset0,
            LineSegment offset1,
            double distance,
            double mitreLimit)
        {
            var basePt = _seg0.P1;

            var ang0 = AngleUtility.Angle(basePt, _seg0.P0);
            //var ang1 = AngleUtility.Angle(basePt, _seg1.P1);

            // oriented angle between segments
            var angDiff = AngleUtility.AngleBetweenOriented(_seg0.P0, basePt, _seg1.P1);
            // half of the interior angle
            var angDiffHalf = angDiff / 2;

            // angle for bisector of the interior angle between the segments
            var midAng = AngleUtility.Normalize(ang0 + angDiffHalf);
            // rotating this by PI gives the bisector of the reflex angle
            var mitreMidAng = AngleUtility.Normalize(midAng + Math.PI);

            // the miterLimit determines the distance to the mitre bevel
            var mitreDist = mitreLimit * distance;
            // the bevel delta is the difference between the buffer distance
            // and half of the length of the bevel segment
            var bevelDelta = mitreDist * Math.Abs(Math.Sin(angDiffHalf));
            var bevelHalfLen = distance - bevelDelta;

            // compute the midpoint of the bevel segment
            var bevelMidX = basePt.X + mitreDist * Math.Cos(mitreMidAng);
            var bevelMidY = basePt.Y + mitreDist * Math.Sin(mitreMidAng);
            var bevelMidPt = new Coordinate(bevelMidX, bevelMidY);

            // compute the mitre midline segment from the corner point to the bevel segment midpoint
            var mitreMidLine = new LineSegment(basePt, bevelMidPt);

            // finally the bevel segment endpoints are computed as offsets from
            // the mitre midline
            var bevelEndLeft = mitreMidLine.PointAlongOffset(1.0, bevelHalfLen);
            var bevelEndRight = mitreMidLine.PointAlongOffset(1.0, -bevelHalfLen);

            if (_side == Positions.Left)
            {
                _segList.AddPt(bevelEndLeft);
                _segList.AddPt(bevelEndRight);
            }
            else
            {
                _segList.AddPt(bevelEndRight);
                _segList.AddPt(bevelEndLeft);
            }
        }
示例#31
0
 /// <summary>
 /// Creates an instance of this class using another instance
 /// </summary>
 /// <param name="ls"></param>
 public LineSegment(LineSegment ls) : this(ls._p0, ls._p1) { }
        /**
         *
         *
         * @param offset0
         * @param offset1
         */

        /// <summary>
        /// Adds a bevel join connecting the two offset segments
        /// around a reflex corner.
        /// </summary>
        /// <param name="offset0">The first offset segment</param>
        /// <param name="offset1">The second offset segment</param>
        private void AddBevelJoin(
            LineSegment offset0,
            LineSegment offset1)
        {
            _segList.AddPt(offset0.P1);
            _segList.AddPt(offset1.P0);
        }
 private static bool IsSnapped(Coordinate v, Coordinate p0, Coordinate p1)
 {
     if (v.Equals2D(p0)) return true;
     if (v.Equals2D(p1)) return true;
     var seg = new LineSegment(p0, p1);
     var dist = seg.Distance(v);
     if (dist < SnapTolerance / 2.05) return false;
     return true;
 }
 private void CheckNodePosition(LineSegment seg, Coordinate p0, Coordinate p1, int expectedPositionValue)
 {
     Octants octant = Octant.GetOctant(seg.P0, seg.P1);
     int posValue = SegmentPointComparator.Compare(octant, p0, p1);
     Console.WriteLine(octant + " " + p0 + " " + p1 + " " + posValue);
     Assert.IsTrue(posValue == expectedPositionValue);
 }