< 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:263_26948838820

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)
 718965018    {
 718965019        var xMax = (ulong)(1 << zoom);
 20
 718965021        return ((uint)(tileId % xMax), (uint)(tileId / xMax));
 718965022    }
 23
 24    public static uint ToLocalId(uint x, uint y, int zoom)
 4344725    {
 4344726        var xMax = 1 << (int)zoom;
 4344727        return (uint)((y * xMax) + x);
 4344728    }
 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)
 11242338    {
 11242339        var tile = ToTile(zoom, tileId);
 40
 11242341        var n = Math.PI - (2.0 * Math.PI * tile.y / Math.Pow(2.0, zoom));
 11242342        var left = (tile.x / Math.Pow(2.0, zoom) * 360.0) - 180.0;
 11242343        var top = 180.0 / Math.PI * Math.Atan(Math.Sinh(n));
 44
 11242345        n = Math.PI - (2.0 * Math.PI * (tile.y + 1) / Math.Pow(2.0, zoom));
 11242346        var right = ((tile.x + 1) / Math.Pow(2.0, zoom) * 360.0) - 180.0;
 11242347        var bottom = 180.0 / Math.PI * Math.Atan(Math.Sinh(n));
 48
 11242349        var latStep = (top - bottom) / resolution;
 11242350        var lonStep = (right - left) / resolution;
 51
 11242352        return ((int)((longitude - left) / lonStep), (int)((top - latitude) / latStep));
 11242353    }
 54
 55    public static void FromLocalTileCoordinates(int zoom, uint tileId, int x, int y, int resolution,
 56        out double longitude, out double latitude)
 707183357    {
 707183358        var tile = ToTile(zoom, tileId);
 59
 707183360        var n = Math.PI - (2.0 * Math.PI * tile.y / Math.Pow(2.0, zoom));
 707183361        var left = (tile.x / Math.Pow(2.0, zoom) * 360.0) - 180.0;
 707183362        var top = 180.0 / Math.PI * Math.Atan(Math.Sinh(n));
 63
 707183364        n = Math.PI - (2.0 * Math.PI * (tile.y + 1) / Math.Pow(2.0, zoom));
 707183365        var right = ((tile.x + 1) / Math.Pow(2.0, zoom) * 360.0) - 180.0;
 707183366        var bottom = 180.0 / Math.PI * Math.Atan(Math.Sinh(n));
 67
 707183368        var latStep = (top - bottom) / resolution;
 707183369        var lonStep = (right - left) / resolution;
 70
 707183371        longitude = left + (lonStep * x);
 707183372        latitude = top - (y * latStep);
 707183373    }
 74
 75    private static int N(int zoom)
 4460476    {
 4460477        return (int)Math.Floor(Math.Pow(2, zoom)); // replace by bit shifting?
 4460478    }
 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)
 42482101    {
 42482102        var n = N(zoom);
 42482103        var rad = latitude / 180d * Math.PI;
 104
 42482105        var x = (uint)((longitude + 180.0f) / 360.0f * n);
 42482106        var y = (uint)(
 42482107            (1.0f - (Math.Log(Math.Tan(rad) + (1.0f / Math.Cos(rad)))
 42482108                / Math.PI)) / 2f * n);
 109
 42482110        return (x, y);
 42482111    }
 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}