SVG Mapa ČR

Ukázka vytvoření mapy České republiky v SVG

Přejížděním kurzorem nad mapou, nebo dotykem na telefonu se zobrazují názvy kresů.

Ukázka vytvoření mapy v SVG

Vytvoření takovéhle mapy je trochu komplexnější úkol, ale nebojte se projdeme to krok po kroku.

1) Vytažení GPS dat z ČÚZK

Nejprve je nutné sestavit url dotazu na server cuzk (katastrální úřad). Rozcestník pro jednotlivé tabulky (stát, kraje, okresy atd) je zde. Nás bude pro příklad zajímat stát, neboli česká republika url je zde. Kompletní url pro získání souřadnic: zde. V celém znění vypadá takto:

http://ags.cuzk.cz/arcgis/rest/services/RUIAN/Vyhledavaci_sluzba_nad_daty_RUIAN/
MapServer/19/query?where=1%3D1&text=&objectIds=&time=&geometry=&geometryType=
esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=
&outFields=*&returnGeometry=true&returnTrueCurves=false&maxAllowableOffset=
&geometryPrecision=&outSR=&having=&returnIdsOnly=false&returnCountOnly=false
&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false
&returnM=false&gdbVersion=&historicMoment=&returnDistinctValues=false
&resultOffset=&resultRecordCount=&queryByDistance=&returnExtentOnly=false
&datumTransformation=&parameterValues=&rangeValues=&quantizationParameters=
&featureEncoding=esriDefault&f=json

2) Pole bodů v JTSK

Tento požadavek Vám vrátí JSON, který obsahuje data o našem státu, tedy nějaký název, kód, Id. Nás ale zajímá pole "geometry", které obsahuje pole dvojic bodů (souřadnic v JTSK). Pole souřadnic odpovídá obálce/obrysu státu.

3) Převod z JTSK do GPS

Tento krok je volitelný. Já se ale rozhodl mít souřadnice v GPS. Algoritmus převodu z JTSK do GPS jsem si vypůjčil od někoho chytrého, viz jeho web: Martin Hinner

4) Zjednodušení - redukce počtu bodů

To co dostaneme od CUZK je cca 133 000 bodů (obrys ČR), což je velmi detailní polyline, a pro účely SVG je důležité ji zjednodušit! Jistě by šlo jen některé body vynechat, nebo vymyslet nějaký chytřejší algoritmus.

Já si ale vypůjčil hotové řešení, které má velmi pěkné výsledky. A velmi mě zaujala jeho "non-intrusive" implementace. Moc pěkné řešení. Adresa tohoto projektu zde GitHub simplify-csharp. Použití:


bool highQualityEnabled = true;
double tolerance = 0.005;
var simplifiedPoints = SimplifyCSharp.SimplificationHelpers.Simplify<Point>(
                            obj.Geometry,
                            (p1, p2) => p1 == p2,
                            (p) => p.E,
                            (p) => p.N,
                            tolerance,
                            highQualityEnabled
                            );
            pole2 = simplifiedPoints.Cast().ToList();

5) Vykreslení SVG

Pro vykreslení SVG jsem našel NuGet balíček SvgNet GitHub SvgNet Použití:


//Root element
SvgSvgElement root = new SvgSvgElement($"100%", $"100%", $"0,0 {widt + 1},{heig + 1}");
root.Id = "svg";
root.Attributes["mine"] = stat.Min.e;
root.Attributes["minn"] = stat.Min.n;
root.Attributes["maxe"] = stat.Max.e;
root.Attributes["maxn"] = stat.Max.n;
root.Attributes["multiplier"] = multiplier;
root.Attributes["constant"] = Point.EastConstant;

//calc points            
var pts = obj.GetMultipliedPoints(min.E, min.N, multiplier);
var ptf = pts.First();
//group
SvgGroupElement grp = new SvgGroupElement(nazev);
SvgPathElement pathy = new SvgPathElement();
pathy.Attributes["nazev"] = nazev;
pathy.Attributes["typ"] = obj.GetType().Name;
//points
StringBuilder sb = new StringBuilder();
sb.Append($"M {ptf.GetX()} {ptf.GetOppY(heig)} "); //moveto
foreach (var pt in pts.Skip(1)) sb.Append($"L {pt.GetX()} {pt.GetOppY(heig)} "); //lineto
sb.Append($"Z"); //close
pathy.D = sb.ToString();
//path style
pathy.Style = pathStyle;
//add to group
grp.AddChild(pathy);
//add to root
root.AddChild(grp);
grp.Style = grpStyle;

//SAVE
string s = root.WriteSVGString(false);
File.WriteAllText(path, s);

Zobrazení SVG v HTML

SVG kód uložený v souboru se dá použít jako src pro img tag, ale kvůli interaktivitě se kód vkládá přímo do HTML. V případě ASP.NET Core je ideální udělat SVG kód jako partial view, jen kvůli přehlednosti. Namísto desítek řádků, je pak ve view jen toto:


<partial name="_Mapa" />

SVG Mapa

Použito:

  • TypeScript/JS
  • AJAX
  • API ČÚZK
  • C#