2

I use hibernate spatial attach a geolocation to a car. My card domain class looks like this:

import com.vividsolutions.jts.geom.Point
class Card {
  String name
  Point location 
}

My program is in Grails so the samples I gave are in Groovy. I found a similar post here which does not really answer the most important question on how to specify the radius correctly to set n kilimeter for the radius.

Here is how I compute a circle Geometry:

  private static Geometry createCircle(double x, double y, final double RADIUS) {
    GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
    shapeFactory.setNumPoints(1000);
    shapeFactory.setCentre(new Coordinate(x, y))
    shapeFactory.setSize( (RADIUS * 2)/88.1)

    return shapeFactory.createCircle().getBoundary()
  }

The size of the circle is divided by 88.1 the is just a dirty fix to get an approximate dimension but it is still wrong.

My query is done like this:

double radius = 40
Geometry filter = createCircle(car.location.x, car.location.y, radius)
Session session = sessionFactory.currentSession
Query q = session.createQuery("select c from Car c where within(c.location, ?) = true")
q.setParameter(0, filter, GeometryUserType.TYPE) 
q.list()

This works not very accurate. Some of the cars which should be outside circle are returned from this query.

Here is an example. My center is Hamburg and the radius is 40km. I made a google maps visualization.

Here is when I set radius = 40:

enter image description here

You can see that at the top left one car which has a location outside of the circle is still drawn. This should not be the case. It appears to me that the circle I draw with google maps is not equal to the circle Geometry I draw in code for my query.

Here is when I set radius = 30:

enter image description here

You see that the cars at the bottom right disappear which is correct, but the car at the top left still remains in the query.

When I draw the circle I created with createCircle I get the following (using getCoordinates() to get the coordinates of the circle):

enter image description here

How can I query all cars within a radius of 40km? How do I get the correct coordinate system?

  • You can set srid = 8307 for Longitude / Latitude (WGS 84) geographic2d – Mert Aksu Jan 20 '17 at 13:00
1

I found a method posted in a forum (credit to some Simon Hartley) that looks good to me : http://osgeo-org.1560.x6.nabble.com/how-to-programmatically-create-circles-tt5001091.html#a5001108

private static Geometry create3DCircle(double lng, double lat, double radiusNm) { 
        GeodeticCalculator calc = new GeodeticCalculator(DefaultEllipsoid.WGS84); 
        calc.setStartingGeographicPoint(lng, lat); 
        final int SIDES = 32 + 16 * ((int)Math.ceil(radiusNm / 40) / 5);       // Fairly random. 

        double distance = radiusNm * 1852      /*1855.3248*/;              // Convert to metres.    
        double baseAzimuth = 360.0 / SIDES; 
        Coordinate coords[] = new Coordinate[SIDES+1]; 
        for( int i = 0; i < SIDES; i++){ 
                double azimuth = 180 - (i * baseAzimuth); 
                calc.setDirection(azimuth, distance); 
                Point2D point = calc.getDestinationGeographicPoint(); 
                coords[i] = new Coordinate(point.getX(), point.getY()); 
        } 
        coords[SIDES] = coords[0]; 

        LinearRing ring = GEOMETRY_FACTORY.createLinearRing( coords ); 
        Polygon polygon = GEOMETRY_FACTORY.createPolygon( ring, null ); 

        return polygon; 
} 

Probably at the end you may want to make sure that the polygon gets the right SRID, in this case a WGS84 projection, something like this :

 polygon.setSRID(4326);

Be aware that the input parameter is in meters, not kms.

  • this looks like exactly what I need, but I did have one question: What is the value of GEOMETRY_FACTORY ? – Michael Draper Nov 22 '17 at 1:37
  • GEOMETRY_FACTORY is just an instance of JTS GeometryFactory class. Quite often you would have a static instance in your class such as : import com.vividsolutions.jts.geom.GeometryFactory; private static GeometryFactory geometryFactory = new GeometryFactory(); – krause Nov 22 '17 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.