Esto es, en muchos sentidos, un problema sencillo si se conocen los detalles. Si se conoce el área en la que caerá una polilínea, se puede proyectar la polilínea a una Proyección apropiada, y luego encontrar la longitud.
Hace unos años, tuve un problema en el que la línea podía estar en cualquier parte. Esto requería una solución general. Para ello, hice las siguientes funciones. La función GetLength iterará sobre cada segmento de la línea, y calculará la longitud de cada segmento usando la fórmula de Haversine. Esta función funciona para líneas de varias partes sin ningún problema.
/// <summary>
/// Gets the length of a given Polyline. This function assumes that the Line is WGS84 Lat-Long
/// </summary>
/// <param name="polyLine">Input Polyline</param>
/// <returns>Length in KM</returns>
internal static double GetLength(IPolyline polyLine)
{
Double Distance = 0;
//first check the Geometry's SR
ISpatialReference SR = polyLine.SpatialReference;
int FactoryCode = SR.FactoryCode;
if (FactoryCode == 4326)//this is in WGS 84 Lat long
{
//iterate over the parts of the PolyLine
IGeometryCollection GeomColl = (IGeometryCollection)polyLine;
for (int i = 0; i < GeomColl.GeometryCount; i++)
{
IGeometry Geom = GeomColl.get_Geometry(i);
if (Geom.GeometryType == esriGeometryType.esriGeometryPath)
{
//Now that we have a Path, we need to find the individual Segments
ISegmentCollection SegColl = (ISegmentCollection)Geom;
for (int j = 0; j < SegColl.SegmentCount; j++)
{
ISegment Segment = SegColl.get_Segment(j);
if (Segment.GeometryType == esriGeometryType.esriGeometryLine)
{
//Calculate the length of the segment and add it to running total
Distance += GetHaverSineDistance(Segment);
}
}
}
}
}
else
{
throw new Exception("Polyline is not in EPSG:4326");
}
return Distance;
}
/// <summary>
/// Returns the distance in kilometers of a segment
/// It's based on the code present at: http://megocode3.wordpress.com/2008/02/05/haversine-formula-in-c/
/// </summary>
/// <param name="seg"> The ISegment whose Length is to be calculated</param>
/// <returns>The length in KM</returns>
private static double GetHaverSineDistance(ISegment seg)
{
Double R = 6371;
Double dLat = toRadian(seg.ToPoint.Y - seg.FromPoint.Y);
Double dLong = toRadian(seg.ToPoint.X - seg.FromPoint.X);
double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
Math.Cos(toRadian(seg.FromPoint.Y)) * Math.Cos(toRadian(seg.ToPoint.Y)) *
Math.Sin(dLong / 2) * Math.Sin(dLong / 2);
double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)));
double d = R * c;
return d;
}
/// <summary>
/// Convert to Radians.
/// </summary>
/// <param name="val">The angle is degrees</param>
/// <returns>Angle in Radians</returns>
private static double toRadian(double val)
{
return (Math.PI / 180) * val;
}