/// <summary> /// /// </summary> /// <param name="subLine"></param> /// <returns></returns> public virtual LinearLocation[] IndicesOf(IGeometry subLine) { ICoordinate startPt = ((ILineString) subLine.GetGeometryN(0)).GetCoordinateN(0); ILineString lastLine = (ILineString) subLine.GetGeometryN(subLine.NumGeometries - 1); ICoordinate endPt = lastLine.GetCoordinateN(lastLine.NumPoints - 1); LocationIndexOfPoint locPt = new LocationIndexOfPoint(linearGeom); LinearLocation[] 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].Clone(); else subLineLoc[1] = locPt.IndexOfAfter(endPt, subLineLoc[0]); return subLineLoc; }
/// <summary> /// /// </summary> /// <param name="loc"></param> /// <returns></returns> public double GetLength(LinearLocation loc) { double totalLength = 0.0; foreach (LinearIterator.LinearElement element in new LinearIterator(linearGeom)) { if (!element.IsEndOfLine) { ICoordinate p0 = element.SegmentStart; ICoordinate p1 = element.SegmentEnd; double segLen = p1.Distance(p0); // length falls in this segment if (loc.ComponentIndex == element.ComponentIndex && loc.SegmentIndex == element.VertexIndex) { return(totalLength + segLen * loc.SegmentFraction); } totalLength += segLen; } } return(totalLength); }
/// <summary> /// /// </summary> /// <param name="inputPt"></param> /// <param name="minIndex"></param> /// <returns></returns> private LinearLocation IndexOfFromStart(ICoordinate inputPt, LinearLocation minIndex) { double minDistance = Double.MaxValue; int minComponentIndex = 0; int minSegmentIndex = 0; double minFrac = -1.0; LineSegment seg = new LineSegment(); foreach (LinearIterator.LinearElement element in new LinearIterator(linearGeom)) { if (!element.IsEndOfLine) { seg.P0 = element.SegmentStart; seg.P1 = element.SegmentEnd; double segDistance = seg.Distance(inputPt); double segFrac = SegmentFraction(seg, inputPt); int candidateComponentIndex = element.ComponentIndex; int candidateSegmentIndex = element.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; } } } } LinearLocation loc = new LinearLocation(minComponentIndex, minSegmentIndex, minFrac); return(loc); }
/// <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) { LinearGeometryBuilder builder = new LinearGeometryBuilder(line.Factory); builder.FixInvalidLines = true; if (!start.IsVertex) { builder.Add(start.GetCoordinate(line)); } LinearIterator it = new LinearIterator(line, start); foreach (LinearIterator.LinearElement element in it) { int compare = end.CompareLocationValues(element.ComponentIndex, element.VertexIndex, 0.0); if (compare < 0) { break; } ICoordinate pt = element.SegmentStart; builder.Add(pt); if (element.IsEndOfLine) { builder.EndLine(); } } if (!end.IsVertex) { builder.Add(end.GetCoordinate(line)); } return(builder.GetGeometry()); }
/// <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(ICoordinate inputPt, LinearLocation minIndex) { if (minIndex == null) { return(IndexOf(inputPt)); } // sanity check for minLocation at or past end of line LinearLocation endLoc = LinearLocation.GetEndLocation(linearGeom); if (endLoc.CompareTo(minIndex) <= 0) { return(endLoc); } LinearLocation 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="linear">The linear geometry to iterate over.</param> /// <param name="start">The location to start at.</param> public LinearIterator(IGeometry linear, LinearLocation start) : this(linear, start.ComponentIndex, SegmentEndVertexIndex(start)) { }
/// <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(IGeometry linearGeom, LinearLocation loc) { LengthLocationMap locater = new LengthLocationMap(linearGeom); return(locater.GetLength(loc)); }
/// <summary> /// Computes the <see cref="LineString" /> for the interval /// on the line between the given indices. /// </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 IGeometry 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. /// If the <paramref name="index" /> is out of range, /// the first or last point on the line will be returned. /// </summary> /// <param name="index">The index of the desired point.</param> /// <returns>The <see cref="Coordinate" /> at the given index.</returns> public ICoordinate ExtractPoint(LinearLocation index) { return(index.GetCoordinate(linearGeom)); }
/// <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 <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> /// <param name="index">The index of the desired point.</param> /// <returns>The <see cref="Coordinate" /> at the given index.</returns> public ICoordinate ExtractPoint(double index) { LinearLocation loc = LengthLocationMap.GetLocation(linearGeom, index); return(loc.GetCoordinate(linearGeom)); }
/// <summary> /// Computes the subline of a <see cref="LineString" /> between /// two LineStringLocations 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) { ExtractLineByLocation ls = new ExtractLineByLocation(line); return(ls.Extract(start, end)); }