Geospatial functions

#1

Hi,

is it possible to implement geospatial functions (e.g. calculating distance between too points given latitude/longitude) ?Normally you would calculate the distance like:

double cx = Math.toRadians(fromLat);
double cy = Math.toRadians(fromLon);
double px = Math.toRadians(toLat);
double py = Math.toRadians(toLon);
// see http://de.wikipedia.org/wiki/Orthodrome
double gamma = Math.acos(Math.sin(cx) * Math.sin(px) + Math.cos(cx) * Math.cos(px) * Math.cos(py - cy));
return gamma * 6370.0;

But I don´t see radians(), sin() or cos() functions for numbers. Is it possible to add such functions by extending ObjectDB? Or do you have a distance() function?

Thanks in advance
Markus

#2

ObjectDB supports user defined methods in queries.

The following example demonstrates using this ability to retrieve cities in a specific radius from Paris:

import java.util.List;

import javax.persistence.*;

public class T1794 {

    public static void main(String[] args) {

        EntityManagerFactory emf =
            Persistence.createEntityManagerFactory(
                "objectdb:$objectdb/db/points2.tmp;drop");
        EntityManager em = emf.createEntityManager();
       
        em.getTransaction().begin();
        em.persist(new Location("London", 51.507351, -0.127758));
        em.persist(new Location("Paris", 48.856614, 2.352222));
        em.persist(new Location("Berlin", 52.520007, 13.404954));
        em.persist(new Location("New York", 40.712784, -74.005941));
        em.persist(new Location("Tokio", 35.689487, 139.691706));
        em.persist(new Location("Sydney", -33.867487, 151.206990));
        em.getTransaction().commit();
               
        findNearby(em, "Paris", 500);
        findNearby(em, "Paris", 1000);
        findNearby(em, "Paris", 6000);
        findNearby(em, "Paris", 10000);

        em.close();
        emf.close();
    }

    private static void findNearby(
        EntityManager em, String locationName, int radius) {
       
        Location location = em.find(Location.class, locationName);

        TypedQuery<Location> query = em.createQuery(
            "SELECT l FROM Location l " +
            "WHERE l.distance((double):latitude, (double):longitude) < :radius",
            Location.class);

        List<Location> resultList = query
            .setParameter("latitude", location.getLatitude())
            .setParameter("longitude", location.getLongitude())
            .setParameter("radius", radius)
            .getResultList();

        System.out.println(radius + "km From " + location + ": "+ resultList);
    }
   
    @Entity
    public static class Location {
    
        @Id private String name;
       
        private double latitude;
        private double longitude;
       
        public String getName() { return name; }
        public double getLatitude() { return latitude; }
        public double getLongitude() { return longitude; }

        public Location(String name, double latitude, double longitude) {
            this.name = name;
            this.latitude = latitude;
            this.longitude = longitude;
        }
       
        public double distance(double toLatitude, double toLongitude) {
            double cx = Math.toRadians(latitude);
            double cy = Math.toRadians(longitude);
            double px = Math.toRadians(toLatitude);
            double py = Math.toRadians(toLongitude);
            double gamma = Math.acos(Math.sin(cx) * Math.sin(px) +
                Math.cos(cx) * Math.cos(px) * Math.cos(py - cy));
            return gamma * 6370.0;
        }
       
        @Override
        public String toString() {
            return name;
        }
   }
}

Note: In client server mode you must make your entity class (with the method that is used in the query) available to the server by running the ObjectDB Server with a classpath that includes your entity classes.

ObjectDB Support
#3
Hi Thanks. Thats great. Best wishes Markus

Reply