示例#1
0
        /// <summary>
        /// Returns the subcurve consisting of the points between the specified locations along the
        /// linestring. The from location must be before the end location, unless the linestring is
        /// closed in which case the new subcurve will cross the original's from/to point.
        /// </summary>
        /// <param name="fromSegment"></param>
        /// <param name="fromSegmentRatio"></param>
        /// <param name="toSegment"></param>
        /// <param name="toSegmentRatio"></param>
        /// <param name="clonePoints"></param>
        /// <returns></returns>
        public Linestring GetSubcurve(int fromSegment, double fromSegmentRatio,
                                      int toSegment, double toSegmentRatio,
                                      bool clonePoints)
        {
            Line3D startSegment = _segments[fromSegment];

            Pnt3D startPoint = fromSegmentRatio > 0
                                                   ? startSegment.GetPointAlong(
                fromSegmentRatio, asRatio: true)
                                                   : clonePoints
                                                           ? startSegment.StartPointCopy
                                                           : startSegment.StartPoint;

            Line3D endSegment = _segments[toSegment];
            Pnt3D  endPoint   = toSegmentRatio > 0
                                                 ? endSegment.GetPointAlong(
                toSegmentRatio, asRatio: true)
                                                 : clonePoints
                                                         ? endSegment.StartPointCopy
                                                         : endSegment.StartPoint;

            var resultPoints = new List <Pnt3D>();

            resultPoints.Add(startPoint);

            double epsilon =
                MathUtils.GetDoubleSignificanceEpsilon(startPoint.X, startPoint.Y);

            bool fromBeforeTo = fromSegmentRatio - toSegmentRatio < epsilon;

            if (fromSegment == toSegment && fromBeforeTo)
            {
                resultPoints.Add(endPoint);
            }
            else
            {
                int currentIndex = fromSegment;

                if (toSegment <= fromSegment)
                {
                    // must go across the From/To point
                    Assert.True(IsClosed,
                                "Cannot get subcurve from non-closed linestring with from point after to point.");
                }

                while ((currentIndex = NextIndexInRing(currentIndex)) != toSegment)
                {
                    if (fromSegmentRatio < 1)
                    {
                        resultPoints.Add(_segments[currentIndex].StartPoint);
                    }
                }

                if (toSegmentRatio > 0)
                {
                    resultPoints.Add(endSegment.StartPoint);
                }

                resultPoints.Add(endPoint);
            }

            return(new Linestring(resultPoints));
        }
示例#2
0
        /// <summary>
        /// Determines whether the two paths cross (i.e. the intersection is a point) in this intersection.
        /// </summary>
        /// <param name="sourceSegments"></param>
        /// <param name="targetSegments"></param>
        /// <param name="tolerance"></param>
        /// <param name="targetDeviatesToLeft">If there is no crossing: Whether the target segment deviates
        /// to the left of the source.</param>
        /// <returns></returns>
        public bool IsCrossingInPoint([NotNull] ISegmentList sourceSegments,
                                      [NotNull] ISegmentList targetSegments,
                                      double tolerance,
                                      out bool?targetDeviatesToLeft)
        {
            targetDeviatesToLeft = null;

            if (HasLinearIntersection)
            {
                return(false);
            }

            if (SingleInteriorIntersectionFactor != null)
            {
                // interior/interior
                targetDeviatesToLeft = true;

                return(true);
            }

            Line3D sourceLine = sourceSegments[SourceIndex];

            // Target start/end on source interior: check previous/next target segments
            if (TargetStartIsOnSourceInterior)
            {
                Line3D thisTargetSegment     = targetSegments[TargetIndex];
                Line3D previousTargetSegment = targetSegments.PreviousSegment(TargetIndex);

                if (previousTargetSegment == null)
                {
                    return(false);
                }

                if (ArePointsOnDifferentSide(sourceLine,
                                             previousTargetSegment.StartPoint,
                                             thisTargetSegment.EndPoint, tolerance,
                                             out targetDeviatesToLeft))
                {
                    return(true);
                }
            }

            if (TargetEndIsOnSourceInterior)
            {
                // check the sides of the target segment and the next target segment
                Line3D thisTargetSegment = targetSegments[TargetIndex];
                Line3D nextTargetSegment = targetSegments.NextSegment(TargetIndex);

                if (nextTargetSegment == null)
                {
                    return(false);
                }

                if (ArePointsOnDifferentSide(sourceLine, thisTargetSegment.StartPoint,
                                             nextTargetSegment.EndPoint, tolerance,
                                             out targetDeviatesToLeft))
                {
                    return(true);
                }
            }

            if (SourceStartIntersects)
            {
                Line3D previousSource =
                    sourceSegments.PreviousSegment(SourceIndex, true);

                return(TargetCrossesBetweenSourceSegments(previousSource, sourceLine,
                                                          targetSegments,
                                                          tolerance,
                                                          out targetDeviatesToLeft));
            }

            if (SourceEndIntersects)
            {
                Line3D nextSource =
                    sourceSegments.NextSegment(SourceIndex, true);

                return(TargetCrossesBetweenSourceSegments(sourceLine, nextSource,
                                                          targetSegments,
                                                          tolerance,
                                                          out targetDeviatesToLeft));
            }

            return(false);
        }
示例#3
0
        /// <summary>
        /// Collects the relevant information of the line vertices that intersect (i.e. are within the tolerance) of
        /// the other line.
        /// </summary>
        /// <param name="thisLine"></param>
        /// <param name="otherLine"></param>
        /// <param name="tolerance"></param>
        /// <param name="knownTargetEndFactor"></param>
        private void CollectVertexIntersectionInfos(
            [NotNull] Line3D thisLine,
            [NotNull] Line3D otherLine,
            double tolerance,
            double?knownTargetEndFactor = null)
        {
            _source1Factor = GetPointFactorWithinLine(otherLine, thisLine.StartPoint,
                                                      tolerance);

            // Consider removing extra property SourceStartIntersects and compute like this:
            //SingleInteriorIntersectionFactor == null && _source1Factor >= 0 && _source1Factor <= 1;
            SourceStartIntersects = _source1Factor >= 0 && _source1Factor <= 1;

            _source2Factor = GetPointFactorWithinLine(otherLine, thisLine.EndPoint,
                                                      tolerance);
            SourceEndIntersects = _source2Factor >= 0 && _source2Factor <= 1;

            double targetStartFactor = knownTargetEndFactor ??
                                       GetPointFactorWithinLine(
                thisLine, otherLine.StartPoint,
                tolerance);

            if (!double.IsNaN(targetStartFactor))
            {
                TargetStartFactor = targetStartFactor;
            }

            double targetEndFactor = GetPointFactorWithinLine(
                thisLine, otherLine.EndPoint, tolerance);

            if (!double.IsNaN(targetEndFactor))
            {
                TargetEndFactor = targetEndFactor;
            }

            // Determine if the linear intersection has opposite line direction
            if (!double.IsNaN(_source1Factor) && !double.IsNaN(_source2Factor))
            {
                LinearIntersectionInOppositeDirection = _source1Factor > _source2Factor;
            }
            else if (!double.IsNaN(targetStartFactor) && !double.IsNaN(targetEndFactor))
            {
                LinearIntersectionInOppositeDirection = targetStartFactor >
                                                        targetEndFactor;
            }
            else
            {
                if (!(double.IsNaN(targetStartFactor) && double.IsNaN(targetEndFactor)))
                {
                    if (SourceStartIntersects)
                    {
                        LinearIntersectionInOppositeDirection =
                            GetTargetStartIntersectionFactor() > 0;
                    }
                    else if (SourceEndIntersects)
                    {
                        LinearIntersectionInOppositeDirection =
                            GetTargetEndIntersectionFactor() < 1;
                    }
                }
            }
        }
示例#4
0
        public Pnt3D GetLinearIntersectionEndOnTarget([NotNull] Line3D targetSegment)
        {
            double factorAlongTarget;

            return(GetLinearIntersectionEndOnTarget(targetSegment, out factorAlongTarget));
        }
示例#5
0
        public IEnumerable <KeyValuePair <int, Line3D> > FindSegments(
            double xMin, double yMin, double xMax, double yMax,
            double tolerance, bool allowIndexing = true, Predicate <int> predicate = null)
        {
            if (SpatialIndex == null && allowIndexing &&
                SegmentCount > AllowIndexingThreshold)
            {
                SpatialIndex = SpatialHashSearcher <SegmentIndex> .CreateSpatialSearcher(this);
            }

            Predicate <SegmentIndex> multipartIndexPredicate = null;

            if (predicate != null)
            {
                multipartIndexPredicate =
                    found =>
                {
                    int globalIdx = GetGlobalSegmentIndex(found.PartIndex, found.LocalIndex);

                    return(predicate(globalIdx));
                };
            }

            // NOTE: Using SpatialHashSearcher<int> and converting to local segment indexes is much slower!
            //       -> consider optimized MultiLinestring that is based off one long array of points (WKSPoint structs?)
            if (SpatialIndex != null)
            {
                foreach (SegmentIndex segmentIndex in SpatialIndex.Search(
                             xMin, yMin, xMax, yMax, this, tolerance, multipartIndexPredicate))
                {
                    Line3D segment = GetSegment(segmentIndex.PartIndex, segmentIndex.LocalIndex);

                    if (segment.ExtentIntersectsXY(
                            xMin, yMin, xMax, yMax, tolerance))
                    {
                        yield return(new KeyValuePair <int, Line3D>(
                                         GetGlobalSegmentIndex(segmentIndex.PartIndex, segmentIndex.LocalIndex),
                                         segment));
                    }
                }
            }
            else
            {
                int i = 0;
                foreach (Line3D segment in this)
                {
                    if (predicate != null && !predicate(i))
                    {
                        continue;
                    }

                    if (segment.ExtentIntersectsXY(
                            xMin, yMin, xMax, yMax, tolerance))
                    {
                        //var identifier = new SegmentIndex(p, s);
                        yield return(new KeyValuePair <int, Line3D>(i, segment));
                    }

                    i++;
                }
            }
        }