Cvičení 4

Cílem cvičení bude implementovat generátor map na základě dat z OSM.

  1. Vytvořte konzolovou aplikaci s názvem OSMMap a knihovnu tříd s názvem OSMMapLib.

  2. V knihovně OSMMapLib vytvořte třídy Tile, Layer a Map.

  3. Třída Tile:

    1. Bude mít vlastnosti (property) X, Y, Zoom a Url. U vlastnosti Zoom zajistěte, aby ji nebylo možné nastavit na hodnotu menší než 1. V případě přiřazení menší hodnoty dojde k nastavení hodnoty na 1.
    2. Všechny uvedené vlastnosti bude možné měnit pouze uvnitř třídy Tile.
    3. Bude mít konstruktor přijímající hodnoty pro X, Y, Zoom a Url.
    4. Bude přetěžovat metodu ToString. Uvnitř této metody dojde k naformátování popisu dlaždice v následujícím formátu: "[X, Y, Z]: url". Při implementaci využijte StringBuilder.
  4. Třída Layer:

    1. Bude mít vlastnosti UrlTemplate (string) a MaxZoom (int). Tyto vlastnosti bude možné nastavit pouze uvnitř třídy. Číst je bude možné odkudkoliv.

    2. Bude obsahovat konstruktor s možností nastavení urlTemplate a maxZoom. Obě tyto hodnoty budou nepovinné a budou mít výchozí hodnoty:

    3. Bude obsahovat metodu FormatUrl, která bude přijímat parametry x, y a zoom (všechny typu int). Tato metoda bude vracet URL konkrétní dlaždice mapy. URL bude vygenerována nahrazením zástupných znaků ve složených závorkách v šabloně URL za konkrétní hodnoty. Hodnotou pro {c} bude náhodně vygenerované písmeno a, b nebo c.

    4. Bude obsahovat indexer přijímající hodnoty x, y a zoom (typu int) a vracející novou dlaždici (Tile) na daných souřadnicích x a y.

  5. Třída Map:

    1. Bude obsahovat veřejnou vlastnost Layer.
    2. Bude obsahovat vlastnosti Lat (double), Lon (double) a Zoom (int). Při čtení vlastnosti Zoom bude vždy vrácena hodnota v rozmezí 1 až MaxZoom aktuální vrstvy (Layer).
    3. Bude obsahovat neveřejnou vlastnost CenterTileX (int), která bude pouze pro čtení a bude vracet výsledek následujícího výpočtu: (int)((lon + 180.0) / 360.0 * (1 << zoom))
    4. Bude obsahovat neveřejnou vlastnost CenterTileY (int), která bude pouze pro čtení a bude vracet výsledek následujícího výpočtu: (int)((1.0 - Math.Log(Math.Tan(lat * Math.PI / 180.0) + 1.0 / Math.Cos(lat * Math.PI / 180.0)) / Math.PI) / 2.0 * (1 << zoom))
    5. V knihovně tříd referencujte knihovnu MapRendererLib.zip (součást zadání).
    6. Třída Map bude obsahovat metodu Render, která bude přijímat název souboru, do kterého se mapa vygeneruje. Tělo této metody bude vypadat následovně:
MapRenderer mapRenderer = new MapRenderer(4, 4);

for (int x = -2; x < 2; x++)
{
    for (int y = -2; y < 2; y++)
    {
        Tile tile = this.Layer[this.CenterTileX + x, this.CenterTileY + y, this.Zoom];

        Console.WriteLine(tile);

        mapRenderer.Set(x + 2, y + 2, tile.Url);
    }
}

mapRenderer.Flush();
mapRenderer.Render(fileName);
  1. Následně otestujte svou implementaci. Pro otestování vytvořte novou mapu a přiřaďte jí vrstvu. Následně na mapě zavolejte metodu Render.

  2. Zkuste vytvořit další vrstvu (šablona "https://b.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png" a maximální zoom 17) a vykreslit mapu s touto vrstvou.