< Summary

Class:Itinero.Instructions.IndexedRoute
Assembly:Itinero.Instructions
File(s):/home/runner/work/routing2/routing2/src/Itinero.Instructions/IndexedRoute.cs
Covered lines:63
Uncovered lines:8
Coverable lines:71
Total lines:205
Line coverage:88.7% (63 of 71)
Covered branches:18
Total branches:26
Branch coverage:69.2% (18 of 26)
Tag:224_14471318300

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.ctor(...)100%1100%
get_Branches()100%1100%
get_Meta()100%1100%
get_Shape()100%1100%
get_Last()100%1100%
BuildMetaList(...)70%1068.42%
BuildBranchesList(...)83.33%686.66%
DistanceToNextPoint(...)50%4100%
DistanceBetween(...)100%2100%
DepartingDirectionAt(...)50%2100%
ArrivingDirectionAt(...)50%2100%
DirectionChangeAt(...)100%1100%

File(s)

/home/runner/work/routing2/routing2/src/Itinero.Instructions/IndexedRoute.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Runtime.CompilerServices;
 5using Itinero.Geo;
 6using Itinero.Routes;
 7
 8[assembly: InternalsVisibleTo("Itinero.Tests.Instructions")]
 9
 10namespace Itinero.Instructions;
 11
 12/// <summary>
 13///  Helper class to allow easy access on some parts of the route
 14/// </summary>
 15public class IndexedRoute
 16{
 17    private readonly Route _route;
 18
 3719    public IndexedRoute(Route route)
 3720    {
 3721        _route = route;
 3722        this.Meta = BuildMetaList(route);
 3723        this.Branches = BuildBranchesList(route);
 3724    }
 25
 26    /// <summary>
 27    /// Gets branches .
 28    /// </summary>
 6629    public List<List<Route.Branch>> Branches { get; }
 30
 31    /// <summary>
 32    ///     A one-on-one list, where every meta is matched with every shape.
 33    ///     (thus: Meta[i] will correspond with the meta for the segment starting at Shape[i]
 34    ///     (Note that Shape[Shape.Count - 1] is thus _not_ defined
 35    /// </summary>
 8236    public List<Route.Meta> Meta { get; }
 37
 38    /// <summary>
 39    /// The shape.
 40    /// </summary>
 103841    public List<(double longitude, double latitude, float? e)> Shape => _route.Shape;
 42
 43    /// <summary>
 44    /// The index of the last shape point.
 45    /// </summary>
 35946    public int Last => this.Shape.Count - 1;
 47
 48    private static List<Route.Meta> BuildMetaList(Route route)
 3749    {
 3750        var metas = new List<Route.Meta>();
 3751        if (route.ShapeMeta == null || route.ShapeMeta.Count == 0)
 052        {
 053            throw new ArgumentException("Cannot generate route instructions if meta information is missing");
 54        }
 55
 25556        foreach (var meta in route.ShapeMeta)
 7257        {
 58            // Meta.shape indicates the last  element in the list
 28959            while (metas.Count < meta.Shape)
 21760            {
 21761                metas.Add(meta);
 21762            }
 7263        }
 64#if DEBUG
 3765        if (metas.Count + 1 != route.Shape.Count)
 066        {
 067            throw new Exception("Length of the meta doesn't match. There are " + route.Shape.Count +
 068                                " shapes, but the last meta has an index of " +
 069                                route.ShapeMeta[^1].Shape + ", resulting in a meta list of " + metas.Count);
 70        }
 71#endif
 72
 3773        return metas;
 3774    }
 75
 76    private static List<List<Route.Branch>> BuildBranchesList(Route route)
 3777    {
 3778        var branches = new List<List<Route.Branch>>();
 3779        if (route.Branches == null)
 080        {
 081            return branches;
 82        }
 83
 61984        foreach (var _ in route.Shape)
 25485        {
 25486            branches.Add(new List<Route.Branch>());
 25487        }
 88
 13789        foreach (var branch in route.Branches)
 1390        {
 1391            branches[branch.Shape].Add(branch);
 1392        }
 93
 3794        return branches;
 3795    }
 96
 97    /// <summary>
 98    /// Returns the distance to the next point.
 99    /// </summary>
 100    /// <param name="shape">The shape point.</param>
 101    /// <returns>The distance to the next shape point.</returns>
 102    public double DistanceToNextPoint(int shape)
 131103    {
 131104        var prevPoint =
 131105            shape == -1 ? _route.Stops[0].Coordinate : this.Shape[shape];
 106
 131107        (double, double, float? e) nextPoint = this.Last == shape ?
 131108            _route.Stops[^1].Coordinate : this.Shape[shape + 1];
 109
 131110        return prevPoint.DistanceEstimateInMeter(nextPoint);
 131111    }
 112
 113
 114    /// <summary>
 115    /// Calculates the total distance in meter between shape-index 'start' and shapeindex 'end'
 116    /// </summary>
 117    /// <param name="shapeStart"></param>
 118    /// <param name="shapeEnd"></param>
 119    /// <returns></returns>
 120    public double DistanceBetween(int shapeStart, int shapeEnd)
 23121    {
 23122        var total = 0.0;
 210123        for (int i = shapeStart; i < shapeEnd; i++)
 82124        {
 82125            total += this.DistanceToNextPoint(i);
 82126        }
 127
 23128        return total;
 23129    }
 130
 131    /// <summary>
 132    /// The departing angle with the meridian.
 133    /// </summary>
 134    /// <param name="shape">The shape point index.</param>
 135    /// <returns>The angle.</returns>
 136    public double DepartingDirectionAt(int shape)
 91137    {
 91138        return this.Shape[shape]
 91139            .AngleWithMeridian(this.Last == shape ? _route.Stops[^1].Coordinate : this.Shape[shape + 1]);
 91140    }
 141
 142    /// <summary>
 143    /// The absolute angle when arriving
 144    /// </summary>
 145    /// <param name="shape"></param>
 146    /// <returns>The angle.</returns>
 147    public double ArrivingDirectionAt(int shape)
 101148    {
 101149        var prevPoint =
 101150            shape == 0 ? _route.Stops[0].Coordinate : this.Shape[shape - 1];
 151
 101152        return prevPoint.AngleWithMeridian(this.Shape[shape]);
 101153    }
 154
 155    /// <summary>
 156    ///     The direction change at a given shape index.
 157    ///     Going straight on at this shape will result in 0° here.
 158    ///     Making a perfectly right turn, results in -90°
 159    ///     Making a perfectly left turn results in +90°
 160    ///     Value will always be between +180 and -180
 161    /// </summary>
 162    /// <param name="shape"></param>
 163    /// <returns></returns>
 164    public int DirectionChangeAt(int shape)
 84165    {
 84166        return (this.ArrivingDirectionAt(shape) - this.DepartingDirectionAt(shape)).NormalizeDegrees();
 84167    }
 168    //
 169    // // ReSharper disable once UnusedMember.Global
 170    // public string GeojsonPoints()
 171    // {
 172    //     var parts = this.Shape.Select(
 173    //         (s, i) =>
 174    //             "{ \"type\": \"Feature\", \"properties\": { \"marker-color\": \"#7e7e7e\", \"marker-size\": \"medium\
 175    //             i + "\" }, \"geometry\": { \"type\": \"Point\", \"coordinates\": [ " + s.longitude + "," +
 176    //             s.latitude + " ] }}");
 177    //     return string.Join(",\n", parts);
 178    // }
 179    //
 180    // public string GeojsonLines()
 181    // {
 182    //     var parts = new List<string>();
 183    //     for (var i = 0; i < this.Shape.Count - 1; i++) {
 184    //         var meta = Meta[i].Attributes.Select(attr => $"\"{attr.key}\": \"{attr.value}\"").ToList();
 185    //         meta.Add($"\"index\": {i}");
 186    //
 187    //         var coordinates =
 188    //             $"[ [{Shape[i].longitude}, {Shape[i].latitude}], [{Shape[i + 1].longitude}, {Shape[i + 1].latitude}] 
 189    //         var part =
 190    //             "\n{\"type\":\"Feature\"," +
 191    //             "\n   \"properties\":{" + string.Join(",", meta) + "}," +
 192    //             $"\n   \"geometry\":{{\"type\":\"LineString\",\"coordinates\": {coordinates} }}" +
 193    //             "\n}";
 194    //
 195    //         parts.Add(part);
 196    //     }
 197    //
 198    //     return InGeoJson(string.Join(",\n", parts));
 199    // }
 200    //
 201    // private static string InGeoJson(string contents)
 202    // {
 203    //     return "{\"type\": \"FeatureCollection\",\"features\": [\n\n" + contents + "\n\n]}";
 204    // }
 205}