Hi Jacob,
well — the geo distance computes the distance of the direct line between the two coordinates:
<gml:coordinates>52.519881,13.407338</gml:coordinates>
and
gml:coordinates51.507351,-0.12766</gml:coordinates>
Which happens to be 13.572817977888896 <=> https://en.wikipedia.org/wiki/Euclidean_distance
Yet, the earth is spherical, so you need to take that into account, https://en.wikipedia.org/wiki/Geographical_distance https://en.wikipedia.org/wiki/Geographical_distance
I think what you are actually looking for is the great-circle distance — the length of a line traveling along the surface between two points on a circle.
A somehow good approximation for that distance can be computed using the haversine formula: http://www.movable-type.co.uk/scripts/latlong.html http://www.movable-type.co.uk/scripts/latlong.html
I rewrote the Javascript as XQuery and the result seems to be about right.
import module namespace geo = "http://expath.org/ns/geo"; declare namespace gml='http://www.opengis.net/gml';
(: formula taken from here: https://www.movable-type.co.uk/scripts/latlong.html :) declare function local:haversine( $point1 as element(gml:Point), $point2 as element(gml:Point) ) as xs:double { let $r := 6371 (: earth radius in KM :) let $lat1 := geo:x($point1) let $lat2 := geo:x($point2) let $lon1 := geo:y($point1) let $lon2 := geo:y($point2) let $φ1 := $lat1 => local:radians() let $φ2 := $lat2 => local:radians() let $Δφ := ($lat2 - $lat1) => local:radians() let $Δλ := ($lon2 - $lon1) => local:radians()
let $a := math:pow(math:sin($Δφ div 2), 2) + math:cos($φ1) * math:cos($φ2) * math:pow(math:sin($Δλ div 2), 2) let $c := 2 * math:asin(math:sqrt($a))
return $c * $r };
declare function local:radians( $deg as xs:double ) as xs:double { $deg * (math:pi() div 180) };
let $berlin := gml:Point gml:coordinates52.519881,13.407338</gml:coordinates> </gml:Point> let $london := gml:Point gml:coordinates51.507351,-0.12766</gml:coordinates> </gml:Point> return local:haversine($berlin, $london) (: returns 931.7188794140812 :)
Maybe you should make yourself comfortable with the maths behind that formula to better understand its shortcomings, nevertheless, here’s what I came up with in a more readable version:
https://gist.github.com/micheee/e47166d0947f925e395504c1e220fbea https://gist.github.com/micheee/e47166d0947f925e395504c1e220fbea
Best Michael
Am 26.02.2019 um 13:19 schrieb Jacob Borisov jacobborisov@gmail.com:
Hi! For example, it's need to get the distance between Berlin and London, which is 934 km.
So I've put the coordinates as they can be found in Google Maps, etc.:
let $berlin := gml:Point gml:coordinates52.519881,13.407338</gml:coordinates> </gml:Point> let $london := gml:Point gml:coordinates51.507351,-0.12766</gml:coordinates> </gml:Point> return geo:distance($berlin, $london)
And the result is 13.572817977888896
Also I had trying to change srsName attribute of gml:Point's to different values like "3857", "EPSG:3857" (it's uses meter units as mentioned here https://epsg.io/3857), but practically this changes nothing. Thanks.
вт, 26 февр. 2019 г. в 19:33, Michael Seiferle ms@basex.org:
Hi Jacob,
I’ve never really used the geo:module but according to the documentation:
in the units of the spatial reference system of geometry1
If I understand it correctly, you would have to convert your coordinates to map them to miles or kilometers for example.
Maybe you can provide an example?
Given this very simple query:
import module namespace geo = "http://expath.org/ns/geo"; declare namespace gml='http://www.opengis.net/gml'; let $point1 :=gml:Pointgml:coordinates1,1</gml:coordinates></gml:Point> let $point2 := gml:Pointgml:coordinates2,2</gml:coordinates></gml:Point> return geo:distance($point1, $point2)
The result is math:sqrt(2), the length of a straight line from P(1,1) — P’(2,2) but this length does not contain any unit of measurement.
Best Michael
Am 26.02.2019 um 12:12 schrieb Jacob Borisov jacobborisov@gmail.com:
Hello. Could anybody explain how to get a result from geo:distance() in kilometers or miles? Thanks.