diff --git a/pom.xml b/pom.xml
index 32518e9..3ebe0fb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,48 +21,84 @@
de.deepamehta
deepamehta-geomaps
4.4-SNAPSHOT
+ provided
org.neo4j
neo4j-kernel
1.8.1
+ provided
+
+
+ org.neo4j
+ neo4j-graph-collections
+ 0.4-neo4j-1.8.2
+ provided
org.neo4j
neo4j-spatial
0.9.1-neo4j-1.8.2
+ provided
+
- org.neo4j
- neo4j-graph-collections
- 0.4-neo4j-1.8.2
+ org.geotools
+ gt-api
+ 8.0
+ runtime
org.geotools
- gt-metadata
+ gt-opengis
8.0
+ runtime
org.geotools
- gt-opengis
+ gt-metadata
8.0
+ runtime
org.geotools
gt-referencing
8.0
+ runtime
+
com.vividsolutions
jts
1.12
+ provided
org.jscience
jscience
4.3.1
+ runtime
+
+
+
+ com.tinkerpop.gremlin
+ gremlin-java
+ 1.5
+ provided
+
+
+ com.tinkerpop.gremlin
+ gremlin-groovy
+ 1.5
+ provided
+
+
+ com.tinkerpop
+ pipes
+ 1.0
+ provided
@@ -93,9 +129,10 @@
org.neo4j.graphdb, org.neo4j.graphdb.traversal, org.neo4j.kernel, !org.neo4j.*,
- !com.tinkerpop.*,
+ !com.tinkerpop.blueprints.*,
!org.geotools.*, !org.json.simple.*,
!au.com.objectix.jgridshift,
+ !groovy.lang, !org.codehaus.groovy.*, !jline,
!org.apache.commons.collections, !org.apache.commons.pool.*, !org.apache.commons.logging.*,
!org.apache.commons.lang,
!org.apache.log4j,
@@ -103,8 +140,9 @@
neo4j-spatial, neo4j-graph-collections,
- gt-metadata, gt-opengis, gt-referencing,
- jts, jscience
+ gt-api, gt-opengis, gt-metadata, gt-referencing,
+ jts, jscience,
+ gremlin-java, gremlin-groovy, pipes
diff --git a/src/main/java/de/deepamehta/plugins/geospatial/GeospatialPlugin.java b/src/main/java/de/deepamehta/plugins/geospatial/GeospatialPlugin.java
index f2182e2..5f44776 100644
--- a/src/main/java/de/deepamehta/plugins/geospatial/GeospatialPlugin.java
+++ b/src/main/java/de/deepamehta/plugins/geospatial/GeospatialPlugin.java
@@ -1,5 +1,6 @@
package de.deepamehta.plugins.geospatial;
+import de.deepamehta.plugins.geospatial.service.GeospatialService;
import de.deepamehta.plugins.geomaps.model.GeoCoordinate;
import de.deepamehta.core.CompositeValue;
@@ -11,26 +12,48 @@
import de.deepamehta.core.service.event.PostCreateTopicListener;
import de.deepamehta.core.service.event.PostUpdateTopicListener;
+import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.collections.rtree.NullListener;
import org.neo4j.gis.spatial.SimplePointLayer;
+import org.neo4j.gis.spatial.SpatialDatabaseRecord;
import org.neo4j.gis.spatial.SpatialDatabaseService;
+import org.neo4j.gis.spatial.pipes.GeoPipeFlow;
+import org.neo4j.gis.spatial.pipes.GeoPipeline;
-// ### import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Point;
// ### import com.vividsolutions.jts.geom.Geometry;
// ### import com.vividsolutions.jts.geom.GeometryFactory;
-// ### import com.vividsolutions.jts.geom.Point;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.Consumes;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.logging.Logger;
-public class GeospatialPlugin extends PluginActivator implements PostCreateTopicListener, PostUpdateTopicListener {
+@Path("/geospatial")
+@Consumes("application/json")
+@Produces("application/json")
+public class GeospatialPlugin extends PluginActivator implements GeospatialService, PostCreateTopicListener,
+ PostUpdateTopicListener {
// ------------------------------------------------------------------------------------------------------- Constants
private static final String DEFAULT_LAYER_NAME = "dm4.geospatial.layer";
+ private static final String PROP_GEO_COORD_ID = "geo_coord_id";
+
// ---------------------------------------------------------------------------------------------- Instance Variables
SimplePointLayer layer;
@@ -41,6 +64,43 @@ public class GeospatialPlugin extends PluginActivator implements PostCreateTopic
+ // ****************************************
+ // *** GeospatialService Implementation ***
+ // ****************************************
+
+
+
+ @GET
+ @Path("/{geo_coord}/distance/{distance}")
+ @Override
+ public List getTopicsWithinDistance(@PathParam("geo_coord") GeoCoordinate geoCoord,
+ @PathParam("distance") double maxDistanceInKm) {
+ try {
+ // query geospatial index
+ Coordinate point = new Coordinate(geoCoord.lon, geoCoord.lat);
+ GeoPipeline spatialRecords = GeoPipeline.startNearestNeighborLatLonSearch(layer, point, maxDistanceInKm);
+ /* ### .sort("OrthodromicDistance") */
+ //
+ // build result
+ List geoCoords = new ArrayList();
+ for (GeoPipeFlow spatialRecord : spatialRecords) {
+ // Note: long distance = spatialRecord.getProperty("OrthodromicDistance")
+ long geoCoordId = (Long) spatialRecord.getRecord().getGeomNode().getProperty(PROP_GEO_COORD_ID, -1L);
+ if (geoCoordId == -1) {
+ Point p = (Point) spatialRecord.getGeometry();
+ throw new RuntimeException("A spatial database record misses the \"" + PROP_GEO_COORD_ID +
+ "\" property (lon=" + p.getX() + ", lat=" + p.getY() + ")");
+ }
+ geoCoords.add(dms.getTopic(geoCoordId, true)); // fetchComposite=true
+ }
+ return geoCoords;
+ } catch (Exception e) {
+ throw new RuntimeException("Quering the geospatial index failed", e);
+ }
+ }
+
+
+
// ****************************
// *** Hook Implementations ***
// ****************************
@@ -52,7 +112,7 @@ public void init() {
GraphDatabaseService neo4j = (GraphDatabaseService) dms.getDatabaseVendorObject();
SpatialDatabaseService spatialDB = new SpatialDatabaseService(neo4j);
//
- //spatialDB.deleteLayer(DEFAULT_LAYER_NAME, null);
+ // spatialDB.deleteLayer(DEFAULT_LAYER_NAME, new NullListener());
//
if (spatialDB.containsLayer(DEFAULT_LAYER_NAME)) {
logger.info("########## Default layer already exists (\"" + DEFAULT_LAYER_NAME + "\")");
@@ -91,7 +151,8 @@ private void indexIfGeoCoordinate(Topic topic) {
GeoCoordinate geoCoord = geoCoordinate(topic);
logger.info("########## Indexing Geo Coordinate " + topic.getId() + " (long=" + geoCoord.lon +
", lat=" + geoCoord.lat + ")");
- layer.add(geoCoord.lon, geoCoord.lat);
+ SpatialDatabaseRecord record = layer.add(geoCoord.lon, geoCoord.lat);
+ record.setProperty(PROP_GEO_COORD_ID, topic.getId());
}
}
@@ -103,4 +164,13 @@ private GeoCoordinate geoCoordinate(Topic geoCoordTopic) {
comp.getDouble("dm4.geomaps.latitude")
);
}
+
+ // ### not used
+ private Map nodeProperties(Node node) {
+ Map props = new HashMap();
+ for (String key : node.getPropertyKeys()) {
+ props.put(key, node.getProperty(key));
+ }
+ return props;
+ }
}
diff --git a/src/main/java/de/deepamehta/plugins/geospatial/service/GeospatialService.java b/src/main/java/de/deepamehta/plugins/geospatial/service/GeospatialService.java
new file mode 100644
index 0000000..0e4cd37
--- /dev/null
+++ b/src/main/java/de/deepamehta/plugins/geospatial/service/GeospatialService.java
@@ -0,0 +1,15 @@
+package de.deepamehta.plugins.geospatial.service;
+
+import de.deepamehta.plugins.geomaps.model.GeoCoordinate;
+
+import de.deepamehta.core.Topic;
+import de.deepamehta.core.service.PluginService;
+
+import java.util.List;
+
+
+
+public interface GeospatialService extends PluginService {
+
+ List getTopicsWithinDistance(GeoCoordinate geoCoord, double maxDistanceInKm);
+}