User:Balrog/Preparing gis.um.szczecin.pl data

From OpenStreetMap Wiki
Jump to navigation Jump to search

This is a description of the procedure I use to prepare building outlines data traced from gis.um.szczecin.pl to bring it up to acceptable quality. Ask me (balrogg@gmail.com) if you need information in English about this project. Feel free to fix mistakes on this page if you spot them.

Tutaj znajdziesz opis kolejnych kroków przygotowywania danych uzyskanych z gis.um.szczecin.pl do tego żeby dało się je zaimportować do OSM. Jeśli potrzebujesz jakichkolwiek dodatkowych informacji o tym przedsięwzięciu, możesz zapytać mnie pod adresem balrogg@gmail.com albo na forum. Możesz poprawiać tę stronę bez ograniczeń.

Zanim powstanie plik .osm

Pliki .osm dostaję na wyjściu skryptu convert.py który użwyając potrace i dużej ilości dziwnych, geometrycznych heurystyk wykrywa kaształty na obrazkach bitmapowych ściągniętych ze strony urzędu, kształtom tym nadaje współrzędne geograficzne, tagi, informacje adresowe i o wykorzystaniu budynków, i zapisuje do pliku output.osm. Obrazki które mam pokrywają lewy brzeg Szczecina i zawierają tylko warstwę budynków. Zostały ściągnięte skryptem getmap-b-old.py który to bierze na wejściu bitmapę overview.png rozmiaru 1600x1600 px która pokrywa cały Szczecin. Zaznaczone są na niej granice Szczecina i obszary w których występują budynki, po to żeby skrypt wiedział które obszary ma ściągać. Skrypt dzieli cały ten kwadratowy obszar na 400x400 kafelków - mniejszych, prostokątnych bitmap każda pokrywająca 58.8 x 64 metry, rozmiaru 1470x1600 pixeli, czyli w rozdzielczości 4cm na pixel. Ściągnięcie każdego kawałka wymaga wykonania dwóch połączeń ze stroną gis.um.szczecin.pl i trwa średnio około 1 sekundy, około 0.5 sekundy kiedy bitmapa jest pusta bo w danym prostokącie nie było żadnych budynków. Bitmapy są kolorowymi plikami .gif, gdzie budynki są wielokątami obrysowanymi czarną lub szarą, ciągłą lub przerywaną linią, i wypełnione jakimś kolorem. Kolor wypełnienia, linii, i rodzaj linii zależy od wykorzystania budynku. Pliki są zapisywane z nazwami btiles/<x>/<y>.gif, gdzie x i y to współrzędne danego kafelka, od 0 do 399. X to współrzędna pozioma patrząc na mapkę na gis.um.szczecin.pl, a y pozioma, osie nie pokrywają się z południkami ani równoleżnikami, chociaż są blisko. Strona gis.um.szczecin.pl czasem zwraca błędy albo niepoprawne pliki .gif.

Podobnie wyglądało otrzymanie adresów z warstwy adresów na mapce gis.um.szczecin.pl, tylko skrypt do ściągnięcia bitmap nazywa się getmap-a-old.py, bitmapy mają mniejszą rozdzielczość i są w podkatalogu atiles/ (a jak adres, b jak budynek). Następnie skrypt scan-addresses.py wczytał każdą bitmapę po kolei i wyszukał na niej wszystkie żółte kółka symbolizujące adresy na stronie urzędu. Niektórych adresów może brakować jeśli były na granicach bitmap albo za blisko siebie. Współrzędne wszystkich znalezionych punktów skrypt zapisał w postaci pliku "curl.a" który z kolei jest skryptem dla popularnego programu curl. Komenda "curl -K curl.a" dla każdego z tych punktów wykonała zapytanie do strony urzędu w stylu "Co znajduje się w danym miejscu na warstwach: adresy i budynki", a wynik zapytania zapisała do pliku o nazwie "features/<x>,<y>,ab" gdzie x i y to współrzędne punktu. Zapytania są dosyć szybkie, pewnie z 5 zapytań na sekundę i curl wykonuje je wszystkie w pojedynczym połączeniu http, co by nie niepokoić panów administratorów.

Teraz program converty.py uruchamiam komendą w stylu "./convert.py 40 40 50 50", gdzie pierwsze dwie liczby to lewy dolny (prawie południowo-zachodni) róg obszaru który chcę skonwertować do pliku .osm, a druga para to przeciwny róg. Dla 40 40 50 50 program wczyta więc 100 bitmap (10x10) z katalogu btiles, przekonwertuje je na dwukolorowe pliki png dla biblioteki potrace, przy tym wykonując jakąs tam obróbkę, i każe potrace'owi załadować to wszystko do pamięci, przerysować znalezione kształty, i zapisać w pliku .svg. Potem wczytuje ten plik i poprawia kształty jak umie, bo potrace generuje bardzo nienaturalne wielokąty z którymi byłoby bardzo dużo ręcznego poprawiania. Następnie wyszukuje w katalogu features/ wszystkie punkty które leżą w danym prostokącie (np. 40x40 - 50x50) i dla każdego punktu sprawdza czy zawiera się w którymś wielokącie. Jeśli tak to wielokąt dostaje odpowiedni adres i informacje o budynku w odpowiednich tagach, jeśli nie, albo jeśli dany wielokąt ma więcej niż jeden adres, to tagi są przypisywane do węzła. Jeśli w wielokącie nie ma żadnych punktów to dostaje tylko building=yes, source=gis.um.szczecin.pl. Wszystkie współrzędne są potem konwertowane na szerokości i długości geograficzne. Punkty które leżą blisko siebie (w odległości mniejszej niż ok. 10cm) są łączone w jeden. Punkty które leżą blisko ( < 5cm) jakiejś krawędzi wielokąta są łączone z tą krawędzią. Znajdowanie odległości od krawędzi jest dosyć powolne więc zastosowany jest szybszy ale niedokładny algorytm, który nie działa najlepiej jeśli punkt jest blisko (ok. 3m) któregoś z końców krawędzi. W przeciwnym wypadku punkt nie zostaje połączony z krawędzią i wtedy może się zdarzyć że dwa budynki które w rzeczywistości dotykają się, nie mają punktów wspólnych w pliku .osm. Jeśli znajdziemy taki przypadek to poprawiamy go używając klawisza "j" w JOSMie.

Dla budynków dla których nie znaleziono żadnego punktu z przypisanym adresem i atrybutami budynku, obliczany jest dowolny punkt który leży wewnątrz wielokąta (biorąc pod uwagę dziury w multipolygonach) i zapisywany jest nowy skrypt dla curla pod nazwą "curl.b". Następnie uruchamiam "curl -K curl.b", i ponownie "./convert.py 40 40 50 50", tym razem w pliku output.osm wszystkie budynki powinny już mieć swoje atrybuty.

Plik output.osm przemianowuję na coś w stylu 40-40-50-50.osm żeby wiadomo było który obszar pokrywa.

Skrypty i patche do potrace'a mogę udostępnić jeśli byłyby potrzebne, ale kod jest średniej jakości a, jak widać, skorzystanie z niego też jest raczej skomplikowane.

Poprawianie błędów

Generalnie najlepiej otworzyć stronę gis.um.szczecin.pl i porównywać zawartość pliku z tym, co widać na mapce. Jeśli zobaczymy błędy to poprawiamy kształy i atrybuty według mapki. Żeby sprawdzić atrybuty wybieramy ikonkę "(i)" nad mapką i klikamy na budynek albo adres.

Niektóre błędy pewnie możnaby wyeliminować w potrace'ie albo w convert.py odpowiednim nakładem pracy, ale chyba szkoda wysiłku biorąc pod uwagę, że importy są jednorazowe.

Dziwactwa na granicach bitmap

Z powodu jakiś błędów zmiennoprzecinkowych albo jakiegoś zaokrąglania, w convert.py albo na serwerze gis.um.szczecin.pl (raczej na serwerze) sąsiednie bitmapy nie zawsze schodzą się na granicach z wystarczającą dokładnością. Jeśli nawet pojedynczy piksel gdzieś na granicy obrazka ma zły kolor to wielokąt może mieć błędy dwojakiego rodzaju:

  • Tam gdzie krawędź wielokąta przecina granicę obrazka, krawędź może mieć jakieś dodatkowe niepotrzebne węzły. Należy je wywalić. Czasem potrace generuje z tego powodu całą masę małych trójkątów albo czworokątów wzdłuż tej krawędzi, też trzeba się ich pozbyć.
  • Tam gdzie linia, która jest wspólną krawędzią dwóch budynków, ma brakujący piksel, w ścianie robi się dziura i potrace myśli, że jest to jeden wielokąt, a nie dwa. To jest chyba najbardziej uciążliwy błąd. Te połączone budynki mają wtedy jakiś nienaturalny kształt i można je zauważyć. Usuwamy niepotrzebne węzły i kawałki krawędzi, potem dzielimy wielokąt na dwa i dorysowujemy brakujące krawędzie. Sprawdzamy na stronie urzędu czy budynki miały różne atrybuty i poprawiamy je. Jeśli w każdy budynek miał po jednym adresie to kopiujemy adres z punktu (ctrl+c) i wklejamy na budynek (ctrl+shift+v), punkt usuwamy.

W trybie wireframe w JOSM-ie zobaczymy oprócz niebieskich obrysów budynków, zieloną kratkę z pionowych i poziomych linii. To są granice między wejściowymi obrazkami. Musimy przejść się po każdej linii od początku do końca i poszukać niepotrzebnych punktów na krawędziach wielokątów, oraz wielokątów błędnie połączonych ze sobą. Potem wywalamy zieloną linię i bierzemy się za następną.

Przerywane linie

Budynki typu "Zbiorniki, silosy i coś tam jeszcze" są obrysowane przerywaną czarną linią, która dla potrace'a wygląda jak pojedyncze odcinki linii albo małe prostokąty i kompletnie wariuje. Budynki tego typu wyglądają jak jeże bo mają takie nierówne krawędzie, więc łatwo je znaleść, naszczęście nie ma ich dużo, przynajmniej nie w centrum. Żeby się upewnić że znajdziemy wszystkie, możemy wyszukać słowo "zbiornik" albo "silo" (ctrl+f, zbiornik, enter). Trzeba pousuwać wszystkie niepotrzebne punkty krawędzi i zostawić tylko rzeczywiste rogi budynku, wtedy krawędzie robią się proste. Tam gdzie dwa takie budynki się stykają, potrace widzi jeden budynek poprzedzielany małymi prostokątami. Tu znów musimy wywalić prostokąty, podzielić budynek i poprawić atrybuty.

Inne niepoprawne kształty

convert.py sprawdza czy kształt jest sensowny licząc sumę wszystkich kątów w wielokącie, która powinna wynieść 360 stopni, jeśli nie wychodzi 360, to dodaje tag note=Weird shape, zwykle znaczy to że wielokąt ma jakieś pętle albo zwroty o 180 stopni, więc trzeba go poprawić. Wyszukujemy w JOSM-ie: ctrl+f, weird, enter.

Sklejone adresy

Serwis gis.um.szczecin.pl dla zapytnia o konkretny punkt zwraca wszystkie adresy i atrybuty budynków w promieniu 2-3 metrów, jeśli adresy leżą bardzo blisko siebie to na jedno zapytanie curl może dostać dwie lub trzy odpowiedzi. Wtedy convert.py zapisuje w tagu wszystkie odpowiedzi poprzedzielane średnikami. Np. jeśli wzdłuż ulicy jest ciąg małych domków albo budek z hot-dogami, o adresach Sowia 5, Sowia 7, Sowia 9, to budka pod siódemką może mieć tag addr:housenumber=5;7;9 a pod dziewiątką addr:housenumber=7;9. Trzeba więc wyszukać średniki (ctrl+f, ;, enter) i poprawić adresy, zwykle tylko numery domów, ale na rogach ulic możliwe też dwie nazwy ulicy w addr:street.

Brak atrybutów

Tam gdzie nie udało się znaleść adresu ani punktu leżącego wewnątrz wielokąta, może brakować tagów na budynku, wtedy zobaczymy tylko tag building=yes. Wyszukujemy je (ctrl+f, building=yes, enter) i dodajemy atrybuty według strony.

Multipolygony

Skrypt nie dodaje relacji, otagowuje tylko zewnętrzny wielokąt a wewnętrzny zostawia bez tagów. Wyszukujemy te wielokąty (ctrl+f, type:way -building, enter) i dodajemy relacje.

Wgrywanie danych

Pojedyncze pliki .osm są na tyle małe że można to zrobić JOSM-em, jeśli każemy mu wgrać wszystkie elementy za pomocą jednego zapytnia ("Upload data in one request") to unikamy ryzyka związanego z zerwaniem połączenia w czasie wgrywania i powstania kompletnej kaszanki.

Przedtem oczywiście łączymy dane z już istniejącymi i pozbywamy się w jakiś sposób duplikatów. Poza centrum nie powinno być ich dużo. Wywalamy też te budynki które już mamy zaimportowane, na granicach prostokątnych obszarów. Możemy też wywalić wszystko to co zostało ucięte w połowie przez granicę obszaru który skonwertowaliśmy, jeśli tego nie zrobimy to importująć sąsiedni fragment będzimy musieli łączyć kawałki budynków. Warto uszczególnić zawartość tagu building= i building:usage:pl= jeśli wiemy co to za budynek, bo domyślne wartości wzięte z gis.um.szczecin.pl są bardzo ogólne, na przykład kościoły mają building=service, które możemy zmienić na coś w stylu building=church i dodać amenity=place_of_worship.