GeoSPARQL support

What is GeoSPARQL

GeoSPARQL is a standard for representing and querying geospatial linked data for the Semantic Web from the Open Geospatial Consortium (OGC). The standard provides:

  • a small topological ontology in RDFS/OWL for representation using Geography Markup Language (GML) and Well-Known Text (WKT) literals;

  • Simple Features, RCC8, and Egenhofer topological relationship vocabularies and ontologies for qualitative reasoning;

  • A SPARQL query interface using a set of topological SPARQL extension functions for quantitative reasoning.

The GraphDB GeoSPARQL plugin allows the conversion of Well-Known Text from different coordinate reference systems (CRS) into the CRS84 format, which is the default CRS according to the Open Geospatial Consortium (OGC). You can input data of all known CRS types - it will be properly indexed by the plugin, and you will also be able to query it in both the default CRS84 format and in the format in which it was imported.

The following is a simplified diagram of the GeoSPARQL classes Feature and Geometry, as well as some of their properties:

_images/geosparql-ontology.png

Usage

Configuration parameters

The following parameters can be used when configuring the plugin:

Parameter

enabled

Predicate

<http://www.ontotext.com/plugins/geosparql#enabled>

Description

Enables and disables plugin

Default

false

Example

PREFIX geoSparql: <http://www.ontotext.com/plugins/geosparql#>
INSERT DATA { _:s geoSparql:enabled "true" . }

Parameter

prefixTree

Predicate

<http://www.ontotext.com/plugins/geosparql#prefixTree>

Description

Implementation of the tree used while building the index; stores value before rebuilding.

Default

prefixTree.QUAD

Example

PREFIX geoSparql: <http://www.ontotext.com/plugins/geosparql#>
INSERT DATA { _:s geoSparql:prefixTree "geohash" . }

Parameter

precision

Predicate

<http://www.ontotext.com/plugins/geosparql#precision>

Description

Specifies the desired precision; stores value before rebuilding

Default

11 min value 1; max value depends on used prefixTree or (24 for geohash and 50 for QUAD)

Example

PREFIX geoSparql: <http://www.ontotext.com/plugins/geosparql#>
INSERT DATA { _:s geoSparql:precision "11" . }

Parameter

currentPrefixTree

Predicate

<http://www.ontotext.com/plugins/geosparql#currentPrefixTree>

Description

Value of last built index

Default

PrefixTree.QUAD

Example

PREFIX geoSparql: <http://www.ontotext.com/plugins/geosparql#>
INSERT DATA { _:s geoSparql:currentPrefixTree "geohash" . }

Parameter

currentPrecision

Predicate

<http://www.ontotext.com/plugins/geosparql#currentPrecision>

Description

Value of last built index

Default

11

Example

PREFIX geoSparql: <http://www.ontotext.com/plugins/geosparql#>
INSERT DATA { _:s geoSparql:currentPrecision "11" . }

Parameter

maxBufferedDocs

Predicate

<http://www.ontotext.com/plugins/geosparql#maxBufferedDocs>

Description

Speeds up building and rebuilding of index

Default

1,000 (max. allowed 5,000)

Example

PREFIX geoSparql: <http://www.ontotext.com/plugins/geosparql#>
INSERT DATA { _:s geoSparql:maxBufferedDocs "3000" . }

Parameter

ramBufferSizeMB

Predicate

<http://www.ontotext.com/plugins/geosparql#ramBufferSizeMB>

Description

Speeds up building and rebuilding of index

Default

32.0 (max. allowed 512.0)

Example

PREFIX geoSparql: <http://www.ontotext.com/plugins/geosparql#>
INSERT DATA { _:s geoSparql:ramBufferSizeMB "256.0" . }

Parameter

ignoreErrors

Predicate

<http://www.ontotext.com/plugins/geosparql#ignoreErrors>

Description

Ensures building of the index even in case of erroneous data

Default

false

Example

PREFIX geoSparql: <http://www.ontotext.com/plugins/geosparql#>
INSERT DATA { _:s geoSparql:ignoreErrors "true" . }

Plugin control predicates

The plugin allows you to configure it through SPARQL UPDATE queries with embedded control predicates.

Enable plugin

When the plugin is enabled, it indexes all existing GeoSPARQL data in the repository and automatically reindexes any updates.

PREFIX : <http://www.ontotext.com/plugins/geosparql#>

INSERT DATA {
  _:s :enabled "true" .
}

Note

All functions require as input WKT or GML literals while the predicates expect resources of type geo:Feature or geo:Geometry. The GraphDB implementation has a non-standard extension that allows you to use literals with the predicates too. See Example 2 (using predicates) for an example of that usage.

Warning

All GeoSPARQL functions starting with geof: like geof:sfOverlaps do not use any indexes and are always enabled! That is why it is recommended to use the indexed operations like geo:sfOverlaps, whenever it is possible.

Disable plugin

When the plugin is disabled, it does not index any data or process updates. It does not handle any of the GeoSPARQL predicates either.

PREFIX : <http://www.ontotext.com/plugins/geosparql#>

INSERT DATA {
  _:s :enabled "false" .
}

Check the current configuration

All the plugin configuration parameters are stored in $GDB_HOME/data/repositories/<repoId>/storage/GeoSPARQL/config.properties. To check the current runtime configuration:

SELECT * WHERE {
    <http://www.ontotext.com/plugins/geosparql> ?p ?o.
}

Update the current configuration

The plugin supports two indexing algorithms quad prefix tree and geohash prefix tree. Both algorithms support approximate matching controlled with the precision parameter. The default 11 precision value of the quad prefix is about ±2.5km on the equator. When increased to 20 the precision goes down to ±6m accuracy. Respectively, the geohash prefix tree with precision 11 results ±1m.

PREFIX : <http://www.ontotext.com/plugins/geosparql#>

INSERT DATA {
    _:s :prefixTree "quad"; #geohash
        :precision  "25".
}

After changing the indexing algorithm, you need to trigger a reindex.

Speed up the building and rebuilding of the GeoSPARQL index

To speed up the building and rebuilding of your GeoSPARQL index, we recommend setting higher values for the ramBufferSizeMB and maxBufferedDocs parameters. This disables the Lucene IndexWriter autocommit, and starts flushing disk changes if one of these values is reached.

Default and maximum values are as follows:

  • ramBufferSizeMB - default 32.0, maximum 512.0.

  • maxBufferedDocs - default 1,000, maximum 5,000.

Depending on your dataset and machine parameters, you can experiment with the values to find the ones most suitable for your use case.

Note

However, do not set these values too high, otherwise you may hit an IndexWriter over-merging issue.

Force reindex geometry data

This configuration option is usually used after a configuration change or when index files are either corrupted or have been mistakenly deleted.

PREFIX : <http://www.ontotext.com/plugins/geosparql#>

INSERT DATA {
    _:s :forceReindex ""
}

Ignore errors on indexing

PREFIX : <http://www.ontotext.com/plugins/geosparql#>

INSERT DATA {
    _:s :ignoreErrors "true"
}

ignoreErrors predicate determines whether the GeoSPARQL index will continue building if an error has occurred. If the value is set to false, the whole index will fail if there is a problem with a document. If the value is set to true, the index will continue building and a warning will be logged in the log. By default, the value of ignoreErrors is false.

GeoSPARQL extensions

On top of the standard GeoSPARQL functions, GraphDB offers a few useful extensions. Those are based on the USeekMSail. All extension functions have the ext prefix, where ext stands for <http://rdf.useekm.com/ext#>.

Function

Description

double

ext:area(geometry)

Calculates the area of the surface of the geometry.

point

ext:closestPoint(geometry, geometry)

For two given geometries, computes the point on the first geometry that is closest to the second geometry.

bool

ext:containsProperly(geometry, geometry)

Tests if the first geometry properly contains the second geometry. Geom1 contains properly geom2 if all geom1 contains geom2 and the boundaries of the two geometries do not intersect.

bool

ext:coveredBy(geometry, geometry)

Tests if the first geometry is covered by the second geometry. Geom1 is covered by geom2 if every point of geom1 is a point of geom2.

bool

ext:covers(geometry, geometry)

Tests if the first geometry covers the second geometry. Geom1 covers geom2 if every point of geom2 is a point of geom1.

double

ext:hausdorffDistance(geometry, geometry)

Measures the degree of similarity between two geometries. The measure is normalized to lie in the range [0, 1]. Higher measures indicate a greater degree of similarity.

line

ext:shortestLine(geometry, geometry)

Computes the shortest line between two geometries. Returns it as a LineString object.

geometry

ext:simplify(geometry, double)

Given a maximum deviation from the curve, computes a simplified version of the given geometry using the Douglas-Peuker algorithm.

geometry

ext:simplifyPreserveTopology(geometry, double)

Given a maximum deviation from the curve, computes a simplified version of the given geometry using the Douglas-Peuker algorithm. Will avoid creating derived geometries (polygons in particular) that are invalid.

bool

ext:isValid(geometry)

Checks whether the input geometry is a valid geometry.

GeoSPARQL examples

This section contains examples of SELECT queries on geographic data.

Examples 1, 2 and 3 have a variant using a function (corresponding to the same example in the GeoSPARQL specification), as well as a variant where the function is substituted with a predicate. Examples 4 and 5 use a predicate and correspond to the same examples in the specification.

To run the examples you need to:

The data defines the following spatial objects:

_images/geosparql-example-objects.png

Example 1

Find all features that feature my:A contains, where spatial calculations are based on my:hasExactGeometry.

Using a function

PREFIX my: <http://example.org/ApplicationSchema#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>

SELECT ?f
WHERE {
    my:A my:hasExactGeometry ?aGeom .
    ?aGeom geo:asWKT ?aWKT .
    ?f my:hasExactGeometry ?fGeom .
    ?fGeom geo:asWKT ?fWKT .
    FILTER (geof:sfContains(?aWKT, ?fWKT) && !sameTerm(?aGeom, ?fGeom))
}

Using a predicate

PREFIX my: <http://example.org/ApplicationSchema#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>

SELECT ?f
WHERE {
    my:A my:hasExactGeometry ?aGeom .
    ?f my:hasExactGeometry ?fGeom .
    ?aGeom geo:sfContains ?fGeom .
    FILTER (!sameTerm(?aGeom, ?fGeom))
}

Example 1 result

?f

my:B

my:F

Example 2

Find all features that are within a transient bounding box geometry, where spatial calculations are based on my:hasPointGeometry.

Using a function

PREFIX my: <http://example.org/ApplicationSchema#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>

SELECT ?f
WHERE {
    ?f my:hasPointGeometry ?fGeom .
    ?fGeom geo:asWKT ?fWKT .
    FILTER (geof:sfWithin(?fWKT, '''
        <http://www.opengis.net/def/crs/OGC/1.3/CRS84>
            Polygon ((-83.4 34.0, -83.1 34.0,
                      -83.1 34.2, -83.4 34.2,
                      -83.4 34.0))
        '''^^geo:wktLiteral))
}

Using a predicate

Note

Using geometry literals in the object position is a GraphDB extension and not part of the GeoSPARQL specification.

PREFIX my: <http://example.org/ApplicationSchema#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>

SELECT ?f
WHERE {
    ?f my:hasPointGeometry ?fGeom .
        ?fGeom geo:sfWithin '''
        <http://www.opengis.net/def/crs/OGC/1.3/CRS84>
            Polygon ((-83.4 34.0, -83.1 34.0,
                      -83.1 34.2, -83.4 34.2,
                      -83.4 34.0))
        '''^^geo:wktLiteral
}

Example 3

Find all features that touch the union of feature my:A and feature my:D, where computations are based on my:hasExactGeometry.

Using a function

PREFIX my: <http://example.org/ApplicationSchema#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>

SELECT ?f
WHERE {
    ?f my:hasExactGeometry ?fGeom .
    ?fGeom geo:asWKT ?fWKT .
    my:A my:hasExactGeometry ?aGeom .
    ?aGeom geo:asWKT ?aWKT .
    my:D my:hasExactGeometry ?dGeom .
    ?dGeom geo:asWKT ?dWKT .
    FILTER (geof:sfTouches(?fWKT, geof:union(?aWKT, ?dWKT)))
}

Using a predicate

PREFIX my: <http://example.org/ApplicationSchema#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>

SELECT ?f
WHERE {
    ?f my:hasExactGeometry ?fGeom .
    ?fGeom geo:asWKT ?fWKT .
    my:A my:hasExactGeometry ?aGeom .
    ?aGeom geo:asWKT ?aWKT .
    my:D my:hasExactGeometry ?dGeom .
    ?dGeom geo:asWKT ?dWKT .
    BIND(geof:union(?aWKT, ?dWKT) AS ?union) .
    ?fGeom geo:sfTouches ?union
}

Example 4

Find the 3 closest features to feature my:C, where computations are based on my:hasExactGeometry.

PREFIX uom: <http://www.opengis.net/def/uom/OGC/1.0/>
PREFIX my: <http://example.org/ApplicationSchema#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>

SELECT ?f
WHERE {
    my:C my:hasExactGeometry ?cGeom .
    ?cGeom geo:asWKT ?cWKT .
    ?f my:hasExactGeometry ?fGeom .
    ?fGeom geo:asWKT ?fWKT .
    FILTER (?fGeom != ?cGeom)
}
ORDER BY ASC(geof:distance(?cWKT, ?fWKT, uom:metre))
LIMIT 3

Example 4 result

?f

my:A

my:E

my:D

Note

The example in the GeoSPARQL specification has a different order in the result: my:A, my:D, my:E. In fact, feature my:E is closer than feature my:D even if that does not seem obvious from the drawing of the objects. my:E’s closest point is 0.1° to the West of my:C, while my:D’s closest point is 0.1° to the South. At that latitude and longitude the difference in terms of distance is larger in latitude, hence my:E is closer.

Example 5

Find all features or geometries that overlap feature my:A.

PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX my: <http://example.org/ApplicationSchema#>

SELECT ?f
WHERE {
    ?f geo:sfOverlaps my:AExactGeom
}

Example 5 result

?f

my:D

my:DExactGeom

Note

The example in the GeoSPARQL specification has additional results my:E and my:EExactGeom. In fact, my:E and my:EExactGeom do not overlap my:AExactGeom because they are of different dimensions (my:AExactGeom is a Polygon and my:EExactGeom is a LineString) and the overlaps relation is defined only for objects of the same dimension.

Tip

For more information on GeoSPARQL predicates and functions, see the current official spec: OGC 11-052r4, Version: 1.0, Approval Date: 2012-04-27, Publication Date: 2012-09-10.