/// <summary> /// Gets the complete shape, including start end end vertices. /// </summary> /// <param name="enumerator">The enumerator.</param> /// <returns>The complete shape.</returns> public static IEnumerable <Coordinate> GetCompleteShape(this RouterDbEdgeEnumerator enumerator) { yield return(enumerator.FromLocation()); var shape = enumerator.GetShape(); if (shape != null) { foreach (var s in shape) { yield return(s); } } yield return(enumerator.ToLocation()); }
/// <summary> /// Gets the length of an edge in centimeters. /// </summary> /// <param name="enumerator">The enumerator.</param> /// <returns>The length in meters.</returns> internal static uint EdgeLength(this RouterDbEdgeEnumerator enumerator) { var distance = 0.0; // compose geometry. var shape = enumerator.GetCompleteShape(); var shapeEnumerator = shape.GetEnumerator(); shapeEnumerator.MoveNext(); var previous = shapeEnumerator.Current; while (shapeEnumerator.MoveNext()) { var current = shapeEnumerator.Current; distance += Coordinate.DistanceEstimateInMeter(previous, current); previous = current; } return((uint)(distance * 100)); }
/// <summary> /// Gets the location of the from vertex. /// </summary> /// <param name="enumerator">The enumerator.</param> /// <returns>The location.</returns> public static Coordinate FromLocation(this RouterDbEdgeEnumerator enumerator) { return(enumerator.RouterDb.GetVertex(enumerator.From)); }
/// <summary> /// Returns the part of the edge between the two offsets not including the vertices at the start or the end. /// </summary> /// <param name="enumerator">The enumerator.</param> /// <param name="offset1">The start offset.</param> /// <param name="offset2">The end offset.</param> /// <param name="includeVertices">Include vertices in case the range start at min offset or ends at max.</param> /// <returns>The shape points between the given offsets. Includes the vertices by default when offsets at min/max.</returns> public static IEnumerable <Coordinate> GetShapeBetween(this RouterDbEdgeEnumerator enumerator, ushort offset1 = 0, ushort offset2 = ushort.MaxValue, bool includeVertices = true) { if (offset1 > offset2) { throw new ArgumentException($"{nameof(offset1)} has to smaller than or equal to {nameof(offset2)}"); } // get edge and shape details. var shape = enumerator.GetShape(); if (shape == null) { shape = new ShapeEnumerable(Enumerable.Empty <Coordinate>()); } // return the entire edge if requested. if (offset1 == 0 && offset2 == ushort.MaxValue) { foreach (var s in enumerator.GetCompleteShape()) { yield return(s); } yield break; } // calculate offsets in meters. var edgeLength = enumerator.EdgeLength(); var offset1Length = (offset1 / (double)ushort.MaxValue) * edgeLength; var offset2Length = (offset2 / (double)ushort.MaxValue) * edgeLength; // TODO: can we make this easier with the complete shape enumeration? // calculate coordinate shape. var before = offset1 > 0; // when there is a start offset. var length = 0.0; var previous = enumerator.FromLocation(); if (offset1 == 0 && includeVertices) { yield return(previous); } for (var i = 0; i < shape.Count + 1; i++) { Coordinate next; if (i < shape.Count) { // the next = shape[i]; } else { // the last location. next = enumerator.ToLocation(); } var segmentLength = Coordinate.DistanceEstimateInMeter(previous, next); if (before) { // check if offset1 length has exceeded. if (segmentLength + length >= offset1Length && offset1 > 0) { // we are before, but not we have move to after. var segmentOffset = offset1Length - length; var location = Coordinate.PositionAlongLine(previous, next, (segmentOffset / segmentLength)); previous = next; before = false; yield return(location); } } if (!before) { // check if offset2 length has exceeded. if (segmentLength + length > offset2Length && offset2 < ushort.MaxValue) { // we are after but now we are after. var segmentOffset = offset2Length - length; var location = Coordinate.PositionAlongLine(previous, next, (segmentOffset / segmentLength)); yield return(location); yield break; } // the case where include vertices is false. if (i == shape.Count && !includeVertices) { yield break; } yield return(next); } // move to the next segment. previous = next; length += segmentLength; } }
/// <summary> /// Returns the location on the given edge using the given offset. /// </summary> /// <param name="enumerator">The enumerator.</param> /// <param name="offset">The offset.</param> /// <returns>The location on the network.</returns> public static Coordinate LocationOnEdge(this RouterDbEdgeEnumerator enumerator, in ushort offset)