Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Odleglosci pomiedzy punktami na mapie a wydajnosc.
Forum PHP.pl > Forum > PHP
mduke
Witam,
jestem ciekaw Waszych propozycji rozwiazania problemu na ktory sie wlasnie natknalem.
Chodzi ogolnie o obliczanie odleglosci pomiedzy punktami na mapie majac ich wspolrzedne.

Sytuacja jest taka. Mam w bazie tabele z nazwa miejsca i osobne kolumny z szerokoscia i dlugoscia geograficzna. Jest tego w tej chwili kilkadziesiat tysiecy i ciagle rosnie. Na stronie stawiamy punkt na mapce googla i mamy znalezc wszystko w promieniu 100 km.

Nie prosze Was o podanie mi wzoru matematycznego bo taki mozna latwo znalezc gdzie indziej. Chodzi o caloksztalt podejscia do tematu.

Jak to zrobic zeby serwer nie wybuchl od obliczania odleglosci pomiedzy punktem jaki wybralem na mapie i wszystkimi punktami w bazie i przy okazji zeby user nie czekal 10 minut na wynik wyszukiwania. Bo to w tej chwili mniej wiecej tak wyglada. Jakis zmyslny cache?

Pozdrawiam
sowiq
Kolego, do obliczenia dokładnej odległości jest dosyć skomplikowany wzór matematyczny, uwzględniający krzywiznę Ziemi i inne takie rzeczy:
http://stackoverflow.com/questions/1502590...-google-maps-v3
http://www.movable-type.co.uk/scripts/latlong.html

Miałem dawno temu podobny problem i rozwiązałem go chyba w najgorszy z możliwych sposobów. Otóż cały ten wzór matematyczny wrzuciłem w zapytanie SQL i wybierałem tylko pasujące rekordy. Jest to bardzo złe podejście, bo takie zapytania przy większej ilości rekordów są bardzo mało wydajne.

Jak radziłbym Ci to zrobić? Ustalić sobie, że 100 km = x stopni szerokości = y stopni wysokości geograficznej (jeśli operujesz tylko na terytorium Polski, nie będziesz miał z tym większego problemu. Mając interesujący Cię punkt (lat, lng), wybierasz z bazy danych takie rekordy, których współrzędne mieszczą się w przedziale(lat - x/2, lat + x/2), (lng - y/2, lng + y/2). Dostaniesz zdecydowanie zawężony zbiór rekordów, a jeśli na kolumnach ze współrzędnymi założysz indeksy, cała operacja będzie bardzo szybka.
Kolejnym krokiem będzie zmniejszenie "oczek sitka", tzn. z zawężonego kręgu rekordów musisz (już w PHP) usunąć te, których odległość (obliczona wzorem z powyższych linków) jest większa. I zostają Ci tylko punkty w odległości, jaka Cię interesuje.
Jeśli używasz Google Maps API, to możesz użyć Geometry Library i te szczegółowe obliczenia przerzucić na przeglądarkę użytkownika.
Crozin
1. Wyznaczasz sobie kwadrat na mapie, który jest opisany na kole które Cię interesuje.
2. Wybierasz jedynie te rekordy, które znajdują się wewnątrz kwadratu (to jest bardzo szybkie sprawdzanie). Następnie ze zbioru (już mocno odchudzonego) tych rekordów wybierasz te, które leżą wewnątrz koła (to jest wolne sprawdzanie).

  1. SELECT * FROM (
  2. SELECT ... FROM .. WHERE [sprawdzanie po kwadracie]
  3. ) WHERE [sprawdzanie po okręgu];
mduke
Do sowiq - poczatkowo chcialem zrobic wlasnie tak jak radzisz. Tylko problem w tym ze operuje nie tylko po mapie Polski ale globalnie - odleglosci pomiedzy rownoleznikami sa zawsze takie same nie zaleznie czy w okolicy rownika czy biegunow, ale z poludnikami juz tak nie jest i tu pies pogrzebany, wiec porzucilem ten pomysl.

Do Crozin - nie bardzo rozumiem jak w szybki sposob wybrac punkty z kwadrata o ktorym mowisz. Jak na moje czy okrag czy kwadrat obliczenia podobne (chyba ze sie myle).

Wynik nie musi byc bardzo dokladny. Do przyjecia jest tolerancja 10%. Bardziej chodzi o wydajnosc - rekordow w bazie jest sporo i bedzie duzo wiecej. Nawet nie mysle o tym zeby uwzgledniac krzywizne Ziemii.
Crozin
Cytat
Jak na moje czy okrag czy kwadrat obliczenia podobne (chyba ze sie myle).
Źle myślisz. Do sprawdzenia czy punkt leży w kwadracie wystarczą cztery, bardzo proste operacje. Sprawdzasz czy długość geograficzna punktu jest większa od lewego boku (długości geograficznej) kwadratu i jednocześnie mniejsza od prawego boku. Analogicznie postępujesz dla szerokości geograficznej.
sabat24
Ja używam tego podejścia http://www.xarg.org/2009/12/people-near-you-with-mysql/ z predefiniowanymi odległościami, które mnie interesują, jako że potrzebuję w miarę dokładnych wyników.
Pilsener
Cytat
Jakis zmyslny cache?
- tak. Podział na sektory, coś podobnego jak Crozin radzi, gdy ktoś zaznacza coś na mapie obliczamy sektor i ewentualnie potrzebną nam liczbę sąsiednich. Potem wystarczy z indeksu pobrać rekordy przypisane do danych sektorów i w razie potrzeby jeszcze je obrobić - ale to już spokojnie ajaxem w tle, po stronie użytkownika niech się liczy.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.