< Summary

Class:Itinero.Routes.Paths.PathExtensions
Assembly:Itinero
File(s):/home/runner/work/routing2/routing2/src/Itinero/Routes/Paths/PathExtensions.cs
Covered lines:16
Uncovered lines:105
Coverable lines:121
Total lines:226
Line coverage:13.2% (16 of 121)
Covered branches:8
Total branches:62
Branch coverage:12.9% (8 of 62)
Tag:224_14471318300

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
Weight(...)0%20%
Weight(...)0%80%
LengthInMeters(...)0%80%
IsNext(...)0%80%
Merge(...)100%10%
<Merge()0%60%
Merge(...)0%200%
Trim(...)100%8100%
HasLength(...)0%20%

File(s)

/home/runner/work/routing2/routing2/src/Itinero/Routes/Paths/PathExtensions.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using Itinero.Network.Enumerators.Edges;
 5
 6namespace Itinero.Routes.Paths;
 7
 8/// <summary>
 9/// Extensions for path.
 10/// </summary>
 11public static class PathExtensions
 12{
 13    /// <summary>
 14    /// Calculates the weight of the path given the weight function.
 15    /// </summary>
 16    /// <param name="path">The path.</param>
 17    /// <param name="getWeight">The weight function.</param>
 18    /// <returns>The total weight.</returns>
 19    public static double? Weight(this Result<Path> path, Func<RoutingNetworkEdgeEnumerator, double> getWeight)
 020    {
 021        if (path.IsError)
 022        {
 023            return null;
 24        }
 25
 026        return path.Value.Weight(getWeight);
 027    }
 28
 29    /// <summary>
 30    /// Calculates the weight of the path given the weight function.
 31    /// </summary>
 32    /// <param name="path">The path.</param>
 33    /// <param name="getWeight">The weight function.</param>
 34    /// <returns>The total weight.</returns>
 35    public static double Weight(this Path path, Func<RoutingNetworkEdgeEnumerator, double> getWeight)
 036    {
 037        var weight = 0.0;
 38
 039        var edgeEnumerator = path.RoutingNetwork.GetEdgeEnumerator();
 040        foreach (var (edge, direction, offset1, offset2) in path)
 041        {
 042            if (!edgeEnumerator.MoveTo(edge, direction))
 043            {
 044                throw new InvalidDataException("An edge in the path is not found!");
 45            }
 46
 047            var edgeWeight = getWeight(edgeEnumerator);
 048            if (offset1 != 0 || offset2 != ushort.MaxValue)
 049            {
 050                edgeWeight *= (double)(offset2 - offset1) / ushort.MaxValue;
 051            }
 52
 053            weight += edgeWeight;
 054        }
 55
 056        return weight;
 057    }
 58
 59    /// <summary>
 60    /// Calculates the length in meters of this path.
 61    /// </summary>
 62    /// <param name="path">The path.</param>
 63    /// <returns>The length in meters.</returns>
 64    /// <exception cref="InvalidDataException"></exception>
 65    public static double LengthInMeters(this Path path)
 066    {
 067        var weight = 0.0;
 68
 069        var edgeEnumerator = path.RoutingNetwork.GetEdgeEnumerator();
 070        foreach (var (edge, direction, offset1, offset2) in path)
 071        {
 072            if (!edgeEnumerator.MoveTo(edge, direction))
 073            {
 074                throw new InvalidDataException("An edge in the path is not found!");
 75            }
 76
 077            var edgeWeight = edgeEnumerator.EdgeLength();
 078            if (offset1 != 0 || offset2 != ushort.MaxValue)
 079            {
 080                edgeWeight *= (double)(offset2 - offset1) / ushort.MaxValue;
 081            }
 82
 083            weight += edgeWeight;
 084        }
 85
 086        return weight;
 087    }
 88
 89    /// <summary>
 90    /// Returns true if the path is next.
 91    /// </summary>
 92    /// <param name="path">The path.</param>
 93    /// <param name="next">The next path.</param>
 94    /// <returns>True if the next path</returns>
 95    public static bool IsNext(this Path path, Path next)
 096    {
 097        var last = path.Last;
 098        var first = next.First;
 99
 100        // check if the same edge and if the offsets match.
 0101        if (last.edge == first.edge &&
 0102            last.direction == first.direction)
 0103        {
 0104            return path.Offset2 == next.Offset1;
 105        }
 106
 107        // check if the same vertices at the end.
 0108        if (next.Offset1 != 0 ||
 0109            path.Offset2 != ushort.MaxValue)
 0110        {
 0111            return false;
 112        }
 113
 0114        var edgeEnumerator = path.RoutingNetwork.GetEdgeEnumerator();
 0115        edgeEnumerator.MoveTo(last.edge, last.direction);
 0116        var lastVertex = edgeEnumerator.Head;
 0117        edgeEnumerator.MoveTo(first.edge, first.direction);
 0118        var firstVertex = edgeEnumerator.Tail;
 119
 0120        return lastVertex == firstVertex;
 0121    }
 122
 123    /// <summary>
 124    /// Merges the paths.
 125    /// </summary>
 126    /// <param name="path">The first part.</param>
 127    /// <param name="paths">The next parts.</param>
 128    /// <returns>The merged path.</returns>
 129    public static Path? Merge(this Path path, params Path[] paths)
 0130    {
 131        IEnumerable<Path> Enumerate()
 0132        {
 0133            yield return path;
 134
 0135            foreach (var p in paths)
 0136            {
 0137                yield return p;
 0138            }
 0139        }
 140
 0141        return Enumerate().Merge();
 0142    }
 143
 144    /// <summary>
 145    /// Merges the paths.
 146    /// </summary>
 147    /// <param name="paths">The paths.</param>
 148    /// <returns>The merged path.</returns>
 149    public static Path? Merge(this IEnumerable<Path> paths)
 0150    {
 0151        Path? merged = null;
 0152        RoutingNetworkEdgeEnumerator? enumerator = null;
 0153        foreach (var path in paths)
 0154        {
 0155            merged ??= new Path(path.RoutingNetwork);
 0156            enumerator ??= path.RoutingNetwork.GetEdgeEnumerator();
 157
 0158            if (merged.Count == 0)
 0159            {
 0160                merged.Offset1 = path.Offset1;
 0161            }
 0162            else if (!merged.IsNext(path))
 0163            {
 0164                throw new InvalidDataException(
 0165                    $"Paths cannot be concatenated.");
 166            }
 167
 0168            var isFirst = true;
 0169            foreach (var (edge, direction, _, _) in path)
 0170            {
 0171                if (isFirst)
 0172                {
 0173                    isFirst = false;
 0174                    if (merged.Count > 0 &&
 0175                        merged.Last.edge == edge &&
 0176                        merged.Last.direction == direction)
 0177                    {
 178                        // first edge may be the same edge as
 179                        // previous path, don't add it again.
 0180                        continue;
 181                    }
 0182                }
 183
 0184                merged.Append(edge, direction);
 0185            }
 186
 0187            merged.Offset2 = path.Offset2;
 0188        }
 189
 0190        return merged;
 0191    }
 192
 193    /// <summary>
 194    /// Removes the first and/or last edge if they are not part of the path via the offset properties.
 195    /// </summary>
 196    /// <param name="path">The path.</param>
 197    public static void Trim(this Path path)
 8198    {
 8199        if (path.Count <= 1)
 2200        {
 2201            return;
 202        }
 203
 6204        if (path.Offset1 == ushort.MaxValue)
 4205        {
 4206            path.RemoveFirst();
 4207        }
 208
 6209        if (path.Count <= 1)
 1210        {
 1211            return;
 212        }
 213
 5214        if (path.Offset2 == 0)
 4215        {
 4216            path.RemoveLast();
 4217        }
 8218    }
 219
 220    public static bool HasLength(this Path path)
 0221    {
 0222        if (path.Count > 1) return true;
 223
 0224        return path.Offset1 != path.Offset2;
 0225    }
 226}