.. include:: /includes.rst.txt .. comments - headings # with overline, for parts * with overline, for chapters = for sections - for subsections ^ for subsubsections " for paragraphs * for H5 + for H6 .. _edg_geo_spatial_capabilities: Geo-spatial capabilities in TopBraid EDG ======================================== The purpose of this document is to showcase how GeoSPARQL can be used within TopBraid Enterprise Data Governance (referred to as EDG). This document will walkthrough steps that enable the usage of the Geo features in EDG, from the creation of schemas to performing actions on items on maps. Finally, the cookbook demonstrates how data governance assets can be enriched with geospatial information. You will need the following EDG project and TriG file to walk through the cookbook. To install this sample project in EDG, navigate to Server Administration, Upload Project. To remove this project in the future use Delete Project. :download:`geosparql_cookbook.trig <_downloads/geosparql_cookbook.trig>` .. contents:: .. _1-prerequisites: 1. Prerequisites ---------------- Google Maps API key set up in EDG: *Server Administration* > *Server Configuration* > *Advanced Parameters*. .. _2-creation-of-a-geo-aware-schema-in-edg: 2. Creation of a geo-aware schema in EDG ---------------------------------------- The following section demonstrates the creation of a generic schema that describe countries and cities. A mixture of RDF constructs and SHACL shapes are used. Under *Asset Collections* select *Ontologies*. On page load, click on the *Create New Ontology* button, which in turn will display the following form. The *Label* field is mandatory, and once filled press *Create Ontology*. By default, EDG creates a skeleton schema, importing the *Default constraints for EDG* and *GraphQL Vocabulary*. .. figure:: _images/create_ontology.png :alt: Create Ontology :align: center :class: edg-figure .. _21-adding-existing-geo-vocabularies-and-shapes: 2.1 Adding existing Geo vocabularies and shapes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EDG provides a general vocabulary defining a number of classes, SHACL shapes and SHACL functions, which drives the various functionality within EDG, for example the *Maps Explorer* panel. The **TopBraid GeoSPARQL Vocabulary** (``prefix: tbgeo:``) gathers concepts from the W3C *WGS84 Geo Positioning* RDF vocabulary [1]_ and the *Open Geospatial Consortium GeoSPARQL - A Geographic Query Language for RDF Data* schema [2]_, and describes these concepts as SHACL shapes. The former vocabulary allows the representation of latitude, longitude and altitude information. The latter vocabulary enables the representation of geospatial data, and defines a SPARQL extension to query the said data. By defining these as SHACL shapes, it ensures that users can query properties in geo-aware asset collections using GraphQL. Furthermore, the TopBraid vocabulary defines a number of shapes that can be extended to enable interactive actions on maps in EDG and other functions relevant for querying. Therefore, adding this vocabulary in the custom geo-aware schema will ensure that the schema contains all the required property and node shapes to create a geo-driven asset collection. In order to include The **TopBraid GeoSPARQL Vocabulary** in the schema, click on the *Settings* tab, followed by the *Includes* link. This will display a dialog box with all possible includes. Filter by the *Collection Name* column, typing **TopBraid GeoSPARQL Vocabulary**, tick the first column and press *Close*. .. figure:: _images/includes.png :alt: Includes :align: center :class: edg-figure The *Settings* page will look as follows, with **TopBraid GeoSPARQL vocabulary** added under *Includes*: .. figure:: _images/includes-full.png :alt: Includes Full :align: center :class: edg-figure Clicking back on the *Ontology* tab, the *Class Hierarchy* panel shows a tree, with three concepts *Geometry*, *Map context*, and *Spatial thing*. These concepts will be explained later on in this document. .. figure:: _images/ontology-page-empty.png :alt: Ontology Page Empty :align: center :class: edg-figure .. _22-defining-the-schema: 2.2 Defining the Schema ~~~~~~~~~~~~~~~~~~~~~~~ This section describes the shapes and properties defined to create a geo-aware ontology. This section is not meant to demonstrate the ontology editing capabilities of EDG. For an introduction in this regard, the reader is referred to [3]_. The inclusion of the **TopBraid GeoSPARQL vocabulary** automatically added three concepts *Geometry* (``geosparql:Geometry``), *Map context* (``tbgeo:MapContext``), and *Spatial thing* (``geo:SpatialThing``). Having these concepts included, public classes have to be defined for the schema. Clicking on the form's dropdown, EDG allows user to view content related to the ontology's metadata, and content related to the ontology's GraphQL schema. For the latter schema, this cookbook defines *Spatial thing* as a public class, meaning that the value and all its subclasses are included and exposed to the GraphQL endpoint [4]_. .. figure:: _images/setting-public-class.png :alt: Public Class Settings :align: center :class: edg-figure .. _221-the-geometry-shape: 2.2.1 The Geometry Shape ^^^^^^^^^^^^^^^^^^^^^^^^ The *Geometry* shape represents the top-level geometry type. This is equivalent to the GM_Object defined in ISO 19107 [5]_, which allows the definition of *geometric shapes* (or geometry objects) on maps, such as points, lines, polygons. The TopBraid vocabulary automatically adds two property shapes that enable the serialisation of geometric shapes (e.g polygons) in geo-aware resources in EDG: (1) *asGML* (``geosparql:asGML``) , and (2) *asWKT* (``geosparql:asWKT``). The following snippet shows an polygon example serialised using GML: .. code:: xml 13.833611 48.773605 14.70028 48.581379 15.025833 49.018883 16.946182 48.619064 17.166386 48.012497 17.053886 47.709442 16.450554 47.698051 16.713886 47.543884 16.510555 47.00666 16.111805 46.86972 14.544998 46.407494 13.718655 46.526611 12.440554 46.690826 12.127777 47.001663 10.471235 46.871353 9.598635 47.063835 9.533569 47.274544 9.566724 47.540451 10.173332 47.274719 10.478054 47.591942 11.095554 47.396111 12.735554 47.684166 13.016666 47.470276 12.758333 48.123886 13.833611 48.773605 The following snippet shows a polygon example serialised in WKT: .. code:: wkt MULTIPOLYGON(((7.697223 47.543327, 8.57642 47.59137, 8.566111 47.806938, 9.566724 47.540451, 9.533569 47.274544, 9.474637 47.057457, 9.598635 47.063835, 10.471235 46.871353, 10.465277 46.546387, 10.050278 46.539993, 10.129999 46.227219, 9.28194400000012 46.495827, 9.036665 45.837776, 8.43638800000014 46.463333, 7.855742 45.919052, 7.038054 45.931938, 6.79138900000015 46.434166, 5.966666 46.209442, 6.99055500000014 47.497215, 7.588268 47.58448, 7.697223 47.543327))) In this cookbook, no concepts or property shapes will be created, extending the *Geometry* shape. .. _222-map-context-shape: 2.2.2 Map Context Shape ^^^^^^^^^^^^^^^^^^^^^^^ The *Map Context* shape is a core EDG shape which enables user interactive actions on maps in geo-aware asset collections. This shape is an abstract superclass of objects that may serve as the context of Context Maps. A Context Map is populated with a set of geo resources that are either asserted or dynamically computed by a ``sh:values`` rule. Section `Creating Interactive Maps <#creating-interactive-maps>`__ details the implementation of *MapContext* subclasses. .. _223-spatial-thing-shape: 2.2.3 Spatial Thing Shape ^^^^^^^^^^^^^^^^^^^^^^^^^ The *Spatial Thing* shape describes anything with spatial extent, that is, size, shape and/or position. By default, the TopBraid vocabulary makes ``geo:lat`` and ``geo:long`` visible to the user by defining them as property shapes. .. figure:: _images/extending-spatial-thing-properties.png :alt: Extending Spatial Thing Properties :align: center :class: edg-figure For purposes of this cookbook, two properties are added to the *Spatial Thing*, (1) *fill color* (``tbgeo:fillColor``), and (2) *hasGeometry* (``geosparql:hasGeometry``). ``tbgeo:fillColor`` is an existing property shape in the core TopBraid GeoSPARQL vocabulary which used internally to define a CSS3 color that is used to fill geometry objects (such as polygons) attached to a *Spatial Thing* resource. The property *hasGeometry* is defined in [6]_, and thus require a definition of a property shape. The shape defines the property path (``sh:path``) to look for values with the predicate ``geosparql:hasGeometry`` (*range value: geosparql:Geometry*). This ensures that the core EDG *Map Explorer* panel can interpret and display any geometric shapes (in GML or WKT) on maps. This shape also defines that a *Spatial Thing* expects at most one ``geosparql:hasGeometry`` which is defined in a blank node [7]_. Furthermore, a *Details Viewer* is a used to show the value of the geometry as a nested form-like display. .. figure:: _images/hasGeometry-shape.png :alt: Has Geometry Shape :align: center :class: edg-figure In this cookbook, we also extend the *Spatial Thing* shape with a number of new shapes, having two direct subclasses *Geographical Concept* and *Points of Interest*, each having a number of children subclasses. The former concept describes countries, cities and roads. The latter describes physical buildings and monuments. All concepts are defined as *Node Shapes*. .. figure:: _images/extended-concepts.png :alt: Extended Concepts :align: center :class: edg-figure Both concepts are extended with more refined concepts, where each concept has its own set of properties, apart from those shared by the super-concept. Taking a closer look to the newly defined concept *Country*, this concept has two new declared properties: (1) *hasCapital* that points to an existing *City* resource, and (2) *wikidata* - a predicate that indicates the corresponding wikidata [8]_ resource URI for a defined resouce in EDG (for example the *Country* Malta in EDG would have a wikidata URI value: http://www.wikidata.org/entity/Q233). EDG makes use of these external links to perform transformation operations such as dynamically computing values (e.g. getting the population of a country from wikidata), however, this is out of scope for this cookbook. .. figure:: _images/country-concept.png :alt: Country Concepts :align: center :class: edg-figure The rest of the concepts are described in the EDG project file attached with this project. .. _224-properties-defined-in-topbraid-geosparql-vocabulary: 2.2.4 Properties defined in TopBraid GeoSPARQL Vocabulary ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The TopBraid GeoSPARQL vocabulary provides a number of properties and property shapes that can be used off the shelf. These properties are used within the available map panels in order to enhance the UX: - ``tbgeo:fillColor`` - The CSS3 color that shall be used to fill the geometry object(s). - ``tbgeo:fillOpacity`` - The fill opacity between 0 and 1. - ``tbgeo:strokeColor`` - The CSS3 color that shall be used for the (out) lines the geometry object(s). For polylines (LineStrings) this can only be a hexadecimal HTML color of the format "#FFFFFF". - ``tbgeo:strokeWeight`` - The stroke weight in pixels. - ``tbgeo:symbolPath`` - For Points, this may specify the SVG Path to render the marker on a map, e.g. "M -20 -10 L 20 -10 L 20 10 L -20 10 L -20 -10" for a rectangle. - ``tbgeo:symbolScale`` - For Points, this may specify the symbol's scaling factor, defaulting to 1. - ``tbgeo:text`` - A (short) text to display on a marker. .. _3-creating-a-geo-aware-asset-collection: 3. Creating a Geo-Aware asset collection ---------------------------------------- For the purpose of this cookbook, a *Data Graph* asset collection is created. Under *Asset Collections* select *Data Graphs*. On page load, click on the *Create New Data Graph* button. The *Label* field is mandatory, and in the *Includes* field search for the schema that was created in `the previous section <#creation-of-a-geo-aware-schema-in-edg>`__. Once filled, press the *Create Data Graph* button. In order to mark the newly created *Data Graph* as geo-aware, the user needs to `enable GeoSPARQL <#enabling-geosparql>`__ for the asset collection A sample data graph, is provided in the cookbook's EDG project. In order to open the project, under *Asset Collections* select *Data Graphs*. On page load, open the GeoSPARQL Cookbook asset. .. _31-enabling-geosparql: 3.1 Enabling GeoSPARQL ~~~~~~~~~~~~~~~~~~~~~~ Any asset collection can become a geo-aware, however, it must be noted that this assumes that the asset collection underlying schema has shapes describing geometry features (as described in `section 2 <#creation-of-a-geo-aware-schema-in-edg>`__). In order to enable GeoSPARQL, the following steps are to be followed: 1. Open relevant asset collection in EDG; 2. Navigate to *Manage* tab; 3. Scroll down to **Enable GeoSPARQL and Related Features** and check the box next to *Enable GeoSPARQL for this {asset_collection_type}*, where *{asset_collection_type}* is the type of the selected asset collection; .. figure:: _images/enable_geosparql.png :alt: Enable GeoSPARQL :align: center :class: edg-figure 4. Click *Rebuild Spatial Index* button. Occasionally, the Spatial Index needs to be rebuild, due to changes in the asset collection resources. The steps mentioned above can be re-performed for this task, however, there is no need to un-check and re-check the enable checkbox. .. _32-exploring-geo-resources: 3.2 Exploring Geo Resources ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The cookbook's sample asset collection has a number of countries and cities that pre-defined. Once the asset collection is loaded, EDG loads the default *Data Graph* view. The left panel is used to filter and search resources, whilst the right panel is the form panel, where resource content is displayed. .. figure:: _images/data-graph-intro.png :alt: Data Graph Intro :align: center :class: edg-figure The user can navigate through the different types of *Spatial Types* (e.g. countries, cities, etc...) by selecting the required type in the search panel dropdown. EDG 7.0 introduces two new map panels, the **Map Explorer** and the **Context Map**. This section will walk through the former panel, whilst the latter is discussed in section `Creating Interactive Maps <#creating-interactive-maps>`__. The **Map Explorer** panel can be added to the view by clicking on the **Panels** dropdown, and drag the panel (highlighted in yellow) anywhere on the screen. .. figure:: _images/map-explorer-panel.png :alt: Map Explorer Panel :align: center :class: edg-figure Once open, EDG will populate the map with all geo latitute and longitute information, and any geometric objects defined: .. figure:: _images/map-explorer-panel-alldata.png :alt: Map Explorer Panel All Data :align: center :class: edg-figure Another feature in EDG 7.0 is to display selected resources on the map. In the search panel, select the desired resources (clicking on the checkbox next to the resource label). With the resources selected, click on the batch action dropdown button and select *Show on Map Result Panel*. .. figure:: _images/show-result-on-map.png :alt: Show results on Map :align: center :class: edg-figure EDG will display the geo latitute and longitude of the selected resources as pins on the map, as well as any other geometry object (such as polygons). The currently selected resource is highligted as a blue pin. The user can click on any displayed pin, with EDG changing the current context resource with the newly selected one. This will also change the information displayed on the form panel. .. _33-creating-a-resource: 3.3 Creating a Resource ~~~~~~~~~~~~~~~~~~~~~~~ In this example, a city will be created. Click the *new* button on the search panel. A dialog is presented to the user. The user needs to type in a *Label*, whilst EDG will take care of generating a new ID. Press OK when done. .. figure:: _images/create-city-resource.png :alt: Create City Resource :align: center :class: edg-figure This will load the new resource in the form panel, where details can be entered. Once done, press *Save Changes*. .. figure:: _images/create-city-form.png :alt: Create City Form :align: center :class: edg-figure .. _331-creating-geometry-objects: 3.3.1 Creating Geometry Objects ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The **TopBraid GeoSPARQL vocabulary** allows users to define geometry objects using the *Well-known Text* representation or the *Geography Markup Language*. EDG 7.0 currently supports the following geometric shapes: ``POINT``, ``LINESTRING``, ``POLYGON``, ``MULTIPOLYGON``. In order to create a geometric shape on a resource, click the *Edit* button and then click on the *New Geometry* button. This will open a second form panel. Click the *Edit* button on the second form panel, and type in the geometry shape values. .. figure:: _images/geometry-entry.png :alt: Geometry Entry :align: center :class: edg-figure Once done, press *Save Changes* in both forms. In this example, the WKT format is used. Creating a Point '''''''''''''''' Example: ``POINT(14.518878068246499 35.90215229036674)`` Map depiction: .. figure:: _images/point-shape.png :alt: Point Shape :align: center :class: edg-figure Creating a Line String '''''''''''''''''''''' Example: ``LINESTRING(14.509179200448648 35.896277248610694,14.517676438607827 35.901491804470666)`` Map depiction: .. figure:: _images/line-shape.png :alt: Line Shape :align: center :class: edg-figure Creating a Polygon '''''''''''''''''' Example: ``POLYGON((14.506690110482827 35.89478234591123,14.50561722687687 35.89860645934702,14.508235062875405 35.900101289830765,14.509908761300698 35.89982318397129,14.513384904183999 35.902048003486435,14.515230263986245 35.90097036434348,14.517290200509683 35.9018741917139,14.518663491525308 35.90048368379201,14.518019761361733 35.89732018726464,14.514543618478433 35.896207718878536,14.513556565560952 35.894608518183865,14.510260930329997 35.89275639869175,14.507771840364176 35.891956767523475,14.506999364167887 35.89272163228715,14.507728925019938 35.893416957478486,14.506690110482827 35.89478234591123))`` Map depiction (with fillColor yellow): .. figure:: _images/polygon-shape.png :alt: Polygon Shape :align: center :class: edg-figure Creating a Multi-Polygon '''''''''''''''''''''''' Example: ``MULTIPOLYGON (((14.506690110482827 35.89478234591123,14.50561722687687 35.89860645934702,14.508235062875405 35.900101289830765,14.509908761300698 35.89982318397129,14.513384904183999 35.902048003486435,14.515230263986245 35.90097036434348,14.517290200509683 35.9018741917139,14.518663491525308 35.90048368379201,14.518019761361733 35.89732018726464,14.514543618478433 35.896207718878536,14.513556565560952 35.894608518183865,14.510260930329997 35.89275639869175,14.507771840364176 35.891956767523475,14.506999364167887 35.89272163228715,14.507728925019938 35.893416957478486,14.506690110482827 35.89478234591123)) , ((14.512335501507883 35.897205967563785,14.51139136393464 35.89824889398179,14.512174568966989 35.89874427921673,14.51366587717927 35.899682895370105,14.514851931908979 35.89847408810674,14.51406872687663 35.89801346527679,14.514508609155072 35.897544148693264,14.513028029778852 35.8966055071787,14.512335501507883 35.897205967563785)))`` .. Note:: Particular attention is required to bracketing when creating a multipolygon, due to the visualisation engine parsing. A multipolygon has to be defined as follows: ``MULTIPOLYGON( ((lat1 lng1, lat2, lng2 ... latn, lngn)) , ((lat1 lng1, lat2, lng2 ... latn, lngn)))``. Notice that each *polygon* is encapsulated within 2 sets of brackets. Map depiction: .. figure:: _images/multipolygon-shape.png :alt: Multipolygon Shape :align: center :class: edg-figure .. _4-querying-using-geosparql: 4. Querying using GeoSPARQL --------------------------- There are three possible ways to query asset collections, in EDG: SPARQL, GraphQL, and Active Data Shapes [9]_. This looks into the GeoSPARQL functionalities embedded into SPARQL. Support for GeoSPARQL functions in GraphQL is planned for future EDG versions. Remember to rebuild the GeoSPARQL index in case of changes to the asset collection. .. _41-required-prefixes-and-functions: 4.1 Required Prefixes and Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In order to use GeoSPARQL functions, the following prefixes must be added to the SPARQL query: .. code:: sparql PREFIX spatial: PREFIX spatialf: PREFIX geof: The ``spatial`` namespace provides property functions [10]_ that carry out the triple matching by executing some backend code. Such functions can have a bounded or unbounded subject and/or object variables, whilst the predicate acts as the property function, which could have parameters. It is not uncommon that a property functions requires the subject or the object variable. Should any of the variables be unbound, the function finds all cases where the pattern is true. Property functions found in this namespace are related to spatial features (e.g. finding features within a box) and cardinal features (e.g. finding features that are present in a specific directions) The ``spatialf`` namespace provides mainly filter, conversion, and distance functions. Filter functions return true or false, whilst conversion functions converts values between two types. Distance functions are used to calculate distance between two points or geometries. The ``geof`` namespace provides functions for performing topological spatial operations, namely covering simple features, simple features, Egenhofer relations and RCC8 relations. The provided functions are based on the Dimensionally Extended 9-Intersection Model (DE-9IM) [11]_. For more informations and exhaustive list of functions: - ``spatial`` and ``spatialf`` - https://jena.apache.org/documentation/geosparql/index.html - ``geof`` - http://www.opengis.net/def/function/geosparql .. _42-querying-geo-aware-collections-using-sparql: 4.2 Querying geo-aware collections using SPARQL ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Open the *SPARQL Query* panel (from the *Panels* dropdown button under *Search and Query*). The addition of geo features in EDG, allows users to visualise SPARQL results to be displayed on a map. The image below shows how the results can be shown in the **Map Results** panel. .. figure:: _images/sparql-geo-panels.png :alt: SPRAQL Geo Panel :align: center :class: edg-figure In this section, a number of examples using the various GeoSPARQL functions are demonstrated in this cookbook. Example 1: Find items within a geometry box ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Functions used: - ``spatial:withinBox``- calculates a rectangle by specifying the bottom-most and top-most coordinates for the edges, and return features that intersect the provided box. - Usage: ``?feature spatial:withinBox(?latMin ?lonMin ?latMax ?lonMax [ ?limit ]) .`` - Parameters: - ``?latMin ?lonMin`` - the minimum latitude and longitude point (bottom corner point of the box); - ``?latMax ?lonMax`` - the maximum latitude and longitude point (opposite top corner point of the box); - ``?limit`` — an integer that limits the number of results returned [optional]. Query: .. code:: sparql # Prefixes ... SELECT * { ?item spatial:withinBox ( 36.01474535055199 14.176477635899216 36.082639559265225 14.35780428732703 ) . } Example 1a: (Alternative) Find items within a geometry box ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Functions used: - ``spatialf:convertLatLonBox`` — converts a set of latitude and longitude double coordinates into a rectangle shaped polygon as a WKT string - Usage: ``BIND(spatialf:convertLatLonBox(?latMin, ?lonMin, ?latMax, ?lonMax) as ?wktString).`` - Parameters: - ``?latMin ?lonMin`` - the minimum latitude and longitude point (bottom corner point of the box); - ``?latMax ?lonMax`` — the maximum latitude and longitude point (opposite top corner point of the box). - ``spatialf:convertLatLon`` — converts latitude and longitude double coordinates into a WKT string of a point. - Usage: ``BIND(spatialf:convertLatLon(?lat, ?lon) as ?wktString).`` - Parameters: - ``?lat`` - the latitude as double value; - ``?lon`` - the longitude as a double value. - ``geof:sfWithin`` - a function that returns true if the first geometry argument is spatially within the second geometry argument. - Usage: ``FILTER(geof:sfWithin(?queryWKT, ?searchAreaWKT))`` - Parameters: - ``?queryWKT``- the geometry WKT that is to be looked for within the *search area* polygon; - ``?searchAreaWKT`` - the geometry WKT search pool. Query: .. code:: sparql # Prefixes ... SELECT ?item WHERE { BIND(spatialf:convertLatLonBox(36.01474535055199, 14.176477635899216, 36.082639559265225, 14.35780428732703) as ?wktBox) . ?item a ?type ; geo:lat ?lat; geo:long ?lon . BIND(spatialf:convertLatLon(?lat, ?lon) as ?itemWKT) . FILTER(geof:sfWithin(?itemWKT, ?wktBox)) . } Results: .. figure:: _images/results-1a.png :alt: Results 1a :align: center :class: edg-figure .. Note:: DE-9IM provides equivalent functions which GeoSPARQL (``prefix geof:``) defines. The function ``geof:sfWithin(?queryWKT, ?polygonWKT)`` can be replaced with: - ``geof:sfContains(?searchAreaWKT, ?queryWKT)`` - ``geof:ehInside(?queryWKT, ?searchAreaWKT)`` Example 1b: (Alternative) Find items within a geometry polygon ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Similar to 1a and 1b, this example shows how a WKT polygon string can be used in queries. .. code:: sparql # Prefixes ... SELECT ?item WHERE { BIND("POLYGON((14.169558943455778 36.092930332940085,14.341906965916715 36.09182062002719,14.341906965916715 36.01243554775603,14.16749900693234 36.0141017909665,14.169558943455778 36.092930332940085))"^^geosparql:wktLiteral as ?wktBox) ?item a ?type ; geo:lat ?lat; geo:long ?lon . BIND(spatialf:convertLatLon(?lat, ?lon) as ?cityWKT) . FILTER(geof:sfWithin(?cityWKT, ?wktBox)) . } Results: .. figure:: _images/results-1a.png :alt: Results 1a :align: center :class: edg-figure Example 2: Find if two polygons intersect ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Functions used: - ``geof:sfIntersects`` - returns true if the input geometries intersect - Usage: ``BIND(geof:sfIntersects(?wktP1, ?wktP2) as ?polygonsIntersect) .`` - Parameters: - ``?wktP1`` - first polygon input; - ``?wktP2`` - second polygon input. Query: .. code:: sparql # Prefixes ... SELECT ?doIntersect WHERE { BIND("POLYGON((14.153112021709822 36.100508784240176,14.495061484600447 36.100508784240176,14.495061484600447 35.92610888887777,14.153112021709822 35.92610888887777,14.153112021709822 36.100508784240176))"^^geosparql:wktLiteral as ?wktP1) BIND("POLYGON((14.260228720928572 35.98891507615424,14.483388510967634 35.98891507615424,14.483388510967634 35.858800895950345,14.260228720928572 35.858800895950345,14.260228720928572 35.98891507615424))"^^geosparql:wktLiteral as ?wktP2) BIND(geof:sfIntersects(?wktP1, ?wktP2) as ?doIntersect) } Result: .. figure:: _images/result-2.png :alt: Results 2 :align: center :class: edg-figure Example 3: Find geometric features within an intersection ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Functions used: - ``geof:intersection``- A query function that returns a geometry consisting of all points that are part of both input geometries. - Usage: ``BIND(geof:intersection(?wktP1, ?wktP2) as ?intersection) .`` - Parameters: - ``?wktP1`` - first polygon input; - ``?wktP2`` - second polygon input. Query: .. code:: sparql # Prefixes ... SELECT ?item WHERE { BIND("POLYGON((14.153112021709822 36.100508784240176,14.495061484600447 36.100508784240176,14.488881675030134 35.95501705425438,14.151738730694197 35.92888897961968,14.153112021709822 36.100508784240176))"^^geosparql:wktLiteral as ?wktP1) BIND("POLYGON((14.260228720928572 35.98891507615424,14.483388510967634 35.98891507615424,14.483388510967634 35.858800895950345,14.260228720928572 35.858800895950345,14.260228720928572 35.98891507615424))"^^geosparql:wktLiteral as ?wktP2) BIND(geof:intersection(?wktP1, ?wktP2) as ?intersection) ?item a ?type ; geo:lat ?lat; geo:long ?lon . BIND(spatialf:convertLatLon(?lat, ?lon) as ?itemWKT) . FILTER(geof:sfWithin(?itemWKT, ?intersection)) . } Result: .. figure:: _images/result-3.png :alt: Results 3 :align: center :class: edg-figure Example 4: Find cities in a 5 km radium of a selected item ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Functions used: - ``spatial:nearby``- find features that are within radius. - Usage: ``?feature spatial:nearby(?lat ?lon ?radius [ ?unitsURI [ ?limit]]) .`` - Parameters: - ``?lat`` - latitude of the selected item as a double value; - ``?lon`` - longitude of the selected item as a double value; - ``?radius`` - the radius as a double value; - ``?unitsURI``- specifies the units of a distance. The default value is kilometres through the string or resource ``http://www.opengis.net/def/uom/OGC/1.0/kilometre`` [optional]; - ``?limit`` - an integer that limits the number of results returned [optional]. Query: .. code:: sparql # Prefixes ... SELECT ?city WHERE { geo:lat ?lat; geo:long ?lon . ?city spatial:nearby(?lat ?lon 5) . ?city a geosparql_cookbook_schema:City . FILTER (?city != ). } Result: .. figure:: _images/result-4.png :alt: Results 4 :align: center :class: edg-figure .. _5-advance-topics: 5. Advance Topics ----------------- This section discusses advanced features of using geo-spatial features in EDG. .. _51-interactive-maps-in-edg: 5.1 Interactive maps in EDG ~~~~~~~~~~~~~~~~~~~~~~~~~~~ EDG provides the functionality for interactive maps, in which geo-aware resources can be edited, to a *context* extent. This means that editing is done on *what is being shown* (referred to *geo features* later on) basis. Previously the `Map Context Shape <#map-context-shape>`__ was introduced whereby *Context Map*\ s were described as: *... a set of geo resources that are either asserted or dynamically computed by a ``sh:values`` rule.* Taking a more concrete example, users can ask EDG to display the countries that are part of the European Union in the map panel. The users can then perform actions on these countries, which may modify the state of the selected country (resource). For example removing their membership from the European Union, or changing the color of the polygon, and so on. These actions are programmatically defined using JavaScript, and this is demonstrated later on in this section. .. _511-creating-context-maps: 5.1.1 Creating Context Maps ^^^^^^^^^^^^^^^^^^^^^^^^^^^ In order to create *Context Maps*, the context needs to be defined in the geo-aware schema. The **TopBraid GeoSPARQL Vocabulary** includes the abstract ``tbgeo:MapContext`` node shape. This node shape has to be subclassed (``ex:myContextMap rdfs:subClassOf tbgeo:MapContext``) with the desired context maps. subclasses must declare a new property shape for the predicate ``tbgeo:mapFeatures`` (i.e. using ``sh:path``) which may be an inferred property based on ``sh:this``, or hold asserted values, using the ``sh:values`` rule. More information on the Shapes Constraint Language (SHACL) can be found in [12]_. In order to define a context map, navigate towards the geo-aware ontology (under *Asset Collections* select *Ontologies*, and on page load click on the schema that was created in `section 2 <#creating-a-geo-aware-schema-in-edg>`__). Once loaded, in the *Class Hierarchy* panel navigate to *Map context*, right click on the tree node and select the action item *Create subclass of Map context...* .. figure:: _images/create-map-context-subclass.png :alt: Create Map Context Subclass :align: center :class: edg-figure This displays a dialog box where the user is required to input a *Label* and optionally modify the *ID* and/or add a *Description*. In the sample cookbook project, a abstract context map, *Organisation Context*, is created, together with two "implementations" called *Intergovernmental Organisation* and *Regional Organisation* .. figure:: _images/context-map-subclasses.png :alt: Context Map Subclass :align: center :class: edg-figure For each context implementation, a property shape is declared for the predicate ``tbgeo:mapFeatures``. Click on the *+* button in the *Property Groups* panel. This displays a dropdown menu, which the user should click on the action *Create Attribute (Datatype property shape)* or *Create Relationship (Object property shape)*. The predicate ``tbgeo:mapFeatures`` has a flexible range which changes based on the values being inferred. Once the property shape is created, the user needs to change the property path value to ``tbgeo:mapFeatures``. Furthermore, the values field (under *Inferences*) needs to be populated. For these two context maps, in the inferred values looks for countries that are part of the organisation. The following rule is defined: ``path(^geosparql_cookbook_schema:inRegionalOrganisation)``. This rule basically takes the context resource and follows the inverse path to find the countries. The property shape form will look as follows: .. figure:: _images/context-property-shape.png :alt: Context Property Shape :align: center :class: edg-figure The following is the property shape definition in turtle syntax (one could see this in EDG using the **Source Code** panel) .. code:: turtle geosparql_cookbook_schema:RegionalOrganisation-countries a sh:PropertyShape ; sh:path tbgeo:mapFeatures ; sh:class geosparql_cookbook_schema:Country ; sh:name "countries" ; sh:values [ sh:path [ sh:inversePath geosparql_cookbook_schema:inRegionalOrganisation ; ] ; ] ; . Prior to creating this property shape, in the *Country* we declared two additional property shapes: *inRegionalOrganisation* and *inIntergovernmentalOrganisation*. These shapes define the groups to which a country belongs in, e.g. ``geosparql_cookbook:ireland geosparql_cookbook_schema:inRegionalOrganisation geosparql_cookbook:EU .`` .. _512-creating-a-click-handler: 5.1.2 Creating a click handler ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Map actions are created as instances of ``tbgeo:MapClickHandler``. Instances of this type must have a script declared by the predicate\ ``dash:js``, which gets triggered when a user clicks on a polygon or marker on a map. The script has access to two pre-bounded variables ``focusNode`` and ``mapContext``. The former is the resource that was clicked on. This is a JavaScript object with the label and URI of the resource. The ``mapContext`` variable is the currently selected ``tbgeo:MapContext``. All scripts implementing click handlers will be invoked at each click. Therefore, it is advisable that guard clauses (e.g if statements) are implemented. In such statements one can verify if the action can proceed, say for example whether the selected resource (``focusNode``) or ``mapContext`` is of a particular instance. .. Note:: Since map actions modify the state of resources, these are only available if the graph is not in read-only mode. In the sample project, these functions are defined in a separate turtle file (``geosparql.topbraid.org > GeoFunctions.ttl``). Whilst these functions, in theory, can be defined in the schema itself, it is a good practice to differentiate between the **A-box** and **T-box** statements Based on the two context maps defined in the previous section, a *map click handler* is defined that removes the *focusNode* from the organisation in context (``mapContext``). The following JavaScript code is declared in the *map click handler* instance. .. code:: javascript if (mapContext.instanceOf(geosparql_cookbook_schema.RegionalOrganisation)) { graph.remove(focusNode, geosparql_cookbook_schema.inRegionalOrganisation, mapContext) } if (mapContext.instanceOf(geosparql_cookbook_schema.IntergovernmentalOrganisation)) { graph.remove(focusNode, geosparql_cookbook_schema.inIntergovernmentalOrganisation, mapContext) } The turtle instance is as follows: .. code:: turtle gfunc:RemoveFromOrg a tbgeo:MapClickHandler ; dash:js """if (mapContext.instanceOf(geosparql_cookbook_schema.RegionalOrganisation)) { graph.remove(focusNode, geosparql_cookbook_schema.inRegionalOrganisation, mapContext) } if (mapContext.instanceOf(geosparql_cookbook_schema.IntergovernmentalOrganisation)) { graph.remove(focusNode, geosparql_cookbook_schema.inIntergovernmentalOrganisation, mapContext) } """ ; rdfs:label "Remove from Organisation" ; . .. _513-using-context-maps-in-geo-aware-data-assets: 5.1.3 Using context maps in geo-aware data assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In the cookbook's sample project, a number of regional organisations and intergovernmental organisations are defined and countries are linked to these organisations with the newly defined predicates. In the GeoSPARQL cookbook data graph, select *Regional Organisation* in the search drop down. Filter the organisations to find "European Union". Once the resource is found, open the **Context Map** panel. This is done by right-clicking the resource > *Explore* > *Show Context Map*. .. figure:: _images/show-context-map.png :alt: Show Context Map :align: center :class: edg-figure This will open the **Context Map** panel, showing points inferred by ``tbgeo:mapFeatures``. .. figure:: _images/context-map.png :alt: Context Map :align: center :class: edg-figure When clicking on a country resource, the *map click handler* script is invoked and the country is no longer part of the context map, and hence removed (in this example, Ireland is removed): .. figure:: _images/context-map-action.png :alt: Context Map Action :align: center :class: edg-figure Since the *map click handler* is driven by JavaScript, more advanced action can be done on the resource to change the state. This cookbook demonstrates a toy example, however, more complex coding can be handled by EDG [13]_. .. _52-shacl-constraints-on-geo-spatial-resources: 5.2 SHACL Constraints on Geo-spatial resources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In EDG, schemas are driven by SHACL node and property shapes. This gives the opportunity for *on-the-fly* validation of data entry. An example in this regard is making sure that the city selected for ``hasCapital`` lies within a country. Assuming that all countries have polygon boundaries, the following SPARQL constraint can be defined: .. code:: sparql SELECT DISTINCT $this $value WHERE { $this $PATH $value . $this geosparql:hasGeometry ?aGeometry . ?aGeometry a geosparql:Geometry ; OPTIONAL { ?aGeometry geosparql:asWKT ?wktPolygon } . OPTIONAL { ?aGeometry geosparql:asGML ?gmlPolygon } . BIND(COALESCE(?wktPolygon, ?gmlPolygon) as ?polygon) . $value a ?type ; geo:lat ?lat; geo:long ?lon BIND(spatialf:convertLatLon(?lat, ?lon) as ?valueWKT) . FILTER(!geof:sfWithin(?valueWKT, ?polygon)) . } This query is added as a SPARQL constraint in the shape ``geosparql_cookbook_schema:Country-hasCapital``, using the ``sh:sparql`` predicate: .. code:: turtle geosparql_cookbook_schema:Country-hasCapital a sh:PropertyShape ; sh:path geosparql_cookbook_schema:hasCapital ; sh:class geosparql_cookbook_schema:City ; sh:group metadata:DescriptionPropertyGroup ; sh:name "hasCapital" ; sh:nodeKind sh:IRI ; sh:order "1"^^xsd:decimal ; sh:severity sh:Violation ; sh:sparql [ sh:message "{$value} is not within {$this}." ; sh:prefixes [ sh:declare [ sh:namespace "http://jena.apache.org/function/spatial#"^^xsd:anyURI ; sh:prefix "spatialf" ; ] ; ] ; sh:prefixes [ sh:declare [ sh:namespace "http://www.opengis.net/def/function/geosparql/"^^xsd:anyURI ; sh:prefix "geof" ; ] ; ] ; sh:prefixes [ sh:declare [ sh:namespace "http://www.opengis.net/ont/geosparql#"^^xsd:anyURI ; sh:prefix "geosparql" ; ] ; ] ; sh:prefixes [ sh:declare [ sh:namespace "http://www.w3.org/2003/01/geo/wgs84_pos#"^^xsd:anyURI ; sh:prefix "geo" ; ] ; ] ; sh:select """SELECT DISTINCT $this $value WHERE { $this $PATH $value . $this geosparql:hasGeometry ?aGeometry . ?aGeometry a geosparql:Geometry ; OPTIONAL { ?aGeometry geosparql:asWKT ?wktPolygon } . OPTIONAL { ?aGeometry geosparql:asGML ?gmlPolygon } . BIND(COALESCE(?wktPolygon, ?gmlPolygon) as ?polygon) . $value a ?type ; geo:lat ?lat; geo:long ?lon BIND(spatialf:convertLatLon(?lat, ?lon) as ?valueWKT) . FILTER(!geof:sfWithin(?valueWKT, ?polygon)) . }""" ; ] ; . Once having this constraint in place, EDG displays an error message when the constraint is validated: .. figure:: _images/error-shacl.png :alt: Error SHACL :align: center :class: edg-figure .. _53-extending-data-governance-ontologies-with-geo-schemas: 5.3 Extending Data Governance Ontologies with Geo Schemas ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start off by creating a new ontology in EDG, naming it for example *Enterprise Asset Extension*. Once created include the following two vocabularies: - EDG Schema - Enterprise Models - TopBraid GeoSPARQL Vocabulary The **EDG Schema - Enterprise Models** describe terms that make up Data Governance (DG) assets, including *Business Assets*, *Data Assets*, *Technical Assets*, and *Governance Assets*. In EDG, a number of DG terms are subclasses of the concept *Locatable* (``edg:Locatable``). This concept provides a number of predicates related to location information, however, it lacks general geospatial information such as ``geo:lat`` and ``geo:long``. Therefore, in order to make ``edg:Locatable`` geo-aware, the concept needs to be a subclass of ``geo:SpatialThing``. This can be done by editing the *superclasses* field in the form. Furthermore, ``geo:SpatialThing`` can be enhanced with geometric shapes by creating a property shape for ``geosparql:hasGeometry``, as described in `section 2.2.2 <#map-context-shape>`__. The following snippet shows the TURTLE code for the property shape: .. code:: turtle geo:SpatialThing sh:property geo:SpatialThing-geometry ; . geo:SpatialThing-geometry a sh:PropertyShape ; sh:path geosparql:hasGeometry ; sh:class geosparql:Geometry ; sh:description "Allows the definition of geometric shapes" ; sh:group tbgeo:MapRenderingPropertyGroup ; sh:maxCount 1 ; sh:name "geometry" ; sh:order "0"^^xsd:decimal ; . Any other concept, such as *Information Asset* (``edg:InformationAsset``) or *Party* (``edg:Party``), that requires geo-spatial information can be extended to be a subclass of ``geo:SpatialThing``. In order to view all different concepts and properties that are displayable in EDG's UI forms, in the *Quick Search* dropdown (**Class Hierarchy** panel) search for *Enterprise Viewpoints*. In EDG, a viewpoint is an abstract class that organises UI "views" for different asset collections. .. figure:: _images/enterprise-viewpoint.png :alt: Enterprise Viewpoint :align: center :class: edg-figure In order to create an enterprise asset, under *Asset Collections* select Enterprise Assets. On page load, click on the *Create New Enterprise Asset Collection* button. Fill in the displayed form, with the *Label* field being mandatory, and once filled press *Create Enterprise Asset Collection*. Once created, click on the *Settings* tab, and then *Includes*. Find and select the extension ontology created. Finally, click on the *Manage* tab and `enable GeoSPARQL <#enabling-geosparql>`__. .. _6-references: 6. References ------------- .. [1] WGS84 Geo Positioning RDF vocabulary - https://www.w3.org/2003/01/geo/wgs84_pos .. [2] Open Geospatial Consortium GeoSPARQL - A Geographic Query Language for RDF Data schema - https://www.ogc.org/standards/geosparql .. [3] https://www.topquadrant.com/project/ontology_modeling_overview/ .. [4] https://www.topquadrant.com/graphql/shacl-graphql.html#schema .. [5] ISO 19107:2019 Geographic information — Spatial schema (https://www.iso.org/standard/66175.html) .. [6] Open Geospatial Consortium GeoSPARQL - A Geographic Query Language for RDF Data schema - https://www.ogc.org/standards/geosparql .. [7] Blank nodes are usually used to define *local scoped* resources, i.e. those resources which are not meant to be shared outside of the asset collection defined. .. [8] https://www.wikidata.org. .. [9] Active Data Shapes Tutorial - http://datashapes.org/active/ .. [10] Jena Extensions in ARQ - https://jena.apache.org/documentation/query/extension.html#property-functions .. [11] Dimensionally Extended 9-Intersection Model (DE-9IM) - https://en.wikipedia.org/wiki/DE-9IM .. [12] Shapes Constraint Language - W3C Recommendation - https://www.w3.org/TR/shacl/ .. [13] The Many Shapes of SHACL - http://www.lotico.com/index.php/The_Many_Shapes_of_SHACL