Using geodb for geography calcualtions (e,g distance between lat/long coordinates)

422 views
Skip to first unread message

Kit Kline

unread,
Jul 16, 2013, 1:46:28 PM7/16/13
to ge...@googlegroups.com
Hi all,

I am struggling to use h2 geodb to perform geographic calculations...like the below link for postgris.
I would be grateful for any tips or pointers from anyone who has achieved this (simply put I want to select out the distance in miles (or any unit!) between two Points holding lat/long co-ordinates)


Any help much appreciated

Cheers

Kit



Justin Deoliveira

unread,
Jul 16, 2013, 6:04:56 PM7/16/13
to ge...@googlegroups.com
Hey Kit,

Actually the version linked from the wiki on github doesn't have the distance function (lame i know) but it has since been added. If you try this build out it should work as you would expect.


I have also updated the wiki to include a link to the newer 0.7 build. Let me know how that works.

-Justin




Kit



--
You received this message because you are subscribed to the Google Groups "geodb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geodb+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Justin Deoliveira
Enterprise support for open source geospatial.

Kit Kline

unread,
Jul 17, 2013, 6:11:06 AM7/17/13
to ge...@googlegroups.com
H - thanks for such a prompt response - I have 0,7 with ST_Distance in it OK (and can select distance between two Point)- but that seems to be doing distance between two Cartesian points on flat surface and not distance between two lat long on curved earht surface - which makes sense. How do I get ST_Distance to process the points as lat/lon on a curved surface? Or....I'd like to either use an ST function that does the great circle calculation or something like this postgris example below.

Any advice or a code snippet much appreciated - ps loving  this library - great work! 

-- Geography example -- same but note units in meters - use sphere for slightly faster less accurate
SELECT ST_Distance(gg1, gg2) As spheroid_dist, ST_Distance(gg1, gg2, false) As sphere_dist 
FROM (SELECT
	ST_GeographyFromText('SRID=4326;POINT(-72.1235 42.3521)') As gg1,
	ST_GeographyFromText('SRID=4326;LINESTRING(-72.1260 42.45, -72.123 42.1546)') As gg2
	) As foo  ;

  spheroid_dist   |   sphere_dist
------------------+------------------
 123.802076746848 | 123.475736916397

Kit Kline

unread,
Jul 17, 2013, 8:08:13 AM7/17/13
to ge...@googlegroups.com
Just follow up to my own past in case helps.

I'm sure I have just committed a terrible hack (knowing little about GIS) - but I only need this function for my unit tests - the production MYSQL database provides the spatial functions needed.
I added the code below to one of my own classes (but I guess it would go in GeoDB more formally?). It includes a haversine implementation (but maybe that should have come out of JTS or Hatbox - did not have time to research that :)

Anyway - it works but I'm pretty sure it's architecturally ugly in terms of reuse etc etc !!!


/**
* Provides an implementation of ST_Distance_Sphere using the Haversine formula
* @param wkb1 the first location
* @param wkb2 the second location
* @return the distance between the two locations
*/
public static double ST_Distance_Sphere( byte[] wkb1, byte[] wkb2 ) {
if ( wkb1 == null || wkb2 == null ) {
return -1;
}
Geometry g1 = GeoDB.gFromWKB(wkb1);
Geometry g2 = GeoDB.gFromWKB(wkb2);
return getHaverSineDistance(g1, g2);
}
/**
* Calculate the Haversine distance between two lat/long geometries
* @param wkb1 the first location
* @param wkb2 the second location
* @return the distance between the two locations
*/
private static double getHaverSineDistance(Geometry g1, Geometry g2) 
{
double lat1 = Math.toRadians(g1.getCoordinate().x);
double lng1 = Math.toRadians(g1.getCoordinate().y);
double lat2 = Math.toRadians(g2.getCoordinate().x);
double lng2 = Math.toRadians(g2.getCoordinate().y);

double dlon = lng2 - lng1;
double dlat = lat2 - lat1;

double a = Math.pow((Math.sin(dlat/2)),2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dlon/2),2);

double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

return EARTH_RADIUS_IN_MILES * c;
}   

 And added the following to my schema: 

CREATE ALIAS ST_Distance_Sphere FOR "uk.co.thirdbridge.core.tools.GeoTools.ST_Distance_Sphere";

Justin Deoliveira

unread,
Jul 18, 2013, 10:40:33 AM7/18/13
to ge...@googlegroups.com
Hey Kit,

Right, the jts distance and really all of the operations will do the math assuming a cartesian space.

It would be great to have a distance function that did the match on a spheroid. Basically just poaching from what postgis does.


It would be even better if we could have these functions in JTS. I'll ping Martin Davis about this to see if it's anywhere on the JTS roadmap. 

Regardless of that though I think your approach is perfect fine. I think it's one of the most powerful aspects of h2 / geodb, the ability to very easily implement your own functions. Nice work!

-Justin



--
You received this message because you are subscribed to the Google Groups "geodb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to geodb+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Nagy Attila

unread,
Feb 13, 2018, 5:55:09 PM2/13/18
to geodb
Hello Kit,

your code fragment helps me very much. Thank you for that.
I just observed that the latitude/longitude coordinates are switched (x=longitude, y=latitude).

        final double lng1 = Math.toRadians(g1.getCoordinate().x);
        final double lat1 = Math.toRadians(g1.getCoordinate().y);
        final double lng2 = Math.toRadians(g2.getCoordinate().x);
        final double lat2 = Math.toRadians(g2.getCoordinate().y);

Regards,
Attila
Reply all
Reply to author
Forward
0 new messages