using GeoAPI.Geometries; using GisSharpBlog.NetTopologySuite.Geometries; namespace GisSharpBlog.NetTopologySuite.LinearReferencing { /// /// Computes the for a given length /// along a linear /// Negative lengths are measured in reverse from end of the linear geometry. /// Out-of-range values are clamped. /// public class LengthLocationMap { private readonly IGeometry linearGeom; /// /// Initializes a new instance of the class. /// /// A linear geometry. public LengthLocationMap(IGeometry linearGeom) { this.linearGeom = linearGeom; } /// /// Computes the for a /// given length along a linear . /// /// The linear geometry to use. /// The length index of the location. /// The for the length. public static LinearLocation GetLocation(IGeometry linearGeom, double length) { LengthLocationMap locater = new LengthLocationMap(linearGeom); return locater.GetLocation(length); } /// /// Computes the length for a given /// on a linear . /// /// The linear geometry to use. /// The index of the location. /// The length for the . public static double GetLength(IGeometry linearGeom, LinearLocation loc) { LengthLocationMap locater = new LengthLocationMap(linearGeom); return locater.GetLength(loc); } /// /// Compute the corresponding to a length. /// Negative lengths are measured in reverse from end of the linear geometry. /// Out-of-range values are clamped. /// /// The length index. /// The corresponding . public LinearLocation GetLocation(double length) { double forwardLength = length; if (length < 0.0) { double lineLen = linearGeom.Length; forwardLength = lineLen + length; } return GetLocationForward(forwardLength); } /// /// /// /// /// 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; } /// /// /// /// /// private LinearLocation GetLocationForward(double length) { if (length <= 0.0) { return new LinearLocation(); } 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 (totalLength + segLen > length) { double frac = (length - totalLength)/segLen; int compIndex = element.ComponentIndex; int segIndex = element.VertexIndex; return new LinearLocation(compIndex, segIndex, frac); } totalLength += segLen; } } // length is longer than line - return end location return LinearLocation.GetEndLocation(linearGeom); } } }