< Summary

Class:Itinero.Network.Tiles.NetworkTileEnumerator
Assembly:Itinero
File(s):/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/NetworkTileEnumerator.cs
Covered lines:195
Uncovered lines:52
Coverable lines:247
Total lines:508
Line coverage:78.9% (195 of 247)
Covered branches:58
Total branches:102
Branch coverage:56.8% (58 of 102)
Tag:251_23667616543

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()0%20%
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>
 93455025    internal NetworkTileEnumerator()
 93455026    {
 93455027    }
 28
 8628239029    public NetworkTile? Tile { get; private set; }
 30
 31    /// <summary>
 32    /// Gets the tile id.
 33    /// </summary>
 766806734    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)
 96701042    {
 96701043        this.Tile = graphTile;
 44
 96701045        this.Reset();
 96701046    }
 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)
 114229354    {
 114229355        if (this.Tile == null)
 056        {
 057            throw new InvalidOperationException("Move to graph tile first.");
 58        }
 59
 114229360        if (vertex.LocalId >= this.Tile.VertexCount)
 1961        {
 1962            return false;
 63        }
 64
 114227465        _headLocation = null;
 114227466        _tailLocation = null;
 114227467        _localId = vertex.LocalId;
 114227468        _nextEdgePointer = uint.MaxValue;
 114227469        this.EdgePointer = uint.MaxValue;
 70
 114227471        this.Tail = vertex;
 114227472        return true;
 114229373    }
 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)
 326366482    {
 326366483        if (this.Tile == null) throw new InvalidOperationException("Move to graph tile first.");
 84
 326366485        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
 326366488        if (this.Tile.IsEdgeDeleted(edge)) return false;
 89
 326366490        _headLocation = null;
 326366491        _tailLocation = null;
 326366492        _nextEdgePointer = edge.LocalId;
 326366493        if (edge.LocalId >= EdgeId.MinCrossId)
 4924794        {
 4924795            _nextEdgePointer = this.Tile.GetEdgeCrossPointer(edge.LocalId - EdgeId.MinCrossId);
 4924796        }
 326366497        this.EdgePointer = _nextEdgePointer.Value;
 98
 99        // decode edge data.
 3263664100        this.EdgeId = edge;
 3263664101        var size = this.Tile.DecodeVertex(_nextEdgePointer.Value, out var localId, out var tileId);
 3263664102        var vertex1 = new VertexId(tileId, localId);
 3263664103        _nextEdgePointer += size;
 3263664104        size = this.Tile.DecodeVertex(_nextEdgePointer.Value, out localId, out tileId);
 3263664105        var vertex2 = new VertexId(tileId, localId);
 3263664106        _nextEdgePointer += size;
 3263664107        size = this.Tile.DecodePointer(_nextEdgePointer.Value, out var vp1);
 3263664108        _nextEdgePointer += size;
 3263664109        size = this.Tile.DecodePointer(_nextEdgePointer.Value, out var vp2);
 3263664110        _nextEdgePointer += size;
 111
 3263664112        if (vertex1.TileId != vertex2.TileId)
 49247113        {
 49247114            size = this.Tile.DecodeEdgeCrossId(_nextEdgePointer.Value, out var edgeCrossId);
 49247115            _nextEdgePointer += size;
 116
 49247117            this.EdgeId = new EdgeId(vertex1.TileId, edgeCrossId);
 49247118        }
 119
 120        // get edge profile id.
 3263664121        size = this.Tile.DecodeEdgePointerId(_nextEdgePointer.Value, out var edgeProfileId);
 3263664122        _nextEdgePointer += size;
 3263664123        this.EdgeTypeId = edgeProfileId;
 124
 125        // get length.
 3263664126        size = this.Tile.DecodeEdgePointerId(_nextEdgePointer.Value, out var length);
 3263664127        _nextEdgePointer += size;
 3263664128        this.Length = length;
 129
 130        // get tail and head order.
 3263664131        this.Tile.GetTailHeadOrder(_nextEdgePointer.Value, ref _tailOrder, ref _headOrder);
 3263664132        _nextEdgePointer++;
 133
 134        // store position of shape/attribute pointers for lazy decoding.
 3263664135        _shapeAttributeStart = _nextEdgePointer.Value;
 3263664136        _shapePointerDecoded = false;
 3263664137        _attributesPointerDecoded = false;
 138
 3263664139        if (forward)
 2348243140        {
 2348243141            this.Tail = vertex1;
 2348243142            this.Head = vertex2;
 2348243143            this.Forward = true;
 144
 2348243145            _nextEdgePointer = vp1;
 2348243146        }
 147        else
 915421148        {
 915421149            this.Tail = vertex2;
 915421150            this.Head = vertex1;
 915421151            this.Forward = false;
 152
 915421153            (_headOrder, _tailOrder) = (_tailOrder, _headOrder);
 154
 915421155            _nextEdgePointer = vp2;
 915421156        }
 157
 3263664158        return true;
 3263664159    }
 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()
 968039170    {
 968039171        if (this.Tile == null)
 0172        {
 0173            throw new InvalidOperationException("Cannot reset an empty enumerator.");
 174        }
 175
 968039176        _headLocation = null;
 968039177        _tailLocation = null;
 968039178        this.EdgePointer = uint.MaxValue;
 968039179        _nextEdgePointer = uint.MaxValue;
 968039180    }
 181
 0182    public bool IsEmpty => this.Tile == null;
 183
 14004657184    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()
 4416771191    {
 4416775192        while (true)
 4416775193        {
 4416775194            _headLocation = null;
 4416775195            _tailLocation = null;
 4416775196            _headOrder = null;
 4416775197            _tailOrder = null;
 4416775198            _shapePointerDecoded = false;
 4416775199            _attributesPointerDecoded = false;
 4416775200            this.EdgePointer = uint.MaxValue;
 201
 4416775202            if (this.Tile == null) throw new InvalidOperationException("Move to graph tile first.");
 203
 4416775204            if (_nextEdgePointer == uint.MaxValue)
 1143302205            {
 206                // move to the first edge.
 1143302207                _nextEdgePointer = this.Tile.VertexEdgePointer(_localId).DecodeNullableData();
 1143302208            }
 209
 4416775210            if (_nextEdgePointer == null)
 1138463211            {
 212                // no more data available.
 1138463213                return false;
 214            }
 215
 216            // decode edge data.
 3278312217            this.EdgePointer = _nextEdgePointer.Value;
 3278312218            this.EdgeId = new EdgeId(this.Tile.TileId, _nextEdgePointer.Value);
 3278312219            var size = this.Tile.DecodeVertex(_nextEdgePointer.Value, out var localId, out var tileId);
 3278312220            var vertex1 = new VertexId(tileId, localId);
 3278312221            _nextEdgePointer += size;
 3278312222            size = this.Tile.DecodeVertex(_nextEdgePointer.Value, out localId, out tileId);
 3278312223            var vertex2 = new VertexId(tileId, localId);
 3278312224            _nextEdgePointer += size;
 3278312225            size = this.Tile.DecodePointer(_nextEdgePointer.Value, out var vp1);
 3278312226            _nextEdgePointer += size;
 3278312227            size = this.Tile.DecodePointer(_nextEdgePointer.Value, out var vp2);
 3278312228            _nextEdgePointer += size;
 229
 3278312230            if (vertex1.TileId != vertex2.TileId)
 62666231            {
 62666232                size = this.Tile.DecodeEdgeCrossId(_nextEdgePointer.Value, out var edgeCrossId);
 62666233                _nextEdgePointer += size;
 234
 62666235                this.EdgeId = new EdgeId(vertex1.TileId, edgeCrossId);
 62666236            }
 237
 238            // get edge profile id.
 3278312239            size = this.Tile.DecodeEdgePointerId(_nextEdgePointer.Value, out var edgeProfileId);
 3278312240            _nextEdgePointer += size;
 3278312241            this.EdgeTypeId = edgeProfileId;
 242
 243            // get length.
 3278312244            size = this.Tile.DecodeEdgePointerId(_nextEdgePointer.Value, out var length);
 3278312245            _nextEdgePointer += size;
 3278312246            this.Length = length;
 247
 248            // get tail and head order.
 3278312249            this.Tile.GetTailHeadOrder(_nextEdgePointer.Value, ref _tailOrder, ref _headOrder);
 3278312250            _nextEdgePointer++;
 251
 252            // store position of shape/attribute pointers for lazy decoding.
 3278312253            _shapeAttributeStart = _nextEdgePointer.Value;
 254
 3278312255            if (vertex1.TileId == this.Tile.TileId && vertex1.LocalId == _localId)
 1640871256            {
 1640871257                _nextEdgePointer = vp1;
 258
 1640871259                this.Head = vertex2;
 1640871260                this.Forward = true;
 1640871261            }
 262            else
 1637441263            {
 1637441264                _nextEdgePointer = vp2;
 265
 1637441266                this.Head = vertex1;
 1637441267                this.Forward = false;
 268
 1637441269                (_headOrder, _tailOrder) = (_tailOrder, _headOrder);
 1637441270            }
 271
 3278312272            if (this.Tile.IsEdgeDeleted(this.EdgeId))
 4273            {
 4274                continue;
 275            }
 276
 3278308277            return true;
 278        }
 4416771279    }
 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
 1295376287        {
 1295376288            if (this.Tile == null)
 0289            {
 0290                throw new InvalidOperationException("Move to graph tile first.");
 291            }
 292
 1295376293            this.EnsureShapePointerDecoded();
 294
 1295376295            if (!this.Forward)
 412423296            {
 412423297                return this.Tile.GetShape(_shapePointer).Reverse();
 298            }
 299
 882953300            return this.Tile.GetShape(_shapePointer);
 1295376301        }
 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
 3420310        {
 3420311            if (this.Tile == null)
 0312            {
 0313                throw new InvalidOperationException("Move to graph tile first.");
 314            }
 315
 3420316            this.EnsureAttributesPointerDecoded();
 317
 3420318            return this.Tile.GetAttributes(_attributesPointer);
 3420319        }
 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
 0329        {
 0330            if (this.Tile == null)
 0331            {
 0332                throw new InvalidOperationException("Move to graph tile first.");
 333            }
 334
 0335            this.EnsureAttributesPointerDecoded();
 336
 0337            return this.Tile.GetGlobalEdgeId(_attributesPointer);
 0338        }
 339    }
 340
 341    private void EnsureShapePointerDecoded()
 1298717342    {
 1300165343        if (_shapePointerDecoded) return;
 1297269344        this.Tile!.DecodePointer(_shapeAttributeStart, out _shapePointer);
 1297269345        _shapePointerDecoded = true;
 1298717346    }
 347
 348    private void EnsureAttributesPointerDecoded()
 3420349    {
 3499350        if (_attributesPointerDecoded) return;
 3341351        this.EnsureShapePointerDecoded();
 3341352        var size = this.Tile!.DecodePointer(_shapeAttributeStart, out _shapePointer);
 3341353        this.Tile.DecodePointer(_shapeAttributeStart + (uint)size, out _attributesPointer);
 3341354        _attributesPointerDecoded = true;
 3420355    }
 356
 357    /// <summary>
 358    /// Gets the first vertex.
 359    /// </summary>
 6808852360    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>
 9274354378    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>
 14088971396    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>
 9924895404    public bool Forward { get; private set; }
 405
 406    /// <summary>
 407    /// Gets the edge profile id, if any.
 408    /// </summary>
 7612999409    public uint? EdgeTypeId { get; private set; }
 410
 411    /// <summary>
 412    /// Gets the length in centimeters, if any.
 413    /// </summary>
 9100545414    public uint? Length { get; private set; }
 415
 416    /// <summary>
 417    /// Gets the head index of this edge in the turn cost table.
 418    /// </summary>
 410867419    public byte? HeadOrder => _headOrder;
 420
 421    /// <summary>
 422    /// Gets the tail index of this edge in the turn cost table.
 423    /// </summary>
 6770424    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)
 2037433    {
 2037434        if (this.Tile == null)
 0435            return ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnum
 436
 2037437        var order = _tailOrder;
 2037438        return order == null
 2037439            ? ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerabl
 2037440            : this.Tile.GetTurnCosts(this.Tail, sourceOrder, order.Value);
 2037441    }
 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)
 8450    {
 8451        if (this.Tile == null)
 0452            return ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnum
 453
 8454        var order = _tailOrder;
 8455        return order == null
 8456            ? ArraySegment<(uint turnCostType, IEnumerable<(string key, string value)> attributes, uint cost, IEnumerabl
 8457            : this.Tile.GetTurnCosts(this.Tail, order.Value, targetOrder);
 8458    }
 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}