Skip to content

spatial

David Valentine edited this page May 2, 2026 · 6 revisions

The geometries that are index compliant are not built into the system. Initially, while testing, we need to just build them into... But realize if the server restarts, we need to reconstruct them.

Before spatial queries attempted.

  • construct queries over qlever store
  • YOU WILL GET AN UNDFINED IN RUNNING INSERT IN THE UI check using the do we have wkt query
  • demonstrate that geosparql works

steps:

  • figure out what is in the triplestore.
  • create easy construct queries (create lat/lon point from Geocoords, and box from geoshape)
  • run those queries over a datastore
  • develop geosparql query
  • test geosparql query
  • add to interface

DOES A STORE HAVE WKT

PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX sf: <http://www.opengis.net/ont/sf#>
PREFIX uom: <http://www.opengis.net/def/uom/OGC/1.0/>
SELECT *
WHERE {

  ?geom geo:asWKT ?wkt .

}
limit 1000

CONSTRUCT QUERIES HERE

lat lon at multipoint

YOU WILL GET AN UNDFINED IN RUNNING IN THE UI check using the do we have wkt query

 PREFIX schema: <https://schema.org/>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX geo:  <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX sf:   <http://www.opengis.net/ont/sf#>

CONSTRUCT {
    # legacy schema.org structure, unchanged
    ?s a schema:Dataset .
    ?s schema:spatialCoverage ?spatialcoverage .
    ?spatialcoverage schema:geo ?geo .
    ?geo a schema:GeoCoordinates .
    ?geo schema:latitude  ?lat .
    ?geo schema:longitude ?long .

    # one MultiPoint per Dataset
    ?s geo:hasGeometry ?geometry .
    ?geometry a sf:MultiPoint .
    ?geometry geo:asWKT ?wkt .
     ?geometry schema:identifier ?id
}
WHERE {
    ?s a schema:Dataset ;
       schema:spatialCoverage ?spatialcoverage .
    ?spatialcoverage schema:geo ?geo .
    ?geo a schema:GeoCoordinates ;
        
         schema:latitude  ?lat ;
         schema:longitude ?long .

    {
        SELECT ?s
               (IRI(CONCAT(STR(?s), "/geometry")) AS ?geometry)
               (STRDT(
                   CONCAT("MULTIPOINT(",
                          GROUP_CONCAT(?pt ; SEPARATOR=", "),
                          ")"),
                   geo:wktLiteral) AS ?wkt) ?id
        WHERE {
           
           ?s a schema:Dataset ;
               schema:spatialCoverage/schema:geo ?geo .
            ?geo schema:latitude  ?la ;
               schema:longitude ?lo .
            BIND(CONCAT("(", STR(?lo), " ", STR(?la), ")") AS ?pt)
            BIND(CONCAT("uri:gleanerio:geo:wkt:multipoint:", STR(?s)) AS ?id)
          
        }
        GROUP BY ?s ?id
    }
}

polygon from box

PREFIX schema: <https://schema.org/>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>

CONSTRUCT {
    # repeat the old, for fun
    ?s a schema:Dataset .
    ?s schema:spatialCoverage ?spatialcoverage .
    ?spatialcoverage schema:geo ?geo .
    
    ?geo geo:hasGeometry ?geometry .
    ?geometry a geo:Geometry .
    # or a <http://www.opengis.net/ont/sf#Point>    might be better
    ?geometry geo:asWKT ?wkt .
       ?geometry schema:identifier ?id .
}
WHERE {
    ?s a schema:Dataset .
    ?s schema:spatialCoverage ?spatialcoverage .
    ?spatialcoverage schema:geo ?geo .
    ?geo a schema:GeoShape .
    ?geo schema:box ?box .
    
  # Parse "lat1 lon1 lat2 lon2"
  BIND(STRBEFORE(?box, " ")                              AS ?lat1) .
  BIND(STRAFTER(?box, " ")                               AS ?r1) .
  BIND(STRBEFORE(?r1, " ")                               AS ?lon1) .
  BIND(STRAFTER(?r1, " ")                                AS ?r2) .
  BIND(STRBEFORE(?r2, " ")                               AS ?lat2) .
  BIND(STRAFTER(?r2, " ")                                AS ?lon2) .
    BIND(IRI(CONCAT(STR(?geo), "/geometry")) AS ?geometry)
  # Build WKT (lon lat order, closed ring: SW, SE, NE, NW, SW)
  BIND(STRDT(CONCAT(
    "POLYGON((",
      ?lon1, " ", ?lat1, ", ",
      ?lon2, " ", ?lat1, ", ",
      ?lon2, " ", ?lat2, ", ",
      ?lon1, " ", ?lat2, ", ",
      ?lon1, " ", ?lat1,
    "))"
  ), geo:wktLiteral) AS ?wkt) .
   BIND(CONCAT("uri:gleanerio:geo:wkt:polygon:", STR(?s)) AS ?id) 
  }

#CONVERT To INSERT BY CHANGING THE CONSTRUCT TO AN INSERT

INSERT {`
    `?geo geo:hasGeometry ?geometry .`
    `?geometry a geo:Geometry .`
    `# or a <http://www.opengis.net/ont/sf#Point>    might be better`
    `?geometry geo:asWKT ?wkt .`
`}

INSERT QUERIES

THESE ADD DATA TO THE TRIPLESTORE YOU WILL GET AN UNDFINED IN RUNNING INSERT IN THE UI check using the do we have wkt query

PREFIX schema: <https://schema.org/>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX sf:   <http://www.opengis.net/ont/sf#>

INSERT {
    ?geo geo:hasGeometry ?geometry .
    ?geometry a sf:Multipoint .
    # or a <http://www.opengis.net/ont/sf#Point>    might be better
    ?geometry geo:asWKT ?wkt .
 ?geometry schema:identifier ?id .
}
WHERE {
    ?s a schema:Dataset ;
       schema:spatialCoverage ?spatialcoverage .
    ?spatialcoverage schema:geo ?geo .
    ?geo a schema:GeoCoordinates ;
        
         schema:latitude  ?lat ;
         schema:longitude ?long .

    {
        SELECT ?s
               (IRI(CONCAT(STR(?s), "/geometry")) AS ?geometry)
               (STRDT(
                   CONCAT("MULTIPOINT(",
                          GROUP_CONCAT(?pt ; SEPARATOR=", "),
                          ")"),
                   geo:wktLiteral) AS ?wkt) ?id
        WHERE {
           
           ?s a schema:Dataset ;
               schema:spatialCoverage/schema:geo ?geo .
            ?geo schema:latitude  ?la ;
               schema:longitude ?lo .
            BIND(CONCAT("(", STR(?lo), " ", STR(?la), ")") AS ?pt)
            BIND(CONCAT("uri:gleanerio:geo:wkt:multipoint:", STR(?s)) AS ?id)
          
        }
        GROUP BY ?s ?id
    }
}

YOU WILL GET AN UNDFINED IN RUNNING INSERT IN THE UI check using the do we have wkt query

PREFIX schema: <https://schema.org/>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX sf:   <http://www.opengis.net/ont/sf#>
INSERT {
    ?geo geo:hasGeometry ?geometry .
    ?geometry a sf:Polygon .
    # or a <http://www.opengis.net/ont/sf#Point>    might be better
    ?geometry geo:asWKT ?wkt .
 ?geometry schema:identifier ?id .
}
WHERE {
    ?s a schema:Dataset .
    ?s schema:spatialCoverage ?spatialcoverage .
    ?spatialcoverage schema:geo ?geo .
    ?geo a schema:GeoShape .
    ?geo schema:box ?box .

  # Parse "lat1 lon1 lat2 lon2"
  BIND(STRBEFORE(?box, " ")                              AS ?lat1) .
  BIND(STRAFTER(?box, " ")                               AS ?r1) .
  BIND(STRBEFORE(?r1, " ")                               AS ?lon1) .
  BIND(STRAFTER(?r1, " ")                                AS ?r2) .
  BIND(STRBEFORE(?r2, " ")                               AS ?lat2) .
  BIND(STRAFTER(?r2, " ")                                AS ?lon2) .
    BIND(IRI(CONCAT(STR(?geo), "/geometry")) AS ?geometry)
  # Build WKT (lon lat order, closed ring: SW, SE, NE, NW, SW)
  BIND(STRDT(CONCAT(
    "POLYGON((",
      ?lon1, " ", ?lat1, ", ",
      ?lon2, " ", ?lat1, ", ",
      ?lon2, " ", ?lat2, ", ",
      ?lon1, " ", ?lat2, ", ",
      ?lon1, " ", ?lat1,
    "))"
  ), geo:wktLiteral) AS ?wkt) .
BIND(CONCAT("uri:gleanerio:geo:wkt:polygon:", STR(?s)) AS ?id)
  }

GEOSPARQL HERE

** limited geosparql at present, so this does a distance** we might look at the service approach: https://docs.qlever.dev/geosparql/#custom-spatial-search

PREFIX geo:  <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX sf:   <http://www.opengis.net/ont/sf#>

SELECT ?s ?wkt
WHERE {
    ?s geo:hasGeometry ?geometry .
    ?geometry a sf:MultiPoint ;
              geo:asWKT ?wkt .

    # rough San Diego County bbox
    BIND(STRDT("POLYGON((-117.6 32.5, -116.1 32.5, -116.1 33.5, -117.6 33.5, -117.6 32.5))",
               geo:wktLiteral) AS ?bbox)

   # FILTER(geof:sfIntersects(?wkt, ?bbox))
   FILTER(geof:metricDistance(?wkt,?bbox) <= 50)
}

Clone this wiki locally