< Summary

Class:Itinero.Network.Tiles.TileStatic
Assembly:Itinero
File(s):/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/TileStatic.cs
Covered lines:85
Uncovered lines:5
Coverable lines:90
Total lines:155
Line coverage:94.4% (85 of 90)
Covered branches:6
Total branches:8
Branch coverage:75% (6 of 8)
Tag:267_28791001112

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
ValidateBox(...)50%260%
ToTile(...)100%1100%
ToLocalId(...)100%1100%
ToLocalId(...)100%1100%
ToLocalTileCoordinates(...)100%1100%
FromLocalTileCoordinates(...)100%1100%
N(...)100%1100%
GetTileBoundingBox(...)100%1100%
WorldToTile(...)100%1100%
TileRange()83.33%688%

File(s)

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

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3
 4namespace Itinero.Network.Tiles;
 5
 6internal static class TileStatic
 7{
 8    private static void ValidateBox(this ((double longitude, double latitude, float? e) topLeft,
 9        (double longitude, double latitude, float? e) bottomRight) box)
 212210    {
 212211        if (box.topLeft.latitude < box.bottomRight.latitude)
 012        {
 013            throw new ArgumentOutOfRangeException($"Top is lower than bottom.");
 14        }
 212215    }
 16
 17    public static (uint x, uint y) ToTile(int zoom, uint tileId)
 719005218    {
 719005219        var xMax = (ulong)(1 << zoom);
 20
 719005221        return ((uint)(tileId % xMax), (uint)(tileId / xMax));
 719005222    }
 23
 24    public static uint ToLocalId(uint x, uint y, int zoom)
 4361125    {
 4361126        var xMax = 1 << (int)zoom;
 4361127        return (uint)((y * xMax) + x);
 4361128    }
 29
 30    public static uint ToLocalId(double longitude, double latitude, int zoom)
 3931    {
 3932        var (x, y) = WorldToTile(longitude, latitude, zoom);
 3933        return ToLocalId(x, y, zoom);
 3934    }
 35
 36    public static (int x, int y) ToLocalTileCoordinates(int zoom, uint tileId, double longitude, double latitude,
 37        int resolution)
 11259138    {
 11259139        var tile = ToTile(zoom, tileId);
 40
 11259141        var n = Math.PI - (2.0 * Math.PI * tile.y / Math.Pow(2.0, zoom));
 11259142        var left = (tile.x / Math.Pow(2.0, zoom) * 360.0) - 180.0;
 11259143        var top = 180.0 / Math.PI * Math.Atan(Math.Sinh(n));
 44
 11259145        n = Math.PI - (2.0 * Math.PI * (tile.y + 1) / Math.Pow(2.0, zoom));
 11259146        var right = ((tile.x + 1) / Math.Pow(2.0, zoom) * 360.0) - 180.0;
 11259147        var bottom = 180.0 / Math.PI * Math.Atan(Math.Sinh(n));
 48
 11259149        var latStep = (top - bottom) / resolution;
 11259150        var lonStep = (right - left) / resolution;
 51
 11259152        return ((int)((longitude - left) / lonStep), (int)((top - latitude) / latStep));
 11259153    }
 54
 55    public static void FromLocalTileCoordinates(int zoom, uint tileId, int x, int y, int resolution,
 56        out double longitude, out double latitude)
 707206757    {
 707206758        var tile = ToTile(zoom, tileId);
 59
 707206760        var n = Math.PI - (2.0 * Math.PI * tile.y / Math.Pow(2.0, zoom));
 707206761        var left = (tile.x / Math.Pow(2.0, zoom) * 360.0) - 180.0;
 707206762        var top = 180.0 / Math.PI * Math.Atan(Math.Sinh(n));
 63
 707206764        n = Math.PI - (2.0 * Math.PI * (tile.y + 1) / Math.Pow(2.0, zoom));
 707206765        var right = ((tile.x + 1) / Math.Pow(2.0, zoom) * 360.0) - 180.0;
 707206766        var bottom = 180.0 / Math.PI * Math.Atan(Math.Sinh(n));
 67
 707206768        var latStep = (top - bottom) / resolution;
 707206769        var lonStep = (right - left) / resolution;
 70
 707206771        longitude = left + (lonStep * x);
 707206772        latitude = top - (y * latStep);
 707206773    }
 74
 75    private static int N(int zoom)
 4476876    {
 4476877        return (int)Math.Floor(Math.Pow(2, zoom)); // replace by bit shifting?
 4476878    }
 79
 80    /// <summary>
 81    /// Returns the geographic bounding box of the tile with the given id at the given zoom level.
 82    /// </summary>
 83    public static (double minLon, double minLat, double maxLon, double maxLat)
 84        GetTileBoundingBox(int zoom, uint tileId)
 539385    {
 539386        var (x, y) = ToTile(zoom, tileId);
 539387        var pow = Math.Pow(2.0, zoom);
 88
 539389        var nTop = Math.PI - 2.0 * Math.PI * y / pow;
 539390        var nBottom = Math.PI - 2.0 * Math.PI * (y + 1) / pow;
 91
 539392        var minLon = (x / pow * 360.0) - 180.0;
 539393        var maxLon = ((x + 1) / pow * 360.0) - 180.0;
 539394        var maxLat = 180.0 / Math.PI * Math.Atan(Math.Sinh(nTop));
 539395        var minLat = 180.0 / Math.PI * Math.Atan(Math.Sinh(nBottom));
 96
 539397        return (minLon, minLat, maxLon, maxLat);
 539398    }
 99
 100    public static (uint x, uint y) WorldToTile(double longitude, double latitude, int zoom)
 42646101    {
 42646102        var n = N(zoom);
 42646103        var rad = latitude / 180d * Math.PI;
 104
 42646105        var x = (uint)((longitude + 180.0f) / 360.0f * n);
 42646106        var y = (uint)(
 42646107            (1.0f - (Math.Log(Math.Tan(rad) + (1.0f / Math.Cos(rad)))
 42646108                / Math.PI)) / 2f * n);
 109
 42646110        return (x, y);
 42646111    }
 112
 113    public static IEnumerable<(uint x, uint y)> TileRange(
 114        this ((double longitude, double latitude, float? e) topLeft,
 115            (double longitude, double latitude, float? e) bottomRight) box, int zoom)
 2122116    {
 2122117        box.ValidateBox();
 118
 2122119        var n = N(zoom);
 2122120        var topLeft = WorldToTile(box.topLeft.longitude, box.topLeft.latitude, zoom);
 2122121        var bottomRight = WorldToTile(box.bottomRight.longitude, box.bottomRight.latitude, zoom);
 122
 2122123        var x = topLeft.x;
 2122124        var y = topLeft.y;
 5413125        while (true)
 5413126        {
 5413127            yield return (x, y);
 128
 5412129            if (y == bottomRight.y)
 3216130            {
 131                // move on with x.
 3216132                if (x == bottomRight.x)
 2121133                {
 134                    // both x and y have reached the end.
 2121135                    break;
 136                }
 137
 138                // reset y.
 1095139                y = topLeft.y;
 140
 141                // move on with x.
 1095142                x++;
 1095143                if (x == n)
 0144                {
 0145                    x = 0;
 0146                }
 147
 1095148                continue;
 149            }
 150
 151            // move on with y.
 2196152            y++;
 2196153        }
 2121154    }
 155}