1

Colleagues and I are working with RDF dataset and RDF4J's in-Memory repository and we are trying to execute GeoSparql queries while using geometry data in WKT format, as shown below:

@prefix geo: <http://www.opengis.net/ont/geosparql#> .
@prefix sf: <http://www.opengis.net/ont/sf> .
@prefix ex: <http://example.org/> .
@prefix geof: <http://www.opengis.net/def/function/geosparql/>.

ex:eiffelTower a ex:Landmark ;
        geo:hasGeometry ex:coordinates-et.
ex:coordinates-et a sf:Point;
        geo:asWKT "POINT(2.2945 48.8584)"^^geo:wktLiteral .

ex:towerBridge a ex:Landmark ;
          geo:hasGeometry ex:coordinates-tb.
ex:coordinates-tb a sf:Point;
        geo:asWKT "POINT(-0.0754 51.5055)"^^geo:wktLiteral .

Scenario-1: So far we managed to successfully use geof:distance function, e.g. of a query and it's result are given below. Intention was to calculate the distance between the coordinates of two landmarks.

SELECT *
WHERE {
  ?lmA a ex:Landmark ;
       geo:hasGeometry [ geo:asWKT ?coord1 ].

  ?lmB a ex:Landmark ;
       geo:hasGeometry [ geo:asWKT ?coord2 ].

  BIND((geof:distance(?coord1, ?coord2, uom:metre)/1000) as ?dist) .
  FILTER (str(?lmA) < str(?lmB))
}

Result of Scenario-1:

lmA => ex:eiffelTower
coord1 => "POINT(2.2945 48.8584)"
lmB =>  ex:towerBridge
coord2 => "POINT(-0.0754 51.5055)"
dist => "339.2412973915987"

Scenario-2: When we tried to use other functions, e.g. geof:sfWithin, geof:sfContains, we ran into some strange behavior. The query with geof:sfWithin example and it's result are shown below. Intention was to get all the points that are positioned inside the given polygon.

SELECT *
WHERE {
  ?lmA a ex:Landmark ;
       geo:hasGeometry ?Geom.

  ?Geom geo:asWKT ?WKT.

  FILTER(geof:sfWithin(?WKT, '''
        <http://www.opengis.net/def/crs/OGC/1.3/CRS84>
            Polygon ((80.0 80.0, -80.0 80.0, -80.0 -80.0, 80.0 -80.0, 80.0 80.0))
        '''^^geo:wktLiteral))
}

Result: -empty table-

Are we doing something wrong in our queries? Our dependencies:

  • rdf4j-storage 3.6.0
  • rdf4j-queryalgebra-geosparql 3.6.1
RedCrusaderJr
  • 350
  • 1
  • 12

1 Answers1

2

I think the problem is the syntax of your polygon wkt literal. You've got:

<http://www.opengis.net/def/crs/OGC/1.3/CRS84>
Polygon ((80.0 80.0, -80.0 80.0, -80.0 -80.0, 80.0 -80.0, 80.0 80.0))

I'm not sure where that URI on the first line comes from (I'm not really a GeoSPARQL expert) but that does not look like a proper WKT literal to me. I tried your query with

Polygon ((80.0 80.0, -80.0 80.0, -80.0 -80.0, 80.0 -80.0, 80.0 80.0))

instead, and got the following two results:

lmA=http://example.org/eiffelTower
WKT="POINT(2.2945 48.8584)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>
Geom=http://example.org/coordinates-et

lmA=http://example.org/towerBridge
WKT="POINT(-0.0754 51.5055)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>
Geom=http://example.org/coordinates-tb

Admittedly, the query silently failing rather than producing some "could not process WKT literal" error or warning is confusing .

Update:

Looking a bit further (see also the comments), this is actually a bug in RDF4J. As section 8.5 in the GeoSPARQL spec indicates the prefixing URI for the reference system is not part of the WKT spec itself, but is a GeoSPARQL-specific addition to the definition of a WKT Literal. So RDF4J needs to take care of preprocessing that before handing it off to the underlying WKTReader. Bug ticket created as https://github.com/eclipse/rdf4j/issues/2935.

As a workaround, you can still get away with removing the URI, as CRS84 is actually the default reference system anyway.

Jeen Broekstra
  • 21,642
  • 4
  • 51
  • 73
  • That is a valid GeoSPARQL literal. See section 8.5 in the [standards](https://portal.ogc.org/files/?artifact_id=47664) : *For geo:wktLiterals, the beginning URI identifies the spatial reference system for the geometry.* - those CRS URIs clearly affect the whole processing as for literals from different CRS you have to apply transformation during evaluation – UninformedUser Mar 22 '21 at 04:01
  • In that case, this is likely a problem in either JTS or in the Spatial4J library (or at least in how RDF4J uses them). @RedCrusaderJr would you mind logging an issue at github.com/eclipse/rdf4j/issues so we can keep track of this? – Jeen Broekstra Mar 22 '21 at 04:30
  • Looking a bit further, this is actually a bug in RDF4J I think - as section 8.5 in the GeoSPARQL spec indicates the prefixing URI for the reference system is not part of the WKT itself, but is a GeoSPARQL-specific addition. So we need to take care of preprocessing that before handing it off to the underlying WKTReader. Bug ticket created as https://github.com/eclipse/rdf4j/issues/2935 – Jeen Broekstra Mar 22 '21 at 04:47
  • well, yes. This is not part of JTS, but a CRS will be used for transformation when comparing WKT literals form different CRS. But yes, the parsing is basically String processing, you can have a look at and basically reuse how it's done in Jena I think: https://github.com/apache/jena/blob/main/jena-geosparql/src/main/java/org/apache/jena/geosparql/implementation/parsers/wkt/WKTReader.java#L255-L293 – UninformedUser Mar 22 '21 at 08:31
  • Thank you all, it was very helpful. For now we will try and work our cases without CRS URIs, at least until the bug is fixed. – RedCrusaderJr Mar 22 '21 at 09:42
  • I would like to talk to you two a bit more. @UninformedUser First of all I am new to java, new to rdf4j and new to geosparql. I have the theoretical understanding of rdf stores, and sparql in general. What is bugging me are some concrete geosparql examples (https://graphdb.ontotext.com/documentation/free/geosparql-support.html). I understand that GraphDB allows for some additional functionalities, not present in geosparql nor in rdf4j in-memory and native repositories. Continuing in next comment... – RedCrusaderJr Mar 22 '21 at 16:28
  • @JeenBroekstra (I could not tag you above) Specifically I understand that all the examples where geosparql functions are used as a predicates will not work without GraphDB repository. Out of all the examples found on the page only the example 4 works as expected, and all the other just return empty queries. Maybe it is not obvious where is the link to a data set: https://graphdb.ontotext.com/documentation/free/_downloads/d10860b42c7c39e3d05ef397f5756ca1/geosparql-example.rdf – RedCrusaderJr Mar 22 '21 at 16:31
  • As I stated in my first comment am a total beginner in this field and that is the reason I am not posting more questions on this topic, but I would rather appreciate if you could give me directions for further research - point me out to some documents for example, or part of the rdf4j source code where I could find for myself what is supported and what is not. – RedCrusaderJr Mar 22 '21 at 16:37
  • 1
    @RedCrusaderJr not sure what you mean by "not present in geosparql" - that is not true. Usage of geospatial relations is specified in the [GeoSPARQL standard document](file:///tmp/mozilla_infai0/11-052r4_OGC_GeoSPARQL_-_A_Geographic_Query_Language_for_RDF_Data-1.pdf) for sure. Usage of those relations as RDF predicate in graph patterns is specified in section 7, usage as spatial function, i.e. in FILTER clauses is defined in section 9. A rewritie RIF rule from relation predicate to FILTER is declared in section 11. – UninformedUser Mar 22 '21 at 18:18
  • 1
    If it does not work in rdf4j, then it's simply not implemented (yet). But as I said, how to rewrite the query to a Filter function is specified in section 11 of the GeoSPARQL standard. So, it wouldn't be too difficult in the end, it's just that somebody would have to do it. I'm pretty sure the RDF4J community is happy for any contributions. – UninformedUser Mar 22 '21 at 18:20
  • 1
    @RedCrusaderJr I think this discussion is going a bit beyond the format of a StackOverflow question :) I suggest you reach out to us via one of the RDF4J community support channels - see https://rdf4j.org/support/ . – Jeen Broekstra Mar 22 '21 at 22:03
  • 1
    @JeenBroekstra I looked trough rdf4j source code and I found geosparql test queries. I'll experiment with that for now, but if that leave me stranded I'll contact you on Gitter. – RedCrusaderJr Mar 23 '21 at 05:59