Około 5 lat temu gdy mój pierwszy syn był mały i mieszkaliśmy we Wrocławiu to często zwiedzaliśmy różne place zabaw. Potem wpadłem na pomysł aby zrobić mapkę, która pozwoli ustalić co jest na placu zabaw. Projekt zacząłem implementować ale natrafiłem na pewne trudności. Otóż OverpassAPI do OSM nie indeksował obiektów bez tagu name
jako area, a to z kolei utrudniało zapytanie, które pobrałoby obiekty wewnątrz obszaru placu zabaw.
Ostatnio postanowiłem poświęcić trochę czasu aby pokończyć projekty z mojego zeszytu. Kod się gdzieś zagubił, ale w sumie projekt był ledwo zaczęty więc pewnie nawet nie stworzyłem repozytorium, a kod pewnie jest na jakimś starym laptopie.
OverpassApi
Overpass API służy do pobierania danych przy użyciu odpowiedniego języka zapytań. Daje on całkiem duże możliwości, a dodatkowo cały czas jest rozwijany. Dawno temu gdy prowadziłem wykłady o OpenStreetMap na GISDayach na uczelniach to lubiłem pokazywać jego możliwości tworząc dość skomplikowane zapytania. Pamiętam, że jedno z nich to było coś w stylu "pobierz wszystkie puby w danym obszarze, które są nie dalej niż X metrów od żabki, ale nie znajdują się w pobliżu monopolowego".
Tym razem zapytanie ma inne zadanie. Pobiera wszystkie place zabaw, które są obszarami, a następnie dla każdego z nich pobiera wszystkie elementy wewnątrz. Potem używając convert
przypisuję do każdego obieku wewnątrz playground_id aby wiedzieć, którego placu jest częścią oraz convert, który przypisuje do placu zabaw wszystkie tagi z podanej kategorii wewnątrz znalezionych elementów -dzięki temu wiem, że na placu zabaw jest piaskownica bez sprawdzania geometrii po stronie klienta.
[out:json][timeout:25];
way[leisure=playground]({{bbox}});
map_to_area;
foreach->.d(
node(area.d)
(if: is_tag("amenity") || is_tag("playground") ) -> .a;
.a out skel;
.a convert node
::=::,
::id=id(),
plac_id=d.min(id());
out;
way(area.d)[playground] -> .b;
.b out geom;
.b convert way
::=::,
::id=id(),
playground_id=d.min(id()),
size=length();
out;
(.a;.b;) -> .c;
.d out geom;
.d convert way
::=::,
::id=id(),
playground_in=c.set(t["playground"]),
amenity_in=c.set(t["amenity"]);
out;
);
https://overpass-turbo.eu/s/1vbg
Serce naszej strony już jest.
Frontend
W sumie frontend nie ma dużej odpowiedzialności. Musi pobrać dane, a potem je wyświetlić. Od pewnego czasu przestałem używać JS, używam już tylko TypeScript. O ile w przypadku backend i cli wiedzoałem czego użyć do kompilacji TS to w przypadku frontend doświadczenia za wiele nie mam. Pisałem jakieś stronki w Vue.js przy użyciu TS, ale Vue.js na tak prostą stronę to jak użycie laptopa aby sterował przekaźnikami.
Po konsultacjach polecono mi ParcelJS. On ładnie konwertuje kod z TS na JS i ogarnia wszystkie assety, cssy itd.
Napisałem kilka klas w TS, które były odpowiedzialne za pobieranie i wyświetlanie danych. Bo mimo, że projekt jest prosty to chciałem go zoptymalizować. Pierwszy problem w przypadku takich stron to ładowanie danych. Pobierać za każdym razem gdy ktoś przesunie mapę? Przycisk do pobierania?
Moją sorawdzoną metodą jest podzielenie mapy na kafelki. Potem pobieram dla każdego kafelka, który jest widoczny dane z overpass. To generuje kolejny problem. API jest tak zrobione, że równocześnie może być prowadzonych kilka zapytań (chyba 3) przy większej liczbie zwraca błąd. Musiałem więc napisać prostą kolejkę pobierającą dane, która gwarantowała mi, że nie będę pobierał danych dla kilku obszarów równocześnie. Ostatni krok optymalizacyjny to było zapisanie danych w localstorage, aby użytkownik nie musiał za każdym razem pobierać danych od nowa.
Efekt wyszedł zadowalający jak na 6 godzin pracy, a w tym już rysowanie ikonek i szukanie najlepszej technologii, która nada się do moich zastosowań.
Stronę można znaleźć tutaj:
https://dotevo.github.io/ludparko/#51.1214,17.0520,18
oraz na github są źródła
https://github.com/dotevo/ludparko/tree/master/src
Chciałbym tym projektem Wam pokazać jak łatwo używać OSM i jaką dają przewagę nad np. GoogleMaps
a te place zabaw to ty dodajesz i aktualizujesz ręcznie do tej mapy?
W jakim sensie? Chyba nie zrozumiałem pytania. Masz na myśli moją stronkę czy OSM?
OpenStreetMap to mapa na otwartej licencji, którą może każdy edytować podobnie jak np. Wikipedię. Wystarczy stworzyć sobie konto i nanieść zmiany. Potem dane trafiają w różne miejsca np. overpassAPI, jest osobnym serwerem i synchronizuje się z główną bazą danych raz na kilka godzin. Taki np. Yanosik, MapsMe też używa map OSM, ale nie wiem jak często pobierają zmiany z głównego serwera, więc jeśli dokonasz zmiany to może pojawić się na ich mapach po kilku dniach.
W OSM jest kilka typów danych, ale to czym dana "linia" lub "punkt" jest definiujemy tagami klucz=wartość. Przykładowo plac zabaw jest tagowany jako leisure=playground tu taka przykładowa linia tworząca obszar z tagami https://www.openstreetmap.org/way/129819798#map=19/51.12156/17.05136
No i jeśli sprawdzimy ile w całej bazie OSM jest tak otagowanych linii to jest ich tam 590 338https://taginfo.openstreetmap.org/tags/leisure=playground#overview
Myślę, że każdy może zająć się mapowaniem tego co lubi. Są ludzie co dodają do OSM hydranty, inni dodają linie energetyczne, a jeszcze inni ławki w parku czy pomniki przyrody. Jeśli coś jest stacjonarne to na pewno da się to jakoś dodać do OSM.
Ok to nie do końca w takim razie zrozumialem o co chodzi ale przeszla mi taka mysl ze cos takiego tez mozna by jakos do blurt podlaczyc i np stworzyc bota z delegacja ktory wynagradza tych co dodaja wpisy do baz danych aby dodatkowo nagradzac userow co to robia.
Kiedyś też o tym myślałem, ale spokojnie do tego można wykorzystać ideę blurtopiana. Tworzysz post, piszesz co dodałeś do bazy. Może jakieś zdjęcia i ew. wpis podobny do tego co ludzie robią w actifit.
Następnie jeśli to ma sens to "blurtopian" wraz z kuratorami wspiera post.
a no tak też można chociaż wiesz niektórzy zupełnie nie mają talentu albo chęci do pisania a takie dodanie w porządny sposób z opisem lokacji to i tak już coś bardo pożytecznego także jakby to działało w taki sposób że wystarczy dodac nową pozycję i automatycznie publikuje się ona jako post z wprowadzonymi danymi które automat upvotuje to było by dogodniejsze i cieszyło się wiekszym powodzeniem.
pewnie masz rację. Ogólnie jest to warte rozważenia.