/// <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)); }
/// <summary> /// Computes the <see cref="LineString" /> for the interval /// on the line between the given indices. /// If the <paramref name="endIndex" /> lies before the <paramref name="startIndex" />, /// the computed geometry is reversed. /// </summary> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <returns></returns> public IGeometry ExtractLine(double startIndex, double endIndex) { LocationIndexedLine lil = new LocationIndexedLine(_linearGeom); double startIndex2 = ClampIndex(startIndex); double endIndex2 = ClampIndex(endIndex); // if extracted line is zero-length, resolve start lower as well to ensure they are equal bool resolveStartLower = startIndex2 == endIndex2; LinearLocation startLoc = LocationOf(startIndex2, resolveStartLower); // LinearLocation endLoc = locationOf(endIndex2, true); // LinearLocation startLoc = locationOf(startIndex2); LinearLocation endLoc = LocationOf(endIndex2); return(ExtractLineByLocation.Extract(_linearGeom, startLoc, endLoc)); }
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); }
private LinearLocation ResolveHigher(LinearLocation loc) { if (!loc.IsEndpoint(_linearGeom)) { return(loc); } int compIndex = loc.ComponentIndex; // if last component can't resolve any higher if (compIndex >= _linearGeom.NumGeometries - 1) { return(loc); } do { compIndex++; } while (compIndex < _linearGeom.NumGeometries - 1 && _linearGeom.GetGeometryN(compIndex).Length == 0); // resolve to next higher location return(new LinearLocation(compIndex, 0, 0.0)); }
/// <summary> /// /// </summary> /// <param name="subLine"></param> /// <returns></returns> public virtual LinearLocation[] IndicesOf(IGeometry subLine) { var startPt = ((ILineString)subLine.GetGeometryN(0)).GetCoordinateN(0); var lastLine = (ILineString)subLine.GetGeometryN(subLine.NumGeometries - 1); var endPt = lastLine.GetCoordinateN(lastLine.NumPoints - 1); var locPt = new LocationIndexOfPoint(_linearGeom); var subLineLoc = new LinearLocation[2]; subLineLoc[0] = locPt.IndexOf(startPt); // check for case where subline is zero length if (subLine.Length == 0) { subLineLoc[1] = (LinearLocation)subLineLoc[0].Copy(); } else { subLineLoc[1] = locPt.IndexOfAfter(endPt, subLineLoc[0]); } return(subLineLoc); }
/// <summary> /// Find the nearest <see cref="LinearLocation" /> along the linear <see cref="Geometry" /> /// to a given <see cref="Geometry" /> after the specified minimum <see cref="LinearLocation" />. /// If possible the location returned will be strictly greater than the <paramref name="minIndex" />. /// If this is not possible, the value returned will equal <paramref name="minIndex" />. /// (An example where this is not possible is when <paramref name="minIndex" /> = [end of line] ). /// </summary> /// <param name="inputPt">The coordinate to locate.</param> /// <param name="minIndex">The minimum location for the point location.</param> /// <returns>The location of the nearest point.</returns> public LinearLocation IndexOfAfter(Coordinate inputPt, LinearLocation minIndex) { if (minIndex == null) { return(IndexOf(inputPt)); } // sanity check for minLocation at or past end of line var endLoc = LinearLocation.GetEndLocation(_linearGeom); if (endLoc.CompareTo(minIndex) <= 0) { return(endLoc); } var closestAfter = IndexOfFromStart(inputPt, minIndex); /* * Return the minDistanceLocation found. * This will not be null, since it was initialized to minLocation */ Assert.IsTrue(closestAfter.CompareTo(minIndex) >= 0, "computed location is before specified minimum location"); return(closestAfter); }
/// <summary> /// Creates an iterator starting at a <see cref="LinearLocation" /> on a linear <see cref="Geometry" />. /// </summary> /// <param name="linearGeom">The linear geometry to iterate over.</param> /// <param name="start">The location to start at.</param> /// <exception cref="ArgumentException"> if <paramref name="linearGeom"/> is not <see cref="ILineal"/></exception> public LinearIterator(IGeometry linearGeom, LinearLocation start) : this(linearGeom, start.ComponentIndex, SegmentEndVertexIndex(start)) { }
/// <summary> /// Computes the <see cref="Coordinate" /> for the point /// on the line at the given index. /// If the index is out of range the first or last point on the /// line will be returned. /// </summary> /// <remarks> /// The Z-ordinate of the computed point will be interpolated from /// the Z-ordinates of the line segment containing it, if they exist. /// </remarks> /// <param name="index">The index of the desired point.</param> /// <returns>The <see cref="Coordinate" /> at the given index.</returns> public Coordinate ExtractPoint(double index) { LinearLocation loc = LengthLocationMap.GetLocation(_linearGeom, index); return(loc.GetCoordinate(_linearGeom)); }
/// <summary> /// Computes the <see cref="LineString" /> for the interval /// on the line between the given indices. /// If the start location is after the end location, /// the computed linear geometry has reverse orientation to the input line. /// </summary> /// <param name="startIndex">The index of the start of the interval.</param> /// <param name="endIndex">The index of the end of the interval.</param> /// <returns>The linear interval between the indices.</returns> public Geometry ExtractLine(LinearLocation startIndex, LinearLocation endIndex) { return(ExtractLineByLocation.Extract(_linearGeom, startIndex, endIndex)); }
/// <summary> /// Computes the <see cref="Coordinate"/> for the point /// on the line at the given index, offset by the given distance. /// If the index is out of range the first or last point on the /// line will be returned.<para/> /// The computed point is offset to the left of the line if the offset distance is /// positive, to the right if negative.<para/> /// The Z-ordinate of the computed point will be interpolated from /// the Z-ordinates of the line segment containing it, if they exist. /// </summary> /// <param name="index">The index of the desired point</param> /// <param name="offsetDistance">The distance the point is offset from the segment /// (positive is to the left, negative is to the right)</param> /// <returns>The Coordinate at the given index</returns> public Coordinate ExtractPoint(LinearLocation index, double offsetDistance) { var indexLow = index.ToLowest(_linearGeom); return(indexLow.GetSegment(_linearGeom).PointAlongOffset(indexLow.SegmentFraction, offsetDistance)); }
/// <summary> /// Computes the <see cref="Coordinate" />for the point on the line at the given index. /// If the <paramref name="index" /> is out of range, /// the first or last point on the line will be returned. /// </summary> /// <remarks> /// The Z-ordinate of the computed point will be interpolated from /// the Z-ordinates of the line segment containing it, if they exist. /// </remarks> /// <param name="index">The index of the desired point.</param> /// <returns>The <see cref="Coordinate" /> at the given index.</returns> public Coordinate ExtractPoint(LinearLocation index) { return(index.GetCoordinate(_linearGeom)); }
/// <summary> /// Finds the index for a point on the line which is greater than the given index. /// If no such index exists, returns <paramref name="minIndex" />. /// </summary> /// <remarks> /// <para> /// This method can be used to determine all indexes for /// a point which occurs more than once on a non-simple line. /// It can also be used to disambiguate cases where the given point lies /// slightly off the line and is equidistant from two different /// points on the line. /// </para> /// <para> /// The supplied point does not <i>necessarily</i> have to lie precisely /// on the line, but if it is far from the line the accuracy and /// performance of this function is not guaranteed. /// Use <see cref="Project"/> to compute a guaranteed result for points /// which may be far from the line. /// </para> /// </remarks> /// <param name="pt">A point on the line</param> /// <param name="minIndex">The value the returned index must be greater than</param> /// <returns>The index of the point greater than the given minimum index</returns> /// <seealso cref="Project(Coordinate)"/> public LinearLocation IndexOfAfter(Coordinate pt, LinearLocation minIndex) { return(LocationIndexOfPoint.IndexOfAfter(_linearGeom, pt, minIndex)); }
public static LinearLocation IndexOfAfter(IGeometry linearGeom, Coordinate inputPt, LinearLocation minIndex) { var locater = new LocationIndexOfPoint(linearGeom); return(locater.IndexOfAfter(inputPt, minIndex)); }
/// <summary> /// Computes the length for a given <see cref="LinearLocation" /> /// on a linear <see cref="Geometry" />. /// </summary> /// <param name="linearGeom">The linear geometry to use.</param> /// <param name="loc">The <see cref="LinearLocation" /> index of the location.</param> /// <returns>The length for the <see cref="LinearLocation" />.</returns> public static double GetLength(Geometry linearGeom, LinearLocation loc) { var locater = new LengthLocationMap(linearGeom); return(locater.GetLength(loc)); }
/// <summary> /// Tests whether an index is in the valid index range for the line. /// </summary> /// <param name="index">The index to test.</param> /// <returns><c>true</c> if the index is in the valid range.</returns> public bool IsValidIndex(LinearLocation index) { return(index.IsValid(_linearGeom)); }
/// <summary> /// Computes the subline of a <see cref="ILineString" /> between /// two <see cref="LinearLocation"/>s on the line. /// If the start location is after the end location, /// the computed geometry is reversed. /// </summary> /// <param name="line">The line to use as the baseline.</param> /// <param name="start">The start location.</param> /// <param name="end">The end location.</param> /// <returns>The extracted subline.</returns> public static IGeometry Extract(IGeometry line, LinearLocation start, LinearLocation end) { var ls = new ExtractLineByLocation(line); return(ls.Extract(start, end)); }
///<summary> /// Computes the <see cref="Coordinate"/> for the point on the line at the given index, offset by the given distance. ///</summary> /// <remarks> /// If the index is out of range the first or last point on the line will be returned. /// The computed point is offset to the left of the line if the offset distance is /// positive, to the right if negative. /// The Z-ordinate of the computed point will be interpolated from the Z-ordinates of the line segment containing it, if they exist. /// </remarks> /// <param name="index">The index of the desired point</param> /// <param name="offsetDistance">The distance the point is offset from the segment (positive is to the left, negative is to the right)</param> /// <returns>The Coordinate at the given index</returns> public Coordinate ExtractPoint(double index, double offsetDistance) { LinearLocation loc = LengthLocationMap.GetLocation(_linearGeom, index); return(loc.GetSegment(_linearGeom).PointAlongOffset(loc.SegmentFraction, offsetDistance)); }