///// <summary>
        ///// Assumes input is valid
        ///// (e.g. <paramref name="start" /> minor or equals to <paramref name="end" />).
        ///// </summary>
        ///// <param name="start"></param>
        ///// <param name="end"></param>
        ///// <returns></returns>
        //private ILineString ComputeLine(LinearLocation start, LinearLocation end)
        //{
        //    var coordinates = _line.Coordinates;
        //    var newCoordinates = new CoordinateList();

        //    var startSegmentIndex = start.SegmentIndex;
        //    if (start.SegmentFraction > 0.0)
        //        startSegmentIndex += 1;
        //    var lastSegmentIndex = end.SegmentIndex;
        //    if (end.SegmentFraction == 1.0)
        //        lastSegmentIndex += 1;
        //    if (lastSegmentIndex >= coordinates.Length)
        //        lastSegmentIndex = coordinates.Length - 1;
        //    // not needed - LinearLocation values should always be correct
        //    // Assert.IsTrue(end.SegmentFraction <= 1.0, "invalid segment fraction value");

        //    if (!start.IsVertex)
        //        newCoordinates.Add(start.GetCoordinate(_line));
        //    for (var i = startSegmentIndex; i <= lastSegmentIndex; i++)
        //        newCoordinates.Add(coordinates[i]);
        //    if (!end.IsVertex)
        //        newCoordinates.Add(end.GetCoordinate(_line));

        //    // ensure there is at least one coordinate in the result
        //    if (newCoordinates.Count <= 0)
        //        newCoordinates.Add(start.GetCoordinate(_line));

        //    var newCoordinateArray = newCoordinates.ToCoordinateArray();

        //    /*
        //     * Ensure there is enough coordinates to build a valid line.
        //     * Make a 2-point line with duplicate coordinates, if necessary.
        //     * There will always be at least one coordinate in the coordList.
        //     */
        //    if (newCoordinateArray.Length <= 1)
        //        newCoordinateArray = new[] { newCoordinateArray[0], newCoordinateArray[0] };

        //    return _line.Factory.CreateLineString(newCoordinateArray);
        //}

        /// <summary>
        /// Assumes input is valid
        /// (e.g. <paramref name="start" /> minor or equals to <paramref name="end" />).
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        private IGeometry ComputeLinear(LinearLocation start, LinearLocation end)
        {
            var builder = new LinearGeometryBuilder(_line.Factory);

            builder.FixInvalidLines = true;

            if (!start.IsVertex)
            {
                builder.Add(start.GetCoordinate(_line));
            }

            for (var it = new LinearIterator(_line, start); it.HasNext(); it.Next())
            {
                if (end.CompareLocationValues(it.ComponentIndex, it.VertexIndex, 0.0) < 0)
                {
                    break;
                }

                var pt = it.SegmentStart;
                builder.Add(pt);
                if (it.IsEndOfLine)
                {
                    builder.EndLine();
                }
            }

            if (!end.IsVertex)
            {
                builder.Add(end.GetCoordinate(_line));
            }

            return(builder.GetGeometry());
        }
Example #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="loc"></param>
        /// <returns></returns>
        public double GetLength(LinearLocation loc)
        {
            double totalLength = 0.0;

            var it = new LinearIterator(_linearGeom);

            while (it.HasNext())
            {
                if (!it.IsEndOfLine)
                {
                    var    p0     = it.SegmentStart;
                    var    p1     = it.SegmentEnd;
                    double segLen = p1.Distance(p0);
                    // length falls in this segment
                    if (loc.ComponentIndex == it.ComponentIndex &&
                        loc.SegmentIndex == it.VertexIndex)
                    {
                        return(totalLength + segLen * loc.SegmentFraction);
                    }
                    totalLength += segLen;
                }
                it.Next();
            }
            return(totalLength);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="inputPt"></param>
        /// <param name="minIndex"></param>
        /// <returns></returns>
        private double IndexOfFromStart(Coordinate inputPt, double minIndex)
        {
            double minDistance = double.MaxValue;

            double ptMeasure           = minIndex;
            double segmentStartMeasure = 0.0;

            var seg = new LineSegment();
            var it  = new LinearIterator(_linearGeom);

            while (it.HasNext())
            {
                if (!it.IsEndOfLine)
                {
                    seg.P0 = it.SegmentStart;
                    seg.P1 = it.SegmentEnd;
                    double segDistance    = seg.Distance(inputPt);
                    double segMeasureToPt = SegmentNearestMeasure(seg, inputPt, segmentStartMeasure);
                    if (segDistance < minDistance &&
                        segMeasureToPt > minIndex)
                    {
                        ptMeasure   = segMeasureToPt;
                        minDistance = segDistance;
                    }
                    segmentStartMeasure += seg.Length;
                }
                it.Next();
            }
            return(ptMeasure);
        }
Example #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        private LinearLocation GetLocationForward(double length)
        {
            if (length <= 0.0)
            {
                return(new LinearLocation());
            }

            double totalLength = 0.0;

            var it = new LinearIterator(_linearGeom);

            while (it.HasNext())
            {
                /**
                 * Special handling is required for the situation when the
                 * length references exactly to a component endpoint.
                 * In this case, the endpoint location of the current component
                 * is returned,
                 * rather than the startpoint location of the next component.
                 * This produces consistent behaviour with the project method.
                 */
                if (it.IsEndOfLine)
                {
                    if (totalLength == length)
                    {
                        int compIndex = it.ComponentIndex;
                        int segIndex  = it.VertexIndex;
                        return(new LinearLocation(compIndex, segIndex, 0.0));
                    }
                }
                else
                {
                    var    p0     = it.SegmentStart;
                    var    p1     = it.SegmentEnd;
                    double segLen = p1.Distance(p0);
                    // length falls in this segment
                    if (totalLength + segLen > length)
                    {
                        double frac      = (length - totalLength) / segLen;
                        int    compIndex = it.ComponentIndex;
                        int    segIndex  = it.VertexIndex;
                        return(new LinearLocation(compIndex, segIndex, frac));
                    }
                    totalLength += segLen;
                }

                it.Next();
            }
            // length is longer than line - return end location
            return(LinearLocation.GetEndLocation(_linearGeom));
        }
        private LinearLocation IndexOfFromStart(Coordinate inputPt, LinearLocation minIndex)
        {
            var minDistance       = Double.MaxValue;
            var minComponentIndex = 0;
            var minSegmentIndex   = 0;
            var minFrac           = -1.0;

            var seg = new LineSegment();

            for (var it = new LinearIterator(_linearGeom);
                 it.HasNext(); it.Next())
            {
                if (!it.IsEndOfLine)
                {
                    seg.P0 = it.SegmentStart;
                    seg.P1 = it.SegmentEnd;
                    var segDistance = seg.Distance(inputPt);
                    var segFrac     = seg.SegmentFraction(inputPt);

                    var candidateComponentIndex = it.ComponentIndex;
                    var candidateSegmentIndex   = it.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;
                        }
                    }
                }
            }

            if (minDistance == Double.MaxValue)
            {
                // no minimum was found past minLocation, so return it
                return(new LinearLocation(minIndex));
            }
            // otherwise, return computed location
            var loc = new LinearLocation(minComponentIndex, minSegmentIndex, minFrac);

            return(loc);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="inputPt"></param>
        /// <param name="minIndex"></param>
        /// <returns></returns>
        private double IndexOfFromStart(Coordinate inputPt, double minIndex)
        {
            var minDistance = Double.MaxValue;

            var ptMeasure = minIndex;
            var segmentStartMeasure = 0.0;

            var seg = new LineSegment();
            var it = new LinearIterator(_linearGeom);

            while (it.HasNext())
            {
                if (!it.IsEndOfLine)
                {
                    seg.P0 = it.SegmentStart;
                    seg.P1 = it.SegmentEnd;
                    var segDistance = seg.Distance(inputPt);
                    var segMeasureToPt = SegmentNearestMeasure(seg, inputPt, segmentStartMeasure);
                    if (segDistance < minDistance
                        && segMeasureToPt > minIndex)
                    {
                        ptMeasure = segMeasureToPt;
                        minDistance = segDistance;
                    }
                    segmentStartMeasure += seg.Length;
                }
                it.Next();
            }
            return ptMeasure;
        }
        private LinearLocation IndexOfFromStart(Coordinate inputPt, LinearLocation minIndex)
        {
            var minDistance = Double.MaxValue;
            var minComponentIndex = 0;
            var minSegmentIndex = 0;
            var minFrac = -1.0;

            var seg = new LineSegment();
            for (var it = new LinearIterator(_linearGeom);
                 it.HasNext(); it.Next())
            {
                if (!it.IsEndOfLine)
                {
                    seg.P0 = it.SegmentStart;
                    seg.P1 = it.SegmentEnd;
                    var segDistance = seg.Distance(inputPt);
                    var segFrac = seg.SegmentFraction(inputPt);

                    var candidateComponentIndex = it.ComponentIndex;
                    var candidateSegmentIndex = it.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;
                        }
                    }
                }
            }

            if (minDistance == Double.MaxValue)
            {
                // no minimum was found past minLocation, so return it
                return new LinearLocation(minIndex);
            }
            // otherwise, return computed location
            var loc = new LinearLocation(minComponentIndex, minSegmentIndex, minFrac);
            return loc;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="loc"></param>
        /// <returns></returns>
        public double GetLength(LinearLocation loc)
        {
            var totalLength = 0.0;

            var it = new LinearIterator(_linearGeom);
            while (it.HasNext())
            {
                if (!it.IsEndOfLine)
                {
                    var p0 = it.SegmentStart;
                    var p1 = it.SegmentEnd;
                    var segLen = p1.Distance(p0);
                    // length falls in this segment
                    if (loc.ComponentIndex == it.ComponentIndex
                        && loc.SegmentIndex == it.VertexIndex)
                    {
                        return totalLength + segLen * loc.SegmentFraction;
                    }
                    totalLength += segLen;
                }
                it.Next();
            }
            return totalLength;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        private LinearLocation GetLocationForward(double length)
        {
            if (length <= 0.0)
                return new LinearLocation();

            var totalLength = 0.0;

            var it = new LinearIterator(_linearGeom);
            while (it.HasNext())
            {
                /**
                 * Special handling is required for the situation when the
                 * length references exactly to a component endpoint.
                 * In this case, the endpoint location of the current component
                 * is returned,
                 * rather than the startpoint location of the next component.
                 * This produces consistent behaviour with the project method.
                 */
                if (it.IsEndOfLine)
                {
                    if (totalLength == length)
                    {
                        int compIndex = it.ComponentIndex;
                        int segIndex = it.VertexIndex;
                        return new LinearLocation(compIndex, segIndex, 0.0);
                    }
                }
                else
                {
                    var p0 = it.SegmentStart;
                    var p1 = it.SegmentEnd;
                    var segLen = p1.Distance(p0);
                    // length falls in this segment
                    if (totalLength + segLen > length)
                    {
                        var frac = (length - totalLength) / segLen;
                        var compIndex = it.ComponentIndex;
                        var segIndex = it.VertexIndex;
                        return new LinearLocation(compIndex, segIndex, frac);
                    }
                    totalLength += segLen;
                }

                it.Next();
            }
            // length is longer than line - return end location
            return LinearLocation.GetEndLocation(_linearGeom);
        }
        ///// <summary>
        ///// Assumes input is valid
        ///// (e.g. <paramref name="start" /> minor or equals to <paramref name="end" />).
        ///// </summary>
        ///// <param name="start"></param>
        ///// <param name="end"></param>
        ///// <returns></returns>
        //private ILineString ComputeLine(LinearLocation start, LinearLocation end)
        //{
        //    var coordinates = _line.Coordinates;
        //    var newCoordinates = new CoordinateList();
        //    var startSegmentIndex = start.SegmentIndex;
        //    if (start.SegmentFraction > 0.0)
        //        startSegmentIndex += 1;
        //    var lastSegmentIndex = end.SegmentIndex;
        //    if (end.SegmentFraction == 1.0)
        //        lastSegmentIndex += 1;
        //    if (lastSegmentIndex >= coordinates.Length)
        //        lastSegmentIndex = coordinates.Length - 1;
        //    // not needed - LinearLocation values should always be correct
        //    // Assert.IsTrue(end.SegmentFraction <= 1.0, "invalid segment fraction value");
        //    if (!start.IsVertex)
        //        newCoordinates.Add(start.GetCoordinate(_line));
        //    for (var i = startSegmentIndex; i <= lastSegmentIndex; i++)
        //        newCoordinates.Add(coordinates[i]);
        //    if (!end.IsVertex)
        //        newCoordinates.Add(end.GetCoordinate(_line));
        //    // ensure there is at least one coordinate in the result
        //    if (newCoordinates.Count <= 0)
        //        newCoordinates.Add(start.GetCoordinate(_line));
        //    var newCoordinateArray = newCoordinates.ToCoordinateArray();
        //    /*
        //     * Ensure there is enough coordinates to build a valid line.
        //     * Make a 2-point line with duplicate coordinates, if necessary.
        //     * There will always be at least one coordinate in the coordList.
        //     */
        //    if (newCoordinateArray.Length <= 1)
        //        newCoordinateArray = new[] { newCoordinateArray[0], newCoordinateArray[0] };
        //    return _line.Factory.CreateLineString(newCoordinateArray);
        //}
        /// <summary>
        /// Assumes input is valid
        /// (e.g. <paramref name="start" /> minor or equals to <paramref name="end" />).
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        private IGeometry ComputeLinear(LinearLocation start, LinearLocation end)
        {
            var builder = new LinearGeometryBuilder(_line.Factory);
            builder.FixInvalidLines = true;

            if (!start.IsVertex)
                builder.Add(start.GetCoordinate(_line));

            for (var it = new LinearIterator(_line, start); it.HasNext(); it.Next())
            {
                if (end.CompareLocationValues(it.ComponentIndex, it.VertexIndex, 0.0) < 0)
                    break;

                var pt = it.SegmentStart;
                builder.Add(pt);
                if (it.IsEndOfLine)
                    builder.EndLine();
            }

            if (!end.IsVertex)
                builder.Add(end.GetCoordinate(_line));

            return builder.GetGeometry();
        }