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);
}
}
}