From d75e0fed25d93f8311a1201443d7684e30a437ac Mon Sep 17 00:00:00 2001 From: Axel Lehmann Date: Thu, 18 Jan 2024 22:20:17 +0100 Subject: [PATCH 1/9] Basic Dataset selection --- include/osm2rdf/config/Config.h | 7 +++++ include/osm2rdf/config/Constants.h | 8 ++++++ src/config/Config.cpp | 31 ++++++++++++++++++--- src/ttl/Writer.cpp | 44 ++++++++++++++++++++---------- 4 files changed, 71 insertions(+), 19 deletions(-) diff --git a/include/osm2rdf/config/Config.h b/include/osm2rdf/config/Config.h index 2e655074..d92b2c04 100644 --- a/include/osm2rdf/config/Config.h +++ b/include/osm2rdf/config/Config.h @@ -36,6 +36,11 @@ enum GeoTriplesMode { full = 2 }; +enum SourceDataset { + OSM = 0, + OHM = 1 +}; + struct Config { // Select what to do std::string storeLocationsOnDisk; @@ -53,6 +58,8 @@ struct Config { bool noWayGeometricRelations = false; double simplifyGeometries = 0; + SourceDataset sourceDataset = OSM; + // the epsilon for the inner/outer douglas-peucker is based on the // circumference of a hypothetical circle. By dividing by ~pi, we base the // epsilon on 1/n of the radius of this hypothetical circle (n = 20 in this diff --git a/include/osm2rdf/config/Constants.h b/include/osm2rdf/config/Constants.h index 6d3463ea..44e8fc1d 100644 --- a/include/osm2rdf/config/Constants.h +++ b/include/osm2rdf/config/Constants.h @@ -94,6 +94,14 @@ const static inline std::string NO_FACTS_OPTION_SHORT = ""; const static inline std::string NO_FACTS_OPTION_LONG = "no-facts"; const static inline std::string NO_FACTS_OPTION_HELP = "Do not dump facts"; +const static inline std::string SOURCE_DATASET_INFO = + "Source dataset"; +const static inline std::string SOURCE_DATASET_OPTION_SHORT = ""; +const static inline std::string SOURCE_DATASET_OPTION_LONG = + "source-dataset"; +const static inline std::string SOURCE_DATASET_OPTION_HELP = + "Source dataset, either 'OSM', or 'OHM'"; + const static inline std::string OSM2RDF_GEO_TRIPLES_INFO = "Writing mode of osm2rdf-style geometric triples"; const static inline std::string OSM2RDF_GEO_TRIPLES_OPTION_SHORT = ""; diff --git a/src/config/Config.cpp b/src/config/Config.cpp index aa96dcdf..dd6c4ae7 100644 --- a/src/config/Config.cpp +++ b/src/config/Config.cpp @@ -32,19 +32,23 @@ // ____________________________________________________________________________ std::string osm2rdf::config::Config::getInfo(std::string_view prefix) const { std::ostringstream oss; + std::string datasetStrings[2] = {"OSM", "OHM"}; oss << prefix << osm2rdf::config::constants::HEADER; oss << "\n" << prefix << osm2rdf::config::constants::SECTION_IO; oss << "\n" - << prefix << osm2rdf::config::constants::INPUT_INFO << " " + << prefix << osm2rdf::config::constants::INPUT_INFO << " " << input; oss << "\n" - << prefix << osm2rdf::config::constants::OUTPUT_INFO << " " + << prefix << osm2rdf::config::constants::SOURCE_DATASET_INFO << ": " + << (datasetStrings[sourceDataset]); + oss << "\n" + << prefix << osm2rdf::config::constants::OUTPUT_INFO << " " << output; oss << "\n" - << prefix << osm2rdf::config::constants::OUTPUT_FORMAT_INFO << " " + << prefix << osm2rdf::config::constants::OUTPUT_FORMAT_INFO << " " << outputFormat; oss << "\n" - << prefix << osm2rdf::config::constants::CACHE_INFO << " " + << prefix << osm2rdf::config::constants::CACHE_INFO << " " << cache; oss << "\n" << prefix << osm2rdf::config::constants::SECTION_FACTS; if (noFacts) { @@ -226,6 +230,12 @@ void osm2rdf::config::Config::fromArgs(int argc, char** argv) { osm2rdf::config::constants::NO_WAY_FACTS_OPTION_LONG, osm2rdf::config::constants::NO_WAY_FACTS_OPTION_HELP); + auto sourceDatasetOp = + parser.add, popl::Attribute::advanced>( + osm2rdf::config::constants::SOURCE_DATASET_OPTION_SHORT, + osm2rdf::config::constants::SOURCE_DATASET_OPTION_LONG, + osm2rdf::config::constants::SOURCE_DATASET_OPTION_HELP, "OSM"); + auto noAreaGeometricRelationsOp = parser.add( osm2rdf::config::constants::NO_AREA_GEOM_RELATIONS_OPTION_SHORT, @@ -449,6 +459,19 @@ void osm2rdf::config::Config::fromArgs(int argc, char** argv) { noWayFacts |= noWaysOp->is_set(); noWayGeometricRelations |= noWaysOp->is_set(); + // Dataset selection + if (sourceDatasetOp->is_set()) { + if (osm2rdfGeoTriplesModeOp->value() == "OSM") { + sourceDataset = OSM; + } else if (osm2rdfGeoTriplesModeOp->value() == "OHM") { + sourceDataset = OHM; + } else { + throw popl::invalid_option( + sourceDatasetOp.get(), popl::invalid_option::Error::invalid_argument, + popl::OptionName::long_name, sourceDatasetOp->value(), ""); + } + } + // Select amount to dump addAreaWayLinestrings = addAreaWayLinestringsOp->is_set(); addWayMetadata = addWayMetadataOp->is_set(); diff --git a/src/ttl/Writer.cpp b/src/ttl/Writer.cpp index 7d535be7..24d5a193 100644 --- a/src/ttl/Writer.cpp +++ b/src/ttl/Writer.cpp @@ -36,6 +36,7 @@ template osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, osm2rdf::util::Output* output) : _config(config), _out(output) { + // Static prefixes _prefixes = { // well-known prefixes {osm2rdf::ttl::constants::NAMESPACE__GEOSPARQL, @@ -53,19 +54,32 @@ osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, "https://osm2rdf.cs.uni-freiburg.de/rdf#"}, {osm2rdf::ttl::constants::NAMESPACE__OSM2RDF_GEOM, "https://osm2rdf.cs.uni-freiburg.de/rdf/geom#"}, + // https://wiki.openstreetmap.org/wiki/Sophox#How_OSM_data_is_stored + // https://github.com/Sophox/sophox/blob/master/osm2rdf/osmutils.py#L35-L39 // osm prefixes {osm2rdf::ttl::constants::NAMESPACE__OSM, "https://www.openstreetmap.org/"}, - // https://wiki.openstreetmap.org/wiki/Sophox#How_OSM_data_is_stored - // https://github.com/Sophox/sophox/blob/master/osm2rdf/osmutils.py#L35-L39 - {osm2rdf::ttl::constants::NAMESPACE__OSM_NODE, - "https://www.openstreetmap.org/node/"}, - {osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION, - "https://www.openstreetmap.org/relation/"}, {osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, - "https://www.openstreetmap.org/wiki/Key:"}, - {osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, - "https://www.openstreetmap.org/way/"}}; + "https://www.openstreetmap.org/wiki/Key:"}}; + + // Dataset specific prefixes + switch (_config.sourceDataset) { + case config::OHM: + _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_NODE] = + "https://www.openhistoricalmap.org/node/"; + _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION] = + "https://www.openhistoricalmap.org/relation/"; + _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_WAY] = + "https://www.openhistoricalmap.org/way/"; + break; + default: + _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_NODE] = + "https://www.openstreetmap.org/node/"; + _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION] = + "https://www.openstreetmap.org/relation/"; + _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_WAY] = + "https://www.openstreetmap.org/way/"; + } // Generate constants osm2rdf::ttl::constants::IRI__GEOSPARQL__HAS_GEOMETRY = @@ -76,14 +90,14 @@ osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, generateIRI(osm2rdf::ttl::constants::NAMESPACE__GEOSPARQL, "asWKT"); osm2rdf::ttl::constants::IRI__GEOSPARQL__WKT_LITERAL = generateIRI(osm2rdf::ttl::constants::NAMESPACE__GEOSPARQL, "wktLiteral"); - osm2rdf::ttl::constants::IRI__OPENGIS_CONTAINS = generateIRI( - osm2rdf::ttl::constants::NAMESPACE__OPENGIS, "sfContains"); - osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_AREA = generateIRI( - osm2rdf::ttl::constants::NAMESPACE__OSM2RDF, "contains_area"); + osm2rdf::ttl::constants::IRI__OPENGIS_CONTAINS = + generateIRI(osm2rdf::ttl::constants::NAMESPACE__OPENGIS, "sfContains"); + osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_AREA = + generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM2RDF, "contains_area"); osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA = generateIRI( osm2rdf::ttl::constants::NAMESPACE__OSM2RDF, "contains_nonarea"); - osm2rdf::ttl::constants::IRI__OPENGIS_INTERSECTS = generateIRI( - osm2rdf::ttl::constants::NAMESPACE__OPENGIS, "sfIntersects"); + osm2rdf::ttl::constants::IRI__OPENGIS_INTERSECTS = + generateIRI(osm2rdf::ttl::constants::NAMESPACE__OPENGIS, "sfIntersects"); osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_AREA = generateIRI( osm2rdf::ttl::constants::NAMESPACE__OSM2RDF, "intersects_area"); osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA = generateIRI( From db6b64035f34ff36f234c224056a0b302ae14ae5 Mon Sep 17 00:00:00 2001 From: Axel Lehmann Date: Thu, 18 Jan 2024 22:20:51 +0100 Subject: [PATCH 2/9] Prepare handling of start_date and end_date --- include/osm2rdf/ttl/Constants.h | 3 +++ src/osm/FactHandler.cpp | 27 +++++++++++++++++++++++++-- src/ttl/Writer.cpp | 6 ++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/include/osm2rdf/ttl/Constants.h b/include/osm2rdf/ttl/Constants.h index 3c221a60..b066a846 100644 --- a/include/osm2rdf/ttl/Constants.h +++ b/include/osm2rdf/ttl/Constants.h @@ -70,10 +70,13 @@ inline std::string IRI__OSM_WAY; inline std::string IRI__RDF_TYPE; +inline std::string IRI__XSD_DATE; inline std::string IRI__XSD_DECIMAL; inline std::string IRI__XSD_DOUBLE; inline std::string IRI__XSD_FLOAT; inline std::string IRI__XSD_INTEGER; +inline std::string IRI__XSD_YEAR; +inline std::string IRI__XSD_YEAR_MONTH; inline std::string LITERAL__NO; inline std::string LITERAL__YES; diff --git a/src/osm/FactHandler.cpp b/src/osm/FactHandler.cpp index 148fb3b7..bccfb7e5 100644 --- a/src/osm/FactHandler.cpp +++ b/src/osm/FactHandler.cpp @@ -52,9 +52,12 @@ using osm2rdf::ttl::constants::IRI__OSMWAY_NODE; using osm2rdf::ttl::constants::IRI__OSMWAY_NODE_COUNT; using osm2rdf::ttl::constants::IRI__OSMWAY_UNIQUE_NODE_COUNT; using osm2rdf::ttl::constants::IRI__RDF_TYPE; +using osm2rdf::ttl::constants::IRI__XSD_DATE; using osm2rdf::ttl::constants::IRI__XSD_DECIMAL; using osm2rdf::ttl::constants::IRI__XSD_DOUBLE; using osm2rdf::ttl::constants::IRI__XSD_INTEGER; +using osm2rdf::ttl::constants::IRI__XSD_YEAR; +using osm2rdf::ttl::constants::IRI__XSD_YEAR_MONTH; using osm2rdf::ttl::constants::LITERAL__NO; using osm2rdf::ttl::constants::LITERAL__YES; using osm2rdf::ttl::constants::NAMESPACE__OSM; @@ -431,7 +434,7 @@ void osm2rdf::osm::FactHandler::writeTagList( (key == "wikidata" || hasSuffix(key, ":wikidata"))) { // Only take first wikidata entry if ; is found std::string valueTmp = value; - auto end = valueTmp.find(';'); + const auto end = valueTmp.find(';'); if (end != std::string::npos) { valueTmp = valueTmp.erase(end); } @@ -448,7 +451,7 @@ void osm2rdf::osm::FactHandler::writeTagList( } if (!_config.skipWikiLinks && (key == "wikipedia" || hasSuffix(key, ":wikipedia"))) { - auto pos = value.find(':'); + const auto pos = value.find(':'); if (pos != std::string::npos) { const std::string& lang = value.substr(0, pos); const std::string& entry = value.substr(pos + 1); @@ -464,6 +467,26 @@ void osm2rdf::osm::FactHandler::writeTagList( tagTripleCount++; } } + if (key == "start_date" || key == "end_date") { + const auto dashCount = std::count(value.begin(), value.end(), '-'); + switch (dashCount) { + case 2: + _writer->writeTriple( + subj, _writer->generateIRIUnsafe(NAMESPACE__OSM, key), + _writer->generateLiteralUnsafe(value, "^^" + IRI__XSD_DATE)); + break; + case 1: + _writer->writeTriple( + subj, _writer->generateIRIUnsafe(NAMESPACE__OSM, key), + _writer->generateLiteralUnsafe(value, "^^" + IRI__XSD_YEAR_MONTH)); + break; + case 0: + _writer->writeTriple( + subj, _writer->generateIRIUnsafe(NAMESPACE__OSM, key), + _writer->generateLiteralUnsafe(value, "^^" + IRI__XSD_YEAR)); + break; + } + } } _writer->writeTriple( subj, _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "facts"), diff --git a/src/ttl/Writer.cpp b/src/ttl/Writer.cpp index 24d5a193..3e74fb43 100644 --- a/src/ttl/Writer.cpp +++ b/src/ttl/Writer.cpp @@ -133,6 +133,8 @@ osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, osm2rdf::ttl::constants::IRI__RDF_TYPE = generateIRI(osm2rdf::ttl::constants::NAMESPACE__RDF, "type"); + osm2rdf::ttl::constants::IRI__XSD_DATE = + generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "date"); osm2rdf::ttl::constants::IRI__XSD_DECIMAL = generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "decimal"); osm2rdf::ttl::constants::IRI__XSD_DOUBLE = @@ -141,6 +143,10 @@ osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "float"); osm2rdf::ttl::constants::IRI__XSD_INTEGER = generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "integer"); + osm2rdf::ttl::constants::IRI__XSD_YEAR = + generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "gYear"); + osm2rdf::ttl::constants::IRI__XSD_YEAR_MONTH = + generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "gYearMont"); osm2rdf::ttl::constants::LITERAL__NO = generateLiteral("no", ""); osm2rdf::ttl::constants::LITERAL__YES = generateLiteral("yes", ""); From 43c3d6006bef3e0ebebf3586ef8a6265d34fbd26 Mon Sep 17 00:00:00 2001 From: Axel Lehmann Date: Fri, 19 Jan 2024 10:46:50 +0100 Subject: [PATCH 3/9] * Improve dataset distinction - prefixes - mediators - ... * Add node/relation/way timestamp meta information --- include/osm2rdf/osm/FactHandler.h | 4 +- include/osm2rdf/osm/Node.h | 4 + include/osm2rdf/osm/Relation.h | 3 + include/osm2rdf/osm/Way.h | 3 + include/osm2rdf/ttl/Constants.h | 14 ++ src/config/Config.cpp | 4 +- src/osm/FactHandler.cpp | 247 ++++++++++++++++++++---------- src/osm/Node.cpp | 18 ++- src/osm/Relation.cpp | 21 ++- src/osm/Way.cpp | 31 +++- src/ttl/Writer.cpp | 40 ++--- 11 files changed, 268 insertions(+), 121 deletions(-) diff --git a/include/osm2rdf/osm/FactHandler.h b/include/osm2rdf/osm/FactHandler.h index efb26f54..631a31f5 100644 --- a/include/osm2rdf/osm/FactHandler.h +++ b/include/osm2rdf/osm/FactHandler.h @@ -48,7 +48,6 @@ class FactHandler { FRIEND_TEST(OSM_FactHandler, writeBoostGeometryWaySimplify3); protected: - void writeBox(const std::string& s, const std::string& p, const osm2rdf::geometry::Box& box); FRIEND_TEST(OSM_FactHandler, writeBoxPrecision1); @@ -77,6 +76,9 @@ class FactHandler { FRIEND_TEST(OSM_FactHandler, writeTagListWikipediaWithoutLang); FRIEND_TEST(OSM_FactHandler, writeTagListSkipWikiLinks); + void writeSecondsAsISO(const std::string& s, const std::string& p, + const std::time_t& t); + bool hasSuffix(const std::string& s, const std::string& suffix) const; const osm2rdf::config::Config _config; diff --git a/include/osm2rdf/osm/Node.h b/include/osm2rdf/osm/Node.h index 052e277f..320e4434 100644 --- a/include/osm2rdf/osm/Node.h +++ b/include/osm2rdf/osm/Node.h @@ -19,6 +19,7 @@ #ifndef OSM2RDF_OSM_NODE_H_ #define OSM2RDF_OSM_NODE_H_ +#include "Generic.h" #include "boost/serialization/nvp.hpp" #include "osm2rdf/geometry/Box.h" #include "osm2rdf/geometry/Location.h" @@ -36,6 +37,7 @@ class Node { explicit Node(const osmium::Node& node); explicit Node(const osmium::NodeRef& nodeRef); [[nodiscard]] id_t id() const noexcept; + [[nodiscard]] std::time_t timestamp() const noexcept; [[nodiscard]] osm2rdf::geometry::Box envelope() const noexcept; [[nodiscard]] const osm2rdf::geometry::Location& geom() const noexcept; [[nodiscard]] const osm2rdf::osm::TagList& tags() const noexcept; @@ -47,6 +49,7 @@ class Node { protected: id_t _id; + std::time_t _timestamp; osm2rdf::geometry::Location _geom; osm2rdf::osm::TagList _tags; @@ -54,6 +57,7 @@ class Node { template void serialize(Archive& ar, [[maybe_unused]] const unsigned int version) { ar& boost::serialization::make_nvp("_id", _id); + ar& boost::serialization::make_nvp("_timestamp", _timestamp); ar& boost::serialization::make_nvp("_geom", _geom); ar& boost::serialization::make_nvp("_tags", _tags); } diff --git a/include/osm2rdf/osm/Relation.h b/include/osm2rdf/osm/Relation.h index a86f9e59..34cba077 100644 --- a/include/osm2rdf/osm/Relation.h +++ b/include/osm2rdf/osm/Relation.h @@ -41,6 +41,7 @@ class Relation { Relation(); explicit Relation(const osmium::Relation& relation); [[nodiscard]] id_t id() const noexcept; + [[nodiscard]] std::time_t timestamp() const noexcept; [[nodiscard]] const std::vector& members() const noexcept; [[nodiscard]] const osm2rdf::osm::TagList& tags() const noexcept; @@ -60,6 +61,7 @@ class Relation { protected: id_t _id; + std::time_t _timestamp; std::vector _members; osm2rdf::osm::TagList _tags; #if BOOST_VERSION >= 107800 @@ -74,6 +76,7 @@ class Relation { template void serialize(Archive& ar, [[maybe_unused]] const unsigned int version) { ar& boost::serialization::make_nvp("_id", _id); + ar& boost::serialization::make_nvp("_timestamp", _timestamp); ar& boost::serialization::make_nvp("_members", _members); ar& boost::serialization::make_nvp("_tags", _tags); #if BOOST_VERSION >= 107800 diff --git a/include/osm2rdf/osm/Way.h b/include/osm2rdf/osm/Way.h index ba38e232..a509ff53 100644 --- a/include/osm2rdf/osm/Way.h +++ b/include/osm2rdf/osm/Way.h @@ -44,6 +44,7 @@ class Way { Way(); explicit Way(const osmium::Way& way); [[nodiscard]] id_t id() const noexcept; + [[nodiscard]] std::time_t timestamp() const noexcept; [[nodiscard]] bool closed() const noexcept; [[nodiscard]] bool isArea() const noexcept; [[nodiscard]] const osm2rdf::geometry::Box& envelope() const noexcept; @@ -60,6 +61,7 @@ class Way { protected: id_t _id; + std::time_t _timestamp; std::vector _nodes; osm2rdf::geometry::Way _geom; osm2rdf::geometry::Box _envelope; @@ -71,6 +73,7 @@ class Way { template void serialize(Archive& ar, [[maybe_unused]] const unsigned int version) { ar& boost::serialization::make_nvp("_id", _id); + ar& boost::serialization::make_nvp("_timestamp", _timestamp); ar& boost::serialization::make_nvp("_nodes", _nodes); ar& boost::serialization::make_nvp("_geom", _geom); ar& boost::serialization::make_nvp("_envelope", _envelope); diff --git a/include/osm2rdf/ttl/Constants.h b/include/osm2rdf/ttl/Constants.h index b066a846..122d05c6 100644 --- a/include/osm2rdf/ttl/Constants.h +++ b/include/osm2rdf/ttl/Constants.h @@ -25,11 +25,16 @@ namespace osm2rdf::ttl::constants { // Real constants const static inline std::string NAMESPACE__GEOSPARQL = "geo"; +const static inline std::string NAMESPACE__OHM_NODE = "ohmnode"; +const static inline std::string NAMESPACE__OHM_RELATION = "ohmrel"; +const static inline std::string NAMESPACE__OHM_WAY = "ohmway"; +const static inline std::string NAMESPACE__OHM = "ohm"; const static inline std::string NAMESPACE__OPENGIS = "ogc"; const static inline std::string NAMESPACE__OSM_NODE = "osmnode"; const static inline std::string NAMESPACE__OSM_RELATION = "osmrel"; const static inline std::string NAMESPACE__OSM_TAG = "osmkey"; const static inline std::string NAMESPACE__OSM_WAY = "osmway"; +const static inline std::string NAMESPACE__OSM_META = "osmmeta"; const static inline std::string NAMESPACE__OSM = "osm"; const static inline std::string NAMESPACE__OSM2RDF = "osm2rdf"; const static inline std::string NAMESPACE__OSM2RDF_GEOM = "osm2rdfgeom"; @@ -57,6 +62,7 @@ inline std::string IRI__OSM2RDF_GEOM__CONVEX_HULL; inline std::string IRI__OSM2RDF_GEOM__ENVELOPE; inline std::string IRI__OSM2RDF_GEOM__OBB; inline std::string IRI__OSM2RDF__POS; +inline std::string IRI__OSMMETA_TIMESTAMP; inline std::string IRI__OSMWAY_IS_CLOSED; inline std::string IRI__OSMWAY_NEXT_NODE; inline std::string IRI__OSMWAY_NEXT_NODE_DISTANCE; @@ -71,6 +77,7 @@ inline std::string IRI__OSM_WAY; inline std::string IRI__RDF_TYPE; inline std::string IRI__XSD_DATE; +inline std::string IRI__XSD_DATE_TIME; inline std::string IRI__XSD_DECIMAL; inline std::string IRI__XSD_DOUBLE; inline std::string IRI__XSD_FLOAT; @@ -81,6 +88,13 @@ inline std::string IRI__XSD_YEAR_MONTH; inline std::string LITERAL__NO; inline std::string LITERAL__YES; +// Arrays holding values depending on the used dataset +inline std::string DATASET_ID[2] = {"osm", "ohm"}; +inline std::string DATASET_NAMESPACE[2] = {NAMESPACE__OSM, NAMESPACE__OHM}; +inline std::string NODE_NAMESPACE[2] = {NAMESPACE__OSM_NODE, NAMESPACE__OHM_NODE}; +inline std::string RELATION_NAMESPACE[2] = {NAMESPACE__OSM_RELATION, NAMESPACE__OHM_RELATION}; +inline std::string WAY_NAMESPACE[2] = {NAMESPACE__OSM_WAY, NAMESPACE__OHM_WAY}; + } // namespace osm2rdf::ttl::constants #endif // OSM2RDF_TTL_CONSTANTS_H diff --git a/src/config/Config.cpp b/src/config/Config.cpp index dd6c4ae7..2d3dbf24 100644 --- a/src/config/Config.cpp +++ b/src/config/Config.cpp @@ -461,9 +461,9 @@ void osm2rdf::config::Config::fromArgs(int argc, char** argv) { // Dataset selection if (sourceDatasetOp->is_set()) { - if (osm2rdfGeoTriplesModeOp->value() == "OSM") { + if (sourceDatasetOp->value() == "OSM") { sourceDataset = OSM; - } else if (osm2rdfGeoTriplesModeOp->value() == "OHM") { + } else if (sourceDatasetOp->value() == "OHM") { sourceDataset = OHM; } else { throw popl::invalid_option( diff --git a/src/osm/FactHandler.cpp b/src/osm/FactHandler.cpp index bccfb7e5..d4a5dd08 100644 --- a/src/osm/FactHandler.cpp +++ b/src/osm/FactHandler.cpp @@ -34,6 +34,8 @@ using osm2rdf::osm::constants::AREA_PRECISION; using osm2rdf::osm::constants::BASE_SIMPLIFICATION_FACTOR; +using osm2rdf::ttl::constants::DATASET_ID; +using osm2rdf::ttl::constants::DATASET_NAMESPACE; using osm2rdf::ttl::constants::IRI__GEOSPARQL__AS_WKT; using osm2rdf::ttl::constants::IRI__GEOSPARQL__HAS_GEOMETRY; using osm2rdf::ttl::constants::IRI__GEOSPARQL__WKT_LITERAL; @@ -45,6 +47,7 @@ using osm2rdf::ttl::constants::IRI__OSM_NODE; using osm2rdf::ttl::constants::IRI__OSM_RELATION; using osm2rdf::ttl::constants::IRI__OSM_TAG; using osm2rdf::ttl::constants::IRI__OSM_WAY; +using osm2rdf::ttl::constants::IRI__OSMMETA_TIMESTAMP; using osm2rdf::ttl::constants::IRI__OSMWAY_IS_CLOSED; using osm2rdf::ttl::constants::IRI__OSMWAY_NEXT_NODE; using osm2rdf::ttl::constants::IRI__OSMWAY_NEXT_NODE_DISTANCE; @@ -53,6 +56,7 @@ using osm2rdf::ttl::constants::IRI__OSMWAY_NODE_COUNT; using osm2rdf::ttl::constants::IRI__OSMWAY_UNIQUE_NODE_COUNT; using osm2rdf::ttl::constants::IRI__RDF_TYPE; using osm2rdf::ttl::constants::IRI__XSD_DATE; +using osm2rdf::ttl::constants::IRI__XSD_DATE_TIME; using osm2rdf::ttl::constants::IRI__XSD_DECIMAL; using osm2rdf::ttl::constants::IRI__XSD_DOUBLE; using osm2rdf::ttl::constants::IRI__XSD_INTEGER; @@ -68,6 +72,9 @@ using osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION; using osm2rdf::ttl::constants::NAMESPACE__OSM_TAG; using osm2rdf::ttl::constants::NAMESPACE__OSM_WAY; using osm2rdf::ttl::constants::NAMESPACE__WIKIDATA_ENTITY; +using osm2rdf::ttl::constants::NODE_NAMESPACE; +using osm2rdf::ttl::constants::RELATION_NAMESPACE; +using osm2rdf::ttl::constants::WAY_NAMESPACE; // ____________________________________________________________________________ template @@ -79,12 +86,14 @@ osm2rdf::osm::FactHandler::FactHandler(const osm2rdf::config::Config& config, template void osm2rdf::osm::FactHandler::area(const osm2rdf::osm::Area& area) { const std::string& subj = _writer->generateIRI( - area.fromWay() ? NAMESPACE__OSM_WAY : NAMESPACE__OSM_RELATION, + area.fromWay() ? WAY_NAMESPACE[_config.sourceDataset] + : RELATION_NAMESPACE[_config.sourceDataset], area.objId()); if (!_config.hasGeometryAsWkt) { const std::string& geomObj = _writer->generateIRI( NAMESPACE__OSM2RDF_GEOM, (area.fromWay() ? "wayarea_" : "relarea_") + + DATASET_ID[_config.sourceDataset] + "_" + std::to_string(area.objId())); _writer->writeTriple(subj, IRI__GEOSPARQL__HAS_GEOMETRY, geomObj); @@ -93,30 +102,52 @@ void osm2rdf::osm::FactHandler::area(const osm2rdf::osm::Area& area) { writeBoostGeometry(subj, IRI__GEOSPARQL__HAS_GEOMETRY, area.geom()); } - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, area.convexHull()); - writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, area.envelope()); - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, area.orientedBoundingBox()); + if (_config.addAreaConvexHull) { + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, area.convexHull()); + } + if (_config.addAreaEnvelope) { + writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, area.envelope()); + } + if (_config.addAreaOrientedBoundingBox) { + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, + area.orientedBoundingBox()); + } - std::ostringstream tmp; - // Increase default precision as areas in regbez freiburg have a 0 area - // otherwise. - tmp << std::fixed << std::setprecision(AREA_PRECISION) << area.geomArea(); - _writer->writeTriple( - subj, _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "area"), - _writer->generateLiteralUnsafe(tmp.str(), "^^" + IRI__XSD_DOUBLE)); + if (_config.addSortMetadata) { + std::ostringstream tmp; + // Increase default precision as areas in regbez freiburg have a 0 area + // otherwise. + tmp << std::fixed << std::setprecision(AREA_PRECISION) << area.geomArea(); + _writer->writeTriple( + subj, _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "area"), + _writer->generateLiteralUnsafe(tmp.str(), "^^" + IRI__XSD_DOUBLE)); + } + + if (_config.addAreaEnvelopeRatio) { + std::ostringstream tmp; + tmp << std::fixed << (area.geomArea() / area.envelopeArea()); + _writer->writeTriple( + subj, + _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "area_envelope_ratio"), + _writer->generateLiteralUnsafe(tmp.str(), "^^" + IRI__XSD_DOUBLE)); + } } // ____________________________________________________________________________ template void osm2rdf::osm::FactHandler::node(const osm2rdf::osm::Node& node) { const std::string& subj = - _writer->generateIRI(NAMESPACE__OSM_NODE, node.id()); + _writer->generateIRI(NODE_NAMESPACE[_config.sourceDataset], node.id()); _writer->writeTriple(subj, IRI__RDF_TYPE, IRI__OSM_NODE); + writeSecondsAsISO(subj, IRI__OSMMETA_TIMESTAMP, node.timestamp()); + writeTagList(subj, node.tags()); + if (!_config.hasGeometryAsWkt) { const std::string& geomObj = _writer->generateIRI( - NAMESPACE__OSM2RDF_GEOM, "node_" + std::to_string(node.id())); + NAMESPACE__OSM2RDF_GEOM, "node_" + DATASET_ID[_config.sourceDataset] + + "_" + std::to_string(node.id())); _writer->writeTriple(subj, IRI__GEOSPARQL__HAS_GEOMETRY, geomObj); writeBoostGeometry(geomObj, IRI__GEOSPARQL__AS_WKT, node.geom()); @@ -124,64 +155,78 @@ void osm2rdf::osm::FactHandler::node(const osm2rdf::osm::Node& node) { writeBoostGeometry(subj, IRI__GEOSPARQL__HAS_GEOMETRY, node.geom()); } - writeTagList(subj, node.tags()); - - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, node.convexHull()); - writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, node.envelope()); - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, node.orientedBoundingBox()); + if (_config.addNodeConvexHull) { + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, node.convexHull()); + } + if (_config.addNodeEnvelope) { + writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, node.envelope()); + } + if (_config.addNodeOrientedBoundingBox) { + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, + node.orientedBoundingBox()); + } } // ____________________________________________________________________________ template void osm2rdf::osm::FactHandler::relation( const osm2rdf::osm::Relation& relation) { - const std::string& subj = - _writer->generateIRI(NAMESPACE__OSM_RELATION, relation.id()); + const std::string& subj = _writer->generateIRI( + RELATION_NAMESPACE[_config.sourceDataset], relation.id()); _writer->writeTriple(subj, IRI__RDF_TYPE, IRI__OSM_RELATION); + writeSecondsAsISO(subj, IRI__OSMMETA_TIMESTAMP, relation.timestamp()); writeTagList(subj, relation.tags()); size_t inRelPos = 0; for (const auto& member : relation.members()) { const std::string& role = member.role(); - const std::string& blankNode = _writer->generateBlankNode(); - _writer->writeTriple( - subj, _writer->generateIRIUnsafe(NAMESPACE__OSM_RELATION, "member"), - blankNode); - - std::string type; - switch (member.type()) { - case osm2rdf::osm::RelationMemberType::NODE: - type = NAMESPACE__OSM_NODE; - break; - case osm2rdf::osm::RelationMemberType::RELATION: - type = NAMESPACE__OSM_RELATION; - break; - case osm2rdf::osm::RelationMemberType::WAY: - type = NAMESPACE__OSM_WAY; - break; - default: - type = NAMESPACE__OSM; - } + if (_config.addRelationBorderMembers || + (role != "outer" && role != "inner")) { + const std::string& blankNode = _writer->generateBlankNode(); + _writer->writeTriple( + subj, _writer->generateIRIUnsafe(NAMESPACE__OSM_RELATION, "member"), + blankNode); - _writer->writeTriple(blankNode, - _writer->generateIRIUnsafe(NAMESPACE__OSM, "id"), - _writer->generateIRI(type, member.id())); - _writer->writeTriple(blankNode, - _writer->generateIRIUnsafe(NAMESPACE__OSM, "role"), - _writer->generateLiteral(role, "")); - _writer->writeTriple( - blankNode, IRI__OSM2RDF__POS, - _writer->generateLiteralUnsafe(std::to_string(inRelPos++), - "^^" + IRI__XSD_INTEGER)); + std::string type; + switch (member.type()) { + case osm2rdf::osm::RelationMemberType::NODE: + type = NODE_NAMESPACE[_config.sourceDataset]; + break; + case osm2rdf::osm::RelationMemberType::RELATION: + type = RELATION_NAMESPACE[_config.sourceDataset]; + break; + case osm2rdf::osm::RelationMemberType::WAY: + type = WAY_NAMESPACE[_config.sourceDataset]; + break; + default: + type = DATASET_NAMESPACE[_config.sourceDataset]; + } + + _writer->writeTriple(blankNode, + _writer->generateIRIUnsafe( + DATASET_NAMESPACE[_config.sourceDataset], "id"), + _writer->generateIRI(type, member.id())); + _writer->writeTriple( + blankNode, + _writer->generateIRIUnsafe(DATASET_NAMESPACE[_config.sourceDataset], + "role"), + _writer->generateLiteral(role, "")); + _writer->writeTriple( + blankNode, IRI__OSM2RDF__POS, + _writer->generateLiteralUnsafe(std::to_string(inRelPos++), + "^^" + IRI__XSD_INTEGER)); + } } #if BOOST_VERSION >= 107800 if (relation.hasGeometry() && !relation.isArea()) { if (!_config.hasGeometryAsWkt) { - const std::string& geomObj = _writer->generateIRI( - NAMESPACE__OSM2RDF_GEOM, "relation_" + std::to_string(relation.id())); + const std::string& geomObj = + _writer->generateIRI(NAMESPACE__OSM2RDF_GEOM, + "relation_" + DATASET_ID[_config.sourceDataset] + + "_" + std::to_string(relation.id())); _writer->writeTriple(subj, IRI__GEOSPARQL__HAS_GEOMETRY, geomObj); writeBoostGeometry(geomObj, IRI__GEOSPARQL__AS_WKT, relation.geom()); @@ -189,12 +234,18 @@ void osm2rdf::osm::FactHandler::relation( writeBoostGeometry(subj, IRI__GEOSPARQL__HAS_GEOMETRY, relation.geom()); } - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, - relation.convexHull()); - writeBox(subj, osm2rdf::ttl::constants::IRI__OSM2RDF_GEOM__ENVELOPE, - relation.envelope()); - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, - relation.orientedBoundingBox()); + if (_config.addRelationConvexHull) { + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, + relation.convexHull()); + } + if (_config.addRelationEnvelope) { + writeBox(subj, osm2rdf::ttl::constants::IRI__OSM2RDF_GEOM__ENVELOPE, + relation.envelope()); + } + if (_config.addRelationOrientedBoundingBox) { + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, + relation.orientedBoundingBox()); + } _writer->writeTriple( subj, _writer->generateIRI(NAMESPACE__OSM2RDF, "completeGeometry"), @@ -207,10 +258,12 @@ void osm2rdf::osm::FactHandler::relation( // ____________________________________________________________________________ template void osm2rdf::osm::FactHandler::way(const osm2rdf::osm::Way& way) { - const std::string& subj = _writer->generateIRI(NAMESPACE__OSM_WAY, way.id()); + const std::string& subj = + _writer->generateIRI(WAY_NAMESPACE[_config.sourceDataset], way.id()); _writer->writeTriple(subj, IRI__RDF_TYPE, IRI__OSM_WAY); + writeSecondsAsISO(subj, IRI__OSMMETA_TIMESTAMP, way.timestamp()); writeTagList(subj, way.tags()); if (_config.addWayNodeOrder) { @@ -223,7 +276,8 @@ void osm2rdf::osm::FactHandler::way(const osm2rdf::osm::Way& way) { _writer->writeTriple( blankNode, osm2rdf::ttl::constants::IRI__OSMWAY_NODE, - _writer->generateIRI(NAMESPACE__OSM_NODE, node.id())); + _writer->generateIRI(NODE_NAMESPACE[_config.sourceDataset], + node.id())); _writer->writeTriple( blankNode, IRI__OSM2RDF__POS, @@ -231,14 +285,16 @@ void osm2rdf::osm::FactHandler::way(const osm2rdf::osm::Way& way) { "^^" + IRI__XSD_INTEGER)); if (_config.addWayNodeGeometry) { - const std::string& subj = - _writer->generateIRI(NAMESPACE__OSM_NODE, node.id()); + const std::string& subj = _writer->generateIRI( + NODE_NAMESPACE[_config.sourceDataset], node.id()); _writer->writeTriple(subj, IRI__RDF_TYPE, IRI__OSM_NODE); if (!_config.hasGeometryAsWkt) { - const std::string& geomObj = _writer->generateIRI( - NAMESPACE__OSM2RDF_GEOM, "node_" + std::to_string(node.id())); + const std::string& geomObj = + _writer->generateIRI(NAMESPACE__OSM2RDF_GEOM, + "node_" + DATASET_ID[_config.sourceDataset] + + "_" + std::to_string(node.id())); _writer->writeTriple(subj, IRI__GEOSPARQL__HAS_GEOMETRY, geomObj); writeBoostGeometry(geomObj, IRI__GEOSPARQL__AS_WKT, node.geom()); @@ -250,7 +306,8 @@ void osm2rdf::osm::FactHandler::way(const osm2rdf::osm::Way& way) { if (_config.addWayNodeSpatialMetadata && !lastBlankNode.empty()) { _writer->writeTriple( lastBlankNode, IRI__OSMWAY_NEXT_NODE, - _writer->generateIRI(NAMESPACE__OSM_NODE, node.id())); + _writer->generateIRI(NODE_NAMESPACE[_config.sourceDataset], + node.id())); // Haversine distance const double distanceLat = (node.geom().y() - lastNode.geom().y()) * osm2rdf::osm::constants::DEGREE; @@ -289,9 +346,16 @@ void osm2rdf::osm::FactHandler::way(const osm2rdf::osm::Way& way) { } } - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, way.convexHull()); - writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, way.envelope()); - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, way.orientedBoundingBox()); + if (_config.addWayConvexHull) { + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, way.convexHull()); + } + if (_config.addWayEnvelope) { + writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, way.envelope()); + } + + if (_config.addWayOrientedBoundingBox) { + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, way.orientedBoundingBox()); + } if (_config.addWayMetadata) { _writer->writeTriple(subj, IRI__OSMWAY_IS_CLOSED, @@ -306,12 +370,13 @@ void osm2rdf::osm::FactHandler::way(const osm2rdf::osm::Way& way) { "^^" + IRI__XSD_INTEGER)); } - - _writer->writeTriple( - subj, _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "length"), - _writer->generateLiteral( - std::to_string(boost::geometry::length(way.geom())), - "^^" + osm2rdf::ttl::constants::IRI__XSD_DOUBLE)); + if (_config.addSortMetadata) { + _writer->writeTriple( + subj, _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "length"), + _writer->generateLiteral( + std::to_string(boost::geometry::length(way.geom())), + "^^" + osm2rdf::ttl::constants::IRI__XSD_DOUBLE)); + } } // ____________________________________________________________________________ @@ -445,7 +510,8 @@ void osm2rdf::osm::FactHandler::writeTagList( valueTmp.end()); _writer->writeTriple( - subj, _writer->generateIRI(NAMESPACE__OSM, key), + subj, + _writer->generateIRI(DATASET_NAMESPACE[_config.sourceDataset], key), _writer->generateIRI(NAMESPACE__WIKIDATA_ENTITY, valueTmp)); tagTripleCount++; } @@ -456,13 +522,15 @@ void osm2rdf::osm::FactHandler::writeTagList( const std::string& lang = value.substr(0, pos); const std::string& entry = value.substr(pos + 1); _writer->writeTriple( - subj, _writer->generateIRI(NAMESPACE__OSM, key), + subj, + _writer->generateIRI(DATASET_NAMESPACE[_config.sourceDataset], key), _writer->generateIRI("https://" + lang + ".wikipedia.org/wiki/", entry)); tagTripleCount++; } else { _writer->writeTriple( - subj, _writer->generateIRI(NAMESPACE__OSM, key), + subj, + _writer->generateIRI(DATASET_NAMESPACE[_config.sourceDataset], key), _writer->generateIRI("https://www.wikipedia.org/wiki/", value)); tagTripleCount++; } @@ -472,17 +540,24 @@ void osm2rdf::osm::FactHandler::writeTagList( switch (dashCount) { case 2: _writer->writeTriple( - subj, _writer->generateIRIUnsafe(NAMESPACE__OSM, key), + subj, + _writer->generateIRIUnsafe( + DATASET_NAMESPACE[_config.sourceDataset], key), _writer->generateLiteralUnsafe(value, "^^" + IRI__XSD_DATE)); break; case 1: _writer->writeTriple( - subj, _writer->generateIRIUnsafe(NAMESPACE__OSM, key), - _writer->generateLiteralUnsafe(value, "^^" + IRI__XSD_YEAR_MONTH)); + subj, + _writer->generateIRIUnsafe( + DATASET_NAMESPACE[_config.sourceDataset], key), + _writer->generateLiteralUnsafe(value, + "^^" + IRI__XSD_YEAR_MONTH)); break; case 0: _writer->writeTriple( - subj, _writer->generateIRIUnsafe(NAMESPACE__OSM, key), + subj, + _writer->generateIRIUnsafe( + DATASET_NAMESPACE[_config.sourceDataset], key), _writer->generateLiteralUnsafe(value, "^^" + IRI__XSD_YEAR)); break; } @@ -494,6 +569,18 @@ void osm2rdf::osm::FactHandler::writeTagList( "^^" + IRI__XSD_INTEGER)); } +// ____________________________________________________________________________ +template +void osm2rdf::osm::FactHandler::writeSecondsAsISO(const std::string& subj, + const std::string& pred, + const std::time_t& time) { + std::stringstream date; + date << std::put_time(std::localtime(&time), "%Y-%m-%dT%X"); + _writer->writeTriple( + subj, pred, + _writer->generateLiteralUnsafe(date.str(), "^^" + IRI__XSD_DATE_TIME)); +} + // ____________________________________________________________________________ template bool osm2rdf::osm::FactHandler::hasSuffix(const std::string& subj, diff --git a/src/osm/Node.cpp b/src/osm/Node.cpp index c750c4d2..d7765c73 100644 --- a/src/osm/Node.cpp +++ b/src/osm/Node.cpp @@ -16,12 +16,13 @@ // You should have received a copy of the GNU General Public License // along with osm2rdf. If not, see . +#include "osm2rdf/osm/Node.h" + #include "boost/geometry.hpp" #include "boost/geometry/algorithms/envelope.hpp" #include "osm2rdf/geometry/Box.h" #include "osm2rdf/geometry/Global.h" #include "osm2rdf/geometry/Polygon.h" -#include "osm2rdf/osm/Node.h" #include "osm2rdf/osm/Generic.h" #include "osm2rdf/osm/TagList.h" #include "osmium/osm/node.hpp" @@ -35,6 +36,7 @@ osm2rdf::osm::Node::Node() { // ____________________________________________________________________________ osm2rdf::osm::Node::Node(const osmium::Node& node) { _id = node.positive_id(); + _timestamp = node.timestamp().seconds_since_epoch(); const auto& loc = node.location(); _geom = osm2rdf::geometry::Location(loc.lon(), loc.lat()); _tags = osm2rdf::osm::convertTagList(node.tags()); @@ -50,6 +52,11 @@ osm2rdf::osm::Node::Node(const osmium::NodeRef& nodeRef) { // ____________________________________________________________________________ osm2rdf::osm::Node::id_t osm2rdf::osm::Node::id() const noexcept { return _id; } +// ____________________________________________________________________________ +std::time_t osm2rdf::osm::Node::timestamp() const noexcept { + return _timestamp; +} + // ____________________________________________________________________________ const osm2rdf::geometry::Location& osm2rdf::osm::Node::geom() const noexcept { return _geom; @@ -57,9 +64,9 @@ const osm2rdf::geometry::Location& osm2rdf::osm::Node::geom() const noexcept { // ____________________________________________________________________________ osm2rdf::geometry::Box osm2rdf::osm::Node::envelope() const noexcept { - osm2rdf::geometry::Box envelope; - boost::geometry::envelope(geom(), envelope); - return envelope; + osm2rdf::geometry::Box envelope; + boost::geometry::envelope(geom(), envelope); + return envelope; } // ____________________________________________________________________________ @@ -68,7 +75,8 @@ osm2rdf::geometry::Polygon osm2rdf::osm::Node::convexHull() const noexcept { } // ____________________________________________________________________________ -osm2rdf::geometry::Polygon osm2rdf::osm::Node::orientedBoundingBox() const noexcept { +osm2rdf::geometry::Polygon osm2rdf::osm::Node::orientedBoundingBox() + const noexcept { return convexHull(); } diff --git a/src/osm/Relation.cpp b/src/osm/Relation.cpp index afc7d0e7..fe46dff7 100644 --- a/src/osm/Relation.cpp +++ b/src/osm/Relation.cpp @@ -38,6 +38,7 @@ osm2rdf::osm::Relation::Relation() { // ____________________________________________________________________________ osm2rdf::osm::Relation::Relation(const osmium::Relation& relation) { _id = relation.positive_id(); + _timestamp = relation.timestamp().seconds_since_epoch(); _tags = osm2rdf::osm::convertTagList(relation.tags()); _members.reserve(relation.cmembers().size()); for (const auto& member : relation.cmembers()) { @@ -51,6 +52,11 @@ osm2rdf::osm::Relation::id_t osm2rdf::osm::Relation::id() const noexcept { return _id; } +// ____________________________________________________________________________ +std::time_t osm2rdf::osm::Relation::timestamp() const noexcept { + return _timestamp; +} + // ____________________________________________________________________________ const osm2rdf::osm::TagList& osm2rdf::osm::Relation::tags() const noexcept { return _tags; @@ -78,22 +84,26 @@ bool osm2rdf::osm::Relation::hasGeometry() const noexcept { } // ____________________________________________________________________________ -const osm2rdf::geometry::Relation& osm2rdf::osm::Relation::geom() const noexcept { +const osm2rdf::geometry::Relation& osm2rdf::osm::Relation::geom() + const noexcept { return _geom; } // ____________________________________________________________________________ -const osm2rdf::geometry::Box& osm2rdf::osm::Relation::envelope() const noexcept { +const osm2rdf::geometry::Box& osm2rdf::osm::Relation::envelope() + const noexcept { return _envelope; } // ____________________________________________________________________________ -const osm2rdf::geometry::Polygon& osm2rdf::osm::Relation::convexHull() const noexcept { +const osm2rdf::geometry::Polygon& osm2rdf::osm::Relation::convexHull() + const noexcept { return _convexHull; } // ____________________________________________________________________________ -const osm2rdf::geometry::Polygon& osm2rdf::osm::Relation::orientedBoundingBox() const noexcept { +const osm2rdf::geometry::Polygon& osm2rdf::osm::Relation::orientedBoundingBox() + const noexcept { return _obb; } @@ -144,7 +154,8 @@ void osm2rdf::osm::Relation::buildGeometry( if (!_geom.empty()) { boost::geometry::envelope(_geom, _envelope); boost::geometry::convex_hull(_geom, _convexHull); - _obb = osm2rdf::osm::generic::orientedBoundingBoxFromConvexHull(_convexHull); + _obb = + osm2rdf::osm::generic::orientedBoundingBoxFromConvexHull(_convexHull); } else { _envelope.min_corner() = geometry::Location{0, 0}; _envelope.max_corner() = geometry::Location{0, 0}; diff --git a/src/osm/Way.cpp b/src/osm/Way.cpp index 6ec85b93..10f8142b 100644 --- a/src/osm/Way.cpp +++ b/src/osm/Way.cpp @@ -17,15 +17,16 @@ // You should have received a copy of the GNU General Public License // along with osm2rdf. If not, see . +#include "osm2rdf/geometry/Way.h" + #include #include "boost/geometry.hpp" #include "osm2rdf/geometry/Box.h" #include "osm2rdf/geometry/Polygon.h" -#include "osm2rdf/geometry/Way.h" #include "osm2rdf/osm/Box.h" -#include "osm2rdf/osm/Node.h" #include "osm2rdf/osm/Generic.h" +#include "osm2rdf/osm/Node.h" #include "osm2rdf/osm/TagList.h" #include "osm2rdf/osm/Way.h" #include "osmium/osm/way.hpp" @@ -40,6 +41,7 @@ osm2rdf::osm::Way::Way() { // ____________________________________________________________________________ osm2rdf::osm::Way::Way(const osmium::Way& way) { _id = way.positive_id(); + _timestamp = way.timestamp().seconds_since_epoch(); _tags = osm2rdf::osm::convertTagList(way.tags()); _nodes.reserve(way.nodes().size()); _geom.reserve(way.nodes().size()); @@ -50,10 +52,18 @@ osm2rdf::osm::Way::Way(const osmium::Way& way) { double latMax = -std::numeric_limits::infinity(); for (const auto& nodeRef : way.nodes()) { - if (nodeRef.lon() < lonMin) { lonMin = nodeRef.lon(); } - if (nodeRef.lat() < latMin) { latMin = nodeRef.lat(); } - if (nodeRef.lon() > lonMax) { lonMax = nodeRef.lon(); } - if (nodeRef.lat() > latMax) { latMax = nodeRef.lat(); } + if (nodeRef.lon() < lonMin) { + lonMin = nodeRef.lon(); + } + if (nodeRef.lat() < latMin) { + latMin = nodeRef.lat(); + } + if (nodeRef.lon() > lonMax) { + lonMax = nodeRef.lon(); + } + if (nodeRef.lat() > latMax) { + latMax = nodeRef.lat(); + } _nodes.emplace_back(nodeRef); @@ -71,6 +81,9 @@ osm2rdf::osm::Way::Way(const osmium::Way& way) { // ____________________________________________________________________________ osm2rdf::osm::Way::id_t osm2rdf::osm::Way::id() const noexcept { return _id; } +// ____________________________________________________________________________ +std::time_t osm2rdf::osm::Way::timestamp() const noexcept { return _timestamp; } + // ____________________________________________________________________________ const osm2rdf::osm::TagList& osm2rdf::osm::Way::tags() const noexcept { return _tags; @@ -93,12 +106,14 @@ const osm2rdf::geometry::Box& osm2rdf::osm::Way::envelope() const noexcept { } // ____________________________________________________________________________ -const osm2rdf::geometry::Polygon& osm2rdf::osm::Way::convexHull() const noexcept { +const osm2rdf::geometry::Polygon& osm2rdf::osm::Way::convexHull() + const noexcept { return _convexHull; } // ____________________________________________________________________________ -const osm2rdf::geometry::Polygon& osm2rdf::osm::Way::orientedBoundingBox() const noexcept { +const osm2rdf::geometry::Polygon& osm2rdf::osm::Way::orientedBoundingBox() + const noexcept { return _obb; } diff --git a/src/ttl/Writer.cpp b/src/ttl/Writer.cpp index 3e74fb43..145609d5 100644 --- a/src/ttl/Writer.cpp +++ b/src/ttl/Writer.cpp @@ -59,27 +59,23 @@ osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, // osm prefixes {osm2rdf::ttl::constants::NAMESPACE__OSM, "https://www.openstreetmap.org/"}, + {osm2rdf::ttl::constants::NAMESPACE__OSM_META, + "https://www.openstreetmap.org/meta/"}, {osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, - "https://www.openstreetmap.org/wiki/Key:"}}; - - // Dataset specific prefixes - switch (_config.sourceDataset) { - case config::OHM: - _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_NODE] = - "https://www.openhistoricalmap.org/node/"; - _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION] = - "https://www.openhistoricalmap.org/relation/"; - _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_WAY] = - "https://www.openhistoricalmap.org/way/"; - break; - default: - _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_NODE] = - "https://www.openstreetmap.org/node/"; - _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION] = - "https://www.openstreetmap.org/relation/"; - _prefixes[osm2rdf::ttl::constants::NAMESPACE__OSM_WAY] = - "https://www.openstreetmap.org/way/"; - } + "https://www.openstreetmap.org/wiki/Key:"}, + {osm2rdf::ttl::constants::NAMESPACE__OSM_NODE, + "https://www.openstreetmap.org/node/"}, + {osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION, + "https://www.openstreetmap.org/relation/"}, + {osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, + "https://www.openstreetmap.org/way/"}, + // ohm prefixes + {osm2rdf::ttl::constants::NAMESPACE__OHM_NODE, + "https://www.openhistoricalmap.org/node/"}, + {osm2rdf::ttl::constants::NAMESPACE__OHM_RELATION, + "https://www.openhistoricalmap.org/relation/"}, + {osm2rdf::ttl::constants::NAMESPACE__OHM_WAY, + "https://www.openhistoricalmap.org/way/"}}; // Generate constants osm2rdf::ttl::constants::IRI__GEOSPARQL__HAS_GEOMETRY = @@ -110,6 +106,8 @@ osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM2RDF_GEOM, "obb"); osm2rdf::ttl::constants::IRI__OSM2RDF__POS = generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM2RDF, "pos"); + osm2rdf::ttl::constants::IRI__OSMMETA_TIMESTAMP = + generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_META, "timestamp"); osm2rdf::ttl::constants::IRI__OSMWAY_IS_CLOSED = generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, "is_closed"); osm2rdf::ttl::constants::IRI__OSMWAY_NEXT_NODE = @@ -135,6 +133,8 @@ osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, osm2rdf::ttl::constants::IRI__XSD_DATE = generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "date"); + osm2rdf::ttl::constants::IRI__XSD_DATE_TIME = + generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "dateTime"); osm2rdf::ttl::constants::IRI__XSD_DECIMAL = generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "decimal"); osm2rdf::ttl::constants::IRI__XSD_DOUBLE = From 75c3b4fba93856b1f136ddaba6c00b9a494a59b0 Mon Sep 17 00:00:00 2001 From: Axel Lehmann Date: Mon, 22 Jan 2024 11:56:31 +0100 Subject: [PATCH 4/9] Make the constant APPROX_CONTAINS_SLACK a configurable value. --- include/osm2rdf/config/Config.h | 1 + include/osm2rdf/config/Constants.h | 12 ++++++++++-- include/osm2rdf/osm/GeometryHandler.h | 2 -- src/config/Config.cpp | 19 ++++++++++++++++++- src/osm/GeometryHandler.cpp | 14 +++++++------- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/include/osm2rdf/config/Config.h b/include/osm2rdf/config/Config.h index d92b2c04..456b97c4 100644 --- a/include/osm2rdf/config/Config.h +++ b/include/osm2rdf/config/Config.h @@ -67,6 +67,7 @@ struct Config { // "collapsed away" by the inner simplification, or added by the outer // simplification double simplifyGeometriesInnerOuter = 1 / (3.14 * 20); + double approxContainsSlack = 0.05; bool dontUseInnerOuterGeoms = false; bool approximateSpatialRels = false; diff --git a/include/osm2rdf/config/Constants.h b/include/osm2rdf/config/Constants.h index 44e8fc1d..ad6a7459 100644 --- a/include/osm2rdf/config/Constants.h +++ b/include/osm2rdf/config/Constants.h @@ -270,8 +270,16 @@ const static inline std::string APPROX_SPATIAL_REL_OPTION_SHORT = const static inline std::string APPROX_SPATIAL_REL_OPTION_LONG = "approximate-spatial-relations"; const static inline std::string APPROX_SPATIAL_REL_OPTION_HELP = "Use " - "simplified inner/outer geometries for approximate calcuation of spatial " - "relations"; + "simplified inner/outer geometries for approximate calculation of spatial " + "relations"; + +const static inline std::string APPROX_CONTAINS_SLACK_INFO = + "Slack for approximate contains"; +const static inline std::string APPROX_CONTAINS_SLACK_OPTION_SHORT = + ""; +const static inline std::string APPROX_CONTAINS_SLACK_OPTION_LONG = + "approximate-contains-slack"; +const static inline std::string APPROX_CONTAINS_SLACK_OPTION_HELP = ""; const static inline std::string SIMPLIFY_WKT_INFO = "Simplifying WKT"; const static inline std::string SIMPLIFY_WKT_OPTION_SHORT = "s"; diff --git a/include/osm2rdf/osm/GeometryHandler.h b/include/osm2rdf/osm/GeometryHandler.h index e8e5fe7e..2eed3a7c 100644 --- a/include/osm2rdf/osm/GeometryHandler.h +++ b/include/osm2rdf/osm/GeometryHandler.h @@ -47,8 +47,6 @@ const static int NUM_GRID_CELLS = 5000; const static double GRID_W = 360.0 / NUM_GRID_CELLS; const static double GRID_H = 180.0 / NUM_GRID_CELLS; -const double APPROX_CONTAINS_SLACK = 0.05; - struct GeomRelationStats { size_t _totalChecks = 0; size_t _fullChecks = 0; diff --git a/src/config/Config.cpp b/src/config/Config.cpp index 2d3dbf24..0a1090b9 100644 --- a/src/config/Config.cpp +++ b/src/config/Config.cpp @@ -126,6 +126,10 @@ std::string osm2rdf::config::Config::getInfo(std::string_view prefix) const { << prefix << osm2rdf::config::constants::OGC_GEO_TRIPLES_INFO << ": " << (modeStrings[ogcGeoTriplesMode]); + oss << "\n" + << prefix << osm2rdf::config::constants::APPROX_CONTAINS_SLACK_INFO + << ": " << approxContainsSlack; + if (ogcGeoTriplesMode || osm2rdfGeoTriplesMode) { if (noAreaGeometricRelations) { oss << "\n" @@ -376,6 +380,13 @@ void osm2rdf::config::Config::fromArgs(int argc, char** argv) { osm2rdf::config::constants::CACHE_OPTION_LONG, osm2rdf::config::constants::CACHE_OPTION_HELP, cache); + auto approxContainsSlackOp = + parser.add, popl::Attribute::expert>( + osm2rdf::config::constants::APPROX_CONTAINS_SLACK_OPTION_SHORT, + osm2rdf::config::constants::APPROX_CONTAINS_SLACK_OPTION_LONG, + osm2rdf::config::constants::APPROX_CONTAINS_SLACK_OPTION_HELP, + approxContainsSlack); + try { parser.parse(argc, argv); @@ -463,14 +474,20 @@ void osm2rdf::config::Config::fromArgs(int argc, char** argv) { if (sourceDatasetOp->is_set()) { if (sourceDatasetOp->value() == "OSM") { sourceDataset = OSM; + approxContainsSlack = 0.05; } else if (sourceDatasetOp->value() == "OHM") { sourceDataset = OHM; + approxContainsSlack = 0; } else { throw popl::invalid_option( - sourceDatasetOp.get(), popl::invalid_option::Error::invalid_argument, + sourceDatasetOp.get(), + popl::invalid_option::Error::invalid_argument, popl::OptionName::long_name, sourceDatasetOp->value(), ""); } } + if (approxContainsSlackOp->is_set()) { + approxContainsSlack = approxContainsSlackOp->value(); + } // Select amount to dump addAreaWayLinestrings = addAreaWayLinestringsOp->is_set(); diff --git a/src/osm/GeometryHandler.cpp b/src/osm/GeometryHandler.cpp index 5a8d1b81..be8d89ad 100644 --- a/src/osm/GeometryHandler.cpp +++ b/src/osm/GeometryHandler.cpp @@ -613,7 +613,7 @@ void GeometryHandler::prepareDAG() { } // skip equal geometries - if (APPROX_CONTAINS_SLACK == 0) { + if (_config.approxContainsSlack == 0) { if (fabs(areaArea - entryArea) < 0.0001 * 0.0001) { continue; } @@ -625,7 +625,7 @@ void GeometryHandler::prepareDAG() { } GeomRelationInfo geomRelInf; - if (APPROX_CONTAINS_SLACK == 0) { + if (_config.approxContainsSlack == 0) { if (!areaInArea(entry, area, &geomRelInf, &stats)) { continue; } @@ -650,9 +650,9 @@ void GeometryHandler::prepareDAG() { } } - if (APPROX_CONTAINS_SLACK > 0 && + if (_config.approxContainsSlack > 0 && fabs(1.0 - areaArea / geomRelInf.intersectArea) < - APPROX_CONTAINS_SLACK) { + _config.approxContainsSlack) { continue; } @@ -2184,7 +2184,7 @@ bool GeometryHandler::areaInAreaApprox(const SpatialAreaValue& a, const auto& areaGeom = std::get<2>(b); const auto& areaConvexHull = std::get<10>(b); - if (areaArea / entryArea <= 1.0 - APPROX_CONTAINS_SLACK) { + if (areaArea / entryArea <= 1.0 - _config.approxContainsSlack) { stats->skippedByAreaSize(); return false; } @@ -2221,7 +2221,7 @@ bool GeometryHandler::areaInAreaApprox(const SpatialAreaValue& a, geomRelInf->intersectArea = boost::geometry::area(intersect); stats->skippedByBoxIdIntersectCutout(); return fabs(1.0 - entryArea / geomRelInf->intersectArea) < - APPROX_CONTAINS_SLACK; + _config.approxContainsSlack; } else { if (!boost::geometry::is_empty(entryConvexHull) && !boost::geometry::is_empty(areaConvexHull) && @@ -2251,7 +2251,7 @@ bool GeometryHandler::areaInAreaApprox(const SpatialAreaValue& a, geomRelInf->intersectArea = boost::geometry::area(intersect); stats->fullCheck(); return fabs(1.0 - entryArea / geomRelInf->intersectArea) < - APPROX_CONTAINS_SLACK; + _config.approxContainsSlack; } } From 99f4cc7e313c5ac599fd777ee89d49ed3e292f48 Mon Sep 17 00:00:00 2001 From: Axel Lehmann Date: Fri, 26 Jan 2024 10:57:31 +0100 Subject: [PATCH 5/9] Format FactHandler.cpp --- src/osm/FactHandler.cpp | 184 +++++++++++++++------------------------- 1 file changed, 70 insertions(+), 114 deletions(-) diff --git a/src/osm/FactHandler.cpp b/src/osm/FactHandler.cpp index d4a5dd08..b0df7291 100644 --- a/src/osm/FactHandler.cpp +++ b/src/osm/FactHandler.cpp @@ -92,9 +92,9 @@ void osm2rdf::osm::FactHandler::area(const osm2rdf::osm::Area& area) { if (!_config.hasGeometryAsWkt) { const std::string& geomObj = _writer->generateIRI( - NAMESPACE__OSM2RDF_GEOM, (area.fromWay() ? "wayarea_" : "relarea_") + - DATASET_ID[_config.sourceDataset] + "_" + - std::to_string(area.objId())); + NAMESPACE__OSM2RDF_GEOM, DATASET_ID[_config.sourceDataset] + "_" + + (area.fromWay() ? "way" : "rel") + + "area_" + std::to_string(area.objId())); _writer->writeTriple(subj, IRI__GEOSPARQL__HAS_GEOMETRY, geomObj); writeBoostGeometry(geomObj, IRI__GEOSPARQL__AS_WKT, area.geom()); @@ -102,35 +102,17 @@ void osm2rdf::osm::FactHandler::area(const osm2rdf::osm::Area& area) { writeBoostGeometry(subj, IRI__GEOSPARQL__HAS_GEOMETRY, area.geom()); } - if (_config.addAreaConvexHull) { - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, area.convexHull()); - } - if (_config.addAreaEnvelope) { - writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, area.envelope()); - } - if (_config.addAreaOrientedBoundingBox) { - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, - area.orientedBoundingBox()); - } + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, area.convexHull()); + writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, area.envelope()); + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, area.orientedBoundingBox()); - if (_config.addSortMetadata) { - std::ostringstream tmp; - // Increase default precision as areas in regbez freiburg have a 0 area - // otherwise. - tmp << std::fixed << std::setprecision(AREA_PRECISION) << area.geomArea(); - _writer->writeTriple( - subj, _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "area"), - _writer->generateLiteralUnsafe(tmp.str(), "^^" + IRI__XSD_DOUBLE)); - } - - if (_config.addAreaEnvelopeRatio) { - std::ostringstream tmp; - tmp << std::fixed << (area.geomArea() / area.envelopeArea()); - _writer->writeTriple( - subj, - _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "area_envelope_ratio"), - _writer->generateLiteralUnsafe(tmp.str(), "^^" + IRI__XSD_DOUBLE)); - } + std::ostringstream tmp; + // Increase default precision as areas in regbez freiburg have a 0 area + // otherwise. + tmp << std::fixed << std::setprecision(AREA_PRECISION) << area.geomArea(); + _writer->writeTriple( + subj, _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "area"), + _writer->generateLiteralUnsafe(tmp.str(), "^^" + IRI__XSD_DOUBLE)); } // ____________________________________________________________________________ @@ -146,8 +128,8 @@ void osm2rdf::osm::FactHandler::node(const osm2rdf::osm::Node& node) { if (!_config.hasGeometryAsWkt) { const std::string& geomObj = _writer->generateIRI( - NAMESPACE__OSM2RDF_GEOM, "node_" + DATASET_ID[_config.sourceDataset] + - "_" + std::to_string(node.id())); + NAMESPACE__OSM2RDF_GEOM, DATASET_ID[_config.sourceDataset] + "_node_" + + std::to_string(node.id())); _writer->writeTriple(subj, IRI__GEOSPARQL__HAS_GEOMETRY, geomObj); writeBoostGeometry(geomObj, IRI__GEOSPARQL__AS_WKT, node.geom()); @@ -155,16 +137,9 @@ void osm2rdf::osm::FactHandler::node(const osm2rdf::osm::Node& node) { writeBoostGeometry(subj, IRI__GEOSPARQL__HAS_GEOMETRY, node.geom()); } - if (_config.addNodeConvexHull) { - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, node.convexHull()); - } - if (_config.addNodeEnvelope) { - writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, node.envelope()); - } - if (_config.addNodeOrientedBoundingBox) { - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, - node.orientedBoundingBox()); - } + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, node.convexHull()); + writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, node.envelope()); + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, node.orientedBoundingBox()); } // ____________________________________________________________________________ @@ -182,51 +157,47 @@ void osm2rdf::osm::FactHandler::relation( size_t inRelPos = 0; for (const auto& member : relation.members()) { const std::string& role = member.role(); - if (_config.addRelationBorderMembers || - (role != "outer" && role != "inner")) { - const std::string& blankNode = _writer->generateBlankNode(); - _writer->writeTriple( - subj, _writer->generateIRIUnsafe(NAMESPACE__OSM_RELATION, "member"), - blankNode); - - std::string type; - switch (member.type()) { - case osm2rdf::osm::RelationMemberType::NODE: - type = NODE_NAMESPACE[_config.sourceDataset]; - break; - case osm2rdf::osm::RelationMemberType::RELATION: - type = RELATION_NAMESPACE[_config.sourceDataset]; - break; - case osm2rdf::osm::RelationMemberType::WAY: - type = WAY_NAMESPACE[_config.sourceDataset]; - break; - default: - type = DATASET_NAMESPACE[_config.sourceDataset]; - } - - _writer->writeTriple(blankNode, - _writer->generateIRIUnsafe( - DATASET_NAMESPACE[_config.sourceDataset], "id"), - _writer->generateIRI(type, member.id())); - _writer->writeTriple( - blankNode, - _writer->generateIRIUnsafe(DATASET_NAMESPACE[_config.sourceDataset], - "role"), - _writer->generateLiteral(role, "")); - _writer->writeTriple( - blankNode, IRI__OSM2RDF__POS, - _writer->generateLiteralUnsafe(std::to_string(inRelPos++), - "^^" + IRI__XSD_INTEGER)); + const std::string& blankNode = _writer->generateBlankNode(); + _writer->writeTriple( + subj, _writer->generateIRIUnsafe(NAMESPACE__OSM_RELATION, "member"), + blankNode); + + std::string type; + switch (member.type()) { + case osm2rdf::osm::RelationMemberType::NODE: + type = NODE_NAMESPACE[_config.sourceDataset]; + break; + case osm2rdf::osm::RelationMemberType::RELATION: + type = RELATION_NAMESPACE[_config.sourceDataset]; + break; + case osm2rdf::osm::RelationMemberType::WAY: + type = WAY_NAMESPACE[_config.sourceDataset]; + break; + default: + type = DATASET_NAMESPACE[_config.sourceDataset]; } + + _writer->writeTriple(blankNode, + _writer->generateIRIUnsafe( + DATASET_NAMESPACE[_config.sourceDataset], "id"), + _writer->generateIRI(type, member.id())); + _writer->writeTriple(blankNode, + _writer->generateIRIUnsafe( + DATASET_NAMESPACE[_config.sourceDataset], "role"), + _writer->generateLiteral(role, "")); + _writer->writeTriple( + blankNode, IRI__OSM2RDF__POS, + _writer->generateLiteralUnsafe(std::to_string(inRelPos++), + "^^" + IRI__XSD_INTEGER)); } #if BOOST_VERSION >= 107800 if (relation.hasGeometry() && !relation.isArea()) { if (!_config.hasGeometryAsWkt) { - const std::string& geomObj = - _writer->generateIRI(NAMESPACE__OSM2RDF_GEOM, - "relation_" + DATASET_ID[_config.sourceDataset] + - "_" + std::to_string(relation.id())); + const std::string& geomObj = _writer->generateIRI( + NAMESPACE__OSM2RDF_GEOM, DATASET_ID[_config.sourceDataset] + + "_relation_" + + std::to_string(relation.id())); _writer->writeTriple(subj, IRI__GEOSPARQL__HAS_GEOMETRY, geomObj); writeBoostGeometry(geomObj, IRI__GEOSPARQL__AS_WKT, relation.geom()); @@ -234,18 +205,12 @@ void osm2rdf::osm::FactHandler::relation( writeBoostGeometry(subj, IRI__GEOSPARQL__HAS_GEOMETRY, relation.geom()); } - if (_config.addRelationConvexHull) { - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, - relation.convexHull()); - } - if (_config.addRelationEnvelope) { - writeBox(subj, osm2rdf::ttl::constants::IRI__OSM2RDF_GEOM__ENVELOPE, - relation.envelope()); - } - if (_config.addRelationOrientedBoundingBox) { - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, - relation.orientedBoundingBox()); - } + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, + relation.convexHull()); + writeBox(subj, osm2rdf::ttl::constants::IRI__OSM2RDF_GEOM__ENVELOPE, + relation.envelope()); + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, + relation.orientedBoundingBox()); _writer->writeTriple( subj, _writer->generateIRI(NAMESPACE__OSM2RDF, "completeGeometry"), @@ -293,8 +258,8 @@ void osm2rdf::osm::FactHandler::way(const osm2rdf::osm::Way& way) { if (!_config.hasGeometryAsWkt) { const std::string& geomObj = _writer->generateIRI(NAMESPACE__OSM2RDF_GEOM, - "node_" + DATASET_ID[_config.sourceDataset] + - "_" + std::to_string(node.id())); + DATASET_ID[_config.sourceDataset] + + "_node_" + std::to_string(node.id())); _writer->writeTriple(subj, IRI__GEOSPARQL__HAS_GEOMETRY, geomObj); writeBoostGeometry(geomObj, IRI__GEOSPARQL__AS_WKT, node.geom()); @@ -346,16 +311,9 @@ void osm2rdf::osm::FactHandler::way(const osm2rdf::osm::Way& way) { } } - if (_config.addWayConvexHull) { - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, way.convexHull()); - } - if (_config.addWayEnvelope) { - writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, way.envelope()); - } - - if (_config.addWayOrientedBoundingBox) { - writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, way.orientedBoundingBox()); - } + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__CONVEX_HULL, way.convexHull()); + writeBox(subj, IRI__OSM2RDF_GEOM__ENVELOPE, way.envelope()); + writeBoostGeometry(subj, IRI__OSM2RDF_GEOM__OBB, way.orientedBoundingBox()); if (_config.addWayMetadata) { _writer->writeTriple(subj, IRI__OSMWAY_IS_CLOSED, @@ -370,13 +328,11 @@ void osm2rdf::osm::FactHandler::way(const osm2rdf::osm::Way& way) { "^^" + IRI__XSD_INTEGER)); } - if (_config.addSortMetadata) { - _writer->writeTriple( - subj, _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "length"), - _writer->generateLiteral( - std::to_string(boost::geometry::length(way.geom())), - "^^" + osm2rdf::ttl::constants::IRI__XSD_DOUBLE)); - } + _writer->writeTriple(subj, + _writer->generateIRIUnsafe(NAMESPACE__OSM2RDF, "length"), + _writer->generateLiteral( + std::to_string(boost::geometry::length(way.geom())), + "^^" + osm2rdf::ttl::constants::IRI__XSD_DOUBLE)); } // ____________________________________________________________________________ @@ -575,7 +531,7 @@ void osm2rdf::osm::FactHandler::writeSecondsAsISO(const std::string& subj, const std::string& pred, const std::time_t& time) { std::stringstream date; - date << std::put_time(std::localtime(&time), "%Y-%m-%dT%X"); + date << std::put_time(std::gmtime(&time), "%Y-%m-%dT%X"); _writer->writeTriple( subj, pred, _writer->generateLiteralUnsafe(date.str(), "^^" + IRI__XSD_DATE_TIME)); From 0ab3add8620b42e6b460460df74b308bbdd2c381 Mon Sep 17 00:00:00 2001 From: Axel Lehmann Date: Fri, 26 Jan 2024 17:56:40 +0100 Subject: [PATCH 6/9] Implement parsing of "Exact dates" as described at https://wiki.openstreetmap.org/wiki/Key:start_date#Exact_dates --- include/osm2rdf/osm/FactHandler.h | 23 + src/osm/FactHandler.cpp | 76 ++-- src/ttl/Writer.cpp | 2 +- tests/osm/FactHandler.cpp | 690 ++++++++++++++++++++++++++++++ 4 files changed, 766 insertions(+), 25 deletions(-) diff --git a/include/osm2rdf/osm/FactHandler.h b/include/osm2rdf/osm/FactHandler.h index 631a31f5..40e0932d 100644 --- a/include/osm2rdf/osm/FactHandler.h +++ b/include/osm2rdf/osm/FactHandler.h @@ -28,6 +28,14 @@ namespace osm2rdf::osm { +enum DateTimeType { + invalid = 0, + date_yyyy = 1, + date_yyyy_mm = 2, + date_yyyy_mm_dd = 3, + date_time = 4 +}; + template class FactHandler { public: @@ -75,6 +83,21 @@ class FactHandler { FRIEND_TEST(OSM_FactHandler, writeTagListWikipediaWithLang); FRIEND_TEST(OSM_FactHandler, writeTagListWikipediaWithoutLang); FRIEND_TEST(OSM_FactHandler, writeTagListSkipWikiLinks); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateInvalid); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateInvalid2); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateInvalid3); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYear1); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYear2); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYear3); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYear4); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYearMonth1); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYearMonth2); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYearMonth3); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYearMonth4); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYearMonthDay1); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYearMonthDay2); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYearMonthDay3); + FRIEND_TEST(OSM_FactHandler, writeTagListStartDateYearMonthDay4); void writeSecondsAsISO(const std::string& s, const std::string& p, const std::time_t& t); diff --git a/src/osm/FactHandler.cpp b/src/osm/FactHandler.cpp index b0df7291..71ebc020 100644 --- a/src/osm/FactHandler.cpp +++ b/src/osm/FactHandler.cpp @@ -492,31 +492,59 @@ void osm2rdf::osm::FactHandler::writeTagList( } } if (key == "start_date" || key == "end_date") { - const auto dashCount = std::count(value.begin(), value.end(), '-'); - switch (dashCount) { - case 2: - _writer->writeTriple( - subj, - _writer->generateIRIUnsafe( - DATASET_NAMESPACE[_config.sourceDataset], key), - _writer->generateLiteralUnsafe(value, "^^" + IRI__XSD_DATE)); - break; - case 1: - _writer->writeTriple( - subj, - _writer->generateIRIUnsafe( - DATASET_NAMESPACE[_config.sourceDataset], key), - _writer->generateLiteralUnsafe(value, - "^^" + IRI__XSD_YEAR_MONTH)); - break; - case 0: - _writer->writeTriple( - subj, - _writer->generateIRIUnsafe( - DATASET_NAMESPACE[_config.sourceDataset], key), - _writer->generateLiteralUnsafe(value, "^^" + IRI__XSD_YEAR)); - break; + // Abort if non digit and not - + if(std::any_of(value.cbegin(), value.cend(), [](char c) { return isdigit(c) == 0 && c != '-'; })) { + continue; } + + // Skip if empty + if (value.empty()) { + continue; + } + // Skip if only '-' + size_t minusCount = std::count(value.begin(), value.end(), '-'); + if (minusCount == value.size()) { + continue; + } + + std::vector parts; + parts.reserve(minusCount + 1); + size_t last = 0; + size_t next; + for (size_t i = 0; i < (minusCount + 1); ++i) { + next = value.find('-', last); + parts.emplace_back(value.substr(last, next - last)); + last = next + 1; + } + + auto resultType = 0; + std::string newValue; + newValue.reserve(value.size()); + std::ostringstream tmp; + tmp << std::setfill('0'); + for (size_t i = 0; i < (minusCount + 1); ++i) { + if (i == 0 && parts[i].empty()) { + newValue += '-'; + continue; + } + tmp << std::setw(resultType == 0 ? 4 : 2) << std::dec + << std::atoi(parts[i].c_str()); + newValue += tmp.str().substr(0, resultType == 0 ? 4 : 2) + '-'; + tmp.seekp(0); + resultType++; + } + if (resultType > 3) { + // Invalid length + continue; + } + std::string typeString[3] = {IRI__XSD_YEAR, IRI__XSD_YEAR_MONTH, + IRI__XSD_DATE}; + _writer->writeTriple(subj, + _writer->generateIRIUnsafe( + DATASET_NAMESPACE[_config.sourceDataset], key), + _writer->generateLiteralUnsafe( + newValue.substr(0, newValue.size() - 1), + "^^" + typeString[resultType - 1])); } } _writer->writeTriple( diff --git a/src/ttl/Writer.cpp b/src/ttl/Writer.cpp index 145609d5..ed1b624f 100644 --- a/src/ttl/Writer.cpp +++ b/src/ttl/Writer.cpp @@ -146,7 +146,7 @@ osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, osm2rdf::ttl::constants::IRI__XSD_YEAR = generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "gYear"); osm2rdf::ttl::constants::IRI__XSD_YEAR_MONTH = - generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "gYearMont"); + generateIRI(osm2rdf::ttl::constants::NAMESPACE__XML_SCHEMA, "gYearMonth"); osm2rdf::ttl::constants::LITERAL__NO = generateLiteral("no", ""); osm2rdf::ttl::constants::LITERAL__YES = generateLiteral("yes", ""); diff --git a/tests/osm/FactHandler.cpp b/tests/osm/FactHandler.cpp index 544f00b2..b27daf77 100644 --- a/tests/osm/FactHandler.cpp +++ b/tests/osm/FactHandler.cpp @@ -1811,4 +1811,694 @@ TEST(OSM_FactHandler, writeTagListSkipWikiLinks) { // Cleanup std::cout.rdbuf(sbuf); } + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateInvalid) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "lorem"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::Not(::testing::HasSubstr("ear"))); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateInvalid2) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "-lo-r-em-"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::Not(::testing::HasSubstr("ear"))); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateInvalid3) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "-1111-22-33-44"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::Not(::testing::HasSubstr("ear"))); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYear1) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "11"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + "0011", "^^" + osm2rdf::ttl::constants::IRI__XSD_YEAR); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYear2) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "-11"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + "-0011", "^^" + osm2rdf::ttl::constants::IRI__XSD_YEAR); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYear3) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "1111"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + tagValue, "^^" + osm2rdf::ttl::constants::IRI__XSD_YEAR); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYear4) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "-1111"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + tagValue, "^^" + osm2rdf::ttl::constants::IRI__XSD_YEAR); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYearMonth1) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "11-1"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + "0011-01", "^^" + osm2rdf::ttl::constants::IRI__XSD_YEAR_MONTH); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYearMonth2) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "-11-1"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + "-0011-01", "^^" + osm2rdf::ttl::constants::IRI__XSD_YEAR_MONTH); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYearMonth3) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "1111-11"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + tagValue, "^^" + osm2rdf::ttl::constants::IRI__XSD_YEAR_MONTH); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYearMonth4) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "-1111-11"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + tagValue, "^^" + osm2rdf::ttl::constants::IRI__XSD_YEAR_MONTH); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYearMonthDay1) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "11-1-1"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + "0011-01-01", "^^" + osm2rdf::ttl::constants::IRI__XSD_DATE); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYearMonthDay2) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "-11-1-1"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + "-0011-01-01", "^^" + osm2rdf::ttl::constants::IRI__XSD_DATE); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYearMonthDay3) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "1111-11-11"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + tagValue, "^^" + osm2rdf::ttl::constants::IRI__XSD_DATE); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} + +// ____________________________________________________________________________ +TEST(OSM_FactHandler, writeTagListStartDateYearMonthDay4) { + // Capture std::cout + std::stringstream buffer; + std::streambuf* sbuf = std::cout.rdbuf(); + std::cout.rdbuf(buffer.rdbuf()); + + osm2rdf::config::Config config; + config.output = ""; + config.hasGeometryAsWkt = true; + config.outputCompress = false; + config.mergeOutput = osm2rdf::util::OutputMergeMode::NONE; + + osm2rdf::util::Output output{config, config.output}; + output.open(); + osm2rdf::ttl::Writer writer{config, &output}; + osm2rdf::osm::FactHandler dh{config, &writer}; + + const std::string tagKey = "start_date"; + const std::string tagValue = "-1111-11-11"; + + const std::string subject = "subject"; + const std::string predicate1 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_TAG, tagKey); + const std::string object1 = writer.generateLiteral(tagValue, ""); + const std::string predicate2 = + writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM, tagKey); + const std::string object2 = writer.generateLiteral( + tagValue, "^^" + osm2rdf::ttl::constants::IRI__XSD_DATE); + + osm2rdf::osm::TagList tagList; + tagList[tagKey] = tagValue; + + dh.writeTagList(subject, tagList); + output.flush(); + output.close(); + + const std::string printedData = buffer.str(); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate1 + + " " + object1 + " .\n")); + ASSERT_THAT(printedData, ::testing::HasSubstr(subject + " " + predicate2 + + " " + object2 + " .\n")); + + // Cleanup + std::cout.rdbuf(sbuf); +} } // namespace osm2rdf::osm From 640b4cf671cd874321ad72a14f5401468d07f1d4 Mon Sep 17 00:00:00 2001 From: Axel Lehmann Date: Mon, 29 Jan 2024 09:33:20 +0100 Subject: [PATCH 7/9] Add missing changes and try to fix history --- src/osm/GeometryHandler.cpp | 1 - tests/issues/Issue24.cpp | 24 +++++++++++++++--------- tests/osm/FactHandler.cpp | 11 ++++++++++- tests/ttl/Writer.cpp | 10 ++++++---- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/osm/GeometryHandler.cpp b/src/osm/GeometryHandler.cpp index be8d89ad..8d1b0793 100644 --- a/src/osm/GeometryHandler.cpp +++ b/src/osm/GeometryHandler.cpp @@ -578,7 +578,6 @@ void GeometryHandler::prepareDAG() { #pragma omp parallel for shared( \ tmpDirectedAreaGraph, std::cout, std::cerr, \ osm2rdf::ttl::constants::IRI__GEOSPARQL__HAS_GEOMETRY, entryCount, \ - APPROX_CONTAINS_SLACK, \ progressBar) reduction(+ : stats) default(none) schedule(dynamic) for (uint32_t i = 0; i < _spatialStorageArea.size(); i++) { diff --git a/tests/issues/Issue24.cpp b/tests/issues/Issue24.cpp index c47a9c72..c0a6466c 100644 --- a/tests/issues/Issue24.cpp +++ b/tests/issues/Issue24.cpp @@ -115,8 +115,8 @@ TEST(Issue24, areaFromWayHasGeometryAsGeoSPARQL) { output.close(); ASSERT_EQ( - "osmway:21 geo:hasGeometry osm2rdfgeom:wayarea_21 .\n" - "osm2rdfgeom:wayarea_21 geo:asWKT \"MULTIPOLYGON(((48.0 7.5,48.0 " + "osmway:21 geo:hasGeometry osm2rdfgeom:osm_wayarea_21 .\n" + "osm2rdfgeom:osm_wayarea_21 geo:asWKT \"MULTIPOLYGON(((48.0 7.5,48.0 " "7.6,48.1 7.6,48.1 7.5,48.0 7.5)))\"^^geo:wktLiteral .\n" "osmway:21 osm2rdfgeom:convex_hull \"POLYGON(())\"^^geo:wktLiteral .\n" "osmway:21 osm2rdfgeom:envelope \"POLYGON((48.0 7.5,48.0 7.6,48.1 " @@ -223,8 +223,8 @@ TEST(Issue24, areaFromRelationHasGeometryAsGeoSPARQL) { output.close(); ASSERT_EQ( - "osmrel:10 geo:hasGeometry osm2rdfgeom:relarea_10 .\n" - "osm2rdfgeom:relarea_10 geo:asWKT \"MULTIPOLYGON(((48.0 7.5,48.0 " + "osmrel:10 geo:hasGeometry osm2rdfgeom:osm_relarea_10 .\n" + "osm2rdfgeom:osm_relarea_10 geo:asWKT \"MULTIPOLYGON(((48.0 7.5,48.0 " "7.6,48.1 7.6,48.1 7.5,48.0 7.5)))\"^^geo:wktLiteral .\n" "osmrel:10 osm2rdfgeom:convex_hull \"POLYGON((48.0 7.5,48.0 7.6,48.1 7.6,48.1 7.5,48.0 7.5))\"^^geo:wktLiteral .\n" "osmrel:10 osm2rdfgeom:envelope \"POLYGON((48.0 7.5,48.0 7.6,48.1 " @@ -273,8 +273,9 @@ TEST(Issue24, nodeHasGeometryAsWkt) { ASSERT_EQ( "osmnode:42 rdf:type osm:node .\n" - "osmnode:42 geo:hasGeometry \"POINT(7.5 48.0)\"^^geo:wktLiteral .\n" + "osmnode:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmnode:42 osm2rdf:facts \"0\"^^xsd:integer .\n" + "osmnode:42 geo:hasGeometry \"POINT(7.5 48.0)\"^^geo:wktLiteral .\n" "osmnode:42 osm2rdfgeom:convex_hull \"POLYGON((7.5 48.0,7.5 48.0,7.5 " "48.0,7.5 48.0,7.5 48.0))\"^^geo:wktLiteral .\n" "osmnode:42 osm2rdfgeom:envelope \"POLYGON((7.5 48.0,7.5 48.0,7.5 " @@ -323,9 +324,10 @@ TEST(Issue24, nodeHasGeometryAsGeoSPARQL) { ASSERT_EQ( "osmnode:42 rdf:type osm:node .\n" - "osmnode:42 geo:hasGeometry osm2rdfgeom:node_42 .\n" - "osm2rdfgeom:node_42 geo:asWKT \"POINT(7.5 48.0)\"^^geo:wktLiteral .\n" + "osmnode:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmnode:42 osm2rdf:facts \"0\"^^xsd:integer .\n" + "osmnode:42 geo:hasGeometry osm2rdfgeom:osm_node_42 .\n" + "osm2rdfgeom:osm_node_42 geo:asWKT \"POINT(7.5 48.0)\"^^geo:wktLiteral .\n" "osmnode:42 osm2rdfgeom:convex_hull \"POLYGON((7.5 48.0,7.5 48.0,7.5 " "48.0,7.5 48.0,7.5 48.0))\"^^geo:wktLiteral .\n" "osmnode:42 osm2rdfgeom:envelope \"POLYGON((7.5 48.0,7.5 48.0,7.5 " @@ -411,6 +413,7 @@ TEST(Issue24, relationWithGeometryHasGeometryAsWkt) { ASSERT_EQ( "osmrel:42 rdf:type osm:relation .\n" + "osmrel:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmrel:42 osm2rdf:facts \"0\"^^xsd:integer .\n" "osmrel:42 osmrel:member _:0_0 .\n" "_:0_0 osm:id osmnode:23 .\n" @@ -507,6 +510,7 @@ TEST(Issue24, relationWithGeometryHasGeometryAsGeoSPARQL) { ASSERT_EQ( "osmrel:42 rdf:type osm:relation .\n" + "osmrel:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmrel:42 osm2rdf:facts \"0\"^^xsd:integer .\n" "osmrel:42 osmrel:member _:0_0 .\n" "_:0_0 osm:id osmnode:23 .\n" @@ -516,8 +520,8 @@ TEST(Issue24, relationWithGeometryHasGeometryAsGeoSPARQL) { "_:0_1 osm:id osmway:55 .\n" "_:0_1 osm:role \"outer\" .\n" "_:0_1 osm2rdf:pos \"1\"^^xsd:integer .\n" - "osmrel:42 geo:hasGeometry osm2rdfgeom:relation_42 .\n" - "osm2rdfgeom:relation_42 geo:asWKT \"GEOMETRYCOLLECTION(POINT(7.5 " + "osmrel:42 geo:hasGeometry osm2rdfgeom:osm_relation_42 .\n" + "osm2rdfgeom:osm_relation_42 geo:asWKT \"GEOMETRYCOLLECTION(POINT(7.5 " "48.0),LINESTRING(7.5 48.0,7.6 48.0))\"^^geo:wktLiteral .\n" "osmrel:42 osm2rdfgeom:convex_hull \"POLYGON((7.5 48.0,7.6 48.0,7.5 " "48.0,7.5 48.0))\"^^geo:wktLiteral .\n" @@ -571,6 +575,7 @@ TEST(Issue24, wayHasGeometryAsWkt) { ASSERT_EQ( "osmway:42 rdf:type osm:way .\n" + "osmway:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmway:42 osm2rdf:facts \"0\"^^xsd:integer .\n" "osmway:42 geo:hasGeometry \"LINESTRING(48.0 7.5,48.1 " "7.6)\"^^geo:wktLiteral .\n" @@ -625,6 +630,7 @@ TEST(Issue24, wayHasGeometryAsGeoSPARQL) { ASSERT_EQ( "osmway:42 rdf:type osm:way .\n" + "osmway:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmway:42 osm2rdf:facts \"0\"^^xsd:integer .\n" "osmway:42 geo:hasGeometry osm2rdf:way_42 .\n" "osm2rdf:way_42 geo:asWKT \"LINESTRING(48.0 7.5,48.1 " diff --git a/tests/osm/FactHandler.cpp b/tests/osm/FactHandler.cpp index b27daf77..5c577e16 100644 --- a/tests/osm/FactHandler.cpp +++ b/tests/osm/FactHandler.cpp @@ -196,9 +196,10 @@ TEST(OSM_FactHandler, node) { ASSERT_EQ( "osmnode:42 rdf:type osm:node .\n" - "osmnode:42 geo:hasGeometry \"POINT(7.5 48.0)\"^^geo:wktLiteral .\n" + "osmnode:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmnode:42 osmkey:city \"Freiburg\" .\n" "osmnode:42 osm2rdf:facts \"1\"^^xsd:integer .\n" + "osmnode:42 geo:hasGeometry \"POINT(7.5 48.0)\"^^geo:wktLiteral .\n" "osmnode:42 osm2rdfgeom:convex_hull \"POLYGON((7.5 48.0,7.5 48.0,7.5 " "48.0,7.5 48.0,7.5 48.0))\"^^geo:wktLiteral .\n" "osmnode:42 osm2rdfgeom:envelope \"POLYGON((7.5 48.0,7.5 48.0,7.5 " @@ -251,6 +252,7 @@ TEST(OSM_FactHandler, relation) { ASSERT_EQ( "osmrel:42 rdf:type osm:relation .\n" + "osmrel:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmrel:42 osmkey:city \"Freiburg\" .\n" "osmrel:42 osm2rdf:facts \"1\"^^xsd:integer .\n" "osmrel:42 osmrel:member _:0_0 .\n" @@ -350,6 +352,7 @@ TEST(OSM_FactHandler, relationWithGeometry) { ASSERT_EQ( "osmrel:42 rdf:type osm:relation .\n" + "osmrel:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmrel:42 osmkey:city \"Freiburg\" .\n" "osmrel:42 osm2rdf:facts \"1\"^^xsd:integer .\n" "osmrel:42 osmrel:member _:0_0 .\n" @@ -415,6 +418,7 @@ TEST(OSM_FactHandler, way) { ASSERT_EQ( "osmway:42 rdf:type osm:way .\n" + "osmway:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmway:42 osmkey:city \"Freiburg\" .\n" "osmway:42 osm2rdf:facts \"1\"^^xsd:integer .\n" "osmway:42 geo:hasGeometry \"LINESTRING(48.0 7.5,48.1 " @@ -473,6 +477,7 @@ TEST(OSM_FactHandler, wayAddWayNodeGeoemtry) { ASSERT_EQ( "osmway:42 rdf:type osm:way .\n" + "osmway:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmway:42 osmkey:city \"Freiburg\" .\n" "osmway:42 osm2rdf:facts \"1\"^^xsd:integer .\n" "osmway:42 osmway:node _:0_0 .\n" @@ -540,6 +545,7 @@ TEST(OSM_FactHandler, wayAddWayNodeOrder) { ASSERT_EQ( "osmway:42 rdf:type osm:way .\n" + "osmway:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmway:42 osmkey:city \"Freiburg\" .\n" "osmway:42 osm2rdf:facts \"1\"^^xsd:integer .\n" "osmway:42 osmway:node _:0_0 .\n" @@ -604,6 +610,7 @@ TEST(OSM_FactHandler, wayAddWayNodeSpatialMetadataShortWay) { ASSERT_EQ( "osmway:42 rdf:type osm:way .\n" + "osmway:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmway:42 osmkey:city \"Freiburg\" .\n" "osmway:42 osm2rdf:facts \"1\"^^xsd:integer .\n" "osmway:42 osmway:node _:0_0 .\n" @@ -673,6 +680,7 @@ TEST(OSM_FactHandler, wayAddWayNodeSpatialMetadataLongerWay) { ASSERT_EQ( "osmway:42 rdf:type osm:way .\n" + "osmway:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmway:42 osmkey:city \"Freiburg\" .\n" "osmway:42 osm2rdf:facts \"1\"^^xsd:integer .\n" "osmway:42 osmway:node _:0_0 .\n" @@ -748,6 +756,7 @@ TEST(OSM_FactHandler, wayAddWayMetaData) { ASSERT_EQ( "osmway:42 rdf:type osm:way .\n" + "osmway:42 osmmeta:timestamp \"1970-01-01T00:00:00\"^^xsd:dateTime .\n" "osmway:42 osmkey:city \"Freiburg\" .\n" "osmway:42 osm2rdf:facts \"1\"^^xsd:integer .\n" "osmway:42 geo:hasGeometry \"LINESTRING(48.0 7.5,48.1 " diff --git a/tests/ttl/Writer.cpp b/tests/ttl/Writer.cpp index 1518a1bc..0d94cba4 100644 --- a/tests/ttl/Writer.cpp +++ b/tests/ttl/Writer.cpp @@ -674,6 +674,7 @@ TEST(TTL_WriterTTL, writeStatisticJson) { // Setup temp dir and stats file std::filesystem::path tmpDir = config.getTempPath("TEST_TTL_WriterTTL", "writeStatisticJson"); + std::filesystem::remove_all(tmpDir); ASSERT_FALSE(std::filesystem::exists(tmpDir)); std::filesystem::create_directories(tmpDir); ASSERT_TRUE(std::filesystem::exists(tmpDir)); @@ -706,8 +707,8 @@ TEST(TTL_WriterTTL, writeStatisticJson) { statsBuffer << statsIFStream.rdbuf(); ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"blankNodes\": 3")); - ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"header\": 12")); - ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"lines\": 17")); + ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"header\": 16")); + ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"lines\": 21")); ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"triples\": 5")); // Cleanup @@ -736,6 +737,7 @@ TEST(TTL_WriterQLEVER, writeStatisticJson) { // Setup temp dir and stats file std::filesystem::path tmpDir = config.getTempPath("TEST_TTL_WriterQLEVER", "writeStatisticJson"); + std::filesystem::remove_all(tmpDir); ASSERT_FALSE(std::filesystem::exists(tmpDir)); std::filesystem::create_directories(tmpDir); ASSERT_TRUE(std::filesystem::exists(tmpDir)); @@ -768,8 +770,8 @@ TEST(TTL_WriterQLEVER, writeStatisticJson) { statsBuffer << statsIFStream.rdbuf(); ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"blankNodes\": 3")); - ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"header\": 12")); - ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"lines\": 17")); + ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"header\": 16")); + ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"lines\": 21")); ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"triples\": 5")); // Cleanup From b12afb51caedb7c1dd3cc8954c7c97c8689209c6 Mon Sep 17 00:00:00 2001 From: Axel Lehmann Date: Mon, 29 Jan 2024 09:56:40 +0100 Subject: [PATCH 8/9] Simplify x_date parsing a bit --- src/osm/FactHandler.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/osm/FactHandler.cpp b/src/osm/FactHandler.cpp index 71ebc020..febae0bf 100644 --- a/src/osm/FactHandler.cpp +++ b/src/osm/FactHandler.cpp @@ -507,31 +507,27 @@ void osm2rdf::osm::FactHandler::writeTagList( continue; } - std::vector parts; - parts.reserve(minusCount + 1); - size_t last = 0; - size_t next; - for (size_t i = 0; i < (minusCount + 1); ++i) { - next = value.find('-', last); - parts.emplace_back(value.substr(last, next - last)); - last = next + 1; - } - - auto resultType = 0; std::string newValue; newValue.reserve(value.size()); std::ostringstream tmp; tmp << std::setfill('0'); + + size_t last = 0; + size_t next; + auto resultType = 0; for (size_t i = 0; i < (minusCount + 1); ++i) { - if (i == 0 && parts[i].empty()) { + next = value.find('-', last); + if (i == 0 && next == 0) { newValue += '-'; + last = next + 1; continue; } tmp << std::setw(resultType == 0 ? 4 : 2) << std::dec - << std::atoi(parts[i].c_str()); + << std::atoi(value.substr(last, next - last).c_str()); newValue += tmp.str().substr(0, resultType == 0 ? 4 : 2) + '-'; tmp.seekp(0); resultType++; + last = next + 1; } if (resultType > 3) { // Invalid length From 9087a0fd4009ef96e72a8ed0f83492c2f68a5bed Mon Sep 17 00:00:00 2001 From: Axel Lehmann Date: Mon, 29 Jan 2024 12:07:14 +0100 Subject: [PATCH 9/9] * Add ohm Header * Use dataset in GeometryHandler.cpp * Remove obsolete IRI__OSM2RDF_CONTAINS and IRI__OSM2RDF_INTERSECTS --- include/osm2rdf/ttl/Constants.h | 3 - src/osm/GeometryHandler.cpp | 161 +++++++++++++++----------------- src/ttl/Writer.cpp | 2 + tests/ttl/Writer.cpp | 8 +- 4 files changed, 82 insertions(+), 92 deletions(-) diff --git a/include/osm2rdf/ttl/Constants.h b/include/osm2rdf/ttl/Constants.h index 122d05c6..46d95899 100644 --- a/include/osm2rdf/ttl/Constants.h +++ b/include/osm2rdf/ttl/Constants.h @@ -55,9 +55,6 @@ inline std::string IRI__OPENGIS_INTERSECTS; inline std::string IRI__OSM2RDF_INTERSECTS_NON_AREA; inline std::string IRI__OSM2RDF_INTERSECTS_AREA; -inline std::string IRI__OSM2RDF_CONTAINS; -inline std::string IRI__OSM2RDF_INTERSECTS; - inline std::string IRI__OSM2RDF_GEOM__CONVEX_HULL; inline std::string IRI__OSM2RDF_GEOM__ENVELOPE; inline std::string IRI__OSM2RDF_GEOM__OBB; diff --git a/src/osm/GeometryHandler.cpp b/src/osm/GeometryHandler.cpp index 8d1b0793..37524bf2 100644 --- a/src/osm/GeometryHandler.cpp +++ b/src/osm/GeometryHandler.cpp @@ -60,8 +60,6 @@ using osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_AREA; using osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA; using osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_AREA; using osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA; -using osm2rdf::ttl::constants::NAMESPACE__OSM_NODE; -using osm2rdf::ttl::constants::NAMESPACE__OSM_WAY; using osm2rdf::util::currentTimeFormatted; using osm2rdf::util::DirectedGraph; @@ -755,19 +753,15 @@ void GeometryHandler::dumpNamedAreaRelations() { std::vector::entry_t> vertices = _directedAreaGraph.getVertices(); -#pragma omp parallel for shared( \ - vertices, osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, \ - osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION, \ - osm2rdf::ttl::constants::IRI__OPENGIS_CONTAINS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_AREA, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA, \ - osm2rdf::ttl::constants::IRI__OPENGIS_INTERSECTS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_AREA, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS, progressBar, \ - entryCount) reduction(+ : intersectStats) default(none) \ - schedule(static) +#pragma omp parallel for shared( \ + vertices, osm2rdf::ttl::constants::IRI__OPENGIS_CONTAINS, \ + osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_AREA, \ + osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA, \ + osm2rdf::ttl::constants::IRI__OPENGIS_INTERSECTS, \ + osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_AREA, \ + osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA, \ + progressBar, entryCount) \ + reduction(+ : intersectStats) default(none) schedule(static) for (size_t i = 0; i < vertices.size(); i++) { const auto id = vertices[i]; const auto& entry = _spatialStorageArea[id]; @@ -924,10 +918,10 @@ void GeometryHandler::dumpUnnamedAreaRelations() { << std::endl; } else if (_numUnnamedAreas == 0) { std::cerr << std::endl; - std::cerr - << currentTimeFormatted() << " " - << "Skipping contains relation for unnamed areas ... no unnamed area" - << std::endl; + std::cerr << currentTimeFormatted() << " " + << "Skipping contains relation for unnamed areas ... " + "no unnamed area" + << std::endl; } else { std::cerr << std::endl; std::cerr << currentTimeFormatted() << " " @@ -944,17 +938,13 @@ void GeometryHandler::dumpUnnamedAreaRelations() { GeomRelationStats intersectStats, containsStats; size_t entryCount = 0; progressBar.update(entryCount); -#pragma omp parallel for shared( \ - osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, \ - osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION, \ - osm2rdf::ttl::constants::IRI__OPENGIS_INTERSECTS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA, \ - osm2rdf::ttl::constants::IRI__OPENGIS_CONTAINS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS, progressBar, \ - entryCount, ia) \ - reduction(+ : intersectStats, containsStats) default(none) \ +#pragma omp parallel for shared( \ + osm2rdf::ttl::constants::IRI__OPENGIS_INTERSECTS, \ + osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA, \ + osm2rdf::ttl::constants::IRI__OPENGIS_CONTAINS, \ + osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA, \ + progressBar, entryCount, ia) \ + reduction(+ : intersectStats, containsStats) default(none) \ schedule(dynamic) for (size_t i = 0; i < _numUnnamedAreas; i++) { SpatialAreaValue entry; @@ -1168,15 +1158,11 @@ void GeometryHandler::dumpNodeRelations() { progressBar.update(entryCount); #pragma omp parallel for shared( \ - std::cout, osm2rdf::ttl::constants::NAMESPACE__OSM_NODE, \ - osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, \ - osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION, \ + std::cout, osm2rdf::ttl::constants::NODE_NAMESPACE, \ osm2rdf::ttl::constants::IRI__OPENGIS_CONTAINS, \ osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA, \ osm2rdf::ttl::constants::IRI__OPENGIS_INTERSECTS, \ osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS, \ osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_AREA, \ progressBar, ia, entryCount) reduction(+ : stats) default(none) \ schedule(dynamic) @@ -1186,7 +1172,9 @@ void GeometryHandler::dumpNodeRelations() { ia >> node; const auto& nodeId = std::get<0>(node); - std::string nodeIRI = _writer->generateIRI(NAMESPACE__OSM_NODE, nodeId); + std::string nodeIRI = _writer->generateIRI( + osm2rdf::ttl::constants::NODE_NAMESPACE[_config.sourceDataset], + nodeId); // Set containing all areas we are inside of SkipSet skip; @@ -1224,9 +1212,9 @@ void GeometryHandler::dumpNodeRelations() { if (relations != _areaBorderWaysIndex.end()) { for (auto r : relations->second) { if (r.second) { - // way is inner geometry of this area relation, so if we - // encounter the enclosing area again for this way, we can - // be sure that we are not contained in it! + // way is inner geometry of this area relation, so if + // we encounter the enclosing area again for this way, + // we can be sure that we are not contained in it! skipByContainedInInner.insert(r.first); } } @@ -1349,18 +1337,15 @@ void GeometryHandler::dumpWayRelations() { GeomRelationStats intersectStats, containsStats; progressBar.update(entryCount); -#pragma omp parallel for shared( \ - std::cout, std::cerr, osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, \ - osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION, \ - osm2rdf::ttl::constants::IRI__OPENGIS_INTERSECTS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_AREA, \ - osm2rdf::ttl::constants::IRI__OPENGIS_CONTAINS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS, \ - osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS, progressBar, \ - entryCount, ia) \ - reduction(+ : intersectStats, containsStats) default(none) \ +#pragma omp parallel for shared( \ + std::cout, std::cerr, osm2rdf::ttl::constants::WAY_NAMESPACE, \ + osm2rdf::ttl::constants::IRI__OPENGIS_INTERSECTS, \ + osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA, \ + osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_AREA, \ + osm2rdf::ttl::constants::IRI__OPENGIS_CONTAINS, \ + osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA, \ + progressBar, entryCount, ia) \ + reduction(+ : intersectStats, containsStats) default(none) \ schedule(dynamic) for (size_t i = 0; i < _numWays; i++) { @@ -1371,14 +1356,15 @@ void GeometryHandler::dumpWayRelations() { const auto& wayId = std::get<1>(way); - // Check if an area computed from this way exists if yes we don't need to - // calculate any relation again. + // Check if an area computed from this way exists if yes we + // don't need to calculate any relation again. auto it = _spatialStorageAreaIndex.find(wayId * 2); if (it != _spatialStorageAreaIndex.end()) { continue; } - std::string wayIRI = _writer->generateIRI(NAMESPACE__OSM_WAY, wayId); + std::string wayIRI = _writer->generateIRI( + osm2rdf::ttl::constants::WAY_NAMESPACE[_config.sourceDataset], wayId); // Set containing all areas we are inside of SkipSet skipIntersects; @@ -1507,9 +1493,10 @@ void GeometryHandler::dumpWayRelations() { if (relations != _areaBorderWaysIndex.end()) { for (auto r : relations->second) { if (r.second) { - // way is inner geometry of this area relation, so if we - // encounter the enclosing area again for this way, we can - // be sure that we are not contained in it! + // way is inner geometry of this area relation, so + // if we encounter the enclosing area again for this + // way, we can be sure that we are not contained in + // it! skipByContainedInInner.insert(r.first); } } @@ -1716,7 +1703,8 @@ bool GeometryHandler::nodeInArea(const SpatialNodeValue& a, } if (!boost::geometry::covered_by(geomA, outerGeomB)) { - // if NOT covered by simplified out, we are definitely not contained + // if NOT covered by simplified out, we are definitely not + // contained stats->skippedByOuter(); return false; } @@ -1770,8 +1758,8 @@ bool GeometryHandler::areaIntersectsArea(const SpatialAreaValue& a, return true; } - // if there is no full contained box, and no potentially contained, we - // surely do not intersect + // if there is no full contained box, and no potentially contained, + // we surely do not intersect if (geomRelInf->toCheck.empty()) { geomRelInf->intersects = RelInfoValue::NO; stats->skippedByBoxIdIntersect(); @@ -1884,16 +1872,16 @@ bool GeometryHandler::wayIntersectsArea(const SpatialWayValue& a, if (geomRelInf->fullContained < 0) boxIdIsect(wayBoxIds, areaBoxIds, geomRelInf); - // if we have at least one of A's boxes fully contained in B, we surely - // intersect + // if we have at least one of A's boxes fully contained in B, we + // surely intersect if (geomRelInf->fullContained > 0) { geomRelInf->intersects = RelInfoValue::YES; stats->skippedByBoxIdIntersect(); return true; } - // if not, and if we also have no potential intersection box, we are not - // contained + // if not, and if we also have no potential intersection box, we are + // not contained if (geomRelInf->toCheck.empty()) { geomRelInf->intersects = RelInfoValue::NO; stats->skippedByBoxIdIntersect(); @@ -1963,7 +1951,8 @@ bool GeometryHandler::wayIntersectsArea(const SpatialWayValue& a, } if (!intersects) { - // if does not intersect with envelope, we definitely don't intersect + // if does not intersect with envelope, we definitely don't + // intersect geomRelInf->intersects = RelInfoValue::NO; stats->skippedByBox(); return false; @@ -2055,8 +2044,8 @@ bool GeometryHandler::wayInArea(const SpatialWayValue& a, return true; } - // the combined number of potential contains and sure contains is not - // equal to the number of A's boxes, so we cannot be contained + // the combined number of potential contains and sure contains is + // not equal to the number of A's boxes, so we cannot be contained if ((static_cast(geomRelInf->toCheck.size()) + geomRelInf->fullContained) != wayBoxIds[0].first) { geomRelInf->contained = RelInfoValue::NO; @@ -2064,8 +2053,8 @@ bool GeometryHandler::wayInArea(const SpatialWayValue& a, return false; } - // if the way is only in one box, and area cutouts are available, we can - // check against the corresponding cutout + // if the way is only in one box, and area cutouts are available, we + // can check against the corresponding cutout if (wayBoxIds[0].first == 1 && !areaCutouts.empty()) { const auto& cutout = areaCutouts.find(abs(wayBoxIds[1].first)); @@ -2309,7 +2298,8 @@ bool GeometryHandler::areaInArea(const SpatialAreaValue& a, } // else, if the number of surely contained and potentially contained - // boxes is unequal the number of A's boxes, we are surely not contained + // boxes is unequal the number of A's boxes, we are surely not + // contained if ((static_cast(geomRelInf->toCheck.size()) + geomRelInf->fullContained) != boxIdsA[0].first) { geomRelInf->contained = RelInfoValue::NO; @@ -2317,8 +2307,8 @@ bool GeometryHandler::areaInArea(const SpatialAreaValue& a, return false; } - // if A is in only one box, we can check it against the corresponding - // cutout of B, if available + // if A is in only one box, we can check it against the + // corresponding cutout of B, if available if (boxIdsA[0].first == 1 && !cutoutsB.empty()) { const auto& cutout = cutoutsB.find(abs(boxIdsA[1].first)); @@ -2586,11 +2576,11 @@ template std::string GeometryHandler::areaNS(AreaFromType type) const { switch (type) { case AreaFromType::RELATION: - return osm2rdf::ttl::constants::NAMESPACE__OSM_RELATION; + return osm2rdf::ttl::constants::RELATION_NAMESPACE[_config.sourceDataset]; case AreaFromType::WAY: - return osm2rdf::ttl::constants::NAMESPACE__OSM_WAY; + return osm2rdf::ttl::constants::WAY_NAMESPACE[_config.sourceDataset]; default: - return osm2rdf::ttl::constants::NAMESPACE__OSM_WAY; + return osm2rdf::ttl::constants::WAY_NAMESPACE[_config.sourceDataset]; } } @@ -2621,8 +2611,8 @@ void GeometryHandler::boxIdIsect(const BoxIdList& idsA, if (idsB[j].first > 0) { geomRelInf->fullContained++; - // we now know that we surely intersect. If we know already that - // we cannot be contained, return here + // we now know that we surely intersect. If we know already + // that we cannot be contained, return here if (noContained) { return; } @@ -2641,8 +2631,8 @@ void GeometryHandler::boxIdIsect(const BoxIdList& idsA, } } else if (abs(idsA[i].first) + ii < abs(idsB[j].first) + jj) { // if we already know that we intersect, we are now sure that we - // cannot be contained - it is irrelevant by how "much" we cannot be - // contained, so just return + // cannot be contained - it is irrelevant by how "much" we + // cannot be contained, so just return if (geomRelInf->fullContained > 0) { return; } @@ -2794,8 +2784,8 @@ std::vector GeometryHandler::indexQryIntersect( // ____________________________________________________________________________ template void GeometryHandler::unique(std::vector& refs) const { - // remove duplicates, may occur since we used multiple envelope queries - // to build the result! + // remove duplicates, may occur since we used multiple envelope + // queries to build the result! std::sort(refs.begin(), refs.end(), [](const auto& a, const auto& b) { return a.second < b.second; }); auto last = std::unique( @@ -2837,8 +2827,9 @@ uint8_t GeometryHandler::borderContained(Way::id_t wayId, // ____________________________________________________________________________ template void GeometryHandler::writeTransitiveClosure( - const std::vector& successors, const SkipSet& skipSet, const std::string& entryIRI, - const std::string& rel, const std::string& symmRel) { + const std::vector& successors, const SkipSet& skipSet, + const std::string& entryIRI, const std::string& rel, + const std::string& symmRel) { // transitive closure for (const auto& succIdx : successors) { if (skipSet.find(succIdx) != skipSet.end()) { @@ -2857,8 +2848,8 @@ void GeometryHandler::writeTransitiveClosure( // ____________________________________________________________________________ template void GeometryHandler::writeTransitiveClosure( - const std::vector& successors, const SkipSet& skipSet, const std::string& entryIRI, - const std::string& rel) { + const std::vector& successors, const SkipSet& skipSet, + const std::string& entryIRI, const std::string& rel) { // transitive closure for (const auto& succIdx : successors) { if (skipSet.find(succIdx) != skipSet.end()) { diff --git a/src/ttl/Writer.cpp b/src/ttl/Writer.cpp index ed1b624f..91ad0c49 100644 --- a/src/ttl/Writer.cpp +++ b/src/ttl/Writer.cpp @@ -70,6 +70,8 @@ osm2rdf::ttl::Writer::Writer(const osm2rdf::config::Config& config, {osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, "https://www.openstreetmap.org/way/"}, // ohm prefixes + {osm2rdf::ttl::constants::NAMESPACE__OHM, + "https://www.openhistoricalmap.org/"}, {osm2rdf::ttl::constants::NAMESPACE__OHM_NODE, "https://www.openhistoricalmap.org/node/"}, {osm2rdf::ttl::constants::NAMESPACE__OHM_RELATION, diff --git a/tests/ttl/Writer.cpp b/tests/ttl/Writer.cpp index 0d94cba4..a57b83b4 100644 --- a/tests/ttl/Writer.cpp +++ b/tests/ttl/Writer.cpp @@ -707,8 +707,8 @@ TEST(TTL_WriterTTL, writeStatisticJson) { statsBuffer << statsIFStream.rdbuf(); ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"blankNodes\": 3")); - ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"header\": 16")); - ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"lines\": 21")); + ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"header\": 17")); + ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"lines\": 22")); ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"triples\": 5")); // Cleanup @@ -770,8 +770,8 @@ TEST(TTL_WriterQLEVER, writeStatisticJson) { statsBuffer << statsIFStream.rdbuf(); ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"blankNodes\": 3")); - ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"header\": 16")); - ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"lines\": 21")); + ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"header\": 17")); + ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"lines\": 22")); ASSERT_THAT(statsBuffer.str(), ::testing::HasSubstr("\"triples\": 5")); // Cleanup