2012-08-30 9 views
9

Mam następujące zapytanie:Get odległość w metrach zamiast stopni w Spatialite

select distance(GeomFromText('POINT(8 49)',4326),GeomFromText('LINESTRING(8.329969 49.919323,8.330181 49.919468)',4326)) 

To daje mi 0,97 stopni. Ale potrzebuję go w metrach i nie wiem, do którego SRIDu się przeliczyć.

Czy ktoś może podać przykład, jak uzyskać wynik w metrach dla przestrzennej przestrzeni?

Pozycje są w całej Europie.

Odpowiedz

14

Po prostu pomnóż wartość w stopniach przez 111195 - ta wartość to (Earth mean radius)*PI/180 - czyli "średnia długość jednego wielkiego koła w metrach na powierzchni Ziemi".

Maksymalny błąd przy użyciu tej metody jest ~ 0,1%


EDIT

OK, moja odpowiedź wyżej stoi na pytanie: „Jak przekonwertować łuki w stopniach do długości w metrach” jednak nie jest to pytanie, które zadałeś (powinno być zadawane).

Nie używałem profesjonalnie Spatialite, więc założyłem, że twoje przykładowe zapytanie rzeczywiście zwraca "długość w stopniach". To nieprawda.

Niestety, wydaje się, że Spatialite nie potrafi obliczyć odległości w "sensie geograficznym". Pomimo, że geometria jest zdefiniowana w SRID 4326, traktuje je tak, jakby były w samolocie.

Oto prosty dowód:

select Distance(GeomFromText('POINT(0 0)',4326),GeomFromText('POINT(3 4)',4326)); 

powraca 5.0.

To wstyd ...

Pozwala spojrzeć na pierwotnym zapytaniu:

select Distance(
    GeomFromText('POINT(8 49)',4326), 
    GeomFromText('LINESTRING(8.329969 49.919323,8.330181 49.919468)',4326) 
) 

Równoważny kwerendy w MS SQL Server:

SELECT (geography::STGeomFromText('POINT(8 49)', 4326)).STDistance(geography::STGeomFromText('LINESTRING(8.329969 49.919323,8.330181 49.919468)', 4326)); 

dostaje poprawny wynik Natychmiast: 105006.59673084648, w metrach i bez dodatkowych brouhaha.

Jakie są Twoje opcje w Spatialite?

Rzeczywiście, jak powiedziałeś w komentarzach, jedną z opcji jest rzutowanie geometrii i obliczanie na niej. Korzystanie z SRID 3035 dla Europy ma sens (jeśli twoje lokalizacje są w większości w Niemczech, rozważam SRID 25832).

select Distance(
    Transform(GeomFromText('POINT(8 49)',4326),25832), 
    Transform(GeomFromText('LINESTRING(8.329969 49.919323,8.330181 49.919468)',4326),25832) 
) 

zwraca 104969.401605453.

Co do swojej drugiej próbie (w komentarzach):

select distance(
    Transform(GeomFromText('POINT(8.328957 49.920900)',4326),3035), 
    Transform(GeomFromText('POINT(8.339665 49.918000)',4326),3035) 
) 

istnieje prostszy sposób to zrobić (jeśli masz dwa punkty, a nie punktem a LineString): Tworzenie LineString ze swoimi punktami i używać GeodesicLength funkcję tak:

select GeodesicLength(GeomFromText('LINESTRING(8.328957 49.920900, 8.339665 49.918000)',4326)) 

zwraca 833.910006698673, jak oczekiwano.

+0

Hmm, to robi mi na powyższych stanowiskach 1218 metrów. Korzystając z Google Earth, osiągam odległość 833 metrów. Po pewnym czasie użyłem tego zapytania: wybierz odległość (transform (GeomFromText ('POINT (8.328957 49.920900)', 4326), 3035), transformuj (GeomFromText ('POINT (8.339665 49.918000)', 4326), 3035)) co daje mi 834 metry – tmanthey

+0

tak, to powinno działać dość dobrze (zobacz moją zredagowaną odpowiedź też) – Incidently

+0

Wielkie dzięki. Ostatnie pytanie. Masz rozbudowany sposób wyboru SRID? – tmanthey

8

W programie SpatiaLite functions reference guide widać dwie wersje funkcji Distance(). Jeden bierze tylko dwa argumenty i zwraca dystans w jednostkach CRS, drugi bierze 3 argumenty i zwraca dystans w metrach.

Aby uzyskać odległość w metrach, po prostu przejść do trzeciego argumentu Odległość:

sqlite> select Distance(MakePoint(0, 0), MakePoint(3, 4)); 
5.0 
sqlite> select Distance(MakePoint(0, 0), MakePoint(3, 4), 1); 
554058.923752633 
Powiązane problemy