3232import org .eclipse .rdf4j .model .Resource ;
3333import org .eclipse .rdf4j .model .Statement ;
3434import org .eclipse .rdf4j .model .ValueFactory ;
35+ import org .eclipse .rdf4j .model .base .CoreDatatype ;
3536import org .eclipse .rdf4j .model .impl .BooleanLiteral ;
3637import org .eclipse .rdf4j .model .impl .SimpleValueFactory ;
3738import org .eclipse .rdf4j .model .vocabulary .GEO ;
4142import org .eclipse .rdf4j .query .MalformedQueryException ;
4243import org .eclipse .rdf4j .query .algebra .Var ;
4344import org .eclipse .rdf4j .query .algebra .evaluation .QueryBindingSet ;
45+ import org .eclipse .rdf4j .query .algebra .evaluation .function .geosparql .SpatialAlgebra ;
46+ import org .eclipse .rdf4j .query .algebra .evaluation .function .geosparql .SpatialSupport ;
4447import org .eclipse .rdf4j .sail .Sail ;
4548import org .eclipse .rdf4j .sail .SailException ;
4649import org .eclipse .rdf4j .sail .lucene .util .MapOfListMaps ;
4750import org .locationtech .spatial4j .context .SpatialContext ;
51+ import org .locationtech .spatial4j .io .ShapeReader ;
4852import org .locationtech .spatial4j .shape .Point ;
4953import org .locationtech .spatial4j .shape .Shape ;
5054import org .slf4j .Logger ;
@@ -855,6 +859,59 @@ private Iterable<? extends DocumentResult> evaluateQuery(GeoRelationQuerySpec qu
855859 return hits ;
856860 }
857861
862+ private IRI toSpatialOp (String relation ) {
863+ if (GEOF .SF_INTERSECTS .stringValue ().equals (relation )) {
864+ return GEOF .SF_INTERSECTS ;
865+ } else if (GEOF .SF_DISJOINT .stringValue ().equals (relation )) {
866+ return GEOF .SF_DISJOINT ;
867+ } else if (GEOF .SF_EQUALS .stringValue ().equals (relation )) {
868+ return GEOF .SF_EQUALS ;
869+ } else if (GEOF .SF_OVERLAPS .stringValue ().equals (relation )) {
870+ return GEOF .SF_OVERLAPS ;
871+ } else if (GEOF .EH_COVERED_BY .stringValue ().equals (relation )) {
872+ return GEOF .SF_WITHIN ;
873+ } else if (GEOF .EH_COVERS .stringValue ().equals (relation )) {
874+ return GEOF .EH_CONTAINS ;
875+ } else if (GEOF .SF_WITHIN .stringValue ().equals (relation )) {
876+ return GEOF .SF_WITHIN ;
877+ } else if (GEOF .EH_CONTAINS .stringValue ().equals (relation )) {
878+ return GEOF .EH_CONTAINS ;
879+ }
880+ return null ;
881+ }
882+
883+ private Shape readShape (String geo ) {
884+ ShapeReader reader = SpatialSupport .getSpatialContext ().getFormats ().getWktReader ();
885+ try {
886+ return reader .read (geo );
887+ } catch (IOException | ParseException e ) {
888+ throw new SailException ("Can't read geo wkt shape" , e );
889+ }
890+ }
891+
892+ private boolean checkSpatialOp (IRI op , Shape arg1 , Shape arg2 ) {
893+ SpatialAlgebra algebra = SpatialSupport .getSpatialAlgebra ();
894+ if (op == GEOF .SF_INTERSECTS ) {
895+ return algebra .sfIntersects (arg1 , arg2 );
896+ }
897+ if (op == GEOF .SF_DISJOINT ) {
898+ return algebra .sfDisjoint (arg1 , arg2 );
899+ }
900+ if (op == GEOF .SF_EQUALS ) {
901+ return algebra .sfEquals (arg1 , arg2 );
902+ }
903+ if (op == GEOF .SF_OVERLAPS ) {
904+ return algebra .sfOverlaps (arg1 , arg2 );
905+ }
906+ if (op == GEOF .SF_WITHIN ) {
907+ return algebra .sfWithin (arg1 , arg2 );
908+ }
909+ if (op == GEOF .EH_CONTAINS ) {
910+ return algebra .ehContains (arg1 , arg2 );
911+ } else
912+ throw new SailException (new IllegalArgumentException ("bad spatial op : " + op ));
913+ }
914+
858915 private BindingSetCollection generateBindingSets (GeoRelationQuerySpec query ,
859916 Iterable <? extends DocumentResult > hits ) throws SailException {
860917 // Since one resource can be returned many times, it can lead now to
@@ -893,8 +950,25 @@ private BindingSetCollection generateBindingSets(GeoRelationQuerySpec query,
893950 }
894951
895952 List <String > geometries = doc .getProperty (SearchFields .getPropertyField (query .getGeoProperty ()));
953+ boolean needValidation = geometries .size () != 1 ;
954+ IRI spatialOp = null ;
955+ Shape funcGeo = null ;
956+ if (needValidation ) {
957+ spatialOp = toSpatialOp (query .getRelation ());
958+ funcGeo = readShape (query .getQueryGeometry ().getLabel ());
959+ }
896960 for (String geometry : geometries ) {
897961 QueryBindingSet derivedBindings = new QueryBindingSet ();
962+ if (geoVar != null ) {
963+ if (needValidation && spatialOp != null ) {
964+ Shape geo = readShape (geometry );
965+
966+ if (!checkSpatialOp (spatialOp , funcGeo , geo )) {
967+ continue ; // not inside the asked shape
968+ }
969+ }
970+ derivedBindings .addBinding (geoVar , SearchFields .wktToLiteral (geometry ));
971+ }
898972 if (subjVar != null ) {
899973 Resource resource = getResource (doc );
900974 derivedBindings .addBinding (subjVar , resource );
@@ -905,9 +979,6 @@ private BindingSetCollection generateBindingSets(GeoRelationQuerySpec query,
905979 derivedBindings .addBinding (contextVar .getName (), ctx );
906980 }
907981 }
908- if (geoVar != null ) {
909- derivedBindings .addBinding (geoVar , SearchFields .wktToLiteral (geometry ));
910- }
911982 if (fVar != null ) {
912983 derivedBindings .addBinding (fVar , BooleanLiteral .TRUE );
913984 }
0 commit comments