Skip to main content

Mapy binarne OsmAnd - .obf

Wprowadzenie

Mowa o *.travel.obf, *.wiki.obf, *.roads.obf, ..

Wiele pytań dotyczy zawartości i problemów z danymi map w aplikacji. Ten temat ujawnia pewne techniczne szczegóły wewnętrznego formatu danych i przetwarzania danych. Może to być interesujące dla osób niebędących programistami, które znają strukturę danych OSM.

Dane map offline OsmAnd są zawarte w plikach „obf”. Pliki „obf” mają złożoną strukturę i mogą składać się z wielu części. Zdecydowanie zaleca się, aby rozmiar plików nie przekraczał 2 GB. Obecnie pliki obf mogą składać się z wielu części, w tym wielu części POI, wielu części danych routingu, wielu części mapy, wielu części transportu i wielu części danych adresowych. Lista ta może zostać rozszerzona w przyszłości. Aby połączyć, podzielić lub usunąć niektóre części z pliku obf, użyj narzędzia konsolowego „binary_inspector” dostarczonego z OsmAndMapCreator.

  • Część POI, transport
  • Część mapy
  • Część adresu

P: W jaki sposób mapcreator generuje listę wszystkich miejsc, które pojawią się później w wyszukiwaniu adresów offline OsmAnd? Jakie obiekty są szczegółowo wykorzystywane do tego celu? Które węzły z tagiem miejsca są uwzględniane, a które wykluczane?

O: Wszystkie miejsca widoczne w OsmAnd jako miasta są pobierane z węzłów, które mają tag „place” https://wiki.openstreetmap.org/wiki/Place. Obecnie używane są: miasto, miasteczko, przedmieście, wieś, przysiółek.

P: W jaki sposób mapcreator obsługuje poligon obszaru, który jest podany za pomocą relacji z boundary=administrative? Jak powiązać miejsce podane jako węzeł z jego granicą, gdy jest ono obecne w danych OSM?

O: Mówiąc prosto: obecnie działa to według nazwy. Mapcreator próbuje odwiedzić wszystkie granice i tworzy zamkniętą (!) granicę z relacji lub z oddzielnych dróg i kojarzy ją tylko z jedną nazwą. Następnie próbuje dopasować miejsce do nazwy granicy za pomocą algorytmu zawiera. Istnieje również dodatkowe sprawdzenie, czy ta granica zawiera to miejsce. Jeśli istnieje wiele granic o różnym poziomie administracyjnym z tą samą nazwą (zawierających się nawzajem, np. dzielnica/miasto/region o tej samej nazwie), zostanie wybrany najwyższy poziom administracyjny z dokładnym dopasowaniem. TODO Więcej szczegółów powinno być tutaj (o dzielnicach miasta ...) ...

P: Gdzie jest dokumentacja opisująca, jaki poziom administracyjny jest odpowiedni do zbudowania powiązania z określonym węzłem miejsca? Które kraje preferują jaki poziom administracyjny?

O: Obecnie powiązanie między relacją admin_level a admin_centre nie jest używane. Ponieważ tylko kilka relacji dostarcza tych informacji.

P: Skąd MapCreator wie, która ulica należy do jakiego miejsca? Czy są różne przypadki, gdy podany jest poligon graniczny, a gdy go nie ma?

O: Istnieje wiele strategii sprawdzania i są one priorytetyzowane w następującej kolejności:

  • Najważniejsze są miejsca i ich granice. Aby algorytm zarządzania ulicami działał poprawnie, dopasowanie miejsca do granic powinno być poprawne. Jeśli ulica należy do wielu granic, zostanie zarejestrowana we wszystkich odpowiednich miejscach.
  • tag is_in (jest przestarzały). Więc jeśli ulica ma tag is_in, zostanie on przeanalizowany i podzielony przecinkami, a ulica zostanie przypisana do wszystkich odpowiednich miast (przez dokładne dopasowanie nazwy). (DO SPRAWDZENIA: podstawowe sprawdzenie, czy ulica znajduje się w promieniu miasta?)
  • Jeśli ulica nie należy do żadnej granicy (nieprawidłowo zamknięte granice mogą być tutaj problemem), próbuje znaleźć najbliższe/największe miasto i zarejestrować ulicę w tym mieście (czasami rejestruje w mieście w odległości 1 km i pomija najbliższy przysiółek w odległości zaledwie 100 m).

Ostatnia część jest bardzo niedokładna. Dlatego wiele ulic jest przypisywanych do sąsiedniego miasta.

W preferencjach MapCreatora masz pięć dodatkowych ustawień dla sufiksów ulic, powiększenia, gładkości i renderowania... jakie są szczegółowe efekty, które można osiągnąć za pomocą każdego z nich? Czy te ustawienia są faktycznie używane?

Narzędzia

  • OsmAndMapCreator może wyświetlić, które ulice są przypisane do jakiego miasta (menu kontekstowe -> Pokaż adres). Lokalne pliki obf powinny być obecne i skonfigurowane w Ustawieniach.
  • Narzędzie Binary Inspector może wyświetlić listę ulic dla każdego miasta. Uruchom narzędzie bez parametrów, aby zobaczyć możliwe parametry.
  • Obecnie wszystkie pliki indeksowe zawierają gen.log. Przeglądając plik dziennika, można znaleźć błędy w procesie tworzenia mapy, co może dać odpowiedź, dlaczego niektóre ulice nie znajdują się we właściwym miejscu w indeksie adresowym.

Część adresowa - przebieg pracy

Istnieją następujące relacje:

miasto -> 0..1 granica

granica -> 0..** miasto (używane do definiowania przedmieść miasta)

iteruj wszystkie węzły OSM i rejestruj jako miasta, jeśli obecny jest tag = PLACE:

  • ekstrahuj miasta (MIASTO, MIEJSCOWOŚĆ).
  • ekstrahuj wioski (wszystko inne).

iteruj wszystkie RELACJE i DROGI z typem=granica i rejestruj wszystkie granice:

  • granica to tzw. Encja (droga lub relacja) z tagiem 'boundary=administrative' lub z tagiem 'place=...'.
  • granica powinna mieć admin_level > 4 lub nie mieć admin_level.
  • granica nie zawsze jest powiązana z miastem (lub stanem, ...).
  • granica może mieć 'admin_center', 'label' wskazujące na węzeł miasta.
  • granica dokładnie pasuje nazwą do węzła miasta, a węzeł miasta znajduje się w granicach.
  • granica pasuje początkiem, końcem lub podciągiem nazwy do węzła miasta, a węzeł miasta znajduje się w granicach.

Wiele granic może być powiązanych z jednym miastem. Oto kolejność, w jakiej najważniejsza granica jest pobierana i powiązana z miastem:

  • Granica jest dokładnie dopasowana nazwą i ma tag miejsca.
  • Granica jest dokładnie dopasowana nazwą i ma admin_level 8 > 7 > 6 > 9 > 10 > 5... lub nic.
  • Granica ma pasujące admin_id.
  • Wszystkie inne przypadki, w tym sortowanie admin_level.

jeśli miasto nie ma przypisanej granicy, to wszystkie granice, które nie mają centrów miast i zawierają to miasto, zostaną sprawdzone, a granica z admin_level >=7 zostanie przypisana.

dla każdej granicy, utwórz listę miast, które się w niej znajdują.

iteruj wszystkie RELACJE i znajdź adresy (Postal_Addresses):

relacja z tagiem typu "address" i jest typu "house" lub "a6" address_type.

szukaj powiązanej relacji ulicy i członków domu.

spróbuj znaleźć miasto dla ulicy i miasto dla adresu domu.

wyszukaj miasta (musieliśmy je już znaleźć w poprzednich krokach!).

jeśli mamy miasto i ulicę, zarejestruj to w bazie danych:

dla rejestracji ulicy, zobacz: zarejestruj ulicę dla miasta

jeśli ulica jest zarejestrowana, a my przetwarzamy ulicę:

iteruj po wszystkich członkach relacji:

  • znajdź ulicę -> zapisz węzły ulicy do bazy danych
  • znajdź dom -> zapisz dom do ulicy

jeśli ulica jest zarejestrowana, a my przetwarzamy dom:

  • znajdź numer domu
  • znajdź granicę domu: jeśli znaleziono, zapisz: budynek dla ulicy

zarejestruj ulicę (ulica, lokalizacja ulicy (los), miasta):

Uwaga: możemy zarejestrować ulicę w wielu miastach = oznacza to, że ulica może znajdować się w zagnieżdżonych obszarach, na przedmieściach, w mieście, przysiółku itp. Dla każdego obszaru chcemy zarejestrować ulicę, w której się znajduje.

dla każdego miasta:

znajdź istniejącą rejestrację ulicy w mieście:

jeśli ulica istnieje:

  • jeśli część miasta jest nieznana -> zaktualizuj istniejącą część miasta ulicy
  • spróbuj znaleźć część miasta dla naszej ulicy i ponownie wyszukaj ulicę

jeśli ulica nie istnieje: (może się zmienić po wyszukiwaniu)

  • zarejestruj ulicę dla miasta, części miasta, lokalizacji i nazwy ulicy

znajdź lub zarejestruj ulicę

  • znajdź bliskie miasta do ulicy
  • jeśli ulica znajduje się w granicach miasta, dodaj miasto do wyszukiwania
  • jeśli nie znaleziono miasta za pomocą granicy, znajdź najbliższe miasto dla ulicy
  • zarejestruj ulicę: dla znalezionych miast

iteruj wszystkie WĘZŁY, następnie DROGI, następnie RELACJE (iteruj główną encję)

znajdź drogi - interpolacje:

  • dla każdej interpolacji, znajdź lub zarejestruj ulicę z lokalizacją interpolacji
  • dla każdych dwóch węzłów utwórz budynek reprezentujący interpolację

dla każdej encji, znajdź tagi addr:housenumber i addr:street (może to być również interpolacja węzłów!!!):

  • pomiń, jeśli budynek dla tej encji już istnieje!
  • znajdź lub zarejestruj ulice dla ulicy
  • znajdź numer domu
  • jeśli numer domu zawiera '-', spróbuj utworzyć interpolowany numer domu (brakuje latlon2?)
  • jeśli numer domu zawiera '/', spróbuj wyszukać drugą ulicę addr:street2 --> wydaje się, że tylko dla RU osm:
  • istnieje więcej wariantów tego: adr:housenumber2, addr2:street, addr2:housenumber itp.
  • dla każdej ulicy, zapisz istniejący dom

dla drogi z tagiem - nazwa i tagiem - highway, ale bez addr:housenumber i addr:street:

  • Uwaga: mogą to być drogi dla samochodów, z nazwami (autostrada, czy coś w tym stylu)
  • pomiń, jeśli taka ulica już istnieje
  • znajdź lub zarejestruj ulicę dla miasta
  • zapisz węzły dla każdej znalezionej ulicy w każdym mieście

Każda relacja z "postal_code", zapisz do późniejszego wykorzystania.

Uwaga: nie obejmuje to address:type = pc i addr:postalcode

przetwarzanie kodów pocztowych:

  • dla każdej zapisanej relacji postal_code
  • dla każdego członka budynku, zaktualizuj postal_code

zapisz indeks:

podziel miasta na: miasta+miasteczka, przedmieścia (przedmieścia z tagiem is_in), wioski (nie miasto ani miasteczko)

zapisz miasta+miasteczka używając przedmieść

odczytaj ulicę z miast+miasteczek + odpowiednie przedmieścia dla każdego miasta

  • tutaj może być więcej ulic o tej samej nazwie dla jednego miasta, w takim przypadku próbujemy znaleźć część miasta dla ulicy (przedmieście), w której znajduje się ulica. Nie powinno być więcej ulic o tej samej nazwie w jednej części miasta!

dla każdej ulicy

  • dla każdego budynku, zarejestruj/utwórz/znajdź kod pocztowy, zarejestruj ulicę

zapisz wioski

  • tak samo jak miasta...

zapisz wyodrębnione kody pocztowe i ich ulice