-------------------------------------------------------------------------- ## Project: GeoKnow, http://geoknow.eu ## Testing geospatial support in Parliament RDF store ver. 2.7.4. ## Using INSPIRE-compliant DATA for Greece taken from geodata.gov.gr. ## Tests performed by Kostas Patroumpas ## Date: 8/4/2014 ## Revised: 9/5/2014 ------------------------------------------------------------------------- ## Tests against a VM installation Tests against a local installation of Parliament RDF 2.7.4 software in a Linux ubuntu 8 64-bit machine **********************************STORAGE********************************* ## Create graph from web interface: CREATE GRAPH ; => RUNNING! ==> Done. -- 27 msec. ## Using a custom Java wrapper for bulk loading of RDF triples: ## IMPORTANT: Use RDF/XML in order to keep Greek characters in string literals (other encodings like N-TRIPLES do NOT preserve encoding!) ## CAUTION: Still, Greek characters are NOT shown properly in graph contents, but they are shown in query results! FILE: /home/user/packages/Parliament/inspire/data/ad_Kalamaria_addresses_GR.rdf => LOADED! ==> Done. -- 8124 msec. -- 277838 triples FILE: /home/user/packages/Parliament/inspire/data/ps_natura2000_GR.rdf => LOADED! ==> Done. -- 3447 msec. -- 10894 triples. FILE: /home/user/packages/Parliament/inspire/data/hy_rivers_GR.rdf => LOADED! ==> Done. -- 5404 msec. -- 120372 triples. FILE: /home/user/packages/Parliament/inspire/data/tn_Kalamaria_roads_GR.rdf => LOADED! ==> Done. -- 1847 msec. -- 59432 triples. FILE: /home/user/packages/Parliament/inspire/data/gn_settlements_GR.rdf => LOADED! ==> Done. -- 11588 msec. -- 304957 triples. FILE: /home/user/packages/Parliament/inspire/data/cp_Kalamaria_parcels_GR.rdf => LOADED! ==> Done. -- 678 msec. -- 13510 triples. FILE: /home/user/packages/Parliament/inspire/data/au_Kallikratis_GR.rdf => LOADED! ==> Done. -- 7007 msec. -- 9454 triples. ## Get total count of triples in the graph (initially, it must be empty): SELECT (COUNT(*) AS ?num) WHERE { GRAPH { ?s ?p ?o } } ==> 796457 statements in the graph (of 796457 originally submitted) --> ALL inserted successfully. ## Create spatial index against the geometries of this data: INSERT {} WHERE { "true"^^ } ==> 32627 geometries indexed in R-tree. ********************************PREFIXES************************************** ## Must use one or more of the following namespaces for data and spatial queries in Parliament: ## Must use the following namespaces with data and spatial queries on INSPIRE schemata: ## For countries PREFIX gmd: ## GeoSPARQL (Parliament instantiation): PREFIX geo: PREFIX sf: PREFIX geof: PREFIX units: ## INSPIRE schemata: PREFIX base: PREFIX gn: PREFIX au: PREFIX hy: PREFIX hy-n: PREFIX net: PREFIX ad: PREFIX cp: PREFIX tn: PREFIX tn-ro: PREFIX ps: *******************************QUERIES****************************** ## All queries about DATA should target the following named graph URI in the SPARQL enpoint: GRAPH ## Queries are very verbose, because they must reflect the corresponding INSPIRE schema. If this is respected, then they run successfully. ## In all queries, the condition '?f geo:hasGeometry ?fGeom .' can be used interchangebly with '?f au:geometry ?fGeom .' (or another INSPIRE data theme prefix instead of 'au') . ## D0: Count all stored triples in the graph (including those with blank nodes!): --------------------------------------------------------------------------------- SELECT (COUNT(*) AS ?num) WHERE { ?s ?p ?o } should be REWRITTEN as: SELECT (COUNT(*) AS ?num) WHERE { GRAPH { ?s ?p ?o } } ## D1: "Which administrative unit (AU) is at the specified geographic location": ------------------------------------------------------------------------------ PREFIX gn: PREFIX au: PREFIX geo: PREFIX geof: PREFIX sf: SELECT ?nCode ?aName WHERE { ?f au:nationalCode ?nCode . ?f au:name ?a . ?a gn:GeographicalName ?gnName . ?gnName gn:spelling ?spn . ?spn gn:SpellingOfName ?spt . ?spt gn:text ?aName . ?f geo:hasGeometry ?fGeom . ?fGeom geo:asWKT ?fWKT . FILTER (geof:sfContains(?fWKT, " POINT (40.582051 22.952149)"^^sf:wktLiteral)) } ==> RUNNING! (and it SHOWS Greek characters in the result!). ## The given point is specified in WGS84 lon/lat coordinates, but the data is stored in GreekGrid87 coordinates (in meters). So, the spatial engine supports multiple georeference systems! ## D2: "Find protected sites (PS) within a distance of 20 km from the given location": ------------------------------------------------------------------------------------ PREFIX gn: PREFIX ps: PREFIX geo: PREFIX geof: PREFIX uom: PREFIX sf: SELECT ?fName ?dist WHERE { ?f ps:siteName ?p . ?p gn:GeographicalName ?gnName . ?gnName gn:spelling ?spn . ?spn gn:SpellingOfName ?spt . ?spt gn:text ?fName . ?f geo:hasGeometry ?fGeom . ?fGeom geo:asWKT ?fWKT . BIND (geof:distance(?fWKT, " POINT (37.975598 23.735933)"^^sf:wktLiteral, uom:metre) AS ?dist) . FILTER (?dist < 20000) } ORDER BY ?dist ==> RUNNING! ## D3: "Identify the administrative unit (AU) where each protected site (PS) belongs to": --------------------------------------------------------------------------------------- PREFIX gn: PREFIX au: PREFIX ps: PREFIX geo: PREFIX geof: SELECT ?adminName ?siteName WHERE { ?q au:name ?r . ?r gn:GeographicalName ?rnName . ?rnName gn:spelling ?rspn . ?rspn gn:SpellingOfName ?rspt . ?rspt gn:text ?adminName . ?q geo:hasGeometry ?qGeom . ?qGeom geo:asWKT ?qWKT . ?f ps:siteName ?p . ?p gn:GeographicalName ?gnName . ?gnName gn:spelling ?spn . ?spn gn:SpellingOfName ?spt . ?spt gn:text ?siteName . ?f geo:hasGeometry ?fGeom . ?fGeom geo:asWKT ?fWKT . FILTER (geof:sfWithin(?fWKT, ?qWKT)) } LIMIT 5 ==> RUNNING! ==> Query should better specify a 'LIMIT k' clause, otherwise it may take a long time to provide a response to this spatial join search. ## D4: "Find settlements (GN) that are contained within the given administrative unit (AU)": ------------------------------------------------------------------------------------------ PREFIX gn: PREFIX au: PREFIX geo: PREFIX geof: SELECT ?sName WHERE { ?f au:nationalCode "9126" . ?f geo:hasGeometry ?fGeom . ?fGeom geo:asWKT ?fWKT . ?s gn:name ?p . ?s geo:hasGeometry ?sGeom . ?sGeom geo:asWKT ?sWKT . ?p gn:GeographicalName ?stName . ?stName gn:spelling ?stn . ?stn gn:SpellingOfName ?sptn . ?sptn gn:text ?sName . FILTER (geof:sfWithin(?sWKT,?fWKT)) } ORDER BY ?sName ==> RUNNING! (but it does NOT support Greek literals in conditions) ## D5: "Retrieve all cadastral parcels (CP) of area greater than 20000 sq.m.": ---------------------------------------------------------------------------- PREFIX cp: SELECT ?pCode ?area WHERE { ?f cp:label ?pCode . ?f cp:areaValue ?area . FILTER ( ?area > 20000) } ORDER BY ?area ==> RUNNING! ## D6: "Find all road names (TN) in lexicographical order": --------------------------------------------------------- PREFIX tn: PREFIX gn: PREFIX geo: SELECT DISTINCT((?roName) AS ?roadName) WHERE { ?r geo:hasGeometry ?rGeom . ?rGeom geo:asWKT ?rWKT . ?r tn:geographicalName ?p . ?p gn:GeographicalName ?rdName . ?rdName gn:spelling ?rpn . ?rpn gn:SpellingOfName ?rpt . ?rpt gn:text ?roName . } ORDER BY ?roadName LIMIT 10 ==> RUNNING! ## D7: "Identify waterstreams (HY) of length longer than 30km": ------------------------------------------------------------- PREFIX gn: PREFIX hy-n: PREFIX xsd: SELECT ?riverName ?len WHERE { ?q hy-n:geographicalName ?r . ?r gn:GeographicalName ?rnName . ?rnName gn:spelling ?rspn . ?rspn gn:SpellingOfName ?rspt . ?rspt gn:text ?riverName . ?q hy-n:length ?len . FILTER ( xsd:decimal(?len) > 30000) } ==> RUNNING! (results refer to parts of rivers, due to geometry splits at intersections with tributaries). ## D8: "Find rivers (HY) that intersect with protected sites (PS)": ----------------------------------------------------------------- PREFIX gn: PREFIX hy-n: PREFIX ps: PREFIX geo: PREFIX geof: SELECT ?riverName ?siteName WHERE { ?q hy-n:geographicalName ?r . ?r gn:GeographicalName ?rnName . ?rnName gn:spelling ?rspn . ?rspn gn:SpellingOfName ?rspt . ?rspt gn:text ?riverName . ?q geo:hasGeometry ?qGeom . ?qGeom geo:asWKT ?qWKT . ?f ps:siteName ?p . ?p gn:GeographicalName ?gnName . ?gnName gn:spelling ?spn . ?spn gn:SpellingOfName ?spt . ?spt gn:text ?siteName . ?f geo:hasGeometry ?fGeom . ?fGeom geo:asWKT ?fWKT . FILTER (geof:sfIntersects(?fWKT, ?qWKT)) } LIMIT 10 ==> RUNNING! (also works with the topological predicate 'sfCrosses'!). ==> Query should better specify a 'LIMIT k' clause, otherwise it may take a long time to provide a response. ## D9: "Identify all addresses (AD) that refer to a particular road": ------------------------------------------------------------------- PREFIX base: PREFIX ad: PREFIX gn: SELECT ?sName ?addNum ?pCode WHERE { ?f ad:locator ?aLoc . ?aLoc ad:AddressLocator ?addDes . ?addDes ad:designator ?aDes . ?aDes ad:LocatorDesignator ?aLocDes . ?aLocDes ad:designator ?addNum . ?f ad:component ?cp . ?cp ad:postCode ?pCode . ?f ad:component ?r . ?r ad:inspireId ?rId . ?rId base:localId "374" . ?r ad:name ?thName . ?thName gn:GeographicalName ?rnName . ?rnName gn:spelling ?rspn . ?rspn gn:SpellingOfName ?rspt . ?rspt gn:text ?sName . } ==> RUNNING! (but it does NOT support Greek literals in condition) ## D10: "Report addresses (AD) within 2km from the given location": ----------------------------------------------------------------- PREFIX ad: PREFIX gn: PREFIX geo: PREFIX geof: PREFIX sf: PREFIX uom: SELECT ?tName ?addNum ?pCode ?dist WHERE { ?f ad:locator ?aLoc . ?aLoc ad:AddressLocator ?addDes . ?addDes ad:designator ?aDes . ?aDes ad:LocatorDesignator ?aLocDes . ?aLocDes ad:designator ?addNum . ?f ad:component ?cp . ?cp ad:postCode ?pCode . ?f ad:component ?r . ?r ad:name ?thName . ?thName gn:GeographicalName ?rnName . ?rnName gn:spelling ?rspn . ?rspn gn:SpellingOfName ?rspt . ?rspt gn:text ?tName . ?f ad:position ?addr . ?addr ad:GeographicPosition ?aPos . ?aPos geo:hasGeometry ?fGeom . ?fGeom geo:asWKT ?fWKT . BIND (geof:distance(?fWKT, " POINT (40.582051 22.952149)"^^sf:wktLiteral, uom:metre) AS ?dist) . FILTER (?dist < 2000) } LIMIT 10 ==> RUNNING!!! (but too slow!) ******************************************************