< Summary

Class:Itinero.Network.Tiles.NetworkTileEnumerator
Assembly:Itinero
File(s):/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/NetworkTileEnumerator.cs
Covered lines:200
Uncovered lines:47
Coverable lines:247
Total lines:508
Line coverage:80.9% (200 of 247)
Covered branches:59
Total branches:102
Branch coverage:57.8% (59 of 102)
Tag:263_26948838820

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.ctor()100%1100%
get_Tile()100%1100%
get_TileId()100%2100%
MoveTo(...)100%1100%
MoveTo(...)75%486.66%
MoveTo(...)60.71%2898.24%
Reset()50%277.77%
get_IsEmpty()100%10%
get_EdgePointer()100%1100%
MoveNext()70%30100%
get_Shape()75%480%
get_Attributes()50%271.42%
get_GlobalEdgeId()50%271.42%
EnsureShapePointerDecoded()100%2100%
EnsureAttributesPointerDecoded()100%2100%
get_Tail()100%1100%
get_TailLocation()0%20%
get_Head()100%1100%
get_HeadLocation()0%20%
get_EdgeId()100%1100%
get_Forward()100%1100%
get_EdgeTypeId()100%1100%
get_Length()100%1100%
get_HeadOrder()100%1100%
get_TailOrder()100%1100%
GetTurnCostToTail(...)75%487.5%
GetTurnCostFromTail(...)75%487.5%
GetTurnCostToHead(...)0%40%
GetTurnCostFromHead(...)0%40%
GetVertex(...)0%40%

File(s)

/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/NetworkTileEnumerator.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using Itinero.Network.Storage;
 5using Itinero.Network.Tiles.Standalone;
 6using Itinero.Network.Tiles.Standalone.Global;
 7
 8namespace Itinero.Network.Tiles;
 9
 10internal class NetworkTileEnumerator : INetworkTileEdge, IStandaloneNetworkTileEnumerator
 11{
 12    private uint _localId;
 13    private uint? _nextEdgePointer;
 14    private uint? _shapePointer;
 15    private bool _shapePointerDecoded;
 16    private uint? _attributesPointer;
 17    private bool _attributesPointerDecoded;
 18    private uint _shapeAttributeStart; // byte position where shape/attribute pointers are encoded.
 19    private byte? _tailOrder;
 20    private byte? _headOrder;
 21
 22    /// <summary>
 23    /// Creates a new graph tile enumerator.
 24    /// </summary>
 96014525    internal NetworkTileEnumerator()
 96014526    {
 96014527    }
 28
 8512365429    public NetworkTile? Tile { get; private set; }
 30
 31    /// <summary>
 32    /// Gets the tile id.
 33    /// </summary>
 767912834    public uint TileId => this.Tile?.TileId ?? uint.MaxValue;
 35
 36    /// <summary>
 37    /// Moves to the given tile.
 38    /// </summary>
 39    /// <param name="graphTile">The graph tile to move to.</param>
 40    /// <returns>True if the move succeeds.</returns>
 41    public void MoveTo(NetworkTile graphTile)
 99285542    {
 99285543        this.Tile = graphTile;
 44
 99285545        this.Reset();
 99285546    }
 47
 48    /// <summary>
 49    /// Move to the vertex.
 50    /// </summary>
 51    /// <param name="vertex">The vertex.</param>
 52    /// <returns>True if the move succeeds and the vertex exists.</returns>
 53    public bool MoveTo(VertexId vertex)
 109540454    {
 109540455        if (this.Tile == null)
 056        {
 057            throw new InvalidOperationException("Move to graph tile first.");
 58        }
 59
 109540460        if (vertex.LocalId >= this.Tile.VertexCount)
 1061        {
 1062            return false;
 63        }
 64
 109539465        _headLocation = null;
 109539466        _tailLocation = null;
 109539467        _localId = vertex.LocalId;
 109539468        _nextEdgePointer = uint.MaxValue;
 109539469        this.EdgePointer = uint.MaxValue;
 70
 109539471        this.Tail = vertex;
 109539472        return true;
 109540473    }
 74
 75    /// <summary>
 76    /// Move to the given edge.
 77    /// </summary>
 78    /// <param name="edge">The edge.</param>
 79    /// <param name="forward">The forward flag.</param>
 80    /// <returns>True if the move succeeds and the edge exists.</returns>
 81    public bool MoveTo(EdgeId edge, bool forward)
 330768082    {
 330768083        if (this.Tile == null) throw new InvalidOperationException("Move to graph tile first.");
 84
 330768085        if (this.TileId != edge.TileId) throw new ArgumentOutOfRangeException(nameof(edge),
 086                "Cannot move to edge not in current tile, move to the tile first.");
 87
 330768088        if (this.Tile.IsEdgeDeleted(edge)) return false;
 89
 330768090        _headLocation = null;
 330768091        _tailLocation = null;
 330768092        _nextEdgePointer = edge.LocalId;
 330768093        if (edge.LocalId >= EdgeId.MinCrossId)
 5180894        {
 5180895            _nextEdgePointer = this.Tile.GetEdgeCrossPointer(edge.LocalId - EdgeId.MinCrossId);
 5180896        }
 330768097        this.EdgePointer = _nextEdgePointer.Value;
 98
 99        // decode edge data.
 3307680100        this.EdgeId = edge;
 3307680101        var size = this.Tile.DecodeVertex(_nextEdgePointer.Value, out var localId, out var tileId);
 3307680102        var vertex1 = new VertexId(tileId, localId);
 3307680103        _nextEdgePointer += size;
 3307680104        size = this.Tile.DecodeVertex(_nextEdgePointer.Value, out localId, out tileId);
 3307680105        var vertex2 = new VertexId(tileId, localId);
 3307680106        _nextEdgePointer += size;
 3307680107        size = this.Tile.DecodePointer(_nextEdgePointer.Value, out var vp1);
 3307680108        _nextEdgePointer += size;
 3307680109        size = this.Tile.DecodePointer(_nextEdgePointer.Value, out var vp2);
 3307680110        _nextEdgePointer += size;
 111
 3307680112        if (vertex1.TileId != vertex2.TileId)
 51808113        {
 51808114            size = this.Tile.DecodeEdgeCrossId(_nextEdgePointer.Value, out var edgeCrossId);
 51808115            _nextEdgePointer += size;
 116
 51808117            this.EdgeId = new EdgeId(vertex1.TileId, edgeCrossId);
 51808118        }
 119
 120        // get edge profile id.
 3307680121        size = this.Tile.DecodeEdgePointerId(_nextEdgePointer.Value, out var edgeProfileId);
 3307680122        _nextEdgePointer += size;
 3307680123        this.EdgeTypeId = edgeProfileId;
 124
 125        // get length.
 3307680126        size = this.Tile.DecodeEdgePointerId(_nextEdgePointer.Value, out var length);
 3307680127        _nextEdgePointer += size;
 3307680128        this.Length = length;
 129
 130        // get tail and head order.
 3307680131        this.Tile.GetTailHeadOrder(_nextEdgePointer.Value, ref _tailOrder, ref _headOrder);
 3307680132        _nextEdgePointer++;
 133
 134        // store position of shape/attribute pointers for lazy decoding.
 3307680135        _shapeAttributeStart = _nextEdgePointer.Value;
 3307680136        _shapePointerDecoded = false;
 3307680137        _attributesPointerDecoded = false;
 138
 3307680139        if (forward)
 2374008140        {
 2374008141            this.Tail = vertex1;
 2374008142            this.Head = vertex2;
 2374008143            this.Forward = true;
 144
 2374008145            _nextEdgePointer = vp1;
 2374008146        }
 147        else
 933672148        {
 933672149            this.Tail = vertex2;
 933672150            this.Head = vertex1;
 933672151            this.Forward = false;
 152
 933672153            (_headOrder, _tailOrder) = (_tailOrder, _headOrder);
 154
 933672155            _nextEdgePointer = vp2;
 933672156        }
 157
 3307680158        return true;
 3307680159    }
 160
 161    /// <summary>
 162    /// Resets this enumerator.
 163    /// </summary>
 164    /// <remarks>
 165    /// Reset this enumerator to:
 166    /// - the first vertex for the currently selected edge.
 167    /// - the first vertex for the graph tile if there is no selected edge.
 168    /// </remarks>
 169    public void Reset()
 997654170    {
 997654171        if (this.Tile == null)
 0172        {
 0173            throw new InvalidOperationException("Cannot reset an empty enumerator.");
 174        }
 175
 997654176        _headLocation = null;
 997654177        _tailLocation = null;
 997654178        this.EdgePointer = uint.MaxValue;
 997654179        _nextEdgePointer = uint.MaxValue;
 997654180    }
 181
 0182    public bool IsEmpty => this.Tile == null;
 183
 13777511184    internal uint EdgePointer { get; private set; } = uint.MaxValue;
 185
 186    /// <summary>
 187    /// Moves to the next edge for the current vertex.
 188    /// </summary>
 189    /// <returns>True when there is a new edge.</returns>
 190    public bool MoveNext()
 4253102191    {
 4253106192        while (true)
 4253106193        {
 4253106194            _headLocation = null;
 4253106195            _tailLocation = null;
 4253106196            _headOrder = null;
 4253106197            _tailOrder = null;
 4253106198            _shapePointerDecoded = false;
 4253106199            _attributesPointerDecoded = false;
 4253106200            this.EdgePointer = uint.MaxValue;
 201
 4253106202            if (this.Tile == null) throw new InvalidOperationException("Move to graph tile first.");
 203
 4253106204            if (_nextEdgePointer == uint.MaxValue)
 1100192205            {
 206                // move to the first edge.
 1100192207                _nextEdgePointer = this.Tile.VertexEdgePointer(_localId).DecodeNullableData();
 1100192208            }
 209
 4253106210            if (_nextEdgePointer == null)
 1094203211            {
 212                // no more data available.
 1094203213                return false;
 214            }
 215
 216            // decode edge data.
 3158903217            this.EdgePointer = _nextEdgePointer.Value;
 3158903218            this.EdgeId = new EdgeId(this.Tile.TileId, _nextEdgePointer.Value);
 3158903219            var size = this.Tile.DecodeVertex(_nextEdgePointer.Value, out var localId, out var tileId);
 3158903220            var vertex1 = new VertexId(tileId, localId);
 3158903221            _nextEdgePointer += size;
 3158903222            size = this.Tile.DecodeVertex(_nextEdgePointer.Value, out localId, out tileId);
 3158903223            var vertex2 = new VertexId(tileId, localId);
 3158903224            _nextEdgePointer += size;
 3158903225            size = this.Tile.DecodePointer(_nextEdgePointer.Value, out var vp1);
 3158903226            _nextEdgePointer += size;
 3158903227            size = this.Tile.DecodePointer(_nextEdgePointer.Value, out var vp2);
 3158903228            _nextEdgePointer += size;
 229
 3158903230            if (vertex1.TileId != vertex2.TileId)
 61197231            {
 61197232                size = this.Tile.DecodeEdgeCrossId(_nextEdgePointer.Value, out var edgeCrossId);
 61197233                _nextEdgePointer += size;
 234
 61197235                this.EdgeId = new EdgeId(vertex1.TileId, edgeCrossId);
 61197236            }
 237
 238            // get edge profile id.
 3158903239            size = this.Tile.DecodeEdgePointerId(_nextEdgePointer.Value, out var edgeProfileId);
 3158903240            _nextEdgePointer += size;
 3158903241            this.EdgeTypeId = edgeProfileId;
 242
 243            // get length.
 3158903244            size = this.Tile.DecodeEdgePointerId(_nextEdgePointer.Value, out var length);
 3158903245            _nextEdgePointer += size;
 3158903246            this.Length = length;
 247
 248            // get tail and head order.
 3158903249            this.Tile.GetTailHeadOrder(_nextEdgePointer.Value, ref _tailOrder, ref _headOrder);
 3158903250            _nextEdgePointer++;
 251
 252            // store position of shape/attribute pointers for lazy decoding.
 3158903253            _shapeAttributeStart = _nextEdgePointer.Value;
 254
 3158903255            if (vertex1.TileId == this.Tile.TileId && vertex1.LocalId == _localId)
 1581627256            {
 1581627257                _nextEdgePointer = vp1;
 258
 1581627259                this.Head = vertex2;
 1581627260                this.Forward = true;
 1581627261            }
 262            else
 1577276263            {
 1577276264                _nextEdgePointer = vp2;
 265
 1577276266                this.Head = vertex1;
 1577276267                this.Forward = false;
 268
 1577276269                (_headOrder, _tailOrder) = (_tailOrder, _headOrder);
 1577276270            }
 271
 3158903272            if (this.Tile.IsEdgeDeleted(this.EdgeId))
 4273            {
 4274                continue;
 275            }
 276
 3158899277            return true;
 278        }
 4253102279    }
 280
 281    /// <summary>
 282    /// Gets the shape of the given edge (not including vertex locations).
 283    /// </summary>
 284    public IEnumerable<(double longitude, double latitude, float? e)> Shape
 285    {
 286        get
 1316703287        {
 1316703288            if (this.Tile == null)
 0289            {
 0290                throw new InvalidOperationException("Move to graph tile first.");
 291            }
 292
 1316703293            this.EnsureShapePointerDecoded();
 294
 1316703295            if (!this.Forward)
 431311296            {
 431311297                return this.Tile.GetShape(_shapePointer).Reverse();
 298            }
 299
 885392300            return this.Tile.GetShape(_shapePointer);
 1316703301        }
 302    }
 303
 304    /// <summary>
 305    /// Gets the attributes of the given edge.
 306    /// </summary>
 307    public IEnumerable<(string key, string value)> Attributes
 308    {
 309        get
 4397310        {
 4397311            if (this.Tile == null)
 0312            {
 0313                throw new InvalidOperationException("Move to graph tile first.");
 314            }
 315
 4397316            this.EnsureAttributesPointerDecoded();
 317
 4397318            return this.Tile.GetAttributes(_attributesPointer);
 4397319        }
 320    }
 321
 322    /// <summary>
 323    /// Gets the global edge id, if any.
 324    /// </summary>
 325    /// <exception cref="InvalidOperationException"></exception>
 326    public GlobalEdgeId? GlobalEdgeId
 327    {
 328        get
 41329        {
 41330            if (this.Tile == null)
 0331            {
 0332                throw new InvalidOperationException("Move to graph tile first.");
 333            }
 334
 41335            this.EnsureAttributesPointerDecoded();
 336
 41337            return this.Tile.GetGlobalEdgeId(_attributesPointer);
 41338        }
 339    }
 340
 341    private void EnsureShapePointerDecoded()
 1321039342    {
 1360656343        if (_shapePointerDecoded) return;
 1281422344        this.Tile!.DecodePointer(_shapeAttributeStart, out _shapePointer);
 1281422345        _shapePointerDecoded = true;
 1321039346    }
 347
 348    private void EnsureAttributesPointerDecoded()
 4438349    {
 4540350        if (_attributesPointerDecoded) return;
 4336351        this.EnsureShapePointerDecoded();
 4336352        var size = this.Tile!.DecodePointer(_shapeAttributeStart, out _shapePointer);
 4336353        this.Tile.DecodePointer(_shapeAttributeStart + (uint)size, out _attributesPointer);
 4336354        _attributesPointerDecoded = true;
 4438355    }
 356
 357    /// <summary>
 358    /// Gets the first vertex.
 359    /// </summary>
 6729807360    public VertexId Tail { get; private set; }
 361
 362    private (double longitude, double latitude, float? e)? _tailLocation;
 363
 364    /// <inheritdoc/>
 365    public (double longitude, double latitude, float? e) TailLocation
 366    {
 367        get
 0368        {
 0369            _tailLocation ??= this.GetVertex(this.Tail);
 370
 0371            return _tailLocation.Value;
 0372        }
 373    }
 374
 375    /// <summary>
 376    /// Gets the second vertex.
 377    /// </summary>
 9276991378    public VertexId Head { get; private set; }
 379
 380    private (double longitude, double latitude, float? e)? _headLocation;
 381
 382    /// <inheritdoc/>
 383    public (double longitude, double latitude, float? e) HeadLocation
 384    {
 385        get
 0386        {
 0387            _headLocation ??= this.GetVertex(this.Head);
 388
 0389            return _headLocation.Value;
 0390        }
 391    }
 392
 393    /// <summary>
 394    /// Gets the local edge id.
 395    /// </summary>
 13707667396    public EdgeId EdgeId { get; private set; }
 397
 398    /// <summary>
 399    /// Gets the forward/backward flag.
 400    /// </summary>
 401    /// <remarks>
 402    /// When true the attributes can be interpreted normally, when false they represent the direction from tail -> head.
 403    /// </remarks>
 9917130404    public bool Forward { get; private set; }
 405
 406    /// <summary>
 407    /// Gets the edge profile id, if any.
 408    /// </summary>
 7563260409    public uint? EdgeTypeId { get; private set; }
 410
 411    /// <summary>
 412    /// Gets the length in centimeters, if any.
 413    /// </summary>
 9064597414    public uint? Length { get; private set; }
 415
 416    /// <summary>
 417    /// Gets the head index of this edge in the turn cost table.
 418    /// </summary>
 432348419    public byte? HeadOrder => _headOrder;
 420
 421    /// <summary>
 422    /// Gets the tail index of this edge in the turn cost table.
 423    /// </summary>
 32448424    public byte? TailOrder => _tailOrder;
 425
 426    /// <summary>
 427    /// Gets the turn cost at the tail turn (source -> [tail -> head]).
 428    /// </summary>
 429    /// <param name="sourceOrder">The order of the source edge.</param>
 430    /// <returns>The turn costs if any.</returns>
 431    public IEnumerable<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerable<Ed
 432        byte sourceOrder)
 19200433    {
 19200434        if (this.Tile == null)
 0435            return ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnum
 436
 19200437        var order = _tailOrder;
 19200438        return order == null
 19200439            ? ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerabl
 19200440            : this.Tile.GetTurnCosts(this.Tail, sourceOrder, order.Value);
 19200441    }
 442
 443    /// <summary>
 444    /// Gets the turn cost at the tail turn ([head -> tail] -> target).
 445    /// </summary>
 446    /// <param name="targetOrder">The order of the target edge.</param>
 447    /// <returns>The turn costs if any.</returns>
 448    public IEnumerable<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerable<Ed
 449        byte targetOrder)
 17450    {
 17451        if (this.Tile == null)
 0452            return ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnum
 453
 17454        var order = _tailOrder;
 17455        return order == null
 17456            ? ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerabl
 17457            : this.Tile.GetTurnCosts(this.Tail, order.Value, targetOrder);
 17458    }
 459
 460    /// <summary>
 461    /// Gets the turn cost at the tail turn (source -> [head -> tail]).
 462    /// </summary>
 463    /// <param name="sourceOrder">The order of the source edge.</param>
 464    /// <returns>The turn costs if any.</returns>
 465    public IEnumerable<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerable<Ed
 466        byte sourceOrder)
 0467    {
 0468        if (this.Tile == null)
 0469            return ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnum
 470
 0471        var order = _headOrder;
 0472        return order == null
 0473            ? ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerabl
 0474            : this.Tile.GetTurnCosts(this.Head, sourceOrder, order.Value);
 0475    }
 476
 477    /// <summary>
 478    /// Gets the turn cost at the tail turn ([tail -> head] -> target).
 479    /// </summary>
 480    /// <param name="targetOrder">The order of the target edge.</param>
 481    /// <returns>The turn costs if any.</returns>
 482    public IEnumerable<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerable<Ed
 483        byte targetOrder)
 0484    {
 0485        if (this.Tile == null)
 0486            return ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnum
 487
 0488        var order = _headOrder;
 0489        return order == null
 0490            ? ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerabl
 0491            : this.Tile.GetTurnCosts(this.Head, order.Value, targetOrder);
 0492    }
 493
 494    private (double longitude, double latitude, float? e) GetVertex(VertexId vertex)
 0495    {
 0496        if (this.Tile == null)
 0497        {
 0498            throw new ArgumentOutOfRangeException(nameof(vertex), $"Vertex {vertex} not found!");
 499        }
 500
 0501        if (!this.Tile.TryGetVertex(vertex, out var longitude, out var latitude, out var e))
 0502        {
 0503            throw new ArgumentOutOfRangeException(nameof(vertex), $"Vertex {vertex} not found!");
 504        }
 505
 0506        return (longitude, latitude, e);
 0507    }
 508}