kDB offers a standardised representation of salient regions.

RDF Representation

They are stored in an RDF Graph using the following structure:

PREFIX askcore_types: <http://askco.re/types#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX time: <http://www.w3.org/2006/time#>

<object_uri> a askcore_types:salientRegion ;
      geo:hasGeometry "POLYGON (...)"^geo:wktLiteral ;
      time:hasTime 124121254151^xsd:dateTime .

Where <object_uri> is a unique identifiant for the salient region, most often, generated from an UUID. "POLYGON (...)"^geo:wktLiteral is a geometry object representing the salient region, it can be a point, polyline or polygon. 124121254151 is the timestamp when the alient region was created.

Extra classes can be also defined with:

<object_uri> a <klass_uri> .

And extra properties can be defined with:

PREFIX askcore_types: <http://askco.re/types#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX ssn: <http://www.w3.org/ns/ssn/>

<object_uri> ssn:hasProperty [
    a  <property_uri>, ssn:property ;
    ssn:hasValue "property_value" ] .

Where <property_uri> is a URI defining the given property, and "property_value" is the associated value.

API

While it is possible to manipulate salient regions directly with turtle data or SPARQL Query, kDB provides a high level API that will generate the queries. The main benefit for using the API is to avoid mistakes and guarantee that the code is still functional if the underlying data model changes in the future.

Create Salient Region

To demonstrate the API, we will create a set of salient points for a rescue scenarios where a group of humans need to be supplied medical supplies that are stored in depots. The salient points indicating the position of the humans and of the depots are stored in a triple store using the kDBSensing salient point API.

  • #include <knowGIS/GeometryObject.h>
    
    #include <kDB/Repository/GraphsManager.h>
    #include <kDB/Repository/TriplesStore.h>
    
    #include <kDBSensing/SalientRegionBuilder.h>
    
    // Create some positions near Gränsö
    knowGIS::GeometryObject po0 = knowGIS::GeometryObject::fromWKT("POINT(16.68297538639311 57.76080352715352)");
    knowGIS::GeometryObject po1 = knowGIS::GeometryObject::fromWKT("POINT(16.682837498772102 57.76068738458424)");
    knowGIS::GeometryObject po2 = knowGIS::GeometryObject::fromWKT("POINT(16.683138674349152 57.76058575952375)");
    knowGIS::GeometryObject po3 = knowGIS::GeometryObject::fromWKT("POINT(16.683545080017666 57.760753198758685)");
    knowGIS::GeometryObject po4 = knowGIS::GeometryObject::fromWKT("POINT(16.68339630651235 57.76085966259949)");
    knowGIS::GeometryObject po5 = knowGIS::GeometryObject::fromWKT("POINT(16.684611752890703 57.76079905287657)");
    knowGIS::GeometryObject po6 = knowGIS::GeometryObject::fromWKT("POINT(16.684735049047816 57.76071040226539)");
    
    // Create a TripleStore.
    knowCore::Uri sr_dataset_uri = "http://askco.re/examples#granso"_kCu;
    kDB::Repository::TriplesStore destination = connection.graphsManager()->createTriplesStore(sr_dataset_uri);
    
    // Create a SalientRegionBuilder.
    kDBSensing::SalientRegionBuilder srb(destination);
    
    // Create four salient points corresponding to humans, the {} indicates no extra properties.
    srb.insert(po0, knowCore::Timestamp::now(), {"http://askco.re/examples#human"_kCu}, {});
    srb.insert(po1, knowCore::Timestamp::now(), {"http://askco.re/examples#human"_kCu}, {});
    srb.insert(po2, knowCore::Timestamp::now(), {"http://askco.re/examples#human"_kCu}, {});
    srb.insert(po3, knowCore::Timestamp::now(), {"http://askco.re/examples#human"_kCu}, {});
    srb.insert(po4, knowCore::Timestamp::now(), {"http://askco.re/examples#human"_kCu}, {});
    
    // Create two salient points corresponding to depots. The content of each depot is stored as
    // a property.
    srb.insert(
        po5, knowCore::Timestamp::now(), {"http://askco.re/examples#depot"_kCu},
        {{"http://askco.re/examples#medical_boxes"_kCu, 3}}
    );
    srb.insert(
        po6, knowCore::Timestamp::now(), {"http://askco.re/examples#depot"_kCu},
        {{"http://askco.re/examples#medical_boxes"_kCu, 2}}
    );
    
  • import knowGIS
    import knowCore
    import kDBSensing
    
    # Create some positions near Gränsö
    po0 = knowGIS.GeometryObject.fromWKT("POINT(16.68297538639311 57.76080352715352)")
    po1 = knowGIS.GeometryObject.fromWKT("POINT(16.682837498772102 57.76068738458424)")
    po2 = knowGIS.GeometryObject.fromWKT("POINT(16.683138674349152 57.76058575952375)")
    po3 = knowGIS.GeometryObject.fromWKT("POINT(16.683545080017666 57.760753198758685)")
    po4 = knowGIS.GeometryObject.fromWKT("POINT(16.68339630651235 57.76085966259949)")
    po5 = knowGIS.GeometryObject.fromWKT("POINT(16.684611752890703 57.76079905287657)")
    po6 = knowGIS.GeometryObject.fromWKT("POINT(16.684735049047816 57.76071040226539)")
    
    # Create a TripleStore.
    sr_dataset_uri = knowCore.Uri("http://askco.re/examples#granso")
    destination = connection.graphsManager().createTriplesStore(sr_dataset_uri)
    
    # Create a SalientRegionBuilder.
    srb = kDBSensing.SalientRegionBuilder(destination)
    
    # Create four salient points corresponding to humans, the {} indicates no extra properties.
    srb.insert(po0, knowCore.Timestamp.now(), [knowCore.Uri("http://askco.re/examples#human")], {})
    srb.insert(po1, knowCore.Timestamp.now(), [knowCore.Uri("http://askco.re/examples#human")], {})
    srb.insert(po2, knowCore.Timestamp.now(), [knowCore.Uri("http://askco.re/examples#human")], {})
    srb.insert(po3, knowCore.Timestamp.now(), [knowCore.Uri("http://askco.re/examples#human")], {})
    srb.insert(po4, knowCore.Timestamp.now(), [knowCore.Uri("http://askco.re/examples#human")], {})
    
    # Create two salient points corresponding to depots. The content of each depot is stored as
    # a property.
    srb.insert(
        po5, knowCore.Timestamp.now(), [knowCore.Uri("http://askco.re/examples#depot")],
        {knowCore.Uri("http://askco.re/examples#medical_boxes"): 3}
    )
    srb.insert(
        po6, knowCore.Timestamp.now(), [knowCore.Uri("http://askco.re/examples#depot")],
        {knowCore.Uri("http://askco.re/examples#medical_boxes"): 2}
    )
    
  • require 'knowGIS'
    require 'knowCore'
    require 'kDBSensing'
    
    # Create some positions near Gränsö
    po0 = KnowGIS::GeometryObject.fromWKT("POINT(16.68297538639311 57.76080352715352)")
    po1 = KnowGIS::GeometryObject.fromWKT("POINT(16.682837498772102 57.76068738458424)")
    po2 = KnowGIS::GeometryObject.fromWKT("POINT(16.683138674349152 57.76058575952375)")
    po3 = KnowGIS::GeometryObject.fromWKT("POINT(16.683545080017666 57.760753198758685)")
    po4 = KnowGIS::GeometryObject.fromWKT("POINT(16.68339630651235 57.76085966259949)")
    po5 = KnowGIS::GeometryObject.fromWKT("POINT(16.684611752890703 57.76079905287657)")
    po6 = KnowGIS::GeometryObject.fromWKT("POINT(16.684735049047816 57.76071040226539)")
    
    # Create a TripleStore.
    sr_dataset_uri = kCu("http://askco.re/examples#granso")
    destination = connection.graphsManager().createTriplesStore(sr_dataset_uri)
    
    # Create a SalientRegionBuilder.
    srb = kDBSensing.SalientRegionBuilder(destination)
    
    # Create four salient points corresponding to humans, the {} indicates no extra properties.
    srb.insert(po0, knowCore.Timestamp.now(), [kCu("http://askco.re/examples#human")], {})
    srb.insert(po1, knowCore.Timestamp.now(), [kCu("http://askco.re/examples#human")], {})
    srb.insert(po2, knowCore.Timestamp.now(), [kCu("http://askco.re/examples#human")], {})
    srb.insert(po3, knowCore.Timestamp.now(), [kCu("http://askco.re/examples#human")], {})
    srb.insert(po4, knowCore.Timestamp.now(), [kCu("http://askco.re/examples#human")], {})
    
    # Create two salient points corresponding to depots. The content of each depot is stored as
    # a property.
    srb.insert(
        po5, KnowCore::Timestamp.now(), [kCu("http://askco.re/examples#depot")],
        {kCu("http://askco.re/examples#medical_boxes"): 3}
    )
    srb.insert(
        po6, KnowCore::Timestamp.now(), [kCu("http://askco.re/examples#depot")],
        {kCu("http://askco.re/examples#medical_boxes"): 2}
    )
    

Query for Salient Region

There are currently no API for querying a Salient Region, the only approach is to use SPARQL queries.

The following can be used to query for depots that contains medical boxes:

PREFIX askcore_types: <http://askco.re/types#>
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX ssn: <http://www.w3.org/ns/ssn/>

SELECT ?geometry ?count WHERE {
    ?uri a <http://askco.re/examples#depot> ;
            geo:hasGeometry ?geometry ;
            ssn:hasProperty [
            a  <http://askco.re/examples#medical_boxes> ;
            ssn:hasValue ?count
        ]  .
}

The following can be used to query for a list of humans and their positions:

PREFIX geo: <http://www.opengis.net/ont/geosparql#>

SELECT ?geometry WHERE {
    ?uri a <http://askco.re/examples#human> ;
        geo:hasGeometry ?geometry .
}

As part of a dataset

Salient regions can be registered as a kDB Dataset. The URI of the triple store used to store the salient regions must be the same as the URI used to identify the dataset.

  • #include <knowGIS/GeometryObject.h>
    
    #include <kDB/Repository/GraphsManager.h>
    #include <kDB/Repository/TriplesStore.h>
    
    #include <kDBDatasets/Dataset.h>
    #include <kDBDatasets/Datasets.h>
    
    // The following enable the 'kDBDatasets' connection. This needs to be done only once after
    // creating the store. Enabled extensions are automatically loaded on re-connecting.
    connection.enableExtension("kDBDatasets");
    
    // This access the set of private datasets.
    kDBDatasets::Datasets dss = kDBDatasets::Datasets::get(
        c, "http://askco.re/graphs#private_datasets"_kCu
    );
    
    // Uri for the dataset we just created
    knowCore::Uri sr_dataset_uri("http://askco.re/examples#granso");
    
    // Polygon area corresponding to the dataset
    knowGIS::GeometryObject go0 = knowGIS::GeometryObject::fromWKT(
        ("POLYGON((16.683875600036536 57.76189821045434,16.681086102661048 57.760765003387945,"
            "16.682416478332435 57.75976912541624,16.684680262741004 57.760621919160826,"
            "16.685205975707923 57.76117135950369,16.683875600036536 57.76189821045434))")
    )
    
    // Create a dataset of salient regions, covering the area defined by go0
    // and with the given URI
    kDBDatasets::Dataset ds = dss.createDataset(
        "http://askco.re/sensing#salient_region"_kCu, go0, sr_dataset_uri
    );
    
    // This set the status of the dataset to completed
    ds.setStatus(kDBDatasets::Dataset::Status::Completed)
    
    // This indicates that the current connection has a copy of the dataset
    ds.associate(connection.serverUri())
    
  • import knowCore
    import knowGIS
    import kDBDatasets
    
    # The following enable the 'kDBDatasets' connection. This needs to be done only once after
    # creating the store. Enabled extensions are automatically loaded on re-connecting.
    connection.enableExtension("kDBDatasets")
    
    # This access the set of private datasets.
    dss = kDBDatasets.Datasets.get(
        connection, knowCore.Uri("http://askco.re/graphs#private_datasets")
    )
    
    # Uri for the dataset we just created
    sr_dataset_uri = knowCore.Uri("http://askco.re/examples#granso")
    
    # Polygon area corresponding to the dataset
    go0 = knowGIS.GeometryObject.fromWKT(
        ("POLYGON((16.683875600036536 57.76189821045434,16.681086102661048 57.760765003387945,"
            "16.682416478332435 57.75976912541624,16.684680262741004 57.760621919160826,"
            "16.685205975707923 57.76117135950369,16.683875600036536 57.76189821045434))")
    )
    
    # Create a dataset of salient regions, covering the area defined by go0
    # and with the given URI
    ds = dss.createDataset(
        knowCore.Uri("http://askco.re/sensing#salient_region"), go0, sr_dataset_uri
    )
    
    # This set the status of the dataset to completed
    ds.setStatus(kDBDatasets.Dataset.Status.Completed)
    
    # This indicates that the current connection has a copy of the dataset
    ds.associate(connection.serverUri())
    
  • require 'knowGIS'
    require 'knowCore'
    require 'kDBDatasets'
    
    # The following enable the 'kDBDatasets' connection. This needs to be done only once after
    # creating the store. Enabled extensions are automatically loaded on re-connecting.
    connection.enableExtension("kDBDatasets")
    
    # This access the set of private datasets.
    dss = KDBDatasets.Datasets.get(
        connection, kCu("http://askco.re/graphs#private_datasets")
    )
    
    # Uri for the dataset we just created
    sr_dataset_uri = kCu("http://askco.re/examples#granso")
    
    # Polygon area corresponding to the dataset
    go0 = KnowGIS::GeometryObject.fromWKT(
        ("POLYGON((16.683875600036536 57.76189821045434,16.681086102661048 57.760765003387945,"
            "16.682416478332435 57.75976912541624,16.684680262741004 57.760621919160826,"
            "16.685205975707923 57.76117135950369,16.683875600036536 57.76189821045434))")
    )
    
    # Create a dataset of salient regions, covering the area defined by go0
    # and with the given URI
    ds = dss.createDataset(
        kCu("http://askco.re/sensing#salient_region"), go0, sr_dataset_uri
    )
    
    # This set the status of the dataset to completed
    ds.setStatus(KDBDatasets::Dataset::Status.Completed)
    
    # This indicates that the current connection has a copy of the dataset
    ds.associate(connection.serverUri())
    

Once a salient region is available as part of a dataset, it is possible to iterate over all its content via the kDBDataset iterator mechanism.

  • #include <kDBDatasets/Dataset.h>
    #include <kDBDatasets/Datasets.h>
    #include <kDBDatasets/DataInterfaceRegistry.h>
    
    
    // This access the set of private datasets.
    kDBDatasets::Datasets dss = kDBDatasets::Datasets::get(
        connection, "http://askco.re/graphs#private_datasets"_kCu
    );
    
    // Uri for our salient point dataset
    knowCore::Uri sr_dataset_uri("http://askco.re/examples#granso");
    
    // The following retrieve the dataset object from the database
    kDBDatasets::Dataset ds = dss.dataset(sr_dataset_uri).expectSuccess();
    
    // Create an iterator to access the values
    kDBDatasets::ValueIterator it = kDBDatasets::DataInterfaceRegistry::createValueIterator(connection, ds).expectSuccess();
    
    // Iterate while it still has more values
    while(it.hasNext())
    {
      // Get the next value and convert it to a SalientRegion object
      knowCore::Value value = it.next().expectSuccess();
      knowValues::Values::SalientRegion salientRegion = value.value<knowValues::Values::SalientRegion>.expectSuccess();
    
      // Access its classes
      QList<knowCore::Uri> classes = salientRegion.classes();
    
      // Access its properties
      knowCore::ValueHash properties = salientRegion.properties();
    
      // Access its timestamp
      knowCore::Timestamp timestamp = salientRegion.timestamp();
    
      // Access its geometry
      knowGIS::GeomnetryObject go = salientRegion.geometry();
      ...
    }
    
  • import knowCore
    import kDBDatasets
    
    # This access the set of private datasets.
    dss = kDBDatasets.Datasets.get(
        connection, knowCore.Uri("http://askco.re/graphs#private_datasets")
    )
    
    # Uri for our salient point dataset
    sr_dataset_uri = knowCore.Uri("http://askco.re/examples#granso")
    
    # The following retrieve the dataset object from the database
    ds = dss.dataset(sr_dataset_uri)
    
    # Create an iterator to access the values
    it = kDBDatasets::DataInterfaceRegistry::createValueIterator(connection, ds)
    
    # Iterate while it still has more values
    while it.hasNext():
      # Get the next value and convert it to a SalientRegion object
      salientRegion = it.next()
    
      # Access its classes
      classes = salientRegion.classes()
    
      # Access its properties
      properties = salientRegion.properties()
    
      # Access its timestamp
      timestamp = salientRegion.timestamp()
    
      # Access its geometry
      go = salientRegion.geometry()
      ...
    
  • require 'knowCore'
    require 'kDBDatasets'
    
    # This access the set of private datasets.
    dss = kDBDatasets.Datasets.get(
        connection, kCu("http://askco.re/graphs#private_datasets")
    )
    
    # Uri for our salient point dataset
    sr_dataset_uri = kCu("http://askco.re/examples#granso")
    
    # The following retrieve the dataset object from the database
    ds = dss.dataset(sr_dataset_uri)
    
    # Create an iterator to access the values
    it = KDBDatasets::DataInterfaceRegistry.createValueIterator(connection, ds)
    
    # Iterate while it still has more values
    while it.hasNext()
      # Get the next value and convert it to a SalientRegion object
      salientRegion = it.next()
    
      # Access its classes
      classes = salientRegion.classes()
    
      # Access its properties
      properties = salientRegion.properties()
    
      # Access its timestamp
      timestamp = salientRegion.timestamp()
    
      # Access its geometry
      go = salientRegion.geometry()
      ...
    end