From 5ec53614039208f020eb810a11e062bc7fb52ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 06:31:59 +0000 Subject: [PATCH 01/57] chore: Refactor navteq_plugin.cpp to use const reference for dataDirs --- plugins/navteq/navteq.hpp | 2 +- plugins/navteq/navteq_plugin.cpp | 47 +++++++++++++++++++------------- plugins/navteq/navteq_plugin.hpp | 18 ++++++++---- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index 8bf3cb9..0945fa8 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -2345,7 +2345,7 @@ add_admin_lines(boost::filesystem::path admin_line_shape_file, return result; } -void addLevel1Boundaries(std::vector &dirs, +void addLevel1Boundaries(const std::vector &dirs, osmium::io::Writer &writer) { std::map> map; diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 874cf0a..121819b 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -125,7 +125,7 @@ bool navteq_plugin::check_files(const boost::filesystem::path &dir) { void navteq_plugin::recurse_dir(const boost::filesystem::path &dir) { if (check_files(dir)) - dirs.push_back(dir); + dataDirs.push_back(dir); for (auto &itr : boost::make_iterator_range( boost::filesystem::directory_iterator(dir), {})) { @@ -158,11 +158,11 @@ bool navteq_plugin::check_input(const boost::filesystem::path &input_path, << "Countries found :" << boost::join(foundCountries, " "); } - if (dirs.empty()) + if (dataDirs.empty()) return false; BOOST_LOG_TRIVIAL(info) << "dirs: "; - for (auto &dir : dirs) + for (auto &dir : dataDirs) BOOST_LOG_TRIVIAL(info) << dir; this->plugin_setup(input_path, output_file); @@ -172,7 +172,9 @@ bool navteq_plugin::check_input(const boost::filesystem::path &input_path, void navteq_plugin::write_output() {} -void navteq_plugin::add_administrative_boundaries(osmium::io::Writer &writer) { +void navteq_plugin::add_administrative_boundaries( + const std::vector &dirs, + osmium::io::Writer &writer) { // todo admin-levels only apply to the US => more generic for all countries g_way_end_points_map.clear(); @@ -195,7 +197,8 @@ void navteq_plugin::add_administrative_boundaries(osmium::io::Writer &writer) { g_way_end_points_map.clear(); } -void navteq_plugin::add_water(osmium::io::Writer &writer) { +void navteq_plugin::add_water(const std::vector &dirs, + osmium::io::Writer &writer) { for (auto dir : dirs) { if (shp_file_exists(dir / WATER_POLY_SHP)) add_water_shape(dir / WATER_POLY_SHP, writer); @@ -204,14 +207,18 @@ void navteq_plugin::add_water(osmium::io::Writer &writer) { } } -void navteq_plugin::add_railways(osmium::io::Writer &writer) { +void navteq_plugin::add_railways( + const std::vector &dirs, + osmium::io::Writer &writer) { for (auto dir : dirs) { if (shp_file_exists(dir / RAILWAYS_POLY_SHP)) add_railways_shape(dir / RAILWAYS_POLY_SHP, writer); } } -void navteq_plugin::add_buildings(osmium::io::Writer &writer) { +void navteq_plugin::add_buildings( + const std::vector &dirs, + osmium::io::Writer &writer) { g_way_end_points_map.clear(); for (auto dir : dirs) { if (shp_file_exists(dir / LANDMARK_SHP)) @@ -220,7 +227,9 @@ void navteq_plugin::add_buildings(osmium::io::Writer &writer) { g_way_end_points_map.clear(); } -void navteq_plugin::add_landuse(osmium::io::Writer &writer) { +void navteq_plugin::add_landuse( + const std::vector &dirs, + osmium::io::Writer &writer) { for (auto dir : dirs) { if (shp_file_exists(dir / LAND_USE_A_SHP)) add_landuse_shape(dir / LAND_USE_A_SHP, writer); @@ -241,37 +250,37 @@ void navteq_plugin::execute() { osmium::io::Writer writer(outfile, hdr, osmium::io::overwrite::allow); BOOST_LOG_TRIVIAL(info) << "Procesing Meta areas"; - preprocess_meta_areas(dirs); + preprocess_meta_areas(dataDirs); BOOST_LOG_TRIVIAL(info) << "Procesing alt street rout types"; - process_alt_steets_route_types(dirs); + process_alt_steets_route_types(dataDirs); BOOST_LOG_TRIVIAL(info) << "Add street shapes"; - add_street_shapes(dirs, writer); + add_street_shapes(dataDirs, writer); BOOST_LOG_TRIVIAL(info) << "Add administrative boundaries"; - add_administrative_boundaries(writer); + add_administrative_boundaries(dataDirs, writer); BOOST_LOG_TRIVIAL(info) << "Add water"; - add_water(writer); + add_water(dataDirs, writer); BOOST_LOG_TRIVIAL(info) << "Add landuse"; - add_landuse(writer); + add_landuse(dataDirs, writer); BOOST_LOG_TRIVIAL(info) << "Add city nodes"; - add_city_nodes(dirs, writer); + add_city_nodes(dataDirs, writer); BOOST_LOG_TRIVIAL(info) << "Add hamlet nodes"; - add_hamlet_nodes(dirs, writer); + add_hamlet_nodes(dataDirs, writer); BOOST_LOG_TRIVIAL(info) << "Add railways"; - add_railways(writer); + add_railways(dataDirs, writer); BOOST_LOG_TRIVIAL(info) << "Add buildings"; - add_buildings(writer); + add_buildings(dataDirs, writer); BOOST_LOG_TRIVIAL(info) << "Add rest areas"; - add_rest_area_nodes(dirs, writer); + add_rest_area_nodes(dataDirs, writer); writer.close(); diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index 400dfcd..d061ccb 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -26,17 +26,23 @@ class navteq_plugin : public base_plugin { void recurse_dir(const boost::filesystem::path &dir); bool check_files(const boost::filesystem::path &dir); void write_output(); - void add_administrative_boundaries(osmium::io::Writer &writer); - void add_water(osmium::io::Writer &writer); - void add_landuse(osmium::io::Writer &writer); - void add_railways(osmium::io::Writer &writer); - void add_buildings(osmium::io::Writer &writer); + void add_administrative_boundaries( + const std::vector &dirs, + osmium::io::Writer &writer); + void add_water(const std::vector &dirs, + osmium::io::Writer &writer); + void add_landuse(const std::vector &dirs, + osmium::io::Writer &writer); + void add_railways(const std::vector &dirs, + osmium::io::Writer &writer); + void add_buildings(const std::vector &dirs, + osmium::io::Writer &writer); void sortPBF(); void copyType(osmium::io::Writer &writer, osmium::io::File &file, osmium::osm_entity_bits::type bits); - std::vector dirs; + std::vector dataDirs; OGREnvelope boundingBox; From 6f151aef9e5b6fddb59092de1c552d687fd7c04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 07:00:46 +0000 Subject: [PATCH 02/57] add converter --- plugins/navteq/converter/Converter.hpp | 36 +++++++++++++++++++++ plugins/navteq/converter/WaterConverter.cpp | 24 ++++++++++++++ plugins/navteq/converter/WaterConverter.hpp | 33 +++++++++++++++++++ plugins/navteq/navteq_plugin.cpp | 3 ++ plugins/navteq/navteq_plugin.hpp | 3 ++ 5 files changed, 99 insertions(+) create mode 100644 plugins/navteq/converter/Converter.hpp create mode 100644 plugins/navteq/converter/WaterConverter.cpp create mode 100644 plugins/navteq/converter/WaterConverter.hpp diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp new file mode 100644 index 0000000..308f74f --- /dev/null +++ b/plugins/navteq/converter/Converter.hpp @@ -0,0 +1,36 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef CONVERTER_HPP +#define CONVERTER_HPP + +namespace osmium { +namespace io { +class Writer; +} // namespace io +} // namespace osmium + +class Converter { + +public: + Converter(); + virtual ~Converter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer) = 0; +}; + +#endif // CONVERTER_HPP diff --git a/plugins/navteq/converter/WaterConverter.cpp b/plugins/navteq/converter/WaterConverter.cpp new file mode 100644 index 0000000..c6ae619 --- /dev/null +++ b/plugins/navteq/converter/WaterConverter.cpp @@ -0,0 +1,24 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "WaterConverter.hpp" + +WaterConverter::WaterConverter() {} + +WaterConverter::~WaterConverter() {} + +void WaterConverter::convert(const std::vector &dirs, + osmium::io::Writer &writer) {} \ No newline at end of file diff --git a/plugins/navteq/converter/WaterConverter.hpp b/plugins/navteq/converter/WaterConverter.hpp new file mode 100644 index 0000000..ef99a26 --- /dev/null +++ b/plugins/navteq/converter/WaterConverter.hpp @@ -0,0 +1,33 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef WATERCONVERTER_HPP +#define WATERCONVERTER_HPP + +#include "Converter.hpp" + +class WaterConverter : public Converter { + +public: + WaterConverter(); + virtual ~WaterConverter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer); +}; +; + +#endif // WATERCONVERTER_HPP \ No newline at end of file diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 121819b..36cc773 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -16,6 +16,7 @@ #include #include +#include "converter/WaterConverter.hpp" #include "navteq.hpp" #include "navteq_plugin.hpp" #include "navteq_util.hpp" @@ -30,6 +31,8 @@ navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) : base_plugin::base_plugin("Navteq Plugin", executable_path) { // setting executable_path in navteq2osm_tag_parser.hpp for reading ISO-file g_executable_path = this->executable_path; + + converter.push_back(std::make_unique()); } navteq_plugin::~navteq_plugin() {} diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index d061ccb..b4c3d9e 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -9,6 +9,7 @@ #define NAVTEQPLUGIN_HPP_ #include "../base_plugin.hpp" +#include "converter/Converter.hpp" #include "navteq_types.hpp" #include #include @@ -44,6 +45,8 @@ class navteq_plugin : public base_plugin { std::vector dataDirs; + std::vector> converter; + OGREnvelope boundingBox; std::vector countriesToConvert; From e33ac697f930d2329ce92f7cfba939b61ee55ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 08:49:17 +0000 Subject: [PATCH 03/57] extract water ways and bodies --- plugins/navteq/converter/Converter.cpp | 186 ++++++++++++++++++ plugins/navteq/converter/Converter.hpp | 80 +++++++- plugins/navteq/converter/WaterConverter.cpp | 199 +++++++++++++++++++- plugins/navteq/converter/WaterConverter.hpp | 50 ++++- plugins/navteq/navteq.hpp | 166 ---------------- plugins/navteq/navteq_mappings.hpp | 3 +- plugins/navteq/navteq_plugin.cpp | 12 +- 7 files changed, 513 insertions(+), 183 deletions(-) create mode 100644 plugins/navteq/converter/Converter.cpp diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp new file mode 100644 index 0000000..81e936d --- /dev/null +++ b/plugins/navteq/converter/Converter.cpp @@ -0,0 +1,186 @@ + +#include "Converter.hpp" + +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" + +osmium::unsigned_object_id_type Converter::g_osm_id = 1; + +/** + * \brief Dummy attributes enable josm to read output xml files. + * + * \param obj OSMObject to set attributess to. + * */ +void Converter::set_dummy_osm_object_attributes(osmium::OSMObject &obj) { + obj.set_version(VERSION.data()); + obj.set_changeset(CHANGESET.data()); + obj.set_uid(USERID.data()); + obj.set_timestamp(TIMESTAMP); +} + +/** + * \brief Adds relation members to relation. + * + * \param builder RelationBuilder to add members to. + * \param ext_osm_way_ids List of external way ids. + * \param int_osm_way_ids List of internal way ids. + * */ +void Converter::build_relation_members( + osmium::builder::RelationBuilder &builder, + const std::vector &ext_osm_way_ids, + const std::vector &int_osm_way_ids) { + osmium::builder::RelationMemberListBuilder rml_builder(builder); + + for (auto osm_id : ext_osm_way_ids) + rml_builder.add_member(osmium::item_type::way, osm_id, "outer"); + + for (auto osm_id : int_osm_way_ids) + rml_builder.add_member(osmium::item_type::way, osm_id, "inner"); +} + +/** + * \brief Creates a polygon from OGRPolygon. + * + * \param poly OGRPolygon to create polygon from. + * \param ext_ring_osm_ids List of osm ids for external ring. + * \param int_ring_osm_ids List of osm ids for internal ring. + * \param node_buffer Buffer to store nodes. + * \param way_buffer Buffer to store ways. + * */ +void Converter::create_multi_polygon( + OGRMultiPolygon *mp, + std::vector &mp_ext_ring_osm_ids, + std::vector &mp_int_ring_osm_ids, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { + + for (const OGRPolygon *poly : mp) { + create_polygon(poly, mp_ext_ring_osm_ids, mp_int_ring_osm_ids, node_buffer, + way_buffer); + } +} + +/** + * \brief Creates a polygon from OGRPolygon. + * + * \param poly OGRPolygon to create polygon from. + * \param exterior_way_ids List of osm ids for exterior ring. + * \param interior_way_ids List of osm ids for interior ring. + * \param node_buffer Buffer to store nodes. + * \param way_buffer Buffer to store ways. + * */ +void Converter::create_polygon( + const OGRPolygon *poly, + std::vector &exterior_way_ids, + std::vector &interior_way_ids, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { + bool isExteriorRing = true; // first ring is the exterior ring + for (const auto ring : *poly) { + auto tmp = build_closed_ways(ring, node_buffer, way_buffer); + if (isExteriorRing) { + std::move(tmp.begin(), tmp.end(), std::back_inserter(exterior_way_ids)); + } else { + std::move(tmp.begin(), tmp.end(), std::back_inserter(interior_way_ids)); + } + isExteriorRing = false; + } +} + +/** + * \brief Creates a closed way from OGRLineString. + * + * \param line OGRLineString to create way from. + * \param node_buffer Buffer to store nodes. + * \param way_buffer Buffer to store ways. + * */ +std::vector> +Converter::create_open_way_nodes(const OGRLineString *line, + osmium::memory::Buffer &node_buffer) { + std::vector> + osm_way_node_ids; + + for (auto &point : *line) { + osmium::Location location(point.getX(), point.getY()); + auto it = g_way_end_points_map.find(location); + if (it != g_way_end_points_map.end()) { + osm_way_node_ids.emplace_back(location, it->second); + } else { + auto osm_id = build_node(location, node_buffer); + osm_way_node_ids.emplace_back(location, osm_id); + g_way_end_points_map.emplace(location, osm_id); + } + } + + return osm_way_node_ids; +} + +std::vector +Converter::build_closed_ways(const OGRLinearRing *ring, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer) { + auto osm_way_node_ids = create_closed_way_nodes(ring, node_buffer); + + std::vector osm_way_ids; + size_t i = 0; + do { + osmium::builder::WayBuilder builder(way_buffer); + builder.object().set_id(g_osm_id++); + set_dummy_osm_object_attributes(builder.object()); + builder.set_user(USER.data()); + osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &builder); + for (size_t j = i; + j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) + wnl_builder.add_node_ref(osm_way_node_ids.at(j).second, + osm_way_node_ids.at(j).first); + osm_way_ids.push_back(builder.object().id()); + i += OSM_MAX_WAY_NODES - 1; + } while (i < osm_way_node_ids.size()); + return osm_way_ids; +} + +std::vector> +Converter::create_closed_way_nodes(const OGRLinearRing *ring, + osmium::memory::Buffer &node_buffer) { + std::vector> + osm_way_node_ids; + for (auto &point : *ring) { + osmium::Location location(point.getX(), point.getY()); + auto it = g_way_end_points_map.find(location); + + if (it != g_way_end_points_map.end()) { + osm_way_node_ids.emplace_back(location, it->second); + } else { + auto osm_id = build_node(location, node_buffer); + osm_way_node_ids.emplace_back(location, osm_id); + g_way_end_points_map.emplace(location, osm_id); + } + } + + // first and last node are the same in rings, hence add first node_id and + // skip last node. + if (!ring->get_IsClosed()) + throw format_error( + "admin boundary ring is invalid. First and last node don't match"); + + return osm_way_node_ids; +} + +osmium::unsigned_object_id_type +Converter::build_node(const osmium::Location &location, + osmium::memory::Buffer &node_buffer) { + osmium::builder::NodeBuilder builder(node_buffer); + return build_node(location, &builder); +} + +osmium::unsigned_object_id_type +Converter::build_node(const osmium::Location &location, + osmium::builder::NodeBuilder *builder) { + builder->object().set_id(g_osm_id++); + set_dummy_osm_object_attributes(builder->object()); + builder->set_user(USER.data()); + builder->object().set_location(location); + return builder->object().id(); +} \ No newline at end of file diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 308f74f..9998121 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -17,20 +17,96 @@ #ifndef CONVERTER_HPP #define CONVERTER_HPP +#include +#include +#include +#include + namespace osmium { +class OSMObject; +class Location; + namespace io { class Writer; } // namespace io + +namespace builder { +class RelationBuilder; +class NodeBuilder; +} // namespace builder + +namespace memory { +class Buffer; +} // namespace memory } // namespace osmium +class OGRMultiPolygon; +class OGRPolygon; +class OGRLineString; +class OGRLinearRing; + class Converter { public: - Converter(); - virtual ~Converter(); + Converter() {} + virtual ~Converter() {} virtual void convert(const std::vector &dirs, osmium::io::Writer &writer) = 0; + + void set_dummy_osm_object_attributes(osmium::OSMObject &obj); + +protected: + void build_relation_members( + osmium::builder::RelationBuilder &builder, + const std::vector &ext_osm_way_ids, + const std::vector &int_osm_way_ids); + + void create_multi_polygon( + OGRMultiPolygon *mp, + std::vector &mp_ext_ring_osm_ids, + std::vector &mp_int_ring_osm_ids, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); + + void + create_polygon(const OGRPolygon *poly, + std::vector &exterior_way_ids, + std::vector &interior_way_ids, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + std::vector> + create_open_way_nodes(const OGRLineString *line, + osmium::memory::Buffer &node_buffer); + + std::vector + build_closed_ways(const OGRLinearRing *ring, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + std::vector> + create_closed_way_nodes(const OGRLinearRing *ring, + osmium::memory::Buffer &node_buffer); + + osmium::unsigned_object_id_type + build_node(const osmium::Location &location, + osmium::memory::Buffer &node_buffer); + + osmium::unsigned_object_id_type + build_node(const osmium::Location &location, + osmium::builder::NodeBuilder *builder); + + static constexpr int BUFFER_SIZE = 10 * 1000 * 1000; + + static constexpr int OSM_MAX_WAY_NODES = 1000; + + static constexpr std::string_view USER = "import"; + static constexpr std::string_view VERSION = "1"; + static constexpr std::string_view CHANGESET = "1"; + static constexpr std::string_view USERID = "1"; + static constexpr int TIMESTAMP = 1; + + static osmium::unsigned_object_id_type g_osm_id; }; #endif // CONVERTER_HPP diff --git a/plugins/navteq/converter/WaterConverter.cpp b/plugins/navteq/converter/WaterConverter.cpp index c6ae619..9ae9f03 100644 --- a/plugins/navteq/converter/WaterConverter.cpp +++ b/plugins/navteq/converter/WaterConverter.cpp @@ -16,9 +16,206 @@ #include "WaterConverter.hpp" +#include +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" + WaterConverter::WaterConverter() {} WaterConverter::~WaterConverter() {} void WaterConverter::convert(const std::vector &dirs, - osmium::io::Writer &writer) {} \ No newline at end of file + osmium::io::Writer &writer) { + + const boost::filesystem::path WATER_SEG_SHP = "WaterSeg.shp"; + const boost::filesystem::path WATER_POLY_SHP = "WaterPoly.shp"; + + for (auto dir : dirs) { + add_water_shape(dir / WATER_POLY_SHP, writer); + add_water_shape(dir / WATER_SEG_SHP, writer); + } +} + +void WaterConverter::add_water_shape(boost::filesystem::path water_shape_file, + osmium::io::Writer &writer) { + g_way_end_points_map.clear(); + + auto ds = GDALDatasetUniquePtr(GDALDataset::Open(water_shape_file.c_str())); + auto layer = ds->GetLayer(0); + if (layer == nullptr) { + BOOST_LOG_TRIVIAL(debug) << "No water layer found in " << water_shape_file; + return; + } + + assert(layer->GetGeomType() == wkbPolygon || + layer->GetGeomType() == wkbLineString); + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + osmium::memory::Buffer rel_buffer(BUFFER_SIZE); + for (const auto &feat : *layer) { + process_water(feat, node_buffer, way_buffer, rel_buffer); + } + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); + writer(std::move(rel_buffer)); + g_way_end_points_map.clear(); +} + +/** + * \brief adds water polygons as Relations to m_buffer + */ +void WaterConverter::process_water(const OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer, + osmium::memory::Buffer &rel_buffer) { + auto geom = feat->GetGeometryRef(); + auto geom_type = geom->getGeometryType(); + + if (geom_type == OGRwkbGeometryType::wkbLineString) { + // handle water ways + build_water_ways_with_tagList(feat, static_cast(geom), + node_buffer, way_buffer); + } else { + // handle water polygons + std::vector exterior_way_ids; + std::vector interior_way_ids; + if (geom_type == OGRwkbGeometryType::wkbMultiPolygon) { + create_multi_polygon(static_cast(geom), + exterior_way_ids, interior_way_ids, node_buffer, + way_buffer); + } else if (geom_type == OGRwkbGeometryType::wkbPolygon) { + create_polygon(static_cast(geom), exterior_way_ids, + interior_way_ids, node_buffer, way_buffer); + } else { + throw(std::runtime_error( + "Water item with geometry=" + std::string(geom->getGeometryName()) + + " is not yet supported.")); + } + build_water_relation_with_tags(feat, exterior_way_ids, interior_way_ids, + rel_buffer); + } + + node_buffer.commit(); + way_buffer.commit(); + rel_buffer.commit(); +} + +std::vector +WaterConverter::build_water_ways_with_tagList( + const OGRFeatureUniquePtr &feat, OGRLineString *line, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { + + auto osm_way_node_ids = create_open_way_nodes(line, node_buffer); + + std::vector osm_way_ids; + size_t i = 0; + do { + osmium::builder::WayBuilder builder(way_buffer); + builder.object().set_id(g_osm_id++); + set_dummy_osm_object_attributes(builder.object()); + builder.set_user(USER.data()); + build_water_way_taglist(builder, feat); + osmium::builder::WayNodeListBuilder wnl_builder(builder); + for (size_t j = i; + j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) + wnl_builder.add_node_ref(osm_way_node_ids.at(j).second, + osm_way_node_ids.at(j).first); + osm_way_ids.push_back(builder.object().id()); + i += OSM_MAX_WAY_NODES - 1; + } while (i < osm_way_node_ids.size()); + return osm_way_ids; +} + +/** + * \brief adds navteq water tags to way + */ +void WaterConverter::build_water_way_taglist( + osmium::builder::WayBuilder &builder, const OGRFeatureUniquePtr &feat) { + // Mind tl_builder scope! + osmium::builder::TagListBuilder tl_builder(builder); + // tl_builder.add_tag("natural", "water"); + + std::string polygonName = feat->GetFieldAsString(POLYGON_NM.data()); + if (!polygonName.empty()) { + std::string waters_name = to_camel_case_with_spaces(polygonName); + if (!waters_name.empty()) + tl_builder.add_tag("name", waters_name); + } + + std::string featureCode = feat->GetFieldAsString(FEAT_COD.data()); + if (featureCode == "500412") { + // FEAT_TYPE 'RIVER' + tl_builder.add_tag("waterway", "river"); + } else if (featureCode == "500414") { + // FEAT_TYPE 'CANAL/WATER CHANNEL' + tl_builder.add_tag("waterway", "canal"); + } else if (featureCode == "500421") { + // FEAT_TYPE 'LAKE' + BOOST_LOG_TRIVIAL(error) + << "Skipping water way as type LAKE should only exist as polygon"; + } else if (featureCode == "507116") { + // FEAT_TYPE 'BAY/HARBOUR' + BOOST_LOG_TRIVIAL(error) + << "Skipping water way as type BAY/HARBOUR should only exist as " + "polygon"; + } else { + BOOST_LOG_TRIVIAL(error) + << "Skipping unknown water way type " << featureCode; + } +} + +osmium::unsigned_object_id_type WaterConverter::build_water_relation_with_tags( + const OGRFeatureUniquePtr &feat, + std::vector ext_osm_way_ids, + std::vector int_osm_way_ids, + osmium::memory::Buffer &rel_buffer) { + osmium::builder::RelationBuilder builder(rel_buffer); + builder.object().set_id(g_osm_id++); + set_dummy_osm_object_attributes(builder.object()); + builder.set_user(USER.data()); + build_water_poly_taglist(builder, feat); + + build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); + return builder.object().id(); +} + +/** + * \brief adds navteq water tags to Relation + */ +void WaterConverter::build_water_poly_taglist( + osmium::builder::RelationBuilder &builder, + const OGRFeatureUniquePtr &feat) { + // Mind tl_builder scope! + osmium::builder::TagListBuilder tl_builder(builder); + tl_builder.add_tag("type", "multipolygon"); + tl_builder.add_tag("natural", "water"); + + std::string polygonName = feat->GetFieldAsString(POLYGON_NM.data()); + if (!polygonName.empty()) { + std::string waters_name = to_camel_case_with_spaces(polygonName); + if (!waters_name.empty()) + tl_builder.add_tag("name", waters_name); + } + + std::string featureCode = feat->GetFieldAsString(FEAT_COD.data()); + if (featureCode == "500412") { + // FEAT_TYPE 'RIVER' + tl_builder.add_tag("water", "river"); + } else if (featureCode == "500414") { + // FEAT_TYPE 'CANAL/WATER CHANNEL' + tl_builder.add_tag("water", "canal"); + } else if (featureCode == "500421") { + // FEAT_TYPE 'LAKE' + tl_builder.add_tag("water", "lake"); + } else if (featureCode == "507116") { + // Type 'BAY/HARBOUR' just gets the 'natural=water' tag + } else { + BOOST_LOG_TRIVIAL(error) + << "Skipping unknown water poly type " << featureCode; + } +} \ No newline at end of file diff --git a/plugins/navteq/converter/WaterConverter.hpp b/plugins/navteq/converter/WaterConverter.hpp index ef99a26..1e4922a 100644 --- a/plugins/navteq/converter/WaterConverter.hpp +++ b/plugins/navteq/converter/WaterConverter.hpp @@ -19,6 +19,23 @@ #include "Converter.hpp" +#include +#include +#include +#include + +namespace osmium { +namespace memory { +class Buffer; +} // namespace memory +namespace builder { +class WayBuilder; +class RelationBuilder; +} // namespace builder +} // namespace osmium + +class OGRLineString; + class WaterConverter : public Converter { public: @@ -27,7 +44,38 @@ class WaterConverter : public Converter { virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); + +private: + void add_water_shape(boost::filesystem::path water_shape_file, + osmium::io::Writer &writer); + + void process_water(const OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer, + osmium::memory::Buffer &rel_buffer); + + std::vector build_water_ways_with_tagList( + const OGRFeatureUniquePtr &feat, OGRLineString *line, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); + + void build_water_way_taglist(osmium::builder::WayBuilder &builder, + const OGRFeatureUniquePtr &feat); + + osmium::unsigned_object_id_type build_water_relation_with_tags( + const OGRFeatureUniquePtr &feat, + std::vector ext_osm_way_ids, + std::vector int_osm_way_ids, + osmium::memory::Buffer &rel_buffer); + + void build_water_poly_taglist(osmium::builder::RelationBuilder &builder, + const OGRFeatureUniquePtr &feat); + + // maps location of way end nodes to node ids + std::map + g_way_end_points_map; + + static constexpr std::string_view POLYGON_NM = "POLYGON_NM"; + static constexpr std::string_view FEAT_COD = "FEAT_COD"; }; -; #endif // WATERCONVERTER_HPP \ No newline at end of file diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index 0945fa8..9b7cf0f 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -890,41 +890,6 @@ void build_admin_boundary_taglist(osmium::builder::Builder &builder, tl_builder.add_tag("admin_level", navteq_2_osm_admin_lvl(level)); } -/** - * \brief adds navteq water tags to Relation - */ -void build_water_poly_taglist(osmium::builder::RelationBuilder &builder, - const OGRFeatureUniquePtr &feat) { - // Mind tl_builder scope! - osmium::builder::TagListBuilder tl_builder(builder); - tl_builder.add_tag("type", "multipolygon"); - tl_builder.add_tag("natural", "water"); - - std::string polygonName = feat->GetFieldAsString(POLYGON_NM); - if (!polygonName.empty()) { - std::string waters_name = to_camel_case_with_spaces(polygonName); - if (!waters_name.empty()) - tl_builder.add_tag("name", waters_name); - } - - std::string featureCode = feat->GetFieldAsString(FEAT_COD); - if (featureCode == "500412") { - // FEAT_TYPE 'RIVER' - tl_builder.add_tag("water", "river"); - } else if (featureCode == "500414") { - // FEAT_TYPE 'CANAL/WATER CHANNEL' - tl_builder.add_tag("water", "canal"); - } else if (featureCode == "500421") { - // FEAT_TYPE 'LAKE' - tl_builder.add_tag("water", "lake"); - } else if (featureCode == "507116") { - // Type 'BAY/HARBOUR' just gets the 'natural=water' tag - } else { - BOOST_LOG_TRIVIAL(error) - << "Skipping unknown water poly type " << featureCode; - } -} - void build_building_poly_taglist(osmium::builder::WayBuilder &builder, const OGRFeatureUniquePtr &feat) { // Mind tl_builder scope! @@ -937,44 +902,6 @@ void build_building_poly_taglist(osmium::builder::WayBuilder &builder, tl_builder.add_tag("name", building_name); } -/** - * \brief adds navteq water tags to way - */ -void build_water_way_taglist(osmium::builder::WayBuilder &builder, - const OGRFeatureUniquePtr &feat) { - // Mind tl_builder scope! - osmium::builder::TagListBuilder tl_builder(builder); - // tl_builder.add_tag("natural", "water"); - - std::string polygonName = feat->GetFieldAsString(POLYGON_NM); - if (!polygonName.empty()) { - std::string waters_name = to_camel_case_with_spaces(polygonName); - if (!waters_name.empty()) - tl_builder.add_tag("name", waters_name); - } - - std::string featureCode = feat->GetFieldAsString(FEAT_COD); - if (featureCode == "500412") { - // FEAT_TYPE 'RIVER' - tl_builder.add_tag("waterway", "river"); - } else if (featureCode == "500414") { - // FEAT_TYPE 'CANAL/WATER CHANNEL' - tl_builder.add_tag("waterway", "canal"); - } else if (featureCode == "500421") { - // FEAT_TYPE 'LAKE' - BOOST_LOG_TRIVIAL(error) - << "Skipping water way as type LAKE should only exist as polygon"; - } else if (featureCode == "507116") { - // FEAT_TYPE 'BAY/HARBOUR' - BOOST_LOG_TRIVIAL(error) - << "Skipping water way as type BAY/HARBOUR should only exist as " - "polygon"; - } else { - BOOST_LOG_TRIVIAL(error) - << "Skipping unknown water way type " << featureCode; - } -} - /** * \brief adds navteq landuse tags to Relation */ @@ -1086,30 +1013,6 @@ void build_landuse_taglist(osmium::builder::RelationBuilder &builder, } } -osm_id_vector_type build_water_ways_with_tagList( - const OGRFeatureUniquePtr &feat, OGRLineString *line, - osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { - node_vector_type osm_way_node_ids = create_open_way_nodes(line, node_buffer); - - osm_id_vector_type osm_way_ids; - size_t i = 0; - do { - osmium::builder::WayBuilder builder(way_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER); - build_water_way_taglist(builder, feat); - osmium::builder::WayNodeListBuilder wnl_builder(builder); - for (size_t j = i; - j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) - wnl_builder.add_node_ref(osm_way_node_ids.at(j).second, - osm_way_node_ids.at(j).first); - osm_way_ids.push_back(builder.object().id()); - i += OSM_MAX_WAY_NODES - 1; - } while (i < osm_way_node_ids.size()); - return osm_way_ids; -} - void build_relation_members(osmium::builder::RelationBuilder &builder, const osm_id_vector_type &ext_osm_way_ids, const osm_id_vector_type &int_osm_way_ids) { @@ -1149,18 +1052,6 @@ osmium::unsigned_object_id_type build_admin_boundary_relation_with_tags( return builder.object().id(); } -osmium::unsigned_object_id_type build_water_relation_with_tags( - const OGRFeatureUniquePtr &feat, osm_id_vector_type ext_osm_way_ids, - osm_id_vector_type int_osm_way_ids, osmium::memory::Buffer &rel_buffer) { - osmium::builder::RelationBuilder builder(rel_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER); - build_water_poly_taglist(builder, feat); - build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); - return builder.object().id(); -} - osmium::unsigned_object_id_type build_landuse_relation_with_tags( const OGRFeatureUniquePtr &feat, osm_id_vector_type ext_osm_way_ids, osm_id_vector_type int_osm_way_ids, osmium::memory::Buffer &rel_buffer) { @@ -1244,42 +1135,6 @@ void process_admin_boundary( way_buffer.commit(); } -/** - * \brief adds water polygons as Relations to m_buffer - */ -void process_water(const OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer, - osmium::memory::Buffer &rel_buffer) { - auto geom = feat->GetGeometryRef(); - auto geom_type = geom->getGeometryType(); - - if (geom_type == wkbLineString) { - OGRLineString *line = static_cast(geom); - build_water_ways_with_tagList(feat, line, node_buffer, way_buffer); - } else { - osm_id_vector_type exterior_way_ids, interior_way_ids; - if (geom_type == wkbMultiPolygon) { - create_multi_polygon(static_cast(geom), - exterior_way_ids, interior_way_ids, node_buffer, - way_buffer); - } else if (geom_type == wkbPolygon) { - create_polygon(static_cast(geom), exterior_way_ids, - interior_way_ids, node_buffer, way_buffer); - } else { - throw(std::runtime_error( - "Water item with geometry=" + std::string(geom->getGeometryName()) + - " is not yet supported.")); - } - build_water_relation_with_tags(feat, exterior_way_ids, interior_way_ids, - rel_buffer); - } - - node_buffer.commit(); - way_buffer.commit(); - rel_buffer.commit(); -} - /** * \brief adds water polygons as Relations to m_buffer */ @@ -2185,27 +2040,6 @@ void add_admin_shape( writer(std::move(rel_buffer)); } -void add_water_shape(boost::filesystem::path water_shape_file, - osmium::io::Writer &writer) { - g_way_end_points_map.clear(); - auto ds = open_shape_file(water_shape_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(water_shape_file.string())); - assert(layer->GetGeomType() == wkbPolygon || - layer->GetGeomType() == wkbLineString); - osmium::memory::Buffer node_buffer(buffer_size); - osmium::memory::Buffer way_buffer(buffer_size); - osmium::memory::Buffer rel_buffer(buffer_size); - for (auto &feat : *layer) { - process_water(feat, node_buffer, way_buffer, rel_buffer); - } - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); - writer(std::move(rel_buffer)); - g_way_end_points_map.clear(); -} - void add_building_shape(boost::filesystem::path landmark_shape_file, osmium::io::Writer &writer) { auto ds = open_shape_file(landmark_shape_file); diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index b55f449..1bbe5cc 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -20,8 +20,7 @@ static const boost::filesystem::path ADMINBNDY_2_SHP = "Adminbndy2.shp"; static const boost::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; static const boost::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; static const boost::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; -static const boost::filesystem::path WATER_SEG_SHP = "WaterSeg.shp"; -static const boost::filesystem::path WATER_POLY_SHP = "WaterPoly.shp"; + static const boost::filesystem::path RAILWAYS_POLY_SHP = "RailRds.shp"; static const boost::filesystem::path LAND_USE_A_SHP = "LandUseA.shp"; static const boost::filesystem::path LAND_USE_B_SHP = "LandUseB.shp"; diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 36cc773..9ccbac2 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -32,7 +32,7 @@ navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) // setting executable_path in navteq2osm_tag_parser.hpp for reading ISO-file g_executable_path = this->executable_path; - converter.push_back(std::make_unique()); + converter.emplace_back(new WaterConverter()); } navteq_plugin::~navteq_plugin() {} @@ -200,16 +200,6 @@ void navteq_plugin::add_administrative_boundaries( g_way_end_points_map.clear(); } -void navteq_plugin::add_water(const std::vector &dirs, - osmium::io::Writer &writer) { - for (auto dir : dirs) { - if (shp_file_exists(dir / WATER_POLY_SHP)) - add_water_shape(dir / WATER_POLY_SHP, writer); - if (shp_file_exists(dir / WATER_SEG_SHP)) - add_water_shape(dir / WATER_SEG_SHP, writer); - } -} - void navteq_plugin::add_railways( const std::vector &dirs, osmium::io::Writer &writer) { From 12596589899b9f8f396e0a916812cb64cacaedbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 09:18:56 +0000 Subject: [PATCH 04/57] chore: Refactor Converter.cpp and Converter.hpp --- plugins/navteq/converter/Converter.cpp | 55 ++++++++++++++++----- plugins/navteq/converter/Converter.hpp | 4 +- plugins/navteq/converter/WaterConverter.cpp | 3 -- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 81e936d..6235eaa 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -117,6 +117,13 @@ Converter::create_open_way_nodes(const OGRLineString *line, return osm_way_node_ids; } +/** + * \brief Creates a closed way from OGRLinearRing. + * + * \param ring OGRLinearRing to create way from. + * \param node_buffer Buffer to store nodes. + * \param way_buffer Buffer to store ways. + * */ std::vector Converter::build_closed_ways(const OGRLinearRing *ring, osmium::memory::Buffer &node_buffer, @@ -127,9 +134,8 @@ Converter::build_closed_ways(const OGRLinearRing *ring, size_t i = 0; do { osmium::builder::WayBuilder builder(way_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER.data()); + setObjectProperties(builder); + osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &builder); for (size_t j = i; j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) @@ -141,6 +147,12 @@ Converter::build_closed_ways(const OGRLinearRing *ring, return osm_way_ids; } +/** + * \brief Creates a closed way from OGRLinearRing. + * + * \param ring OGRLinearRing to create way from. + * \param node_buffer Buffer to store nodes. + * */ std::vector> Converter::create_closed_way_nodes(const OGRLinearRing *ring, osmium::memory::Buffer &node_buffer) { @@ -168,19 +180,40 @@ Converter::create_closed_way_nodes(const OGRLinearRing *ring, return osm_way_node_ids; } +/** + * \brief Creates a node from location. + * + * \param location Location to create node from. + * \param node_buffer Buffer to store nodes. + * */ osmium::unsigned_object_id_type Converter::build_node(const osmium::Location &location, osmium::memory::Buffer &node_buffer) { osmium::builder::NodeBuilder builder(node_buffer); - return build_node(location, &builder); + return build_node(location, builder); } +/** + * \brief Creates a node from location. + * + * \param location Location to create node from. + * \param builder NodeBuilder to create node from. + * */ osmium::unsigned_object_id_type Converter::build_node(const osmium::Location &location, - osmium::builder::NodeBuilder *builder) { - builder->object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder->object()); - builder->set_user(USER.data()); - builder->object().set_location(location); - return builder->object().id(); -} \ No newline at end of file + osmium::builder::NodeBuilder &builder) { + setObjectProperties(builder); + builder.object().set_location(location); + return builder.object().id(); +} + +/** + * \brief Sets object properties. + * + * \param builder Builder to set properties to. + * */ +template void Converter::setObjectProperties(T &builder) { + builder.object().set_id(g_osm_id++); + set_dummy_osm_object_attributes(builder.object()); + builder.set_user(USER.data()); +} diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 9998121..930c28e 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -94,7 +94,9 @@ class Converter { osmium::unsigned_object_id_type build_node(const osmium::Location &location, - osmium::builder::NodeBuilder *builder); + osmium::builder::NodeBuilder &builder); + + template void setObjectProperties(T &builder); static constexpr int BUFFER_SIZE = 10 * 1000 * 1000; diff --git a/plugins/navteq/converter/WaterConverter.cpp b/plugins/navteq/converter/WaterConverter.cpp index 9ae9f03..ae6b494 100644 --- a/plugins/navteq/converter/WaterConverter.cpp +++ b/plugins/navteq/converter/WaterConverter.cpp @@ -184,9 +184,6 @@ osmium::unsigned_object_id_type WaterConverter::build_water_relation_with_tags( return builder.object().id(); } -/** - * \brief adds navteq water tags to Relation - */ void WaterConverter::build_water_poly_taglist( osmium::builder::RelationBuilder &builder, const OGRFeatureUniquePtr &feat) { From 23a26d401a60477069e4bdd4c34d18e5bf3b57d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 09:38:03 +0000 Subject: [PATCH 05/57] extract Railways --- plugins/navteq/converter/Converter.hpp | 3 + plugins/navteq/converter/RailwayConverter.cpp | 77 +++++++++++++++++++ plugins/navteq/converter/RailwayConverter.hpp | 45 +++++++++++ plugins/navteq/navteq.hpp | 35 --------- plugins/navteq/navteq_plugin.cpp | 13 ++-- plugins/navteq/navteq_plugin.hpp | 3 +- plugins/util.hpp | 6 ++ 7 files changed, 139 insertions(+), 43 deletions(-) create mode 100644 plugins/navteq/converter/RailwayConverter.cpp create mode 100644 plugins/navteq/converter/RailwayConverter.hpp diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 930c28e..76e9432 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -108,6 +108,9 @@ class Converter { static constexpr std::string_view USERID = "1"; static constexpr int TIMESTAMP = 1; + static constexpr std::string_view YES = "yes"; + static constexpr std::string_view NO = "no"; + static osmium::unsigned_object_id_type g_osm_id; }; diff --git a/plugins/navteq/converter/RailwayConverter.cpp b/plugins/navteq/converter/RailwayConverter.cpp new file mode 100644 index 0000000..dfcb922 --- /dev/null +++ b/plugins/navteq/converter/RailwayConverter.cpp @@ -0,0 +1,77 @@ +#include "RailwayConverter.hpp" + +#include +#include +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" + +RailwayConverter::RailwayConverter() {} + +RailwayConverter::~RailwayConverter() {} + +void RailwayConverter::convert(const std::vector &dirs, + osmium::io::Writer &writer) { + + const boost::filesystem::path RAILWAYS_POLY_SHP = "RailRds.shp"; + + for (auto dir : dirs) { + add_railways_shape(dir / RAILWAYS_POLY_SHP, writer); + } +} + +void RailwayConverter::add_railways_shape( + boost::filesystem::path railway_shape_file, osmium::io::Writer &writer) { + g_way_end_points_map.clear(); + auto ds = GDALDatasetUniquePtr(GDALDataset::Open(railway_shape_file.c_str())); + auto layer = ds->GetLayer(0); + if (layer == nullptr) { + BOOST_LOG_TRIVIAL(debug) + << "No railway layer found in " << railway_shape_file; + return; + } + assert(layer->GetGeomType() == OGRwkbGeometryType::wkbPolygon || + layer->GetGeomType() == OGRwkbGeometryType::wkbLineString); + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + for (auto &feat : *layer) { + process_railways(feat, node_buffer, way_buffer); + } + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); + g_way_end_points_map.clear(); +} + +void RailwayConverter::process_railways(const OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer) { + auto osm_way_node_ids = create_open_way_nodes( + static_cast(feat->GetGeometryRef()), node_buffer); + { + osmium::builder::WayBuilder builder(way_buffer); + setObjectProperties(builder); + { + osmium::builder::TagListBuilder tl_builder(builder); + tl_builder.add_tag("railway", "rail"); + tl_builder.add_tag("usage", "main"); + + if (parse_bool(feat->GetFieldAsString(BRIDGE.data()))) + tl_builder.add_tag("bridge", YES.data()); + + if (parse_bool(feat->GetFieldAsString(TUNNEL.data()))) + tl_builder.add_tag("tunnel", YES.data()); + } + { + osmium::builder::WayNodeListBuilder wnl_builder(builder); + for (auto osm_way_node_id : osm_way_node_ids) { + wnl_builder.add_node_ref(osm_way_node_id.second, osm_way_node_id.first); + } + } + } + node_buffer.commit(); + way_buffer.commit(); +} \ No newline at end of file diff --git a/plugins/navteq/converter/RailwayConverter.hpp b/plugins/navteq/converter/RailwayConverter.hpp new file mode 100644 index 0000000..f0ae025 --- /dev/null +++ b/plugins/navteq/converter/RailwayConverter.hpp @@ -0,0 +1,45 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef RAILWAYCONVERTER_HPP +#define RAILWAYCONVERTER_HPP + +#include "Converter.hpp" + +#include + +class RailwayConverter : public Converter { + +public: + RailwayConverter(); + virtual ~RailwayConverter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer); + +private: + void add_railways_shape(boost::filesystem::path railway_shape_file, + osmium::io::Writer &writer); + + void process_railways(const OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + static constexpr std::string_view BRIDGE = "BRIDGE"; + static constexpr std::string_view TUNNEL = "TUNNEL"; +}; + +#endif // RAILWAYCONVERTER_HPP diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index 9b7cf0f..e7d3c34 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -1168,41 +1168,6 @@ void process_building(const OGRFeatureUniquePtr &feat, way_buffer.commit(); } -void process_railways(const OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - - const OGRLineString *line = - static_cast(feat->GetGeometryRef()); - - node_vector_type osm_way_node_ids = create_open_way_nodes(line, node_buffer); - { - osmium::builder::WayBuilder builder(way_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER); - { - osmium::builder::TagListBuilder tl_builder(builder); - tl_builder.add_tag("railway", "rail"); - tl_builder.add_tag("usage", "main"); - - if (parse_bool(feat->GetFieldAsString(BRIDGE))) - tl_builder.add_tag("bridge", YES); - - if (parse_bool(feat->GetFieldAsString(TUNNEL))) - tl_builder.add_tag("tunnel", YES); - } - { - osmium::builder::WayNodeListBuilder wnl_builder(builder); - for (auto osm_way_node_id : osm_way_node_ids) { - wnl_builder.add_node_ref(osm_way_node_id.second, osm_way_node_id.first); - } - } - } - node_buffer.commit(); - way_buffer.commit(); -} - /** * \brief adds landuse polygons as Relations to m_buffer */ diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 9ccbac2..18e1dbf 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -16,7 +16,9 @@ #include #include +#include "converter/RailwayConverter.hpp" #include "converter/WaterConverter.hpp" + #include "navteq.hpp" #include "navteq_plugin.hpp" #include "navteq_util.hpp" @@ -32,6 +34,7 @@ navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) // setting executable_path in navteq2osm_tag_parser.hpp for reading ISO-file g_executable_path = this->executable_path; + converter.emplace_back(new RailwayConverter()); converter.emplace_back(new WaterConverter()); } @@ -254,9 +257,6 @@ void navteq_plugin::execute() { BOOST_LOG_TRIVIAL(info) << "Add administrative boundaries"; add_administrative_boundaries(dataDirs, writer); - BOOST_LOG_TRIVIAL(info) << "Add water"; - add_water(dataDirs, writer); - BOOST_LOG_TRIVIAL(info) << "Add landuse"; add_landuse(dataDirs, writer); @@ -266,15 +266,16 @@ void navteq_plugin::execute() { BOOST_LOG_TRIVIAL(info) << "Add hamlet nodes"; add_hamlet_nodes(dataDirs, writer); - BOOST_LOG_TRIVIAL(info) << "Add railways"; - add_railways(dataDirs, writer); - BOOST_LOG_TRIVIAL(info) << "Add buildings"; add_buildings(dataDirs, writer); BOOST_LOG_TRIVIAL(info) << "Add rest areas"; add_rest_area_nodes(dataDirs, writer); + // run converters + for (auto &c : converter) + c->convert(dataDirs, writer); + writer.close(); BOOST_LOG_TRIVIAL(info) << "Start sorting PBF "; diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index b4c3d9e..16b447c 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -30,8 +30,7 @@ class navteq_plugin : public base_plugin { void add_administrative_boundaries( const std::vector &dirs, osmium::io::Writer &writer); - void add_water(const std::vector &dirs, - osmium::io::Writer &writer); + void add_landuse(const std::vector &dirs, osmium::io::Writer &writer); void add_railways(const std::vector &dirs, diff --git a/plugins/util.hpp b/plugins/util.hpp index 5f25dd4..52681a7 100644 --- a/plugins/util.hpp +++ b/plugins/util.hpp @@ -245,4 +245,10 @@ bool checkInBoundingBox(const OGREnvelope &boundingBox, return result; } +bool parse_bool(const char *value) { + if (!strcmp(value, "Y")) + return true; + return false; +} + #endif /* UTIL_HPP_ */ From 962acd0d2416075109a143252cec66301216ee90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 12:04:00 +0000 Subject: [PATCH 06/57] add building converter --- .../navteq/converter/BuildingConverter.cpp | 118 ++++++++++++++++++ .../navteq/converter/BuildingConverter.hpp | 48 +++++++ plugins/navteq/converter/Converter.cpp | 44 ++++--- plugins/navteq/converter/Converter.hpp | 25 +++- plugins/navteq/converter/RailwayConverter.cpp | 43 +++++-- plugins/navteq/converter/RailwayConverter.hpp | 9 +- plugins/navteq/converter/WaterConverter.cpp | 56 +++++---- plugins/navteq/converter/WaterConverter.hpp | 11 +- plugins/navteq/navteq.hpp | 83 ------------ plugins/navteq/navteq2osm_tag_parser.hpp | 7 -- plugins/navteq/navteq_plugin.cpp | 20 --- plugins/navteq/navteq_plugin.hpp | 3 +- 12 files changed, 293 insertions(+), 174 deletions(-) create mode 100644 plugins/navteq/converter/BuildingConverter.cpp create mode 100644 plugins/navteq/converter/BuildingConverter.hpp diff --git a/plugins/navteq/converter/BuildingConverter.cpp b/plugins/navteq/converter/BuildingConverter.cpp new file mode 100644 index 0000000..782e60b --- /dev/null +++ b/plugins/navteq/converter/BuildingConverter.cpp @@ -0,0 +1,118 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "BuildingConverter.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" + +BuildingConverter::BuildingConverter() {} + +BuildingConverter::~BuildingConverter() {} + +void BuildingConverter::convert( + const std::vector &dirs, + osmium::io::Writer &writer) { + + static const boost::filesystem::path LANDMARK_SHP = "Landmark.shp"; + + for (auto dir : dirs) { + add_building_shape(dir / LANDMARK_SHP, writer); + } +} + +void BuildingConverter::add_building_shape( + boost::filesystem::path landmark_shape_file, osmium::io::Writer &writer) { + + auto ds = + GDALDatasetUniquePtr(GDALDataset::Open(landmark_shape_file.c_str())); + if (!ds) { + BOOST_LOG_TRIVIAL(debug) + << "No building shp found in " << landmark_shape_file; + return; + } + auto layer = ds->GetLayer(0); + if (!layer) { + throw(shp_empty_error(landmark_shape_file.string())); + } + + assert(layer->GetGeomType() == wkbPolygon || + layer->GetGeomType() == wkbLineString); + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + + std::map + g_way_end_points_map; + for (auto &feat : *layer) { + if (!strcmp(feat->GetFieldAsString(FEAT_COD.data()), "2005999")) { + process_building(feat, g_way_end_points_map, node_buffer, way_buffer); + } + } + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); +} + +void BuildingConverter::process_building( + const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { + auto geom = feat->GetGeometryRef(); + + auto osm_way_node_ids = create_closed_way_nodes( + static_cast(geom)->getExteriorRing(), g_way_end_points_map, + node_buffer); + + std::vector osm_way_ids; + size_t i = 0; + do { + osmium::builder::WayBuilder builder(way_buffer); + setObjectProperties(builder); + { + osmium::builder::WayNodeListBuilder wnl_builder(builder); + for (size_t j = i; + j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) { + const auto [location, osm_id] = osm_way_node_ids.at(j); + wnl_builder.add_node_ref(osm_id, location); + } + } + osm_way_ids.push_back(builder.object().id()); + i += OSM_MAX_WAY_NODES - 1; + build_building_poly_taglist(builder, feat); + } while (i < osm_way_node_ids.size()); + node_buffer.commit(); + way_buffer.commit(); +} + +void BuildingConverter::build_building_poly_taglist( + osmium::builder::WayBuilder &builder, const OGRFeatureUniquePtr &feat) { + // Mind tl_builder scope! + osmium::builder::TagListBuilder tl_builder(builder); + tl_builder.add_tag("building", "yes"); + + std::string name = feat->GetFieldAsString(POLYGON_NM.data()); + std::string building_name = to_camel_case_with_spaces(name); + if (!building_name.empty()) + tl_builder.add_tag("name", building_name); +} \ No newline at end of file diff --git a/plugins/navteq/converter/BuildingConverter.hpp b/plugins/navteq/converter/BuildingConverter.hpp new file mode 100644 index 0000000..fa24513 --- /dev/null +++ b/plugins/navteq/converter/BuildingConverter.hpp @@ -0,0 +1,48 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef BUILDINGCONVERTER_HPP +#define BUILDINGCONVERTER_HPP + +#include "Converter.hpp" + +#include + +class BuildingConverter : public Converter { + +public: + BuildingConverter(); + virtual ~BuildingConverter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer); + +private: + void add_building_shape(boost::filesystem::path landmark_shape_file, + osmium::io::Writer &writer); + + void + process_building(const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + void build_building_poly_taglist(osmium::builder::WayBuilder &builder, + const OGRFeatureUniquePtr &feat); +}; + +#endif // BUILDINGCONVERTER_HPP diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 6235eaa..e8b946b 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -55,11 +55,13 @@ void Converter::create_multi_polygon( OGRMultiPolygon *mp, std::vector &mp_ext_ring_osm_ids, std::vector &mp_int_ring_osm_ids, + std::map + &g_way_end_points_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { for (const OGRPolygon *poly : mp) { - create_polygon(poly, mp_ext_ring_osm_ids, mp_int_ring_osm_ids, node_buffer, - way_buffer); + create_polygon(poly, mp_ext_ring_osm_ids, mp_int_ring_osm_ids, + g_way_end_points_map, node_buffer, way_buffer); } } @@ -76,10 +78,13 @@ void Converter::create_polygon( const OGRPolygon *poly, std::vector &exterior_way_ids, std::vector &interior_way_ids, + std::map + &g_way_end_points_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { bool isExteriorRing = true; // first ring is the exterior ring for (const auto ring : *poly) { - auto tmp = build_closed_ways(ring, node_buffer, way_buffer); + auto tmp = + build_closed_ways(ring, g_way_end_points_map, node_buffer, way_buffer); if (isExteriorRing) { std::move(tmp.begin(), tmp.end(), std::back_inserter(exterior_way_ids)); } else { @@ -97,8 +102,11 @@ void Converter::create_polygon( * \param way_buffer Buffer to store ways. * */ std::vector> -Converter::create_open_way_nodes(const OGRLineString *line, - osmium::memory::Buffer &node_buffer) { +Converter::create_open_way_nodes( + const OGRLineString *line, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer) { std::vector> osm_way_node_ids; @@ -124,11 +132,13 @@ Converter::create_open_way_nodes(const OGRLineString *line, * \param node_buffer Buffer to store nodes. * \param way_buffer Buffer to store ways. * */ -std::vector -Converter::build_closed_ways(const OGRLinearRing *ring, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - auto osm_way_node_ids = create_closed_way_nodes(ring, node_buffer); +std::vector Converter::build_closed_ways( + const OGRLinearRing *ring, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { + auto osm_way_node_ids = + create_closed_way_nodes(ring, g_way_end_points_map, node_buffer); std::vector osm_way_ids; size_t i = 0; @@ -138,9 +148,10 @@ Converter::build_closed_ways(const OGRLinearRing *ring, osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &builder); for (size_t j = i; - j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) - wnl_builder.add_node_ref(osm_way_node_ids.at(j).second, - osm_way_node_ids.at(j).first); + j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) { + const auto [location, osm_id] = osm_way_node_ids.at(j); + wnl_builder.add_node_ref(osm_id, location); + } osm_way_ids.push_back(builder.object().id()); i += OSM_MAX_WAY_NODES - 1; } while (i < osm_way_node_ids.size()); @@ -154,8 +165,11 @@ Converter::build_closed_ways(const OGRLinearRing *ring, * \param node_buffer Buffer to store nodes. * */ std::vector> -Converter::create_closed_way_nodes(const OGRLinearRing *ring, - osmium::memory::Buffer &node_buffer) { +Converter::create_closed_way_nodes( + const OGRLinearRing *ring, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer) { std::vector> osm_way_node_ids; for (auto &point : *ring) { diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 76e9432..698c2b4 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -18,6 +18,7 @@ #define CONVERTER_HPP #include +#include #include #include #include @@ -33,6 +34,7 @@ class Writer; namespace builder { class RelationBuilder; class NodeBuilder; +class WayBuilder; } // namespace builder namespace memory { @@ -66,27 +68,39 @@ class Converter { OGRMultiPolygon *mp, std::vector &mp_ext_ring_osm_ids, std::vector &mp_int_ring_osm_ids, + std::map + &g_way_end_points_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); void create_polygon(const OGRPolygon *poly, std::vector &exterior_way_ids, std::vector &interior_way_ids, + std::map + &g_way_end_points_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); std::vector> - create_open_way_nodes(const OGRLineString *line, - osmium::memory::Buffer &node_buffer); + create_open_way_nodes( + const OGRLineString *line, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer); std::vector build_closed_ways(const OGRLinearRing *ring, + std::map + &g_way_end_points_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); std::vector> - create_closed_way_nodes(const OGRLinearRing *ring, - osmium::memory::Buffer &node_buffer); + create_closed_way_nodes( + const OGRLinearRing *ring, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer); osmium::unsigned_object_id_type build_node(const osmium::Location &location, @@ -112,6 +126,9 @@ class Converter { static constexpr std::string_view NO = "no"; static osmium::unsigned_object_id_type g_osm_id; + + static constexpr std::string_view FEAT_COD = "FEAT_COD"; + static constexpr std::string_view POLYGON_NM = "POLYGON_NM"; }; #endif // CONVERTER_HPP diff --git a/plugins/navteq/converter/RailwayConverter.cpp b/plugins/navteq/converter/RailwayConverter.cpp index dfcb922..df87d72 100644 --- a/plugins/navteq/converter/RailwayConverter.cpp +++ b/plugins/navteq/converter/RailwayConverter.cpp @@ -1,3 +1,19 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + #include "RailwayConverter.hpp" #include @@ -26,31 +42,38 @@ void RailwayConverter::convert(const std::vector &dirs, void RailwayConverter::add_railways_shape( boost::filesystem::path railway_shape_file, osmium::io::Writer &writer) { - g_way_end_points_map.clear(); + auto ds = GDALDatasetUniquePtr(GDALDataset::Open(railway_shape_file.c_str())); - auto layer = ds->GetLayer(0); - if (layer == nullptr) { + if (!ds) { BOOST_LOG_TRIVIAL(debug) - << "No railway layer found in " << railway_shape_file; + << "No railway shp found in " << railway_shape_file; return; } + auto layer = ds->GetLayer(0); + if (!layer) { + throw(shp_empty_error(railway_shape_file.string())); + } assert(layer->GetGeomType() == OGRwkbGeometryType::wkbPolygon || layer->GetGeomType() == OGRwkbGeometryType::wkbLineString); osmium::memory::Buffer node_buffer(BUFFER_SIZE); osmium::memory::Buffer way_buffer(BUFFER_SIZE); + std::map + g_way_end_points_map; for (auto &feat : *layer) { - process_railways(feat, node_buffer, way_buffer); + process_railways(feat, g_way_end_points_map, node_buffer, way_buffer); } writer(std::move(node_buffer)); writer(std::move(way_buffer)); - g_way_end_points_map.clear(); } -void RailwayConverter::process_railways(const OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { +void RailwayConverter::process_railways( + const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { auto osm_way_node_ids = create_open_way_nodes( - static_cast(feat->GetGeometryRef()), node_buffer); + static_cast(feat->GetGeometryRef()), + g_way_end_points_map, node_buffer); { osmium::builder::WayBuilder builder(way_buffer); setObjectProperties(builder); diff --git a/plugins/navteq/converter/RailwayConverter.hpp b/plugins/navteq/converter/RailwayConverter.hpp index f0ae025..b8c4eac 100644 --- a/plugins/navteq/converter/RailwayConverter.hpp +++ b/plugins/navteq/converter/RailwayConverter.hpp @@ -34,9 +34,12 @@ class RailwayConverter : public Converter { void add_railways_shape(boost::filesystem::path railway_shape_file, osmium::io::Writer &writer); - void process_railways(const OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer); + void + process_railways(const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); static constexpr std::string_view BRIDGE = "BRIDGE"; static constexpr std::string_view TUNNEL = "TUNNEL"; diff --git a/plugins/navteq/converter/WaterConverter.cpp b/plugins/navteq/converter/WaterConverter.cpp index ae6b494..7a33d36 100644 --- a/plugins/navteq/converter/WaterConverter.cpp +++ b/plugins/navteq/converter/WaterConverter.cpp @@ -43,13 +43,15 @@ void WaterConverter::convert(const std::vector &dirs, void WaterConverter::add_water_shape(boost::filesystem::path water_shape_file, osmium::io::Writer &writer) { - g_way_end_points_map.clear(); auto ds = GDALDatasetUniquePtr(GDALDataset::Open(water_shape_file.c_str())); + if (!ds) { + BOOST_LOG_TRIVIAL(debug) << "No water shp found in " << water_shape_file; + return; + } auto layer = ds->GetLayer(0); if (layer == nullptr) { - BOOST_LOG_TRIVIAL(debug) << "No water layer found in " << water_shape_file; - return; + throw(shp_empty_error(water_shape_file.string())); } assert(layer->GetGeomType() == wkbPolygon || @@ -57,40 +59,47 @@ void WaterConverter::add_water_shape(boost::filesystem::path water_shape_file, osmium::memory::Buffer node_buffer(BUFFER_SIZE); osmium::memory::Buffer way_buffer(BUFFER_SIZE); osmium::memory::Buffer rel_buffer(BUFFER_SIZE); + + std::map + g_way_end_points_map; for (const auto &feat : *layer) { - process_water(feat, node_buffer, way_buffer, rel_buffer); + process_water(feat, g_way_end_points_map, node_buffer, way_buffer, + rel_buffer); } writer(std::move(node_buffer)); writer(std::move(way_buffer)); writer(std::move(rel_buffer)); - g_way_end_points_map.clear(); } /** * \brief adds water polygons as Relations to m_buffer */ -void WaterConverter::process_water(const OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer, - osmium::memory::Buffer &rel_buffer) { +void WaterConverter::process_water( + const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer, + osmium::memory::Buffer &rel_buffer) { auto geom = feat->GetGeometryRef(); auto geom_type = geom->getGeometryType(); if (geom_type == OGRwkbGeometryType::wkbLineString) { // handle water ways build_water_ways_with_tagList(feat, static_cast(geom), - node_buffer, way_buffer); + g_way_end_points_map, node_buffer, + way_buffer); } else { // handle water polygons std::vector exterior_way_ids; std::vector interior_way_ids; if (geom_type == OGRwkbGeometryType::wkbMultiPolygon) { create_multi_polygon(static_cast(geom), - exterior_way_ids, interior_way_ids, node_buffer, - way_buffer); + exterior_way_ids, interior_way_ids, + g_way_end_points_map, node_buffer, way_buffer); } else if (geom_type == OGRwkbGeometryType::wkbPolygon) { create_polygon(static_cast(geom), exterior_way_ids, - interior_way_ids, node_buffer, way_buffer); + interior_way_ids, g_way_end_points_map, node_buffer, + way_buffer); } else { throw(std::runtime_error( "Water item with geometry=" + std::string(geom->getGeometryName()) + @@ -108,26 +117,29 @@ void WaterConverter::process_water(const OGRFeatureUniquePtr &feat, std::vector WaterConverter::build_water_ways_with_tagList( const OGRFeatureUniquePtr &feat, OGRLineString *line, + std::map + &g_way_end_points_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { - auto osm_way_node_ids = create_open_way_nodes(line, node_buffer); + auto osm_way_node_ids = + create_open_way_nodes(line, g_way_end_points_map, node_buffer); std::vector osm_way_ids; size_t i = 0; do { osmium::builder::WayBuilder builder(way_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER.data()); + setObjectProperties(builder); build_water_way_taglist(builder, feat); osmium::builder::WayNodeListBuilder wnl_builder(builder); for (size_t j = i; - j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) - wnl_builder.add_node_ref(osm_way_node_ids.at(j).second, - osm_way_node_ids.at(j).first); + j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) { + const auto [location, osm_id] = osm_way_node_ids.at(j); + wnl_builder.add_node_ref(osm_id, location); + } osm_way_ids.push_back(builder.object().id()); i += OSM_MAX_WAY_NODES - 1; } while (i < osm_way_node_ids.size()); + return osm_way_ids; } @@ -175,9 +187,7 @@ osmium::unsigned_object_id_type WaterConverter::build_water_relation_with_tags( std::vector int_osm_way_ids, osmium::memory::Buffer &rel_buffer) { osmium::builder::RelationBuilder builder(rel_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER.data()); + setObjectProperties(builder); build_water_poly_taglist(builder, feat); build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); diff --git a/plugins/navteq/converter/WaterConverter.hpp b/plugins/navteq/converter/WaterConverter.hpp index 1e4922a..13b0978 100644 --- a/plugins/navteq/converter/WaterConverter.hpp +++ b/plugins/navteq/converter/WaterConverter.hpp @@ -50,12 +50,16 @@ class WaterConverter : public Converter { osmium::io::Writer &writer); void process_water(const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer, osmium::memory::Buffer &rel_buffer); std::vector build_water_ways_with_tagList( const OGRFeatureUniquePtr &feat, OGRLineString *line, + std::map + &g_way_end_points_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); void build_water_way_taglist(osmium::builder::WayBuilder &builder, @@ -69,13 +73,6 @@ class WaterConverter : public Converter { void build_water_poly_taglist(osmium::builder::RelationBuilder &builder, const OGRFeatureUniquePtr &feat); - - // maps location of way end nodes to node ids - std::map - g_way_end_points_map; - - static constexpr std::string_view POLYGON_NM = "POLYGON_NM"; - static constexpr std::string_view FEAT_COD = "FEAT_COD"; }; #endif // WATERCONVERTER_HPP \ No newline at end of file diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index e7d3c34..f001cca 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -890,18 +890,6 @@ void build_admin_boundary_taglist(osmium::builder::Builder &builder, tl_builder.add_tag("admin_level", navteq_2_osm_admin_lvl(level)); } -void build_building_poly_taglist(osmium::builder::WayBuilder &builder, - const OGRFeatureUniquePtr &feat) { - // Mind tl_builder scope! - osmium::builder::TagListBuilder tl_builder(builder); - tl_builder.add_tag("building", "yes"); - - std::string name = feat->GetFieldAsString(POLYGON_NM); - std::string building_name = to_camel_case_with_spaces(name); - if (!building_name.empty()) - tl_builder.add_tag("name", building_name); -} - /** * \brief adds navteq landuse tags to Relation */ @@ -1135,39 +1123,6 @@ void process_admin_boundary( way_buffer.commit(); } -/** - * \brief adds water polygons as Relations to m_buffer - */ -void process_building(const OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - auto geom = feat->GetGeometryRef(); - - node_vector_type osm_way_node_ids = create_closed_way_nodes( - static_cast(geom)->getExteriorRing(), node_buffer); - - osm_id_vector_type osm_way_ids; - size_t i = 0; - do { - osmium::builder::WayBuilder builder(way_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER); - { - osmium::builder::WayNodeListBuilder wnl_builder(builder); - for (size_t j = i; - j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) - wnl_builder.add_node_ref(osm_way_node_ids.at(j).second, - osm_way_node_ids.at(j).first); - } - osm_way_ids.push_back(builder.object().id()); - i += OSM_MAX_WAY_NODES - 1; - build_building_poly_taglist(builder, feat); - } while (i < osm_way_node_ids.size()); - node_buffer.commit(); - way_buffer.commit(); -} - /** * \brief adds landuse polygons as Relations to m_buffer */ @@ -2005,44 +1960,6 @@ void add_admin_shape( writer(std::move(rel_buffer)); } -void add_building_shape(boost::filesystem::path landmark_shape_file, - osmium::io::Writer &writer) { - auto ds = open_shape_file(landmark_shape_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(landmark_shape_file.string())); - assert(layer->GetGeomType() == wkbPolygon || - layer->GetGeomType() == wkbLineString); - osmium::memory::Buffer node_buffer(buffer_size); - osmium::memory::Buffer way_buffer(buffer_size); - for (auto &feat : *layer) { - if (!strcmp(feat->GetFieldAsString(FEAT_COD), "2005999")) { - process_building(feat, node_buffer, way_buffer); - } - } - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); -} - -void add_railways_shape(boost::filesystem::path water_shape_file, - osmium::io::Writer &writer) { - g_way_end_points_map.clear(); - auto ds = open_shape_file(water_shape_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(water_shape_file.string())); - assert(layer->GetGeomType() == wkbPolygon || - layer->GetGeomType() == wkbLineString); - osmium::memory::Buffer node_buffer(buffer_size); - osmium::memory::Buffer way_buffer(buffer_size); - for (auto &feat : *layer) { - process_railways(feat, node_buffer, way_buffer); - } - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); - g_way_end_points_map.clear(); -} - void add_landuse_shape(boost::filesystem::path landuse_shape_file, osmium::io::Writer &writer) { g_way_end_points_map.clear(); diff --git a/plugins/navteq/navteq2osm_tag_parser.hpp b/plugins/navteq/navteq2osm_tag_parser.hpp index 67e3cdc..71f0f72 100644 --- a/plugins/navteq/navteq2osm_tag_parser.hpp +++ b/plugins/navteq/navteq2osm_tag_parser.hpp @@ -13,13 +13,6 @@ const boost::filesystem::path PLUGINS_NAVTEQ_ISO_639_2_UTF_8_TXT("plugins/navteq/ISO-639-2_utf-8.txt"); int ctr = 0; -// helper -bool parse_bool(const char *value) { - if (!strcmp(value, "Y")) - return true; - return false; -} - bool fits_street_ref(const std::string &st_name) { if (st_name.empty()) return false; diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 18e1dbf..1e646a5 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -203,26 +203,6 @@ void navteq_plugin::add_administrative_boundaries( g_way_end_points_map.clear(); } -void navteq_plugin::add_railways( - const std::vector &dirs, - osmium::io::Writer &writer) { - for (auto dir : dirs) { - if (shp_file_exists(dir / RAILWAYS_POLY_SHP)) - add_railways_shape(dir / RAILWAYS_POLY_SHP, writer); - } -} - -void navteq_plugin::add_buildings( - const std::vector &dirs, - osmium::io::Writer &writer) { - g_way_end_points_map.clear(); - for (auto dir : dirs) { - if (shp_file_exists(dir / LANDMARK_SHP)) - add_building_shape(dir / LANDMARK_SHP, writer); - } - g_way_end_points_map.clear(); -} - void navteq_plugin::add_landuse( const std::vector &dirs, osmium::io::Writer &writer) { diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index 16b447c..83ebffa 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -33,8 +33,7 @@ class navteq_plugin : public base_plugin { void add_landuse(const std::vector &dirs, osmium::io::Writer &writer); - void add_railways(const std::vector &dirs, - osmium::io::Writer &writer); + void add_buildings(const std::vector &dirs, osmium::io::Writer &writer); From 02f243d03493506038388e2e47454aa63c2a2bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 12:25:09 +0000 Subject: [PATCH 07/57] chore: Update file associations in .vscode/settings.json --- .vscode/settings.json | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9e89848..b21e0bd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { + "*.FTL": "csv", "cctype": "cpp", "clocale": "cpp", "cmath": "cpp", @@ -55,7 +56,24 @@ "stdexcept": "cpp", "streambuf": "cpp", "thread": "cpp", - "typeinfo": "cpp" + "typeinfo": "cpp", + "strstream": "cpp", + "bit": "cpp", + "charconv": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "source_location": "cpp", + "format": "cpp", + "numbers": "cpp", + "ranges": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "span": "cpp", + "stdfloat": "cpp", + "stop_token": "cpp", + "typeindex": "cpp", + "variant": "cpp" }, "C_Cpp.default.configurationProvider": "vector-of-bool.cmake-tools", "cmake.configureSettings": { From 58cc1fdb185938157c312d8afa186af7482c79b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 12:26:42 +0000 Subject: [PATCH 08/57] add rest areas --- plugins/navteq/converter/Converter.hpp | 4 + .../navteq/converter/RestAreaConverter.cpp | 89 +++++++++++++++++++ .../navteq/converter/RestAreaConverter.hpp | 41 +++++++++ plugins/navteq/navteq.hpp | 64 ------------- plugins/navteq/navteq_mappings.hpp | 3 - plugins/navteq/navteq_plugin.cpp | 10 +-- plugins/navteq/navteq_plugin.hpp | 3 - 7 files changed, 138 insertions(+), 76 deletions(-) create mode 100644 plugins/navteq/converter/RestAreaConverter.cpp create mode 100644 plugins/navteq/converter/RestAreaConverter.hpp diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 698c2b4..8ea3fb8 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -129,6 +129,10 @@ class Converter { static constexpr std::string_view FEAT_COD = "FEAT_COD"; static constexpr std::string_view POLYGON_NM = "POLYGON_NM"; + + static constexpr std::string_view FAC_TYPE = "FAC_TYPE"; + static constexpr std::string_view POI_NMTYPE = "POI_NMTYPE"; + static constexpr std::string_view POI_NAME = "POI_NAME"; }; #endif // CONVERTER_HPP diff --git a/plugins/navteq/converter/RestAreaConverter.cpp b/plugins/navteq/converter/RestAreaConverter.cpp new file mode 100644 index 0000000..1165deb --- /dev/null +++ b/plugins/navteq/converter/RestAreaConverter.cpp @@ -0,0 +1,89 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "RestAreaConverter.hpp" + +void RestAreaConverter::convert( + const std::vector &dirs, + osmium::io::Writer &writer) { + + const boost::filesystem::path TRAVDEST_SHP = "TravDest.shp"; + for (auto dir : dirs) { + add_rest_area(dir / TRAVDEST_SHP, writer); + } +} + +void RestAreaConverter::add_rest_area(boost::filesystem::path rest_area_file, + osmium::io::Writer &writer) { + + auto ds = GDALDatasetUniquePtr(GDALDataset::Open(rest_area_file.c_str())); + if (!ds) { + BOOST_LOG_TRIVIAL(debug) << "No rest area shp found in " << rest_area_file; + return; + } + auto layer = ds->GetLayer(0); + if (!layer) { + throw(shp_empty_error(rest_area_file.string())); + } + + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + + int facTypeField = layer->FindFieldIndex(FAC_TYPE.data(), true); + int poiNmTypeField = layer->FindFieldIndex(POI_NMTYPE.data(), true); + + for (auto &feat : *layer) { + uint fac_type = feat->GetFieldAsInteger(facTypeField); + if (fac_type != 7897) { + continue; + } + + std::string name_type = feat->GetFieldAsString(poiNmTypeField); + if (name_type != "B") { + // Skip this entry as it's just a translated namePlc of former one + continue; + } + process_rest_area(feat, node_buffer); + } + writer(std::move(node_buffer)); +} + +void RestAreaConverter::process_rest_area(const OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer) { + + auto geom = feat->GetGeometryRef(); + auto geom_type = geom->getGeometryType(); + + if (geom_type != wkbPoint) { + throw(std::runtime_error( + "Rest area item with geometry=" + std::string(geom->getGeometryName()) + + " is not yet supported.")); + } + + auto point = static_cast(geom); + osmium::Location location(point->getX(), point->getY()); + { + // scope node_builder + // Add new node + osmium::builder::NodeBuilder node_builder(node_buffer); + build_node(location, &node_builder); + osmium::builder::TagListBuilder tl_builder(node_builder); + + std::string name = feat->GetFieldAsString(POI_NAME.data()); + tl_builder.add_tag("name", to_camel_case_with_spaces(name)); + tl_builder.add_tag("highway", "rest_area"); + } + node_buffer.commit(); +} \ No newline at end of file diff --git a/plugins/navteq/converter/RestAreaConverter.hpp b/plugins/navteq/converter/RestAreaConverter.hpp new file mode 100644 index 0000000..a79017a --- /dev/null +++ b/plugins/navteq/converter/RestAreaConverter.hpp @@ -0,0 +1,41 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef RESTAREACONVERTER_HPP +#define RESTAREACONVERTER_HPP + +#include "Converter.hpp" + +#include + +class RestAreaConverter : public Converter { + +public: + RestAreaConverter(); + virtual ~RestAreaConverter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer); + +private: + void add_rest_area(boost::filesystem::path rest_area_file, + osmium::io::Writer &writer); + + void process_rest_area(const OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer); +}; + +#endif // RESTAREACONVERTER_HPP \ No newline at end of file diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index f001cca..d9c8fd1 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -1239,34 +1239,6 @@ void process_hamlets(const OGRFeatureUniquePtr &feat, node_buffer.commit(); } -void process_rest_area(const OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer) { - - auto geom = feat->GetGeometryRef(); - auto geom_type = geom->getGeometryType(); - - if (geom_type != wkbPoint) { - throw(std::runtime_error( - "Rest area item with geometry=" + std::string(geom->getGeometryName()) + - " is not yet supported.")); - } - - auto point = static_cast(geom); - osmium::Location location(point->getX(), point->getY()); - { - // scope node_builder - // Add new node - osmium::builder::NodeBuilder node_builder(node_buffer); - build_node(location, &node_builder); - osmium::builder::TagListBuilder tl_builder(node_builder); - - std::string name = feat->GetFieldAsString(POI_NAME); - tl_builder.add_tag("name", to_camel_case_with_spaces(name)); - tl_builder.add_tag("highway", "rest_area"); - } - node_buffer.commit(); -} - /** * \brief adds tags from administrative boundaries to mtd_area_map. * adds tags from administrative boundaries to mtd_area_map @@ -1435,42 +1407,6 @@ void add_hamlet_nodes(const std::vector &dirs, } } -void add_rest_area_nodes(const std::vector &dirs, - osmium::io::Writer &writer) { - - for (auto dir : dirs) { - - // hamlets are optional - if (!shp_file_exists(dir / TRAVDEST_SHP)) - continue; - - auto ds = open_shape_file(dir / TRAVDEST_SHP); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(dir.string())); - - osmium::memory::Buffer node_buffer(buffer_size); - - int facTypeField = layer->FindFieldIndex(FAC_TYPE, true); - int poiNmTypeField = layer->FindFieldIndex(POI_NMTYPE, true); - - for (auto &feat : *layer) { - uint fac_type = feat->GetFieldAsInteger(facTypeField); - if (fac_type != 7897) { - continue; - } - - std::string name_type = feat->GetFieldAsString(poiNmTypeField); - if (name_type != "B") { - // Skip this entry as it's just a translated namePlc of former one - continue; - } - process_rest_area(feat, node_buffer); - } - writer(std::move(node_buffer)); - } -} - void init_g_cnd_mod_map(const boost::filesystem::path &dir) { DBFHandle cnd_mod_handle = read_dbf_file(dir / CND_MOD_DBF); for (int i = 0; i < DBFGetRecordCount(cnd_mod_handle); i++) { diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 1bbe5cc..06ce232 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -21,14 +21,11 @@ static const boost::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; static const boost::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; static const boost::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; -static const boost::filesystem::path RAILWAYS_POLY_SHP = "RailRds.shp"; static const boost::filesystem::path LAND_USE_A_SHP = "LandUseA.shp"; static const boost::filesystem::path LAND_USE_B_SHP = "LandUseB.shp"; static const boost::filesystem::path NAMED_PLC_SHP = "NamedPlc.shp"; static const boost::filesystem::path HAMLET_SHP = "Hamlet.shp"; static const boost::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; -static const boost::filesystem::path LANDMARK_SHP = "Landmark.shp"; -static const boost::filesystem::path TRAVDEST_SHP = "TravDest.shp"; static const boost::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; static const boost::filesystem::path MTD_AREA_DBF = "MtdArea.dbf"; diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 1e646a5..7d0594a 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -16,7 +16,9 @@ #include #include +#include "converter/BuildingConverter.hpp" #include "converter/RailwayConverter.hpp" +#include "converter/RestAreaConverter.hpp" #include "converter/WaterConverter.hpp" #include "navteq.hpp" @@ -34,6 +36,8 @@ navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) // setting executable_path in navteq2osm_tag_parser.hpp for reading ISO-file g_executable_path = this->executable_path; + converter.emplace_back(new BuildingConverter()); + converter.emplace_back(new RestAreaConverter()); converter.emplace_back(new RailwayConverter()); converter.emplace_back(new WaterConverter()); } @@ -246,12 +250,6 @@ void navteq_plugin::execute() { BOOST_LOG_TRIVIAL(info) << "Add hamlet nodes"; add_hamlet_nodes(dataDirs, writer); - BOOST_LOG_TRIVIAL(info) << "Add buildings"; - add_buildings(dataDirs, writer); - - BOOST_LOG_TRIVIAL(info) << "Add rest areas"; - add_rest_area_nodes(dataDirs, writer); - // run converters for (auto &c : converter) c->convert(dataDirs, writer); diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index 83ebffa..f723c09 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -34,9 +34,6 @@ class navteq_plugin : public base_plugin { void add_landuse(const std::vector &dirs, osmium::io::Writer &writer); - void add_buildings(const std::vector &dirs, - osmium::io::Writer &writer); - void sortPBF(); void copyType(osmium::io::Writer &writer, osmium::io::File &file, osmium::osm_entity_bits::type bits); From f5c8b22b1159454ee2e63f66c05acb176a92410a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 12:49:42 +0000 Subject: [PATCH 09/57] add hamletconverter --- plugins/navteq/converter/HamletConverter.cpp | 101 ++++++++++++++++++ plugins/navteq/converter/HamletConverter.hpp | 41 +++++++ .../navteq/converter/PointLayerConverter.hpp | 36 +++++++ .../navteq/converter/RestAreaConverter.cpp | 12 ++- .../navteq/converter/RestAreaConverter.hpp | 4 +- plugins/navteq/navteq.hpp | 69 ------------ plugins/navteq/navteq_mappings.hpp | 2 +- plugins/navteq/navteq_plugin.cpp | 5 +- 8 files changed, 194 insertions(+), 76 deletions(-) create mode 100644 plugins/navteq/converter/HamletConverter.cpp create mode 100644 plugins/navteq/converter/HamletConverter.hpp create mode 100644 plugins/navteq/converter/PointLayerConverter.hpp diff --git a/plugins/navteq/converter/HamletConverter.cpp b/plugins/navteq/converter/HamletConverter.cpp new file mode 100644 index 0000000..bfb685d --- /dev/null +++ b/plugins/navteq/converter/HamletConverter.cpp @@ -0,0 +1,101 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "HamletConverter.hpp" + +#include +#include +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" + +void HamletConverter::convert(const std::vector &dirs, + osmium::io::Writer &writer) { + + const boost::filesystem::path HAMLET_SHP = "Hamlet.shp"; + + for (const auto &dir : dirs) { + add_hamlet(dir / HAMLET_SHP, writer); + } +} + +void HamletConverter::add_hamlet(boost::filesystem::path hamlet_file, + osmium::io::Writer &writer) { + + auto ds = GDALDatasetUniquePtr(GDALDataset::Open(hamlet_file.c_str())); + if (!ds) { + BOOST_LOG_TRIVIAL(debug) << "No hamlet shp found in " << hamlet_file; + return; + } + auto layer = ds->GetLayer(0); + if (!layer) { + throw(shp_empty_error(hamlet_file.string())); + } + + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + + int facTypeField = layer->FindFieldIndex(FAC_TYPE.data(), true); + int poiNmTypeField = layer->FindFieldIndex(POI_NMTYPE.data(), true); + + for (auto &feat : *layer) { + uint fac_type = feat->GetFieldAsInteger(facTypeField); + if (fac_type != 9998) { + BOOST_LOG_TRIVIAL(error) + << "Skipping hamlet node because of wrong POI type"; + continue; + } + + std::string name_type = feat->GetFieldAsString(poiNmTypeField); + if (name_type != "B") { + // Skip this entry as it's just a translated namePlc of former one + continue; + } + process_hamlets(feat, node_buffer); + } + writer(std::move(node_buffer)); +} + +void HamletConverter::process_hamlets(const OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer) { + + auto geom = feat->GetGeometryRef(); + auto geom_type = geom->getGeometryType(); + + if (geom_type != wkbPoint) { + throw(std::runtime_error( + "Hamlet item with geometry=" + std::string(geom->getGeometryName()) + + " is not yet supported.")); + } + + auto point = static_cast(geom); + osmium::Location location(point->getX(), point->getY()); + { + // scope node_builder + // Add new node + osmium::builder::NodeBuilder node_builder(node_buffer); + build_node(location, node_builder); + osmium::builder::TagListBuilder tl_builder(node_builder); + + std::string name = feat->GetFieldAsString(POI_NAME.data()); + tl_builder.add_tag("name", to_camel_case_with_spaces(name)); + tl_builder.add_tag("place", "hamlet"); + } + node_buffer.commit(); +} \ No newline at end of file diff --git a/plugins/navteq/converter/HamletConverter.hpp b/plugins/navteq/converter/HamletConverter.hpp new file mode 100644 index 0000000..4fd7e79 --- /dev/null +++ b/plugins/navteq/converter/HamletConverter.hpp @@ -0,0 +1,41 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef HAMELTCONVERTER_HPP +#define HAMELTCONVERTER_HPP + +#include "PointLayerConverter.hpp" + +#include + +class HamletConverter : public PointLayerConverter { + +public: + HamletConverter(); + virtual ~HamletConverter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer); + +private: + void add_hamlet(boost::filesystem::path hamlet_file, + osmium::io::Writer &writer); + + void process_hamlets(const OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer); +}; + +#endif // HAMELTCONVERTER_HPP diff --git a/plugins/navteq/converter/PointLayerConverter.hpp b/plugins/navteq/converter/PointLayerConverter.hpp new file mode 100644 index 0000000..5ca5697 --- /dev/null +++ b/plugins/navteq/converter/PointLayerConverter.hpp @@ -0,0 +1,36 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef POINTLAYERCONVERTER_HPP +#define POINTLAYERCONVERTER_HPP + +#include "Converter.hpp" + +#include + +class PointLayerConverter : public Converter { + +public: + PointLayerConverter(); + virtual ~PointLayerConverter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer); + +private: +}; + +#endif // POINTLAYERCONVERTER_HPP \ No newline at end of file diff --git a/plugins/navteq/converter/RestAreaConverter.cpp b/plugins/navteq/converter/RestAreaConverter.cpp index 1165deb..d055ca9 100644 --- a/plugins/navteq/converter/RestAreaConverter.cpp +++ b/plugins/navteq/converter/RestAreaConverter.cpp @@ -16,6 +16,16 @@ #include "RestAreaConverter.hpp" +#include +#include +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" + void RestAreaConverter::convert( const std::vector &dirs, osmium::io::Writer &writer) { @@ -78,7 +88,7 @@ void RestAreaConverter::process_rest_area(const OGRFeatureUniquePtr &feat, // scope node_builder // Add new node osmium::builder::NodeBuilder node_builder(node_buffer); - build_node(location, &node_builder); + build_node(location, node_builder); osmium::builder::TagListBuilder tl_builder(node_builder); std::string name = feat->GetFieldAsString(POI_NAME.data()); diff --git a/plugins/navteq/converter/RestAreaConverter.hpp b/plugins/navteq/converter/RestAreaConverter.hpp index a79017a..6084e65 100644 --- a/plugins/navteq/converter/RestAreaConverter.hpp +++ b/plugins/navteq/converter/RestAreaConverter.hpp @@ -17,11 +17,11 @@ #ifndef RESTAREACONVERTER_HPP #define RESTAREACONVERTER_HPP -#include "Converter.hpp" +#include "PointLayerConverter.hpp" #include -class RestAreaConverter : public Converter { +class RestAreaConverter : public PointLayerConverter { public: RestAreaConverter(); diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index d9c8fd1..0009012 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -1208,37 +1208,6 @@ void process_city(const OGRFeatureUniquePtr &feat, uint fac_type, node_buffer.commit(); } -/** - * \brief adds hamlets to the node_buffer - */ -void process_hamlets(const OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer) { - - auto geom = feat->GetGeometryRef(); - auto geom_type = geom->getGeometryType(); - - if (geom_type != wkbPoint) { - throw(std::runtime_error( - "Hamlet item with geometry=" + std::string(geom->getGeometryName()) + - " is not yet supported.")); - } - - auto point = static_cast(geom); - osmium::Location location(point->getX(), point->getY()); - { - // scope node_builder - // Add new node - osmium::builder::NodeBuilder node_builder(node_buffer); - build_node(location, &node_builder); - osmium::builder::TagListBuilder tl_builder(node_builder); - - std::string name = feat->GetFieldAsString(POI_NAME); - tl_builder.add_tag("name", to_camel_case_with_spaces(name)); - tl_builder.add_tag("place", "hamlet"); - } - node_buffer.commit(); -} - /** * \brief adds tags from administrative boundaries to mtd_area_map. * adds tags from administrative boundaries to mtd_area_map @@ -1369,44 +1338,6 @@ void add_city_nodes(const std::vector &dirs, } } -void add_hamlet_nodes(const std::vector &dirs, - osmium::io::Writer &writer) { - - for (auto dir : dirs) { - - // hamlets are optional - if (!shp_file_exists(dir / HAMLET_SHP)) - continue; - - auto ds = open_shape_file(dir / HAMLET_SHP); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(dir.string())); - - osmium::memory::Buffer node_buffer(buffer_size); - - int facTypeField = layer->FindFieldIndex(FAC_TYPE, true); - int poiNmTypeField = layer->FindFieldIndex(POI_NMTYPE, true); - - for (auto &feat : *layer) { - uint fac_type = feat->GetFieldAsInteger(facTypeField); - if (fac_type != 9998) { - BOOST_LOG_TRIVIAL(error) - << "Skipping hamlet node because of wrong POI type"; - continue; - } - - std::string name_type = feat->GetFieldAsString(poiNmTypeField); - if (name_type != "B") { - // Skip this entry as it's just a translated namePlc of former one - continue; - } - process_hamlets(feat, node_buffer); - } - writer(std::move(node_buffer)); - } -} - void init_g_cnd_mod_map(const boost::filesystem::path &dir) { DBFHandle cnd_mod_handle = read_dbf_file(dir / CND_MOD_DBF); for (int i = 0; i < DBFGetRecordCount(cnd_mod_handle); i++) { diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 06ce232..344dac2 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -24,7 +24,7 @@ static const boost::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; static const boost::filesystem::path LAND_USE_A_SHP = "LandUseA.shp"; static const boost::filesystem::path LAND_USE_B_SHP = "LandUseB.shp"; static const boost::filesystem::path NAMED_PLC_SHP = "NamedPlc.shp"; -static const boost::filesystem::path HAMLET_SHP = "Hamlet.shp"; + static const boost::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; static const boost::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 7d0594a..7c955e0 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -17,6 +17,7 @@ #include #include "converter/BuildingConverter.hpp" +#include "converter/HamletConverter.hpp" #include "converter/RailwayConverter.hpp" #include "converter/RestAreaConverter.hpp" #include "converter/WaterConverter.hpp" @@ -36,6 +37,7 @@ navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) // setting executable_path in navteq2osm_tag_parser.hpp for reading ISO-file g_executable_path = this->executable_path; + converter.emplace_back(new HamletConverter()); converter.emplace_back(new BuildingConverter()); converter.emplace_back(new RestAreaConverter()); converter.emplace_back(new RailwayConverter()); @@ -247,9 +249,6 @@ void navteq_plugin::execute() { BOOST_LOG_TRIVIAL(info) << "Add city nodes"; add_city_nodes(dataDirs, writer); - BOOST_LOG_TRIVIAL(info) << "Add hamlet nodes"; - add_hamlet_nodes(dataDirs, writer); - // run converters for (auto &c : converter) c->convert(dataDirs, writer); From e5e18b1329aade5948ce89bb0295366af0085217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 13:26:21 +0000 Subject: [PATCH 10/57] add CityConverter --- plugins/navteq/converter/CityConverter.cpp | 174 ++++++++++++++++++ ...ntLayerConverter.hpp => CityConverter.hpp} | 25 ++- plugins/navteq/converter/Converter.cpp | 10 + plugins/navteq/converter/Converter.hpp | 5 + plugins/navteq/converter/HamletConverter.cpp | 4 + plugins/navteq/converter/HamletConverter.hpp | 4 +- .../navteq/converter/RestAreaConverter.cpp | 4 + .../navteq/converter/RestAreaConverter.hpp | 4 +- plugins/navteq/navteq.hpp | 117 ------------ plugins/navteq/navteq2osm_tag_parser.hpp | 17 -- plugins/navteq/navteq_mappings.hpp | 2 +- plugins/navteq/navteq_plugin.cpp | 5 +- 12 files changed, 223 insertions(+), 148 deletions(-) create mode 100644 plugins/navteq/converter/CityConverter.cpp rename plugins/navteq/converter/{PointLayerConverter.hpp => CityConverter.hpp} (53%) diff --git a/plugins/navteq/converter/CityConverter.cpp b/plugins/navteq/converter/CityConverter.cpp new file mode 100644 index 0000000..313d271 --- /dev/null +++ b/plugins/navteq/converter/CityConverter.cpp @@ -0,0 +1,174 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "CityConverter.hpp" + +#include +#include +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" + +CityConverter::CityConverter() {} + +CityConverter::~CityConverter() {} + +void CityConverter::convert(const std::vector &dirs, + osmium::io::Writer &writer) { + + const boost::filesystem::path NAMED_PLC_SHP = "NamedPlc.shp"; + + for (auto dir : dirs) { + add_city_shape(dir / NAMED_PLC_SHP, writer); + } +} + +void CityConverter::add_city_shape(boost::filesystem::path city_shape_file, + osmium::io::Writer &writer) { + + auto ds = GDALDatasetUniquePtr(GDALDataset::Open(city_shape_file.c_str())); + if (!ds) { + BOOST_LOG_TRIVIAL(debug) << "No city shp found in " << city_shape_file; + return; + } + auto layer = ds->GetLayer(0); + if (!layer) + throw(shp_empty_error(city_shape_file.string())); + + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + + int facTypeField = layer->FindFieldIndex(FAC_TYPE.data(), true); + int poiNmTypeField = layer->FindFieldIndex(POI_NMTYPE.data(), true); + int poiLangCodeField = layer->FindFieldIndex(POI_LANGCD.data(), true); + int poiIdField = layer->FindFieldIndex(POI_ID.data(), true); + int poiNameField = layer->FindFieldIndex(POI_NAME.data(), true); + + std::map> translations; + // read translations + for (auto &feat : *layer) { + uint fac_type = feat->GetFieldAsInteger(facTypeField); + if (fac_type != 4444 && fac_type != 9709) { + BOOST_LOG_TRIVIAL(error) + << "Skipping city node because of wrong POI type"; + continue; + } + std::string name_type = feat->GetFieldAsString(poiNmTypeField); + if (name_type == "B") { + // Skip this entry as it's just a translated namePlc of former one + continue; + } + int poiId = feat->GetFieldAsInteger(poiIdField); + std::string langCode = feat->GetFieldAsString(poiLangCodeField); + std::string locName = feat->GetFieldAsString(poiNameField); + + translations[poiId].emplace(parse_lang_code(langCode), + to_camel_case_with_spaces(locName)); + } + + layer->ResetReading(); + + for (auto &feat : *layer) { + uint fac_type = feat->GetFieldAsInteger(facTypeField); + if (fac_type != 4444 && fac_type != 9709) { + BOOST_LOG_TRIVIAL(error) + << "Skipping city node because of wrong POI type"; + continue; + } + + std::string name_type = feat->GetFieldAsString(poiNmTypeField); + if (name_type != "B") { + // Skip this entry as it's just a translated namePlc of former one + continue; + } + int poiId = feat->GetFieldAsInteger(poiIdField); + + process_city(feat, fac_type, node_buffer, translations[poiId]); + } + node_buffer.commit(); + writer(std::move(node_buffer)); +} + +void CityConverter::process_city( + const OGRFeatureUniquePtr &feat, uint fac_type, + osmium::memory::Buffer &node_buffer, + const std::map &translations) { + + auto geom = feat->GetGeometryRef(); + auto geom_type = geom->getGeometryType(); + + if (geom_type != wkbPoint) { + throw(std::runtime_error( + "City item with geometry=" + std::string(geom->getGeometryName()) + + " is not yet supported.")); + } + + auto point = static_cast(geom); + osmium::Location location(point->getX(), point->getY()); + { + // scope node_builder + // Add new node + osmium::builder::NodeBuilder node_builder(node_buffer); + build_node(location, node_builder); + osmium::builder::TagListBuilder tl_builder(node_builder); + + std::string name = feat->GetFieldAsString(POI_NAME.data()); + tl_builder.add_tag("name", to_camel_case_with_spaces(name)); + if (fac_type == 9709) { + // 9709 means 'neighbourhood' + tl_builder.add_tag("place", "suburb"); + } else { //=> fac_type = 4444 means 'named place' which is the city centre + int population = feat->GetFieldAsInteger(POPULATION.data()); + if (population > 0) + tl_builder.add_tag("population", std::to_string(population)); + uint capital = feat->GetFieldAsInteger(CAPITAL.data()); + tl_builder.add_tag("place", get_place_value(population, capital)); + if (capital == 1) { + // for capitals of countries use 'capital' = 'yes' + tl_builder.add_tag("capital", "yes"); + } else if (capital > 1) { + // for subdivisions of countries use 'capital' = admin_lvl + tl_builder.add_tag("capital", navteq_2_osm_admin_lvl(capital)); + } + } + + // add translation tags + for (const auto &[langCode, name] : translations) { + tl_builder.add_tag("name:" + langCode, name); + } + } + node_buffer.commit(); +} + +std::string CityConverter::get_place_value(uint population, uint capital) { + if (capital == 1 || capital == 2 || population > 100000) + return "city"; + + if (capital == 3 || capital == 4 || population > 10000) + return "town"; + + if (capital == 5 || population > 100) + return "village"; + + if (population > 0) + return "hamlet"; + + // population = 0 is more often a village than a hamlet + return "village"; +} \ No newline at end of file diff --git a/plugins/navteq/converter/PointLayerConverter.hpp b/plugins/navteq/converter/CityConverter.hpp similarity index 53% rename from plugins/navteq/converter/PointLayerConverter.hpp rename to plugins/navteq/converter/CityConverter.hpp index 5ca5697..6b52091 100644 --- a/plugins/navteq/converter/PointLayerConverter.hpp +++ b/plugins/navteq/converter/CityConverter.hpp @@ -14,23 +14,36 @@ * along with Morituri. If not, see . */ -#ifndef POINTLAYERCONVERTER_HPP -#define POINTLAYERCONVERTER_HPP +#ifndef CITYCONVERTER_HPP +#define CITYCONVERTER_HPP #include "Converter.hpp" #include -class PointLayerConverter : public Converter { +class CityConverter : public Converter { public: - PointLayerConverter(); - virtual ~PointLayerConverter(); + CityConverter(); + virtual ~CityConverter(); virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: + void add_city_shape(boost::filesystem::path city_shape_file, + osmium::io::Writer &writer); + + void process_city(const OGRFeatureUniquePtr &feat, uint fac_type, + osmium::memory::Buffer &node_buffer, + const std::map &translations); + + std::string get_place_value(uint population, uint capital); + + static constexpr std::string_view POI_LANGCD = "POI_LANGCD"; + static constexpr std::string_view POI_ID = "POI_ID"; + static constexpr std::string_view POPULATION = "POPULATION"; + static constexpr std::string_view CAPITAL = "CAPITAL"; }; -#endif // POINTLAYERCONVERTER_HPP \ No newline at end of file +#endif // CITYCONVERTER_HPP diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index e8b946b..dd573b9 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -231,3 +231,13 @@ template void Converter::setObjectProperties(T &builder) { set_dummy_osm_object_attributes(builder.object()); builder.set_user(USER.data()); } + +std::string Converter::navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { + if (NAVTEQ_ADMIN_LVL_MIN > navteq_admin_lvl_int || + navteq_admin_lvl_int > NAVTEQ_ADMIN_LVL_MAX) + throw std::runtime_error("invalid admin level. admin level '" + + std::to_string(navteq_admin_lvl_int) + + "' is out of range."); + + return std::to_string(2 * navteq_admin_lvl_int); +} diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 8ea3fb8..932e14c 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -112,6 +112,8 @@ class Converter { template void setObjectProperties(T &builder); + std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int); + static constexpr int BUFFER_SIZE = 10 * 1000 * 1000; static constexpr int OSM_MAX_WAY_NODES = 1000; @@ -133,6 +135,9 @@ class Converter { static constexpr std::string_view FAC_TYPE = "FAC_TYPE"; static constexpr std::string_view POI_NMTYPE = "POI_NMTYPE"; static constexpr std::string_view POI_NAME = "POI_NAME"; + + static constexpr int NAVTEQ_ADMIN_LVL_MIN = 1; + static constexpr int NAVTEQ_ADMIN_LVL_MAX = 7; }; #endif // CONVERTER_HPP diff --git a/plugins/navteq/converter/HamletConverter.cpp b/plugins/navteq/converter/HamletConverter.cpp index bfb685d..5cf0b40 100644 --- a/plugins/navteq/converter/HamletConverter.cpp +++ b/plugins/navteq/converter/HamletConverter.cpp @@ -26,6 +26,10 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" +HamletConverter::HamletConverter() {} + +HamletConverter::~HamletConverter() {} + void HamletConverter::convert(const std::vector &dirs, osmium::io::Writer &writer) { diff --git a/plugins/navteq/converter/HamletConverter.hpp b/plugins/navteq/converter/HamletConverter.hpp index 4fd7e79..12d1084 100644 --- a/plugins/navteq/converter/HamletConverter.hpp +++ b/plugins/navteq/converter/HamletConverter.hpp @@ -17,11 +17,11 @@ #ifndef HAMELTCONVERTER_HPP #define HAMELTCONVERTER_HPP -#include "PointLayerConverter.hpp" +#include "Converter.hpp" #include -class HamletConverter : public PointLayerConverter { +class HamletConverter : public Converter { public: HamletConverter(); diff --git a/plugins/navteq/converter/RestAreaConverter.cpp b/plugins/navteq/converter/RestAreaConverter.cpp index d055ca9..f2170c1 100644 --- a/plugins/navteq/converter/RestAreaConverter.cpp +++ b/plugins/navteq/converter/RestAreaConverter.cpp @@ -26,6 +26,10 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" +RestAreaConverter::RestAreaConverter() {} + +RestAreaConverter::~RestAreaConverter() {} + void RestAreaConverter::convert( const std::vector &dirs, osmium::io::Writer &writer) { diff --git a/plugins/navteq/converter/RestAreaConverter.hpp b/plugins/navteq/converter/RestAreaConverter.hpp index 6084e65..a79017a 100644 --- a/plugins/navteq/converter/RestAreaConverter.hpp +++ b/plugins/navteq/converter/RestAreaConverter.hpp @@ -17,11 +17,11 @@ #ifndef RESTAREACONVERTER_HPP #define RESTAREACONVERTER_HPP -#include "PointLayerConverter.hpp" +#include "Converter.hpp" #include -class RestAreaConverter : public PointLayerConverter { +class RestAreaConverter : public Converter { public: RestAreaConverter(); diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index 0009012..d2f11ca 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -1154,60 +1154,6 @@ void process_landuse(const OGRFeatureUniquePtr &feat, rel_buffer.commit(); } -/** - * \brief adds cities to the node buffer - */ -void process_city(const OGRFeatureUniquePtr &feat, uint fac_type, - osmium::memory::Buffer &node_buffer, - const std::map &translations) { - - auto geom = feat->GetGeometryRef(); - auto geom_type = geom->getGeometryType(); - - osm_id_vector_type exterior_way_ids, interior_way_ids; - if (geom_type != wkbPoint) { - throw(std::runtime_error( - "City item with geometry=" + std::string(geom->getGeometryName()) + - " is not yet supported.")); - } - - auto point = static_cast(geom); - osmium::Location location(point->getX(), point->getY()); - { - // scope node_builder - // Add new node - osmium::builder::NodeBuilder node_builder(node_buffer); - build_node(location, &node_builder); - osmium::builder::TagListBuilder tl_builder(node_builder); - - std::string name = feat->GetFieldAsString(POI_NAME); - tl_builder.add_tag("name", to_camel_case_with_spaces(name)); - if (fac_type == 9709) { - // 9709 means 'neighbourhood' - tl_builder.add_tag("place", "suburb"); - } else { //=> fac_type = 4444 means 'named place' which is the city centre - int population = feat->GetFieldAsInteger(POPULATION); - if (population > 0) - tl_builder.add_tag("population", std::to_string(population)); - uint capital = feat->GetFieldAsInteger(CAPITAL); - tl_builder.add_tag("place", get_place_value(population, capital)); - if (capital == 1) { - // for capitals of countries use 'capital' = 'yes' - tl_builder.add_tag("capital", "yes"); - } else if (capital > 1) { - // for subdivisions of countries use 'capital' = admin_lvl - tl_builder.add_tag("capital", navteq_2_osm_admin_lvl(capital)); - } - } - - // add translation tags - for (auto loc : translations) { - tl_builder.add_tag("name:" + loc.first, loc.second); - } - } - node_buffer.commit(); -} - /** * \brief adds tags from administrative boundaries to mtd_area_map. * adds tags from administrative boundaries to mtd_area_map @@ -1275,69 +1221,6 @@ void init_cdms_map( } } -void add_city_nodes(const std::vector &dirs, - osmium::io::Writer &writer) { - - for (auto dir : dirs) { - auto ds = open_shape_file(dir / NAMED_PLC_SHP); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(dir.string())); - - osmium::memory::Buffer node_buffer(buffer_size); - - int facTypeField = layer->FindFieldIndex(FAC_TYPE, true); - int poiNmTypeField = layer->FindFieldIndex(POI_NMTYPE, true); - int poiLangCodeField = layer->FindFieldIndex(POI_LANGCD, true); - int poiIdField = layer->FindFieldIndex(POI_ID, true); - int poiNameField = layer->FindFieldIndex(POI_NAME, true); - - std::map> translations; - // read translations - for (auto &feat : *layer) { - uint fac_type = feat->GetFieldAsInteger(facTypeField); - if (fac_type != 4444 && fac_type != 9709) { - BOOST_LOG_TRIVIAL(error) - << "Skipping city node because of wrong POI type"; - continue; - } - std::string name_type = feat->GetFieldAsString(poiNmTypeField); - if (name_type == "B") { - // Skip this entry as it's just a translated namePlc of former one - continue; - } - int poiId = feat->GetFieldAsInteger(poiIdField); - std::string langCode = feat->GetFieldAsString(poiLangCodeField); - std::string locName = feat->GetFieldAsString(poiNameField); - - translations[poiId].emplace(parse_lang_code(langCode), - to_camel_case_with_spaces(locName)); - } - - layer->ResetReading(); - - for (auto &feat : *layer) { - uint fac_type = feat->GetFieldAsInteger(facTypeField); - if (fac_type != 4444 && fac_type != 9709) { - BOOST_LOG_TRIVIAL(error) - << "Skipping city node because of wrong POI type"; - continue; - } - - std::string name_type = feat->GetFieldAsString(poiNmTypeField); - if (name_type != "B") { - // Skip this entry as it's just a translated namePlc of former one - continue; - } - int poiId = feat->GetFieldAsInteger(poiIdField); - - process_city(feat, fac_type, node_buffer, translations[poiId]); - } - node_buffer.commit(); - writer(std::move(node_buffer)); - } -} - void init_g_cnd_mod_map(const boost::filesystem::path &dir) { DBFHandle cnd_mod_handle = read_dbf_file(dir / CND_MOD_DBF); for (int i = 0; i < DBFGetRecordCount(cnd_mod_handle); i++) { diff --git a/plugins/navteq/navteq2osm_tag_parser.hpp b/plugins/navteq/navteq2osm_tag_parser.hpp index 71f0f72..70f8a58 100644 --- a/plugins/navteq/navteq2osm_tag_parser.hpp +++ b/plugins/navteq/navteq2osm_tag_parser.hpp @@ -728,23 +728,6 @@ link_id_type parse_street_tags( return link_id; } -const char *get_place_value(uint population, uint capital) { - if (capital == 1 || capital == 2 || population > 100000) - return "city"; - - if (capital == 3 || capital == 4 || population > 10000) - return "town"; - - if (capital == 5 || population > 100) - return "village"; - - if (population > 0) - return "hamlet"; - - // population = 0 is more often a village than a hamlet - return "village"; -} - // matching from http://www.loc.gov/standards/iso639-2/php/code_list.php // http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt // ISO-639 conversion diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 344dac2..8a9b967 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -124,7 +124,7 @@ const char *HIGHWAY_NM = "HIGHWAY_NM"; // NAMED_PLC columns // const char* LINK_ID = "LINK_ID"; const char *POI_NAME = "POI_NAME"; -const char *POI_LANGCD = "POI_LANGCD"; + const char *POI_ID = "POI_ID"; const char *FAC_TYPE = "FAC_TYPE"; const char *POI_NMTYPE = "POI_NMTYPE"; diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 7c955e0..8c7a805 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -17,6 +17,7 @@ #include #include "converter/BuildingConverter.hpp" +#include "converter/CityConverter.hpp" #include "converter/HamletConverter.hpp" #include "converter/RailwayConverter.hpp" #include "converter/RestAreaConverter.hpp" @@ -37,6 +38,7 @@ navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) // setting executable_path in navteq2osm_tag_parser.hpp for reading ISO-file g_executable_path = this->executable_path; + converter.emplace_back(new CityConverter()); converter.emplace_back(new HamletConverter()); converter.emplace_back(new BuildingConverter()); converter.emplace_back(new RestAreaConverter()); @@ -246,9 +248,6 @@ void navteq_plugin::execute() { BOOST_LOG_TRIVIAL(info) << "Add landuse"; add_landuse(dataDirs, writer); - BOOST_LOG_TRIVIAL(info) << "Add city nodes"; - add_city_nodes(dataDirs, writer); - // run converters for (auto &c : converter) c->convert(dataDirs, writer); From 5bb62e6cc70a6d29f47cf7062f0a6880e26cff35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 12 Jul 2024 13:43:05 +0000 Subject: [PATCH 11/57] add LanduseConverter --- plugins/navteq/converter/LanduseConverter.cpp | 224 ++++++++++++++++++ plugins/navteq/converter/LanduseConverter.hpp | 55 +++++ plugins/navteq/navteq.hpp | 167 ------------- plugins/navteq/navteq_mappings.hpp | 14 -- plugins/navteq/navteq_plugin.cpp | 18 +- plugins/navteq/navteq_plugin.hpp | 3 - 6 files changed, 281 insertions(+), 200 deletions(-) create mode 100644 plugins/navteq/converter/LanduseConverter.cpp create mode 100644 plugins/navteq/converter/LanduseConverter.hpp diff --git a/plugins/navteq/converter/LanduseConverter.cpp b/plugins/navteq/converter/LanduseConverter.cpp new file mode 100644 index 0000000..a36801b --- /dev/null +++ b/plugins/navteq/converter/LanduseConverter.cpp @@ -0,0 +1,224 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "LanduseConverter.hpp" + +#include +#include +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" + +LanduseConverter::LanduseConverter() {} + +LanduseConverter::~LanduseConverter() {} + +void LanduseConverter::convert(const std::vector &dirs, + osmium::io::Writer &writer) { + const boost::filesystem::path LAND_USE_A_SHP = "LandUseA.shp"; + const boost::filesystem::path LAND_USE_B_SHP = "LandUseB.shp"; + + for (auto dir : dirs) { + add_landuse_shape(dir / LAND_USE_A_SHP, writer); + add_landuse_shape(dir / LAND_USE_B_SHP, writer); + } +} + +void LanduseConverter::add_landuse_shape( + boost::filesystem::path landuse_shape_file, osmium::io::Writer &writer) { + std::map + g_way_end_points_map; + auto ds = GDALDatasetUniquePtr(GDALDataset::Open(landuse_shape_file.c_str())); + if (ds == nullptr) { + BOOST_LOG_TRIVIAL(debug) + << "No landuse shp found in " << landuse_shape_file; + return; + } + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(landuse_shape_file.string())); + assert(layer->GetGeomType() == wkbPolygon); + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + osmium::memory::Buffer rel_buffer(BUFFER_SIZE); + for (auto &feat : *layer) { + process_landuse(feat, g_way_end_points_map, node_buffer, way_buffer, + rel_buffer); + } + + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); + writer(std::move(rel_buffer)); +} + +void LanduseConverter::process_landuse( + const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer, + osmium::memory::Buffer &rel_buffer) { + auto geom = feat->GetGeometryRef(); + auto geom_type = geom->getGeometryType(); + + std::vector exterior_way_ids; + std::vector interior_way_ids; + if (geom_type == wkbMultiPolygon) { + create_multi_polygon(static_cast(geom), exterior_way_ids, + interior_way_ids, g_way_end_points_map, node_buffer, + way_buffer); + } else if (geom_type == wkbPolygon) { + create_polygon(static_cast(geom), exterior_way_ids, + interior_way_ids, g_way_end_points_map, node_buffer, + way_buffer); + } else { + throw(std::runtime_error( + "Landuse item with geometry=" + std::string(geom->getGeometryName()) + + " is not yet supported.")); + } + + build_landuse_relation_with_tags(feat, exterior_way_ids, interior_way_ids, + rel_buffer); + + node_buffer.commit(); + way_buffer.commit(); + rel_buffer.commit(); +} + +osmium::unsigned_object_id_type +LanduseConverter::build_landuse_relation_with_tags( + const OGRFeatureUniquePtr &feat, + std::vector &ext_osm_way_ids, + std::vector &int_osm_way_ids, + osmium::memory::Buffer &rel_buffer) { + osmium::builder::RelationBuilder builder(rel_buffer); + setObjectProperties(builder); + build_landuse_taglist(builder, feat); + build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); + return builder.object().id(); +} + +void LanduseConverter::build_landuse_taglist( + osmium::builder::RelationBuilder &builder, + const OGRFeatureUniquePtr &feat) { + // Mind tl_builder scope! + osmium::builder::TagListBuilder tl_builder(builder); + tl_builder.add_tag("type", "multipolygon"); + + std::string polygonName = feat->GetFieldAsString(POLYGON_NM.data()); + if (!polygonName.empty()) { + std::string poly_name = to_camel_case_with_spaces(polygonName); + if (!poly_name.empty()) + tl_builder.add_tag("name", poly_name); + } + + std::string featureCode = feat->GetFieldAsString(FEAT_COD.data()); + + // Land Use A types + if (featureCode == "509998") { + // FEAT_TYPE 'BEACH' + tl_builder.add_tag("natural", "beach"); + } else if (featureCode == "900103") { + // FEAT_TYPE 'PARK/MONUMENT (NATIONAL)' + tl_builder.add_tag("boundary", "national_park"); + } else if (featureCode == "900130") { + // FEAT_TYPE 'PARK (STATE)' + // In many cases this is meant to be a national park or + // protected area but this is not guaranteed + tl_builder.add_tag("leisure", "park"); + } else if (featureCode == "900140") { + // FEAT_TYPE 'PARK IN WATER' + tl_builder.add_tag("boundary", "national_park"); + } else if (featureCode == "900150") { + // FEAT_TYPE 'PARK (CITY/COUNTY)' + tl_builder.add_tag("leisure", "park"); + } else if (featureCode == "900159") { + // FEAT_TYPE 'UNDEFINED TRAFFIC AREA' + // Possible handling: area=yes, highway=pedestrian + } else if (featureCode == "900202") { + // FEAT_TYPE 'WOODLAND' + tl_builder.add_tag("landuse", "forest"); + } else if (featureCode == "1700215") { + // FEAT_TYPE 'PARKING LOT' + tl_builder.add_tag("amenity", "parking"); + } else if (featureCode == "1900403") { + // FEAT_TYPE 'AIRPORT' + tl_builder.add_tag("aeroway", "aerodrome"); + } else if (featureCode == "2000124") { + // FEAT_TYPE 'SHOPPING CENTRE' + tl_builder.add_tag("shop", "mall"); + tl_builder.add_tag("building", "retail"); + } else if (featureCode == "2000200") { + // FEAT_TYPE 'INDUSTRIAL COMPLEX' + tl_builder.add_tag("landuse", "commercial"); + } else if (featureCode == "2000403") { + // FEAT_TYPE 'UNIVERSITY/COLLEGE' + tl_builder.add_tag("amenity", "university"); + } else if (featureCode == "2000408") { + // FEAT_TYPE 'HOSPITAL' + tl_builder.add_tag("amenity", "hospital"); + } else if (featureCode == "2000420") { + // FEAT_TYPE 'CEMETERY' + tl_builder.add_tag("landuse", "cemetery"); + } else if (featureCode == "2000457") { + // FEAT_TYPE 'SPORTS COMPLEX' + tl_builder.add_tag("leisure", "stadium"); + // tl_builder.add_tag("building", "yes"); + } else if (featureCode == "2000460") { + // FEAT_TYPE 'AMUSEMENT PARK' + tl_builder.add_tag("leisure", "park"); + tl_builder.add_tag("tourism", "theme_park"); + } else if (featureCode == "908002") { + // FEAT_TYPE 'Neighbourhood' + tl_builder.add_tag("place", "suburb"); + } else if (featureCode == "2000461") { + // FEAT_TYPE 'ANIMAL PARK' + tl_builder.add_tag("tourism", "zoo"); + } + + // Not implemented so far due to missing sample in data: + // MILITARY BASE (900108), NATIVE AMERICAN + // RESERVATION (900107), RAILYARD (9997007) + // Land Use B types + else if (featureCode == "900158") { + // FEAT_TYPE 'PEDESTRIAN ZONE' + tl_builder.add_tag("highway", "pedestrian"); + } else if (featureCode == "1907403") { + // FEAT_TYPE 'AIRCRAFT ROADS' + tl_builder.add_tag("aeroway", "runway"); + } else if (featureCode == "2000123") { + // FEAT_TYPE 'GOLF COURSE' + tl_builder.add_tag("leisure", "golf_course"); + tl_builder.add_tag("sport", "golf"); + } else if (featureCode == "9997004") { + // FEAT_TYPE 'CONGESTION ZONE' + // skipping due to no osm equivalent + } else if (featureCode == "9997010") { + // FEAT_TYPE 'ENVIRONMENTAL ZONE' + tl_builder.add_tag("boundary", "low_emission_zone"); + tl_builder.add_tag("type", "boundary"); + } + // Unknown if Land Use A or B types, but seems to appear somewhere + else if (featureCode == "509997") { + // FEAT_TYPE 'GLACIER' + tl_builder.add_tag("natural", "glacier"); + } else { + BOOST_LOG_TRIVIAL(error) << "Skipping unknown landuse type " << featureCode; + } +} diff --git a/plugins/navteq/converter/LanduseConverter.hpp b/plugins/navteq/converter/LanduseConverter.hpp new file mode 100644 index 0000000..8b605b4 --- /dev/null +++ b/plugins/navteq/converter/LanduseConverter.hpp @@ -0,0 +1,55 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef LANDUSECONVERTER_HPP +#define LANDUSECONVERTER_HPP + +#include "Converter.hpp" + +#include + +class LanduseConverter : public Converter { + +public: + LanduseConverter(); + virtual ~LanduseConverter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer); + +private: + void add_landuse_shape(boost::filesystem::path landuse_shape_file, + osmium::io::Writer &writer); + + void + process_landuse(const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer, + osmium::memory::Buffer &rel_buffer); + + osmium::unsigned_object_id_type build_landuse_relation_with_tags( + const OGRFeatureUniquePtr &feat, + std::vector &ext_osm_way_ids, + std::vector &int_osm_way_ids, + osmium::memory::Buffer &rel_buffer); + + void build_landuse_taglist(osmium::builder::RelationBuilder &builder, + const OGRFeatureUniquePtr &feat); +}; + +#endif // LANDUSECONVERTER_HPP \ No newline at end of file diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index d2f11ca..9b56402 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -893,113 +893,6 @@ void build_admin_boundary_taglist(osmium::builder::Builder &builder, /** * \brief adds navteq landuse tags to Relation */ -void build_landuse_taglist(osmium::builder::RelationBuilder &builder, - const OGRFeatureUniquePtr &feat) { - // Mind tl_builder scope! - osmium::builder::TagListBuilder tl_builder(builder); - tl_builder.add_tag("type", "multipolygon"); - - std::string polygonName = feat->GetFieldAsString(POLYGON_NM); - if (!polygonName.empty()) { - std::string poly_name = to_camel_case_with_spaces(polygonName); - if (!poly_name.empty()) - tl_builder.add_tag("name", poly_name); - } - - std::string featureCode = feat->GetFieldAsString(FEAT_COD); - - // Land Use A types - if (featureCode == "509998") { - // FEAT_TYPE 'BEACH' - tl_builder.add_tag("natural", "beach"); - } else if (featureCode == "900103") { - // FEAT_TYPE 'PARK/MONUMENT (NATIONAL)' - tl_builder.add_tag("boundary", "national_park"); - } else if (featureCode == "900130") { - // FEAT_TYPE 'PARK (STATE)' - // In many cases this is meant to be a national park or - // protected area but this is not guaranteed - tl_builder.add_tag("leisure", "park"); - } else if (featureCode == "900140") { - // FEAT_TYPE 'PARK IN WATER' - tl_builder.add_tag("boundary", "national_park"); - } else if (featureCode == "900150") { - // FEAT_TYPE 'PARK (CITY/COUNTY)' - tl_builder.add_tag("leisure", "park"); - } else if (featureCode == "900159") { - // FEAT_TYPE 'UNDEFINED TRAFFIC AREA' - // Possible handling: area=yes, highway=pedestrian - } else if (featureCode == "900202") { - // FEAT_TYPE 'WOODLAND' - tl_builder.add_tag("landuse", "forest"); - } else if (featureCode == "1700215") { - // FEAT_TYPE 'PARKING LOT' - tl_builder.add_tag("amenity", "parking"); - } else if (featureCode == "1900403") { - // FEAT_TYPE 'AIRPORT' - tl_builder.add_tag("aeroway", "aerodrome"); - } else if (featureCode == "2000124") { - // FEAT_TYPE 'SHOPPING CENTRE' - tl_builder.add_tag("shop", "mall"); - tl_builder.add_tag("building", "retail"); - } else if (featureCode == "2000200") { - // FEAT_TYPE 'INDUSTRIAL COMPLEX' - tl_builder.add_tag("landuse", "commercial"); - } else if (featureCode == "2000403") { - // FEAT_TYPE 'UNIVERSITY/COLLEGE' - tl_builder.add_tag("amenity", "university"); - } else if (featureCode == "2000408") { - // FEAT_TYPE 'HOSPITAL' - tl_builder.add_tag("amenity", "hospital"); - } else if (featureCode == "2000420") { - // FEAT_TYPE 'CEMETERY' - tl_builder.add_tag("landuse", "cemetery"); - } else if (featureCode == "2000457") { - // FEAT_TYPE 'SPORTS COMPLEX' - tl_builder.add_tag("leisure", "stadium"); - // tl_builder.add_tag("building", "yes"); - } else if (featureCode == "2000460") { - // FEAT_TYPE 'AMUSEMENT PARK' - tl_builder.add_tag("leisure", "park"); - tl_builder.add_tag("tourism", "theme_park"); - } else if (featureCode == "908002") { - // FEAT_TYPE 'Neighbourhood' - tl_builder.add_tag("place", "suburb"); - } else if (featureCode == "2000461") { - // FEAT_TYPE 'ANIMAL PARK' - tl_builder.add_tag("tourism", "zoo"); - } - - // Not implemented so far due to missing sample in data: - // MILITARY BASE (900108), NATIVE AMERICAN - // RESERVATION (900107), RAILYARD (9997007) - // Land Use B types - else if (featureCode == "900158") { - // FEAT_TYPE 'PEDESTRIAN ZONE' - tl_builder.add_tag("highway", "pedestrian"); - } else if (featureCode == "1907403") { - // FEAT_TYPE 'AIRCRAFT ROADS' - tl_builder.add_tag("aeroway", "runway"); - } else if (featureCode == "2000123") { - // FEAT_TYPE 'GOLF COURSE' - tl_builder.add_tag("leisure", "golf_course"); - tl_builder.add_tag("sport", "golf"); - } else if (featureCode == "9997004") { - // FEAT_TYPE 'CONGESTION ZONE' - // skipping due to no osm equivalent - } else if (featureCode == "9997010") { - // FEAT_TYPE 'ENVIRONMENTAL ZONE' - tl_builder.add_tag("boundary", "low_emission_zone"); - tl_builder.add_tag("type", "boundary"); - } - // Unknown if Land Use A or B types, but seems to appear somewhere - else if (featureCode == "509997") { - // FEAT_TYPE 'GLACIER' - tl_builder.add_tag("natural", "glacier"); - } else { - BOOST_LOG_TRIVIAL(error) << "Skipping unknown landuse type " << featureCode; - } -} void build_relation_members(osmium::builder::RelationBuilder &builder, const osm_id_vector_type &ext_osm_way_ids, @@ -1040,18 +933,6 @@ osmium::unsigned_object_id_type build_admin_boundary_relation_with_tags( return builder.object().id(); } -osmium::unsigned_object_id_type build_landuse_relation_with_tags( - const OGRFeatureUniquePtr &feat, osm_id_vector_type ext_osm_way_ids, - osm_id_vector_type int_osm_way_ids, osmium::memory::Buffer &rel_buffer) { - osmium::builder::RelationBuilder builder(rel_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER); - build_landuse_taglist(builder, feat); - build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); - return builder.object().id(); -} - void create_polygon(const OGRPolygon *poly, osm_id_vector_type &exterior_way_ids, osm_id_vector_type &interior_way_ids, @@ -1126,33 +1007,6 @@ void process_admin_boundary( /** * \brief adds landuse polygons as Relations to m_buffer */ -void process_landuse(const OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer, - osmium::memory::Buffer &rel_buffer) { - auto geom = feat->GetGeometryRef(); - auto geom_type = geom->getGeometryType(); - - osm_id_vector_type exterior_way_ids, interior_way_ids; - if (geom_type == wkbMultiPolygon) { - create_multi_polygon(static_cast(geom), exterior_way_ids, - interior_way_ids, node_buffer, way_buffer); - } else if (geom_type == wkbPolygon) { - create_polygon(static_cast(geom), exterior_way_ids, - interior_way_ids, node_buffer, way_buffer); - } else { - throw(std::runtime_error( - "Landuse item with geometry=" + std::string(geom->getGeometryName()) + - " is not yet supported.")); - } - - build_landuse_relation_with_tags(feat, exterior_way_ids, interior_way_ids, - rel_buffer); - - node_buffer.commit(); - way_buffer.commit(); - rel_buffer.commit(); -} /** * \brief adds tags from administrative boundaries to mtd_area_map. @@ -1710,27 +1564,6 @@ void add_admin_shape( writer(std::move(rel_buffer)); } -void add_landuse_shape(boost::filesystem::path landuse_shape_file, - osmium::io::Writer &writer) { - g_way_end_points_map.clear(); - auto ds = open_shape_file(landuse_shape_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(landuse_shape_file.string())); - assert(layer->GetGeomType() == wkbPolygon); - osmium::memory::Buffer node_buffer(buffer_size); - osmium::memory::Buffer way_buffer(buffer_size); - osmium::memory::Buffer rel_buffer(buffer_size); - for (auto &feat : *layer) { - process_landuse(feat, node_buffer, way_buffer, rel_buffer); - } - - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); - writer(std::move(rel_buffer)); - g_way_end_points_map.clear(); -} - /**************************************************** * cleanup and assertions ****************************************************/ diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 8a9b967..4057380 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -21,10 +21,6 @@ static const boost::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; static const boost::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; static const boost::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; -static const boost::filesystem::path LAND_USE_A_SHP = "LandUseA.shp"; -static const boost::filesystem::path LAND_USE_B_SHP = "LandUseB.shp"; -static const boost::filesystem::path NAMED_PLC_SHP = "NamedPlc.shp"; - static const boost::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; static const boost::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; @@ -121,16 +117,6 @@ const char *COND_TYPE = "COND_TYPE"; // const char* LINK_ID = "LINK_ID"; const char *HIGHWAY_NM = "HIGHWAY_NM"; -// NAMED_PLC columns -// const char* LINK_ID = "LINK_ID"; -const char *POI_NAME = "POI_NAME"; - -const char *POI_ID = "POI_ID"; -const char *FAC_TYPE = "FAC_TYPE"; -const char *POI_NMTYPE = "POI_NMTYPE"; -const char *POPULATION = "POPULATION"; -const char *CAPITAL = "CAPITAL"; - // WaterSeg and WaterPoly columns const char *POLYGON_NM = "POLYGON_NM"; const char *FEAT_COD = "FEAT_COD"; diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 8c7a805..0903f63 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -19,6 +19,7 @@ #include "converter/BuildingConverter.hpp" #include "converter/CityConverter.hpp" #include "converter/HamletConverter.hpp" +#include "converter/LanduseConverter.hpp" #include "converter/RailwayConverter.hpp" #include "converter/RestAreaConverter.hpp" #include "converter/WaterConverter.hpp" @@ -38,6 +39,7 @@ navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) // setting executable_path in navteq2osm_tag_parser.hpp for reading ISO-file g_executable_path = this->executable_path; + converter.emplace_back(new LanduseConverter()); converter.emplace_back(new CityConverter()); converter.emplace_back(new HamletConverter()); converter.emplace_back(new BuildingConverter()); @@ -81,8 +83,6 @@ bool navteq_plugin::check_files(const boost::filesystem::path &dir) { if (!shp_file_exists(dir / POINT_ADDRESS_SHP)) BOOST_LOG_TRIVIAL(warning) << " point addresses are missing"; - if (!shp_file_exists(dir / NAMED_PLC_SHP)) - BOOST_LOG_TRIVIAL(warning) << " named places are missing"; if (!shp_file_exists(dir / ADMINBNDY_1_SHP)) BOOST_LOG_TRIVIAL(warning) << " administrative boundaries level 1 are missing"; @@ -211,17 +211,6 @@ void navteq_plugin::add_administrative_boundaries( g_way_end_points_map.clear(); } -void navteq_plugin::add_landuse( - const std::vector &dirs, - osmium::io::Writer &writer) { - for (auto dir : dirs) { - if (shp_file_exists(dir / LAND_USE_A_SHP)) - add_landuse_shape(dir / LAND_USE_A_SHP, writer); - if (shp_file_exists(dir / LAND_USE_B_SHP)) - add_landuse_shape(dir / LAND_USE_B_SHP, writer); - } -} - void navteq_plugin::execute() { if (output_path.empty()) throw std::exception(); @@ -245,9 +234,6 @@ void navteq_plugin::execute() { BOOST_LOG_TRIVIAL(info) << "Add administrative boundaries"; add_administrative_boundaries(dataDirs, writer); - BOOST_LOG_TRIVIAL(info) << "Add landuse"; - add_landuse(dataDirs, writer); - // run converters for (auto &c : converter) c->convert(dataDirs, writer); diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index f723c09..ecb011e 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -31,9 +31,6 @@ class navteq_plugin : public base_plugin { const std::vector &dirs, osmium::io::Writer &writer); - void add_landuse(const std::vector &dirs, - osmium::io::Writer &writer); - void sortPBF(); void copyType(osmium::io::Writer &writer, osmium::io::File &file, osmium::osm_entity_bits::type bits); From 7e2151cdf04dc121922775458d10c1df3d1d8e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Sat, 13 Jul 2024 10:15:49 +0000 Subject: [PATCH 12/57] extract admin boundaries --- .../converter/AdminBoundariesConverter.cpp | 343 ++++++++++++++++++ .../converter/AdminBoundariesConverter.hpp | 94 +++++ plugins/navteq/navteq.hpp | 290 --------------- 3 files changed, 437 insertions(+), 290 deletions(-) create mode 100644 plugins/navteq/converter/AdminBoundariesConverter.cpp create mode 100644 plugins/navteq/converter/AdminBoundariesConverter.hpp diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp new file mode 100644 index 0000000..acac43e --- /dev/null +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -0,0 +1,343 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "AdminBoundariesConverter.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" + +AdminBoundariesConverter::AdminBoundariesConverter() {} + +AdminBoundariesConverter::~AdminBoundariesConverter() {} + +void AdminBoundariesConverter::convert( + const std::vector &dirs, + osmium::io::Writer &writer) { + + const boost::filesystem::path ADMINBNDY_2_SHP = "Adminbndy2.shp"; + const boost::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; + const boost::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; + const boost::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; + + g_way_end_points_map.clear(); + addLevel1Boundaries(dirs, writer); + + for (auto dir : dirs) { + addLevelNBoundaries(dir / ADMINBNDY_2_SHP, writer, 2); + addLevelNBoundaries(dir / ADMINBNDY_3_SHP, writer, 3); + addLevelNBoundaries(dir / ADMINBNDY_4_SHP, writer, 4); + addLevelNBoundaries(dir / ADMINBNDY_5_SHP, writer, 5); + } + + // build relations for the admin line + g_mtd_area_map.clear(); + + g_way_end_points_map.clear(); +} + +void AdminBoundariesConverter::addLevel1Boundaries( + const std::vector &dirs, + osmium::io::Writer &writer) { + + const boost::filesystem::path ADMINLINE_1_SHP = "AdminLine1.shp"; + const boost::filesystem::path ADMINBNDY_1_SHP = "Adminbndy1.shp"; + + std::map, + std::vector>> + map; + + for (auto dir : dirs) { + // for some countries the Adminbndy1.shp doesn't contain the whole country + // border therefore we additionally add the links from AdminLine1.shp + if (shp_file_exists(dir / ADMINLINE_1_SHP)) { + auto adminLine = add_admin_lines(dir / ADMINLINE_1_SHP, writer); + // merge maps + for (auto &mapEntry : adminLine) { + std::ranges::copy(mapEntry.second, + std::back_inserter(map[mapEntry.first].first)); + } + } else if (shp_file_exists(dir / ADMINBNDY_1_SHP)) { + add_admin_shape(dir / ADMINBNDY_1_SHP, writer, map); + } + } + + // create relations for admin boundary 1 + osmium::memory::Buffer rel_buffer(BUFFER_SIZE); + for (auto &adminBoundary : map) { + + build_admin_boundary_relation_with_tags( + adminBoundary.first, adminBoundary.second.first, + adminBoundary.second.second, rel_buffer, 1); + } + rel_buffer.commit(); + writer(std::move(rel_buffer)); +} + +void AdminBoundariesConverter::add_admin_shape( + boost::filesystem::path admin_shape_file, osmium::io::Writer &writer, + std::map, + std::vector>> + &adminLineMap) { + + auto ds = open_shape_file(admin_shape_file); + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(admin_shape_file.string())); + assert(layer->GetGeomType() == wkbPolygon); + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + osmium::memory::Buffer rel_buffer(BUFFER_SIZE); + for (auto &feat : *layer) { + process_admin_boundary(feat, node_buffer, way_buffer, rel_buffer, + adminLineMap); + } + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); + writer(std::move(rel_buffer)); +} + +std::map> +AdminBoundariesConverter::add_admin_lines( + boost::filesystem::path admin_line_shape_file, osmium::io::Writer &writer) { + std::map> result; + + auto ds = open_shape_file(admin_line_shape_file); + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(admin_line_shape_file.string())); + assert(layer->GetGeomType() == wkbLineString); + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + + std::set> convertedLinkIds; + + for (auto &feat : *layer) { + auto areaId = feat->GetFieldAsInteger(AREA_ID.data()); + auto linkId = feat->GetFieldAsInteger(LINK_ID.data()); + + if (convertedLinkIds.find(std::make_pair(linkId, areaId)) == + convertedLinkIds.end()) { + auto osmIdVector = build_admin_line(feat, node_buffer, way_buffer); + std::ranges::copy(osmIdVector, std::back_inserter(result[areaId])); + convertedLinkIds.insert(std::make_pair(linkId, areaId)); + } + } + node_buffer.commit(); + way_buffer.commit(); + + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); + + return result; +} + +void AdminBoundariesConverter::process_admin_boundary( + const OGRFeatureUniquePtr &feat, osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer, osmium::memory::Buffer &rel_buffer, + std::map, + std::vector>> + &adminLineMap) { + auto geom = feat->GetGeometryRef(); + + std::vector exterior_way_ids; + std::vector interior_way_ids; + if (geom->getGeometryType() == wkbMultiPolygon) { + create_multi_polygon(static_cast(geom), exterior_way_ids, + interior_way_ids, node_buffer, way_buffer); + } else if (geom->getGeometryType() == wkbPolygon) { + create_polygon(static_cast(geom), exterior_way_ids, + interior_way_ids, node_buffer, way_buffer); + } else { + throw(std::runtime_error("Adminboundaries with geometry=" + + std::string(geom->getGeometryName()) + + " are not yet supported.")); + } + osmium::unsigned_object_id_type area_id = + feat->GetFieldAsInteger(AREA_ID.data()); + if (area_id != 0) { + std::ranges::copy(exterior_way_ids, + std::back_inserter(adminLineMap[area_id].first)); + std::ranges::copy(interior_way_ids, + std::back_inserter(adminLineMap[area_id].second)); + } else { + // need to tag here because there is no unique Area_ID + build_admin_boundary_relation_with_tags(feat, exterior_way_ids, + interior_way_ids, rel_buffer); + rel_buffer.commit(); + } + + node_buffer.commit(); + way_buffer.commit(); +} + +std::vector +AdminBoundariesConverter::build_admin_line(OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer) { + + auto line = static_cast(feat->GetGeometryRef()); + + auto osm_way_node_ids = create_open_way_nodes(line, node_buffer); + + std::vector osm_way_ids; + size_t i = 0; + do { + osmium::builder::WayBuilder builder(way_buffer); + setObjectProperties(builder); + osmium::builder::WayNodeListBuilder wnl_builder(builder); + for (size_t j = i; + j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) { + const auto &[location, osm_id] = osm_way_node_ids.at(j); + wnl_builder.add_node_ref(osm_id, location); + } + osm_way_ids.push_back(builder.object().id()); + i += OSM_MAX_WAY_NODES - 1; + } while (i < osm_way_node_ids.size()); + return osm_way_ids; +} + +osmium::unsigned_object_id_type +AdminBoundariesConverter::build_admin_boundary_relation_with_tags( + osmium::unsigned_object_id_type area_id, + const std::vector &ext_osm_way_ids, + const std::vector &int_osm_way_ids, + osmium::memory::Buffer &rel_buffer, uint level) { + osmium::builder::RelationBuilder builder(rel_buffer); + setObjectProperties(builder); + build_admin_boundary_taglist(builder, area_id, level); + build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); + return builder.object().id(); +} + +osmium::unsigned_object_id_type +AdminBoundariesConverter::build_admin_boundary_relation_with_tags( + const OGRFeatureUniquePtr &feat, + const std::vector &ext_osm_way_ids, + const std::vector &int_osm_way_ids, + osmium::memory::Buffer &rel_buffer) { + osmium::builder::RelationBuilder builder(rel_buffer); + setObjectProperties(builder); + build_admin_boundary_taglist(builder, feat); + build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); + return builder.object().id(); +} + +void AdminBoundariesConverter::addLevelNBoundaries(boost::filesystem::path dir, + osmium::io::Writer &writer, + uint level) { + std::map, + std::vector>> + map; + add_admin_shape(dir, writer, map); + + // bild boundary relation + osmium::memory::Buffer rel_buffer(BUFFER_SIZE); + for (auto &adminBoundary : map) { + + build_admin_boundary_relation_with_tags( + adminBoundary.first, adminBoundary.second.first, + adminBoundary.second.second, rel_buffer, level); + } + rel_buffer.commit(); + writer(std::move(rel_buffer)); +} + +void AdminBoundariesConverter::build_admin_boundary_taglist( + osmium::builder::Builder &builder, osmium::unsigned_object_id_type area_id, + uint level) { + osmium::builder::TagListBuilder tl_builder(builder); + // Mind tl_builder scope in calling method! + if (level == 5) { + // only landuse residential + tl_builder.add_tag("type", "multipolygon"); + tl_builder.add_tag("landuse", "residential"); + } else { + tl_builder.add_tag("type", "boundary"); + tl_builder.add_tag("boundary", "administrative"); + } + + auto it = g_mtd_area_map.find(area_id); + if (it != g_mtd_area_map.end()) { + auto d = it->second; + if (!d.admin_lvl.empty()) + tl_builder.add_tag("navteq_admin_level", d.admin_lvl); + + if (!d.admin_lvl.empty()) + tl_builder.add_tag("admin_level", navteq_2_osm_admin_lvl(d.admin_lvl)); + if (!d.name.empty()) + tl_builder.add_tag("name", d.name); + if (!d.short_name.empty()) + tl_builder.add_tag("short_name", d.short_name); + if (level != 5) { + for (auto it : d.lang_code_2_area_name) + tl_builder.add_tag(std::string("name:" + parse_lang_code(it.first)), + it.second); + } + } else { + BOOST_LOG_TRIVIAL(error) << "Skipping unknown navteq_admin_level"; + } +} + +void AdminBoundariesConverter::build_admin_boundary_taglist( + osmium::builder::Builder &builder, const OGRFeatureUniquePtr &feat) { + osmium::builder::TagListBuilder tl_builder(builder); + + int level = 0; + + std::string featureCode = feat->GetFieldAsString(FEAT_COD.data()); + if (featureCode == "907196") { + level = 1; + } else if (featureCode == "909996") { + level = 2; + } else if (featureCode == "900170") { + level = 3; + } else if (featureCode == "900101") { + level = 4; + } else if (featureCode == "900156") { + level = 5; + } else { + BOOST_LOG_TRIVIAL(error) << "Unknown admin level " << featureCode; + return; + } + + // Mind tl_builder scope in calling method! + if (level == 5) { + // only landuse residential + tl_builder.add_tag("type", "multipolygon"); + tl_builder.add_tag("landuse", "residential"); + } else { + tl_builder.add_tag("type", "boundary"); + tl_builder.add_tag("boundary", "administrative"); + } + + std::string polygonName = feat->GetFieldAsString(POLYGON_NM.data()); + if (!polygonName.empty()) { + std::string waters_name = to_camel_case_with_spaces(polygonName); + if (!waters_name.empty()) + tl_builder.add_tag("name", waters_name); + } + + tl_builder.add_tag("admin_level", navteq_2_osm_admin_lvl(level)); +} diff --git a/plugins/navteq/converter/AdminBoundariesConverter.hpp b/plugins/navteq/converter/AdminBoundariesConverter.hpp new file mode 100644 index 0000000..4595044 --- /dev/null +++ b/plugins/navteq/converter/AdminBoundariesConverter.hpp @@ -0,0 +1,94 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef ADMINBOUNDARIESCONVERTER_HPP +#define ADMINBOUNDARIESCONVERTER_HPP + +#include "Converter.hpp" + +#include + +namespace osmium { +namespace memory { +class Buffer; +} // namespace memory +namespace builder { +class Builder; +} // namespace builder +} // namespace osmium + +class AdminBoundariesConverter : public Converter { + +public: + AdminBoundariesConverter(); + virtual ~AdminBoundariesConverter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer); + +private: + void addLevel1Boundaries(const std::vector &dirs, + osmium::io::Writer &writer); + + void add_admin_shape( + boost::filesystem::path admin_shape_file, osmium::io::Writer &writer, + std::map, + std::vector>> + &adminLineMap); + + std::map> + add_admin_lines(boost::filesystem::path admin_line_shape_file, + osmium::io::Writer &writer); + + void process_admin_boundary( + const OGRFeatureUniquePtr &feat, osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer, osmium::memory::Buffer &rel_buffer, + std::map, + std::vector>> + &adminLineMap); + + std::vector + build_admin_line(OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + osmium::unsigned_object_id_type build_admin_boundary_relation_with_tags( + osmium::unsigned_object_id_type area_id, + const std::vector &ext_osm_way_ids, + const std::vector &int_osm_way_ids, + osmium::memory::Buffer &rel_buffer, uint level); + + osmium::unsigned_object_id_type build_admin_boundary_relation_with_tags( + const OGRFeatureUniquePtr &feat, + const std::vector &ext_osm_way_ids, + const std::vector &int_osm_way_ids, + osmium::memory::Buffer &rel_buffer); + + void addLevelNBoundaries(boost::filesystem::path dir, + osmium::io::Writer &writer, uint level); + + void build_admin_boundary_taglist(osmium::builder::Builder &builder, + osmium::unsigned_object_id_type area_id, + uint level); + + void build_admin_boundary_taglist(osmium::builder::Builder &builder, + const OGRFeatureUniquePtr &feat); + + static constexpr std::string_view AREA_ID = "AREA_ID"; + static constexpr std::string_view LINK_ID = "LINK_ID"; +}; + +#endif // ADMINBOUNDARIESCONVERTER_HPP \ No newline at end of file diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index 9b56402..b527d63 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -809,86 +809,6 @@ osm_id_vector_type build_closed_ways(const OGRLinearRing *ring, /** * \brief adds navteq administrative boundary tags to Relation */ -void build_admin_boundary_taglist(osmium::builder::Builder &builder, - osmium::unsigned_object_id_type area_id, - uint level) { - osmium::builder::TagListBuilder tl_builder(builder); - // Mind tl_builder scope in calling method! - if (level == 5) { - // only landuse residential - tl_builder.add_tag("type", "multipolygon"); - tl_builder.add_tag("landuse", "residential"); - } else { - tl_builder.add_tag("type", "boundary"); - tl_builder.add_tag("boundary", "administrative"); - } - - auto it = g_mtd_area_map.find(area_id); - if (it != g_mtd_area_map.end()) { - auto d = it->second; - if (!d.admin_lvl.empty()) - tl_builder.add_tag("navteq_admin_level", d.admin_lvl); - - if (!d.admin_lvl.empty()) - tl_builder.add_tag("admin_level", navteq_2_osm_admin_lvl(d.admin_lvl)); - if (!d.name.empty()) - tl_builder.add_tag("name", d.name); - if (!d.short_name.empty()) - tl_builder.add_tag("short_name", d.short_name); - if (level != 5) { - for (auto it : d.lang_code_2_area_name) - tl_builder.add_tag(std::string("name:" + parse_lang_code(it.first)), - it.second); - } - } else { - BOOST_LOG_TRIVIAL(error) << "Skipping unknown navteq_admin_level"; - } -} - -/** - * \brief adds navteq administrative boundary tags to Relation - */ -void build_admin_boundary_taglist(osmium::builder::Builder &builder, - const OGRFeatureUniquePtr &feat) { - osmium::builder::TagListBuilder tl_builder(builder); - - int level = 0; - - std::string featureCode = feat->GetFieldAsString(FEAT_COD); - if (featureCode == "907196") { - level = 1; - } else if (featureCode == "909996") { - level = 2; - } else if (featureCode == "900170") { - level = 3; - } else if (featureCode == "900101") { - level = 4; - } else if (featureCode == "900156") { - level = 5; - } else { - BOOST_LOG_TRIVIAL(error) << "Unknown admin level " << featureCode; - return; - } - - // Mind tl_builder scope in calling method! - if (level == 5) { - // only landuse residential - tl_builder.add_tag("type", "multipolygon"); - tl_builder.add_tag("landuse", "residential"); - } else { - tl_builder.add_tag("type", "boundary"); - tl_builder.add_tag("boundary", "administrative"); - } - - std::string polygonName = feat->GetFieldAsString(POLYGON_NM); - if (!polygonName.empty()) { - std::string waters_name = to_camel_case_with_spaces(polygonName); - if (!waters_name.empty()) - tl_builder.add_tag("name", waters_name); - } - - tl_builder.add_tag("admin_level", navteq_2_osm_admin_lvl(level)); -} /** * \brief adds navteq landuse tags to Relation @@ -906,33 +826,6 @@ void build_relation_members(osmium::builder::RelationBuilder &builder, rml_builder.add_member(osmium::item_type::way, osm_id, "inner"); } -osmium::unsigned_object_id_type build_admin_boundary_relation_with_tags( - osmium::unsigned_object_id_type area_id, - const osm_id_vector_type &ext_osm_way_ids, - const osm_id_vector_type &int_osm_way_ids, - osmium::memory::Buffer &rel_buffer, uint level) { - osmium::builder::RelationBuilder builder(rel_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER); - build_admin_boundary_taglist(builder, area_id, level); - build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); - return builder.object().id(); -} - -osmium::unsigned_object_id_type build_admin_boundary_relation_with_tags( - const OGRFeatureUniquePtr &feat, const osm_id_vector_type &ext_osm_way_ids, - const osm_id_vector_type &int_osm_way_ids, - osmium::memory::Buffer &rel_buffer) { - osmium::builder::RelationBuilder builder(rel_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER); - build_admin_boundary_taglist(builder, feat); - build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); - return builder.object().id(); -} - void create_polygon(const OGRPolygon *poly, osm_id_vector_type &exterior_way_ids, osm_id_vector_type &interior_way_ids, @@ -965,49 +858,6 @@ void create_multi_polygon(OGRMultiPolygon *mp, } } -/** - * \brief adds administrative boundaries as Relations to m_buffer - */ -void process_admin_boundary( - const OGRFeatureUniquePtr &feat, osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer, osmium::memory::Buffer &rel_buffer, - std::map> - &adminLineMap) { - auto geom = feat->GetGeometryRef(); - - osm_id_vector_type exterior_way_ids, interior_way_ids; - if (geom->getGeometryType() == wkbMultiPolygon) { - create_multi_polygon(static_cast(geom), exterior_way_ids, - interior_way_ids, node_buffer, way_buffer); - } else if (geom->getGeometryType() == wkbPolygon) { - create_polygon(static_cast(geom), exterior_way_ids, - interior_way_ids, node_buffer, way_buffer); - } else { - throw(std::runtime_error("Adminboundaries with geometry=" + - std::string(geom->getGeometryName()) + - " are not yet supported.")); - } - osmium::unsigned_object_id_type area_id = feat->GetFieldAsInteger(AREA_ID); - if (area_id != 0) { - boost::copy(exterior_way_ids, - std::back_inserter(adminLineMap[area_id].first)); - boost::copy(interior_way_ids, - std::back_inserter(adminLineMap[area_id].second)); - } else { - // need to tag here because there is no unique Area_ID - build_admin_boundary_relation_with_tags(feat, exterior_way_ids, - interior_way_ids, rel_buffer); - rel_buffer.commit(); - } - - node_buffer.commit(); - way_buffer.commit(); -} - -/** - * \brief adds landuse polygons as Relations to m_buffer - */ - /** * \brief adds tags from administrative boundaries to mtd_area_map. * adds tags from administrative boundaries to mtd_area_map @@ -1537,33 +1387,6 @@ void add_street_shapes(const boost::filesystem::path &dir, add_street_shapes(dir_vector, writer); } -/** - * \brief adds administrative boundaries to m_buffer / osmium. - * \param layer pointer to administrative layer. - */ - -void add_admin_shape( - boost::filesystem::path admin_shape_file, osmium::io::Writer &writer, - std::map> - &adminLineMap) { - - auto ds = open_shape_file(admin_shape_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(admin_shape_file.string())); - assert(layer->GetGeomType() == wkbPolygon); - osmium::memory::Buffer node_buffer(buffer_size); - osmium::memory::Buffer way_buffer(buffer_size); - osmium::memory::Buffer rel_buffer(buffer_size); - for (auto &feat : *layer) { - process_admin_boundary(feat, node_buffer, way_buffer, rel_buffer, - adminLineMap); - } - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); - writer(std::move(rel_buffer)); -} - /**************************************************** * cleanup and assertions ****************************************************/ @@ -1579,117 +1402,4 @@ void clear_all() { g_mtd_area_map.clear(); } -osm_id_vector_type build_admin_line(OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - - auto line = static_cast(feat->GetGeometryRef()); - - node_vector_type osm_way_node_ids = create_open_way_nodes(line, node_buffer); - - osm_id_vector_type osm_way_ids; - size_t i = 0; - do { - osmium::builder::WayBuilder builder(way_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER); - osmium::builder::WayNodeListBuilder wnl_builder(builder); - for (size_t j = i; - j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) - wnl_builder.add_node_ref(osm_way_node_ids.at(j).second, - osm_way_node_ids.at(j).first); - osm_way_ids.push_back(builder.object().id()); - i += OSM_MAX_WAY_NODES - 1; - } while (i < osm_way_node_ids.size()); - return osm_way_ids; -} - -/** - * \brief adds administrative lines to m_buffer / osmium. - * \param layer pointer to administrative layer. - */ -std::map -add_admin_lines(boost::filesystem::path admin_line_shape_file, - osmium::io::Writer &writer) { - std::map result; - - auto ds = open_shape_file(admin_line_shape_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(admin_line_shape_file.string())); - assert(layer->GetGeomType() == wkbLineString); - osmium::memory::Buffer node_buffer(buffer_size); - osmium::memory::Buffer way_buffer(buffer_size); - - std::set> convertedLinkIds; - - for (auto &feat : *layer) { - auto areaId = feat->GetFieldAsInteger(AREA_ID); - auto linkId = feat->GetFieldAsInteger(LINK_ID); - - if (convertedLinkIds.find(std::make_pair(linkId, areaId)) == - convertedLinkIds.end()) { - auto osmIdVector = build_admin_line(feat, node_buffer, way_buffer); - boost::copy(osmIdVector, std::back_inserter(result[areaId])); - convertedLinkIds.insert(std::make_pair(linkId, areaId)); - } - } - node_buffer.commit(); - way_buffer.commit(); - - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); - - return result; -} - -void addLevel1Boundaries(const std::vector &dirs, - osmium::io::Writer &writer) { - std::map> map; - - for (auto dir : dirs) { - // for some countries the Adminbndy1.shp doesn't contain the whole country - // border therefore we additionally add the links from AdminLine1.shp - if (shp_file_exists(dir / ADMINLINE_1_SHP)) { - auto adminLine = add_admin_lines(dir / ADMINLINE_1_SHP, writer); - // merge maps - for (auto &mapEntry : adminLine) { - boost::copy(mapEntry.second, - std::back_inserter(map[mapEntry.first].first)); - } - } else if (shp_file_exists(dir / ADMINBNDY_1_SHP)) { - add_admin_shape(dir / ADMINBNDY_1_SHP, writer, map); - } - } - - // create relations for admin boundary 1 - osmium::memory::Buffer rel_buffer(buffer_size); - for (auto &adminBoundary : map) { - - build_admin_boundary_relation_with_tags( - adminBoundary.first, adminBoundary.second.first, - adminBoundary.second.second, rel_buffer, 1); - } - rel_buffer.commit(); - writer(std::move(rel_buffer)); -} - -void addLevelNBoundaries(boost::filesystem::path dir, - osmium::io::Writer &writer, uint level) { - std::map> map; - add_admin_shape(dir, writer, map); - - // bild boundary relation - osmium::memory::Buffer rel_buffer(buffer_size); - for (auto &adminBoundary : map) { - - build_admin_boundary_relation_with_tags( - adminBoundary.first, adminBoundary.second.first, - adminBoundary.second.second, rel_buffer, level); - } - rel_buffer.commit(); - writer(std::move(rel_buffer)); -} - #endif /* NAVTEQ_HPP_ */ From c338c6e3d1b200d3ae3f5c614c51c7349ddce0f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 06:38:29 +0000 Subject: [PATCH 13/57] add adminboundaries converter --- .../converter/AdminBoundariesConverter.cpp | 6 +- plugins/navteq/converter/Converter.cpp | 73 +++++++++++++++++++ plugins/navteq/converter/Converter.hpp | 20 +++++ plugins/navteq/navteq.hpp | 56 -------------- plugins/navteq/navteq2osm_tag_parser.hpp | 23 ------ plugins/navteq/navteq_mappings.hpp | 6 +- plugins/navteq/navteq_plugin.cpp | 28 ------- plugins/navteq/navteq_plugin.hpp | 3 - plugins/navteq/navteq_types.hpp | 19 ----- 9 files changed, 97 insertions(+), 137 deletions(-) diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index acac43e..22a16ce 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -41,7 +41,9 @@ void AdminBoundariesConverter::convert( const boost::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; const boost::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; - g_way_end_points_map.clear(); + std::map + g_way_end_points_map; + addLevel1Boundaries(dirs, writer); for (auto dir : dirs) { @@ -53,8 +55,6 @@ void AdminBoundariesConverter::convert( // build relations for the admin line g_mtd_area_map.clear(); - - g_way_end_points_map.clear(); } void AdminBoundariesConverter::addLevel1Boundaries( diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index dd573b9..33ee3ce 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -241,3 +241,76 @@ std::string Converter::navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { return std::to_string(2 * navteq_admin_lvl_int); } + +void Converter::process_meta_areas(boost::filesystem::path dir) { + const boost::filesystem::path MTD_AREA_DBF = "MtdArea.dbf"; + + DBFHandle handle = read_dbf_file(dir / MTD_AREA_DBF); + + for (int i = 0; i < DBFGetRecordCount(handle); i++) { + + osmium::unsigned_object_id_type area_id = + dbf_get_uint_by_field(handle, i, AREA_ID); + + // find or create a new area data set + mtd_area_dataset &data = g_mtd_area_map[area_id]; + + data.area_id = area_id; + + std::string admin_lvl = + std::to_string(dbf_get_uint_by_field(handle, i, ADMIN_LVL)); + if (data.admin_lvl.empty()) { + data.admin_lvl = admin_lvl; + } else if (data.admin_lvl != admin_lvl) { + BOOST_LOG_TRIVIAL(error) + << "entry with area_id=" << area_id + << " has multiple admin_lvls:" << data.admin_lvl << ", " << admin_lvl; + } + + std::string lang_code = dbf_get_string_by_field(handle, i, LANG_CODE); + std::string area_name = dbf_get_string_by_field(handle, i, AREA_NAME); + + std::string area_type = dbf_get_string_by_field(handle, i, "AREA_TYPE"); + if (area_type == "B") { + data.name = to_camel_case_with_spaces(area_name); + data.lang_code_2_area_name.emplace_back( + lang_code, to_camel_case_with_spaces(area_name)); + data.area_code_1 = dbf_get_uint_by_field(handle, i, AREA_CODE_1); + } else if (area_type == "A") { + data.short_name = to_camel_case_with_spaces(area_name); + } else { + data.lang_code_2_area_name.emplace_back( + lang_code, to_camel_case_with_spaces(area_name)); + data.area_code_1 = dbf_get_uint_by_field(handle, i, AREA_CODE_1); + } + } + DBFClose(handle); +} + +uint Converter::get_area_code_l( + uint64_t l_area_id, uint64_t r_area_id, + const std::map + &mtd_area_map) { + + auto l_area = mtd_area_map.find(l_area_id); + if (l_area != mtd_area_map.end()) + return l_area->second.area_code_1; + + auto r_area = mtd_area_map.find(r_area_id); + if (r_area != mtd_area_map.end()) + return r_area->second.area_code_1; + + throw(out_of_range_exception("could not find area_id " + + std::to_string(++ctr) + ", " + + std::to_string(mtd_area_map.size()))); +} + +uint Converter::get_area_code_l( + const OGRFeatureUniquePtr &f, + const std::map + &mtd_area_map) { + uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); + uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); + + return get_area_code_l(l_area_id, r_area_id, mtd_area_map); +} diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 932e14c..4d76130 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -114,6 +114,16 @@ class Converter { std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int); + void process_meta_areas(boost::filesystem::path dir); + + uint get_area_code_l(uint64_t l_area_id, uint64_t r_area_id, + const std::map &mtd_area_map); + + uint get_area_code_l(const OGRFeatureUniquePtr &f, + const std::map &mtd_area_map); + static constexpr int BUFFER_SIZE = 10 * 1000 * 1000; static constexpr int OSM_MAX_WAY_NODES = 1000; @@ -138,6 +148,16 @@ class Converter { static constexpr int NAVTEQ_ADMIN_LVL_MIN = 1; static constexpr int NAVTEQ_ADMIN_LVL_MAX = 7; + + // data structure to store admin boundary tags + struct mtd_area_dataset { + osmium::unsigned_object_id_type area_id; + std::string admin_lvl; + uint area_code_1; + std::string name; + std::string short_name; + std::vector> lang_code_2_area_name; + }; }; #endif // CONVERTER_HPP diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index b527d63..fc15257 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -858,62 +858,6 @@ void create_multi_polygon(OGRMultiPolygon *mp, } } -/** - * \brief adds tags from administrative boundaries to mtd_area_map. - * adds tags from administrative boundaries to mtd_area_map - * to be accesible when creating the Relations of - * administrative boundaries. - * \param handle file handle to navteq administrative meta data. - */ -void process_meta_areas(boost::filesystem::path dir) { - DBFHandle handle = read_dbf_file(dir / MTD_AREA_DBF); - - for (int i = 0; i < DBFGetRecordCount(handle); i++) { - - osmium::unsigned_object_id_type area_id = - dbf_get_uint_by_field(handle, i, AREA_ID); - - // find or create a new area data set - mtd_area_dataset &data = g_mtd_area_map[area_id]; - - data.area_id = area_id; - - std::string admin_lvl = - std::to_string(dbf_get_uint_by_field(handle, i, ADMIN_LVL)); - if (data.admin_lvl.empty()) { - data.admin_lvl = admin_lvl; - } else if (data.admin_lvl != admin_lvl) { - BOOST_LOG_TRIVIAL(error) - << "entry with area_id=" << area_id - << " has multiple admin_lvls:" << data.admin_lvl << ", " << admin_lvl; - } - - std::string lang_code = dbf_get_string_by_field(handle, i, LANG_CODE); - std::string area_name = dbf_get_string_by_field(handle, i, AREA_NAME); - - std::string area_type = dbf_get_string_by_field(handle, i, "AREA_TYPE"); - if (area_type == "B") { - data.name = to_camel_case_with_spaces(area_name); - data.lang_code_2_area_name.emplace_back( - lang_code, to_camel_case_with_spaces(area_name)); - data.area_code_1 = dbf_get_uint_by_field(handle, i, AREA_CODE_1); - } else if (area_type == "A") { - data.short_name = to_camel_case_with_spaces(area_name); - } else { - data.lang_code_2_area_name.emplace_back( - lang_code, to_camel_case_with_spaces(area_name)); - data.area_code_1 = dbf_get_uint_by_field(handle, i, AREA_CODE_1); - } - } - DBFClose(handle); -} - -void preprocess_meta_areas(const std::vector &dirs) { - for (auto dir : dirs) { - process_meta_areas(dir); - } -} - void init_cdms_map( DBFHandle cdms_handle, std::map &cdms_map) { diff --git a/plugins/navteq/navteq2osm_tag_parser.hpp b/plugins/navteq/navteq2osm_tag_parser.hpp index 70f8a58..16029cb 100644 --- a/plugins/navteq/navteq2osm_tag_parser.hpp +++ b/plugins/navteq/navteq2osm_tag_parser.hpp @@ -72,29 +72,6 @@ bool is_motorized_allowed(OGRFeatureUniquePtr &f) { return false; } -uint get_area_code_l(area_id_type l_area_id, area_id_type r_area_id, - mtd_area_map_type *mtd_area_map) { - - auto l_area = mtd_area_map->find(l_area_id); - if (l_area != mtd_area_map->end()) - return l_area->second.area_code_1; - - auto r_area = mtd_area_map->find(r_area_id); - if (r_area != mtd_area_map->end()) - return r_area->second.area_code_1; - - throw(out_of_range_exception("could not find area_id " + - std::to_string(++ctr) + ", " + - std::to_string(mtd_area_map->size()))); -} - -uint get_area_code_l(OGRFeatureUniquePtr &f, mtd_area_map_type *mtd_area_map) { - area_id_type l_area_id = get_uint_from_feature(f, L_AREA_ID); - area_id_type r_area_id = get_uint_from_feature(f, R_AREA_ID); - - return get_area_code_l(l_area_id, r_area_id, mtd_area_map); -} - std::vector get_hwy_vector(const std::map> &HWY_TYPE_MAP, uint area_code_1) { diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 4057380..2b98fff 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -24,7 +24,7 @@ static const boost::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; static const boost::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; static const boost::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; -static const boost::filesystem::path MTD_AREA_DBF = "MtdArea.dbf"; + static const boost::filesystem::path RDMS_DBF = "Rdms.dbf"; static const boost::filesystem::path CDMS_DBF = "Cdms.dbf"; static const boost::filesystem::path CND_MOD_DBF = "CndMod.dbf"; @@ -117,10 +117,6 @@ const char *COND_TYPE = "COND_TYPE"; // const char* LINK_ID = "LINK_ID"; const char *HIGHWAY_NM = "HIGHWAY_NM"; -// WaterSeg and WaterPoly columns -const char *POLYGON_NM = "POLYGON_NM"; -const char *FEAT_COD = "FEAT_COD"; - // condition types (CT) #define CT_RESTRICTED_DRIVING_MANOEUVRE 7 #define CT_TRANSPORT_ACCESS_RESTRICTION 23 diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 0903f63..07b2350 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -186,31 +186,6 @@ bool navteq_plugin::check_input(const boost::filesystem::path &input_path, void navteq_plugin::write_output() {} -void navteq_plugin::add_administrative_boundaries( - const std::vector &dirs, - osmium::io::Writer &writer) { - // todo admin-levels only apply to the US => more generic for all countries - - g_way_end_points_map.clear(); - addLevel1Boundaries(dirs, writer); - - for (auto dir : dirs) { - if (shp_file_exists(dir / ADMINBNDY_2_SHP)) - addLevelNBoundaries(dir / ADMINBNDY_2_SHP, writer, 2); - if (shp_file_exists(dir / ADMINBNDY_3_SHP)) - addLevelNBoundaries(dir / ADMINBNDY_3_SHP, writer, 3); - if (shp_file_exists(dir / ADMINBNDY_4_SHP)) - addLevelNBoundaries(dir / ADMINBNDY_4_SHP, writer, 4); - if (shp_file_exists(dir / ADMINBNDY_5_SHP)) - addLevelNBoundaries(dir / ADMINBNDY_5_SHP, writer, 5); - } - - // build relations for the admin line - g_mtd_area_map.clear(); - - g_way_end_points_map.clear(); -} - void navteq_plugin::execute() { if (output_path.empty()) throw std::exception(); @@ -231,9 +206,6 @@ void navteq_plugin::execute() { BOOST_LOG_TRIVIAL(info) << "Add street shapes"; add_street_shapes(dataDirs, writer); - BOOST_LOG_TRIVIAL(info) << "Add administrative boundaries"; - add_administrative_boundaries(dataDirs, writer); - // run converters for (auto &c : converter) c->convert(dataDirs, writer); diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index ecb011e..9184e0d 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -27,9 +27,6 @@ class navteq_plugin : public base_plugin { void recurse_dir(const boost::filesystem::path &dir); bool check_files(const boost::filesystem::path &dir); void write_output(); - void add_administrative_boundaries( - const std::vector &dirs, - osmium::io::Writer &writer); void sortPBF(); void copyType(osmium::io::Writer &writer, osmium::io::File &file, diff --git a/plugins/navteq/navteq_types.hpp b/plugins/navteq/navteq_types.hpp index 70eaa1e..7ac4b75 100644 --- a/plugins/navteq/navteq_types.hpp +++ b/plugins/navteq/navteq_types.hpp @@ -63,25 +63,6 @@ typedef std::map cntry_ref_map_type; typedef std::map admin_bndy_map_type; -// data structure to store admin boundary tags -struct mtd_area_dataset { - osmium::unsigned_object_id_type area_id; - std::string admin_lvl; - uint area_code_1; - std::string name; - std::string short_name; - std::vector> lang_code_2_area_name; - - void print() { - std::cout << "area_id=" << area_id; - std::cout << ", admin_lvl=" << admin_lvl; - std::cout << std::endl; - } -}; - -typedef std::map - mtd_area_map_type; - typedef uint64_t link_id_type; // vector of osm_ids From 428b2550236b524f71e3fb4b1bd7d4d989134270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 07:22:38 +0000 Subject: [PATCH 14/57] move iso parse logic to converter --- .../converter/AdminBoundariesConverter.cpp | 4 +- .../converter/AdminBoundariesConverter.hpp | 2 +- .../navteq/converter/BuildingConverter.cpp | 4 +- .../navteq/converter/BuildingConverter.hpp | 2 +- plugins/navteq/converter/CityConverter.cpp | 3 +- plugins/navteq/converter/CityConverter.hpp | 2 +- plugins/navteq/converter/Converter.cpp | 60 ++++++++++++++++++- plugins/navteq/converter/Converter.hpp | 34 +++++++---- plugins/navteq/converter/HamletConverter.cpp | 3 +- plugins/navteq/converter/HamletConverter.hpp | 2 +- plugins/navteq/converter/LanduseConverter.cpp | 4 +- plugins/navteq/converter/LanduseConverter.hpp | 2 +- plugins/navteq/converter/RailwayConverter.cpp | 4 +- plugins/navteq/converter/RailwayConverter.hpp | 2 +- .../navteq/converter/RestAreaConverter.cpp | 4 +- .../navteq/converter/RestAreaConverter.hpp | 2 +- plugins/navteq/converter/WaterConverter.cpp | 3 +- plugins/navteq/converter/WaterConverter.hpp | 2 +- plugins/navteq/navteq.hpp | 3 - plugins/navteq/navteq2osm_tag_parser.hpp | 52 ---------------- plugins/navteq/navteq_plugin.cpp | 20 +++---- 21 files changed, 120 insertions(+), 94 deletions(-) diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index 22a16ce..5f88a55 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -28,7 +28,9 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -AdminBoundariesConverter::AdminBoundariesConverter() {} +AdminBoundariesConverter::AdminBoundariesConverter( + const boost::filesystem::path &executable_path) + : Converter(executable_path) {} AdminBoundariesConverter::~AdminBoundariesConverter() {} diff --git a/plugins/navteq/converter/AdminBoundariesConverter.hpp b/plugins/navteq/converter/AdminBoundariesConverter.hpp index 4595044..c238760 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.hpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.hpp @@ -33,7 +33,7 @@ class Builder; class AdminBoundariesConverter : public Converter { public: - AdminBoundariesConverter(); + AdminBoundariesConverter(const boost::filesystem::path &executable_path); virtual ~AdminBoundariesConverter(); virtual void convert(const std::vector &dirs, diff --git a/plugins/navteq/converter/BuildingConverter.cpp b/plugins/navteq/converter/BuildingConverter.cpp index 782e60b..7433bde 100644 --- a/plugins/navteq/converter/BuildingConverter.cpp +++ b/plugins/navteq/converter/BuildingConverter.cpp @@ -27,7 +27,9 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -BuildingConverter::BuildingConverter() {} +BuildingConverter::BuildingConverter( + const boost::filesystem::path &executable_path) + : Converter(executable_path) {} BuildingConverter::~BuildingConverter() {} diff --git a/plugins/navteq/converter/BuildingConverter.hpp b/plugins/navteq/converter/BuildingConverter.hpp index fa24513..54ac794 100644 --- a/plugins/navteq/converter/BuildingConverter.hpp +++ b/plugins/navteq/converter/BuildingConverter.hpp @@ -24,7 +24,7 @@ class BuildingConverter : public Converter { public: - BuildingConverter(); + BuildingConverter(const boost::filesystem::path &executable_path); virtual ~BuildingConverter(); virtual void convert(const std::vector &dirs, diff --git a/plugins/navteq/converter/CityConverter.cpp b/plugins/navteq/converter/CityConverter.cpp index 313d271..3b7fe0c 100644 --- a/plugins/navteq/converter/CityConverter.cpp +++ b/plugins/navteq/converter/CityConverter.cpp @@ -26,7 +26,8 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -CityConverter::CityConverter() {} +CityConverter::CityConverter(const boost::filesystem::path &executable_path) + : Converter(executable_path) {} CityConverter::~CityConverter() {} diff --git a/plugins/navteq/converter/CityConverter.hpp b/plugins/navteq/converter/CityConverter.hpp index 6b52091..f95d608 100644 --- a/plugins/navteq/converter/CityConverter.hpp +++ b/plugins/navteq/converter/CityConverter.hpp @@ -24,7 +24,7 @@ class CityConverter : public Converter { public: - CityConverter(); + CityConverter(const boost::filesystem::path &executable_path); virtual ~CityConverter(); virtual void convert(const std::vector &dirs, diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 33ee3ce..14ce7a0 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -1,6 +1,7 @@ #include "Converter.hpp" +#include #include #include #include @@ -242,9 +243,63 @@ std::string Converter::navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { return std::to_string(2 * navteq_admin_lvl_int); } -void Converter::process_meta_areas(boost::filesystem::path dir) { +// matching from http://www.loc.gov/standards/iso639-2/php/code_list.php +// http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt +// ISO-639 conversion + +void Converter::parse_lang_code_file() { + const boost::filesystem::path PLUGINS_NAVTEQ_ISO_639_2_UTF_8_TXT( + "plugins/navteq/ISO-639-2_utf-8.txt"); + + if (executable_path.empty()) + throw(std::runtime_error("executable_path is empty")); + + boost::filesystem::path iso_file(executable_path / + PLUGINS_NAVTEQ_ISO_639_2_UTF_8_TXT); + std::ifstream file(iso_file.string()); + assert(file.is_open()); + std::string line; + std::string delim = "|"; + if (file.is_open()) { + while (getline(file, line, '\n')) { + std::vector lv; + auto start = 0u; + auto end = line.find(delim); + while (end != std::string::npos) { + lv.push_back(line.substr(start, end - start)); + start = end + delim.length(); + end = line.find(delim, start); + } + std::string iso_639_2 = lv.at(0); + std::string iso_639_1 = lv.at(2); + lang_code_map.emplace(std::make_pair(iso_639_2, iso_639_1)); + } + file.close(); + } +} + +std::string Converter::parse_lang_code(std::string lang_code) { + std::ranges::transform(lang_code, lang_code.begin(), ::tolower); + if (lang_code_map.empty()) + parse_lang_code_file(); + + auto lc = lang_code_map.find(lang_code); + if (lc != lang_code_map.end()) { + if (!lc->second.empty()) + return lc->second; + else + return lang_code; // fallback + } + BOOST_LOG_TRIVIAL(error) << lang_code << " not found!\n"; + return lang_code; // fallback +} + +std::map +Converter::process_meta_areas(boost::filesystem::path dir) { const boost::filesystem::path MTD_AREA_DBF = "MtdArea.dbf"; + std::map mtd_area_map; + DBFHandle handle = read_dbf_file(dir / MTD_AREA_DBF); for (int i = 0; i < DBFGetRecordCount(handle); i++) { @@ -253,7 +308,7 @@ void Converter::process_meta_areas(boost::filesystem::path dir) { dbf_get_uint_by_field(handle, i, AREA_ID); // find or create a new area data set - mtd_area_dataset &data = g_mtd_area_map[area_id]; + mtd_area_dataset &data = mtd_area_map[area_id]; data.area_id = area_id; @@ -285,6 +340,7 @@ void Converter::process_meta_areas(boost::filesystem::path dir) { } } DBFClose(handle); + return mtd_area_map; } uint Converter::get_area_code_l( diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 4d76130..444e5cd 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -50,7 +51,9 @@ class OGRLinearRing; class Converter { public: - Converter() {} + Converter(const boost::filesystem::path &_executable_path) { + executable_path = _executable_path; + } virtual ~Converter() {} virtual void convert(const std::vector &dirs, @@ -59,6 +62,16 @@ class Converter { void set_dummy_osm_object_attributes(osmium::OSMObject &obj); protected: + // data structure to store admin boundary tags + struct mtd_area_dataset { + osmium::unsigned_object_id_type area_id; + std::string admin_lvl; + uint area_code_1; + std::string name; + std::string short_name; + std::vector> lang_code_2_area_name; + }; + void build_relation_members( osmium::builder::RelationBuilder &builder, const std::vector &ext_osm_way_ids, @@ -114,7 +127,8 @@ class Converter { std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int); - void process_meta_areas(boost::filesystem::path dir); + std::map + process_meta_areas(boost::filesystem::path dir); uint get_area_code_l(uint64_t l_area_id, uint64_t r_area_id, const std::map &mtd_area_map); + void parse_lang_code_file(); + + std::string parse_lang_code(std::string lang_code); + static constexpr int BUFFER_SIZE = 10 * 1000 * 1000; static constexpr int OSM_MAX_WAY_NODES = 1000; @@ -149,15 +167,9 @@ class Converter { static constexpr int NAVTEQ_ADMIN_LVL_MIN = 1; static constexpr int NAVTEQ_ADMIN_LVL_MAX = 7; - // data structure to store admin boundary tags - struct mtd_area_dataset { - osmium::unsigned_object_id_type area_id; - std::string admin_lvl; - uint area_code_1; - std::string name; - std::string short_name; - std::vector> lang_code_2_area_name; - }; +private: + static std::map lang_code_map; + boost::filesystem::path &executable_path; }; #endif // CONVERTER_HPP diff --git a/plugins/navteq/converter/HamletConverter.cpp b/plugins/navteq/converter/HamletConverter.cpp index 5cf0b40..304ac57 100644 --- a/plugins/navteq/converter/HamletConverter.cpp +++ b/plugins/navteq/converter/HamletConverter.cpp @@ -26,7 +26,8 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -HamletConverter::HamletConverter() {} +HamletConverter::HamletConverter(const boost::filesystem::path &executable_path) + : Converter(executable_path) {} HamletConverter::~HamletConverter() {} diff --git a/plugins/navteq/converter/HamletConverter.hpp b/plugins/navteq/converter/HamletConverter.hpp index 12d1084..20ca57b 100644 --- a/plugins/navteq/converter/HamletConverter.hpp +++ b/plugins/navteq/converter/HamletConverter.hpp @@ -24,7 +24,7 @@ class HamletConverter : public Converter { public: - HamletConverter(); + HamletConverter(const boost::filesystem::path &executable_path); virtual ~HamletConverter(); virtual void convert(const std::vector &dirs, diff --git a/plugins/navteq/converter/LanduseConverter.cpp b/plugins/navteq/converter/LanduseConverter.cpp index a36801b..ed6f7a7 100644 --- a/plugins/navteq/converter/LanduseConverter.cpp +++ b/plugins/navteq/converter/LanduseConverter.cpp @@ -26,7 +26,9 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -LanduseConverter::LanduseConverter() {} +LanduseConverter::LanduseConverter( + const boost::filesystem::path &executable_path) + : Converter(executable_path) {} LanduseConverter::~LanduseConverter() {} diff --git a/plugins/navteq/converter/LanduseConverter.hpp b/plugins/navteq/converter/LanduseConverter.hpp index 8b605b4..372db5a 100644 --- a/plugins/navteq/converter/LanduseConverter.hpp +++ b/plugins/navteq/converter/LanduseConverter.hpp @@ -24,7 +24,7 @@ class LanduseConverter : public Converter { public: - LanduseConverter(); + LanduseConverter(const boost::filesystem::path &executable_path); virtual ~LanduseConverter(); virtual void convert(const std::vector &dirs, diff --git a/plugins/navteq/converter/RailwayConverter.cpp b/plugins/navteq/converter/RailwayConverter.cpp index df87d72..2152b3d 100644 --- a/plugins/navteq/converter/RailwayConverter.cpp +++ b/plugins/navteq/converter/RailwayConverter.cpp @@ -26,7 +26,9 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -RailwayConverter::RailwayConverter() {} +RailwayConverter::RailwayConverter( + const boost::filesystem::path &executable_path) + : Converter(executable_path) {} RailwayConverter::~RailwayConverter() {} diff --git a/plugins/navteq/converter/RailwayConverter.hpp b/plugins/navteq/converter/RailwayConverter.hpp index b8c4eac..31e9291 100644 --- a/plugins/navteq/converter/RailwayConverter.hpp +++ b/plugins/navteq/converter/RailwayConverter.hpp @@ -24,7 +24,7 @@ class RailwayConverter : public Converter { public: - RailwayConverter(); + RailwayConverter(const boost::filesystem::path &executable_path); virtual ~RailwayConverter(); virtual void convert(const std::vector &dirs, diff --git a/plugins/navteq/converter/RestAreaConverter.cpp b/plugins/navteq/converter/RestAreaConverter.cpp index f2170c1..25273aa 100644 --- a/plugins/navteq/converter/RestAreaConverter.cpp +++ b/plugins/navteq/converter/RestAreaConverter.cpp @@ -26,7 +26,9 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -RestAreaConverter::RestAreaConverter() {} +RestAreaConverter::RestAreaConverter( + const boost::filesystem::path &executable_path) + : Converter(executable_path) {} RestAreaConverter::~RestAreaConverter() {} diff --git a/plugins/navteq/converter/RestAreaConverter.hpp b/plugins/navteq/converter/RestAreaConverter.hpp index a79017a..3333945 100644 --- a/plugins/navteq/converter/RestAreaConverter.hpp +++ b/plugins/navteq/converter/RestAreaConverter.hpp @@ -24,7 +24,7 @@ class RestAreaConverter : public Converter { public: - RestAreaConverter(); + RestAreaConverter(const boost::filesystem::path &executable_path); virtual ~RestAreaConverter(); virtual void convert(const std::vector &dirs, diff --git a/plugins/navteq/converter/WaterConverter.cpp b/plugins/navteq/converter/WaterConverter.cpp index 7a33d36..b58a81b 100644 --- a/plugins/navteq/converter/WaterConverter.cpp +++ b/plugins/navteq/converter/WaterConverter.cpp @@ -25,7 +25,8 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -WaterConverter::WaterConverter() {} +WaterConverter::WaterConverter(const boost::filesystem::path &executable_path) + : Converter(executable_path) {} WaterConverter::~WaterConverter() {} diff --git a/plugins/navteq/converter/WaterConverter.hpp b/plugins/navteq/converter/WaterConverter.hpp index 13b0978..20d1bf9 100644 --- a/plugins/navteq/converter/WaterConverter.hpp +++ b/plugins/navteq/converter/WaterConverter.hpp @@ -39,7 +39,7 @@ class OGRLineString; class WaterConverter : public Converter { public: - WaterConverter(); + WaterConverter(const boost::filesystem::path &executable_path); virtual ~WaterConverter(); virtual void convert(const std::vector &dirs, diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index fc15257..410e194 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -56,9 +56,6 @@ std::set g_construction_set; // g_ramps_ref_map maps navteq link_ids to a vector of ramp names std::map> g_ramps_ref_map; -// auxiliary map which maps datasets with tags for administrative boundaries -mtd_area_map_type g_mtd_area_map; - // map for conditional modifications cnd_mod_map_type g_cnd_mod_map; diff --git a/plugins/navteq/navteq2osm_tag_parser.hpp b/plugins/navteq/navteq2osm_tag_parser.hpp index 16029cb..229418c 100644 --- a/plugins/navteq/navteq2osm_tag_parser.hpp +++ b/plugins/navteq/navteq2osm_tag_parser.hpp @@ -8,9 +8,6 @@ #include "navteq_types.hpp" #include "navteq_util.hpp" -boost::filesystem::path g_executable_path; -const boost::filesystem::path - PLUGINS_NAVTEQ_ISO_639_2_UTF_8_TXT("plugins/navteq/ISO-639-2_utf-8.txt"); int ctr = 0; bool fits_street_ref(const std::string &st_name) { @@ -705,55 +702,6 @@ link_id_type parse_street_tags( return link_id; } -// matching from http://www.loc.gov/standards/iso639-2/php/code_list.php -// http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt -// ISO-639 conversion -std::map g_lang_code_map; -void parse_lang_code_file() { - if (g_executable_path.empty()) - throw(std::runtime_error("executable_path is empty")); - - boost::filesystem::path iso_file(g_executable_path / - PLUGINS_NAVTEQ_ISO_639_2_UTF_8_TXT); - std::ifstream file(iso_file.string()); - assert(file.is_open()); - std::string line; - std::string delim = "|"; - if (file.is_open()) { - while (getline(file, line, '\n')) { - std::vector lv; - auto start = 0u; - auto end = line.find(delim); - while (end != std::string::npos) { - lv.push_back(line.substr(start, end - start)); - start = end + delim.length(); - end = line.find(delim, start); - } - std::string iso_639_2 = lv.at(0); - std::string iso_639_1 = lv.at(2); - g_lang_code_map.emplace(std::make_pair(iso_639_2, iso_639_1)); - } - file.close(); - } -} - -std::string parse_lang_code(std::string lang_code) { - std::transform(lang_code.begin(), lang_code.end(), lang_code.begin(), - ::tolower); - if (g_lang_code_map.empty()) - parse_lang_code_file(); - - auto lc = g_lang_code_map.find(lang_code); - if (lc != g_lang_code_map.end()) { - if (!lc->second.empty()) - return lc->second; - else - return lang_code; // fallback - } - std::cerr << lang_code << " not found!" << std::endl; - return lang_code; // fallback -} - std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { if (!is_in_range(navteq_admin_lvl_int, (uint)NAVTEQ_ADMIN_LVL_MIN, (uint)NAVTEQ_ADMIN_LVL_MAX)) diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 07b2350..42e319c 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -16,6 +16,7 @@ #include #include +#include "converter/AdminBoundariesConverter.hpp" #include "converter/BuildingConverter.hpp" #include "converter/CityConverter.hpp" #include "converter/HamletConverter.hpp" @@ -36,16 +37,15 @@ navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) : base_plugin::base_plugin("Navteq Plugin", executable_path) { - // setting executable_path in navteq2osm_tag_parser.hpp for reading ISO-file - g_executable_path = this->executable_path; - - converter.emplace_back(new LanduseConverter()); - converter.emplace_back(new CityConverter()); - converter.emplace_back(new HamletConverter()); - converter.emplace_back(new BuildingConverter()); - converter.emplace_back(new RestAreaConverter()); - converter.emplace_back(new RailwayConverter()); - converter.emplace_back(new WaterConverter()); + + convetrer.emplace_back(new AdminBoundariesConverter(executable_path)); + converter.emplace_back(new LanduseConverter(executable_path)); + converter.emplace_back(new CityConverter(executable_path)); + converter.emplace_back(new HamletConverter(executable_path)); + converter.emplace_back(new BuildingConverter(executable_path)); + converter.emplace_back(new RestAreaConverter(executable_path); + converter.emplace_back(new RailwayConverter(executable_path)); + converter.emplace_back(new WaterConverter(executable_path)); } navteq_plugin::~navteq_plugin() {} From 5ed90fd63436b58c14cf28fa075de16929dfd692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 07:39:05 +0000 Subject: [PATCH 15/57] Extract admin boundaries and refactor AdminBoundariesConverter --- .../converter/AdminBoundariesConverter.cpp | 71 ++++++++++++------- .../converter/AdminBoundariesConverter.hpp | 30 ++++++-- plugins/navteq/converter/Converter.cpp | 2 +- 3 files changed, 68 insertions(+), 35 deletions(-) diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index 5f88a55..138c648 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -46,21 +46,20 @@ void AdminBoundariesConverter::convert( std::map g_way_end_points_map; - addLevel1Boundaries(dirs, writer); + addLevel1Boundaries(dirs, g_way_end_points_map, writer); for (auto dir : dirs) { - addLevelNBoundaries(dir / ADMINBNDY_2_SHP, writer, 2); - addLevelNBoundaries(dir / ADMINBNDY_3_SHP, writer, 3); - addLevelNBoundaries(dir / ADMINBNDY_4_SHP, writer, 4); - addLevelNBoundaries(dir / ADMINBNDY_5_SHP, writer, 5); + addLevelNBoundaries(dir / ADMINBNDY_2_SHP, g_way_end_points_map, writer, 2); + addLevelNBoundaries(dir / ADMINBNDY_3_SHP, g_way_end_points_map, writer, 3); + addLevelNBoundaries(dir / ADMINBNDY_4_SHP, g_way_end_points_map, writer, 4); + addLevelNBoundaries(dir / ADMINBNDY_5_SHP, g_way_end_points_map, writer, 5); } - - // build relations for the admin line - g_mtd_area_map.clear(); } void AdminBoundariesConverter::addLevel1Boundaries( const std::vector &dirs, + std::map + &g_way_end_points_map, osmium::io::Writer &writer) { const boost::filesystem::path ADMINLINE_1_SHP = "AdminLine1.shp"; @@ -74,14 +73,15 @@ void AdminBoundariesConverter::addLevel1Boundaries( // for some countries the Adminbndy1.shp doesn't contain the whole country // border therefore we additionally add the links from AdminLine1.shp if (shp_file_exists(dir / ADMINLINE_1_SHP)) { - auto adminLine = add_admin_lines(dir / ADMINLINE_1_SHP, writer); + auto adminLine = + add_admin_lines(dir / ADMINLINE_1_SHP, g_way_end_points_map, writer); // merge maps for (auto &mapEntry : adminLine) { std::ranges::copy(mapEntry.second, std::back_inserter(map[mapEntry.first].first)); } } else if (shp_file_exists(dir / ADMINBNDY_1_SHP)) { - add_admin_shape(dir / ADMINBNDY_1_SHP, writer, map); + add_admin_shape(dir / ADMINBNDY_1_SHP, g_way_end_points_map, writer, map); } } @@ -98,7 +98,10 @@ void AdminBoundariesConverter::addLevel1Boundaries( } void AdminBoundariesConverter::add_admin_shape( - boost::filesystem::path admin_shape_file, osmium::io::Writer &writer, + boost::filesystem::path admin_shape_file, + std::map + &g_way_end_points_map, + osmium::io::Writer &writer, std::map, std::vector>> &adminLineMap) { @@ -112,8 +115,8 @@ void AdminBoundariesConverter::add_admin_shape( osmium::memory::Buffer way_buffer(BUFFER_SIZE); osmium::memory::Buffer rel_buffer(BUFFER_SIZE); for (auto &feat : *layer) { - process_admin_boundary(feat, node_buffer, way_buffer, rel_buffer, - adminLineMap); + process_admin_boundary(feat, g_way_end_points_map, node_buffer, way_buffer, + rel_buffer, adminLineMap); } writer(std::move(node_buffer)); writer(std::move(way_buffer)); @@ -122,7 +125,10 @@ void AdminBoundariesConverter::add_admin_shape( std::map> AdminBoundariesConverter::add_admin_lines( - boost::filesystem::path admin_line_shape_file, osmium::io::Writer &writer) { + boost::filesystem::path admin_line_shape_file, + std::map + &g_way_end_points_map, + osmium::io::Writer &writer) { std::map> result; auto ds = open_shape_file(admin_line_shape_file); @@ -141,7 +147,8 @@ AdminBoundariesConverter::add_admin_lines( if (convertedLinkIds.find(std::make_pair(linkId, areaId)) == convertedLinkIds.end()) { - auto osmIdVector = build_admin_line(feat, node_buffer, way_buffer); + auto osmIdVector = + build_admin_line(feat, g_way_end_points_map, node_buffer, way_buffer); std::ranges::copy(osmIdVector, std::back_inserter(result[areaId])); convertedLinkIds.insert(std::make_pair(linkId, areaId)); } @@ -156,8 +163,11 @@ AdminBoundariesConverter::add_admin_lines( } void AdminBoundariesConverter::process_admin_boundary( - const OGRFeatureUniquePtr &feat, osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer, osmium::memory::Buffer &rel_buffer, + const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer, + osmium::memory::Buffer &rel_buffer, std::map, std::vector>> &adminLineMap) { @@ -167,10 +177,12 @@ void AdminBoundariesConverter::process_admin_boundary( std::vector interior_way_ids; if (geom->getGeometryType() == wkbMultiPolygon) { create_multi_polygon(static_cast(geom), exterior_way_ids, - interior_way_ids, node_buffer, way_buffer); + interior_way_ids, g_way_end_points_map, node_buffer, + way_buffer); } else if (geom->getGeometryType() == wkbPolygon) { create_polygon(static_cast(geom), exterior_way_ids, - interior_way_ids, node_buffer, way_buffer); + interior_way_ids, g_way_end_points_map, node_buffer, + way_buffer); } else { throw(std::runtime_error("Adminboundaries with geometry=" + std::string(geom->getGeometryName()) + @@ -195,13 +207,16 @@ void AdminBoundariesConverter::process_admin_boundary( } std::vector -AdminBoundariesConverter::build_admin_line(OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { +AdminBoundariesConverter::build_admin_line( + OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { auto line = static_cast(feat->GetGeometryRef()); - auto osm_way_node_ids = create_open_way_nodes(line, node_buffer); + auto osm_way_node_ids = + create_open_way_nodes(line, g_way_end_points_map, node_buffer); std::vector osm_way_ids; size_t i = 0; @@ -246,13 +261,15 @@ AdminBoundariesConverter::build_admin_boundary_relation_with_tags( return builder.object().id(); } -void AdminBoundariesConverter::addLevelNBoundaries(boost::filesystem::path dir, - osmium::io::Writer &writer, - uint level) { +void AdminBoundariesConverter::addLevelNBoundaries( + boost::filesystem::path dir, + std::map + &g_way_end_points_map, + osmium::io::Writer &writer, uint level) { std::map, std::vector>> map; - add_admin_shape(dir, writer, map); + add_admin_shape(dir, g_way_end_points_map, writer, map); // bild boundary relation osmium::memory::Buffer rel_buffer(BUFFER_SIZE); diff --git a/plugins/navteq/converter/AdminBoundariesConverter.hpp b/plugins/navteq/converter/AdminBoundariesConverter.hpp index c238760..0c86421 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.hpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.hpp @@ -40,28 +40,41 @@ class AdminBoundariesConverter : public Converter { osmium::io::Writer &writer); private: - void addLevel1Boundaries(const std::vector &dirs, - osmium::io::Writer &writer); + void addLevel1Boundaries( + const std::vector &dirs, + std::map + &g_way_end_points_map, + osmium::io::Writer &writer); void add_admin_shape( - boost::filesystem::path admin_shape_file, osmium::io::Writer &writer, + boost::filesystem::path admin_shape_file, + std::map + &g_way_end_points_map, + osmium::io::Writer &writer, std::map, std::vector>> &adminLineMap); std::map> add_admin_lines(boost::filesystem::path admin_line_shape_file, + std::map + &g_way_end_points_map, osmium::io::Writer &writer); void process_admin_boundary( - const OGRFeatureUniquePtr &feat, osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer, osmium::memory::Buffer &rel_buffer, + const OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer, + osmium::memory::Buffer &rel_buffer, std::map, std::vector>> &adminLineMap); std::vector build_admin_line(OGRFeatureUniquePtr &feat, + std::map + &g_way_end_points_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); @@ -77,8 +90,11 @@ class AdminBoundariesConverter : public Converter { const std::vector &int_osm_way_ids, osmium::memory::Buffer &rel_buffer); - void addLevelNBoundaries(boost::filesystem::path dir, - osmium::io::Writer &writer, uint level); + void addLevelNBoundaries( + boost::filesystem::path dir, + std::map + &g_way_end_points_map, + osmium::io::Writer &writer, uint level); void build_admin_boundary_taglist(osmium::builder::Builder &builder, osmium::unsigned_object_id_type area_id, diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 14ce7a0..54283ad 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -2,6 +2,7 @@ #include "Converter.hpp" #include +#include #include #include #include @@ -357,7 +358,6 @@ uint Converter::get_area_code_l( return r_area->second.area_code_1; throw(out_of_range_exception("could not find area_id " + - std::to_string(++ctr) + ", " + std::to_string(mtd_area_map.size()))); } From 03b5716827d073985c32c81dad69812df92e3d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 10:43:49 +0000 Subject: [PATCH 16/57] Refactor code to add LINK_ID constant in Converter.hpp and remove LINK_ID constant in AdminBoundariesConverter.hpp --- .../converter/AdminBoundariesConverter.hpp | 1 - plugins/navteq/converter/Converter.hpp | 2 + plugins/navteq/converter/StreetConverter.cpp | 806 +++++++++++++++ plugins/navteq/converter/StreetConverter.hpp | 201 ++++ plugins/navteq/navteq.hpp | 951 ------------------ plugins/navteq/navteq2osm_tag_parser.hpp | 169 ---- plugins/navteq/navteq_mappings.hpp | 30 +- plugins/navteq/navteq_plugin.cpp | 17 +- plugins/navteq/navteq_types.hpp | 25 +- plugins/util.hpp | 58 ++ 10 files changed, 1073 insertions(+), 1187 deletions(-) create mode 100644 plugins/navteq/converter/StreetConverter.cpp create mode 100644 plugins/navteq/converter/StreetConverter.hpp diff --git a/plugins/navteq/converter/AdminBoundariesConverter.hpp b/plugins/navteq/converter/AdminBoundariesConverter.hpp index 0c86421..de0e09d 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.hpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.hpp @@ -104,7 +104,6 @@ class AdminBoundariesConverter : public Converter { const OGRFeatureUniquePtr &feat); static constexpr std::string_view AREA_ID = "AREA_ID"; - static constexpr std::string_view LINK_ID = "LINK_ID"; }; #endif // ADMINBOUNDARIESCONVERTER_HPP \ No newline at end of file diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 444e5cd..bca7400 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -164,6 +164,8 @@ class Converter { static constexpr std::string_view POI_NMTYPE = "POI_NMTYPE"; static constexpr std::string_view POI_NAME = "POI_NAME"; + static constexpr std::string_view LINK_ID = "LINK_ID"; + static constexpr int NAVTEQ_ADMIN_LVL_MIN = 1; static constexpr int NAVTEQ_ADMIN_LVL_MAX = 7; diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp new file mode 100644 index 0000000..7c5e6f5 --- /dev/null +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -0,0 +1,806 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "StreetConverter.hpp" + +#include +#include +#include +#include +#include +#include + +#include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" + +StreetConverter::StreetConverter(const boost::filesystem::path &executable_path) + : Converter(executable_path) {} + +StreetConverter::~StreetConverter() {} + +void StreetConverter::convert(const std::vector &dirs, + osmium::io::Writer &writer) { + + auto route_type_map = process_alt_steets_route_types(dirs); + + add_street_shapes(dirs, writer); +} + +std::map StreetConverter::process_alt_steets_route_types( + const std::vector &dirs) { + + std::map route_type_map; + + const boost::filesystem::path ALT_STREETS_DBF = "AltStreets.dbf"; + for (auto dir : dirs) { + DBFHandle alt_streets_handle = read_dbf_file(dir / ALT_STREETS_DBF); + for (int i = 0; i < DBFGetRecordCount(alt_streets_handle); i++) { + + if (dbf_get_string_by_field(alt_streets_handle, i, ROUTE).empty()) + continue; + + osmium::unsigned_object_id_type link_id = + dbf_get_uint_by_field(alt_streets_handle, i, LINK_ID.data()); + ushort route_type = dbf_get_uint_by_field(alt_streets_handle, i, ROUTE); + + // try to emplace pair + auto [insertion, inserted] = route_type_map.emplace(link_id, route_type); + + // if its already exists update routetype + if (!inserted && insertion->second > route_type) { + // As link id's aren't unique in AltStreets.dbf + // just store the lowest route type + insertion->second = route_type; + } + } + DBFClose(alt_streets_handle); + } + + return route_type_map; +} + +void StreetConverter::add_street_shapes( + const std::vector &dirs, + osmium::io::Writer &writer) { + + BOOST_LOG_TRIVIAL(info) << " processing z-levels"; + auto z_level_map = process_z_levels(dirs); + + BOOST_LOG_TRIVIAL(info) << " processing way end points"; + process_way_end_nodes(dirs, z_level_map, writer); + + BOOST_LOG_TRIVIAL(info) << " processing ways"; + process_way(dirs, z_level_map, writer); + + // create house numbers + BOOST_LOG_TRIVIAL(info) << " processing house numbers"; + process_house_numbers(dirs, writer); +} + +std::map> +StreetConverter::process_z_levels( + const std::vector &dirs) { + std::map> z_level_map; + + for (auto &dir : dirs) { + auto path = dir / STREETS_SHP; + auto ds = open_shape_file(path); + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(path.string())); + assert(layer->GetGeomType() == wkbLineString); + + init_z_level_map(dir, z_level_map); + init_conditional_modifications(dir); + init_country_reference(dir); + } + return z_level_map; +} + +void StreetConverter::init_z_level_map( + boost::filesystem::path dir, + std::map> &z_level_map) { + + const boost::filesystem::path ZLEVELS_DBF = "Zlevels.dbf"; + // open dbf + DBFHandle handle = read_dbf_file(dir / ZLEVELS_DBF); + + uint64_t last_link_id = 0; + std::vector v; + + for (int i = 0; i < DBFGetRecordCount(handle); i++) { + uint64_t link_id = dbf_get_uint_by_field(handle, i, LINK_ID.data()); + ushort point_num = dbf_get_uint_by_field(handle, i, POINT_NUM.data()) - 1; + short z_level = dbf_get_uint_by_field(handle, i, Z_LEVEL.data()); + + if (i > 0 && last_link_id != link_id && !v.empty()) { + z_level_map.emplace(last_link_id, v); + v = std::vector(); + } + if (z_level != 0) + v.emplace_back(point_num, z_level); + last_link_id = link_id; + } + + // close dbf + DBFClose(handle); + + if (!v.empty()) + z_level_map.emplace(last_link_id, v); +} + +void StreetConverter::init_conditional_modifications( + const boost::filesystem::path &dir) { + init_g_cnd_mod_map(dir); + init_g_cdms_map(dir); +} + +void StreetConverter::init_g_cnd_mod_map(const boost::filesystem::path &dir) { + const boost::filesystem::path CND_MOD_DBF = "CndMod.dbf"; + DBFHandle cnd_mod_handle = read_dbf_file(dir / CND_MOD_DBF); + for (int i = 0; i < DBFGetRecordCount(cnd_mod_handle); i++) { + uint64_t cond_id = dbf_get_uint_by_field(cnd_mod_handle, i, COND_ID); + std::string lang_code = + dbf_get_string_by_field(cnd_mod_handle, i, LANG_CODE.data()); + uint64_t mod_type = + dbf_get_uint_by_field(cnd_mod_handle, i, CM_MOD_TYPE.data()); + uint64_t mod_val = + dbf_get_uint_by_field(cnd_mod_handle, i, CM_MOD_VAL.data()); + + auto it2 = g_cnd_mod_map.find(cond_id); + if (it2 == g_cnd_mod_map.end()) { + std::vector new_vector; + new_vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); + g_cnd_mod_map.emplace(cond_id, new_vector); + } else { + //(std::vector) ()’ + auto vector = it2->second; + g_cnd_mod_map.erase(it2); + vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); + g_cnd_mod_map.emplace(cond_id, vector); + } + } + DBFClose(cnd_mod_handle); +} + +void StreetConverter::init_g_cdms_map(const boost::filesystem::path &dir) { + const boost::filesystem::path CDMS_DBF = "Cdms.dbf"; + DBFHandle cdms_handle = read_dbf_file(dir / CDMS_DBF); + for (int i = 0; i < DBFGetRecordCount(cdms_handle); i++) { + uint64_t link_id = dbf_get_uint_by_field(cdms_handle, i, LINK_ID.data()); + uint64_t cond_id = dbf_get_uint_by_field(cdms_handle, i, COND_ID.data()); + ushort cond_type = dbf_get_uint_by_field(cdms_handle, i, COND_TYPE); + g_cdms_map.emplace(link_id, cond_pair_type(cond_id, cond_type)); + } + DBFClose(cdms_handle); +} + +void StreetConverter::init_country_reference( + const boost::filesystem::path &dir) { + if (dbf_file_exists(dir / MTD_AREA_DBF) && + dbf_file_exists(dir / MTD_CNTRY_REF_DBF)) { + init_g_area_to_govt_code_map(dir); + init_g_cntry_ref_map(dir); + } +} + +void StreetConverter::init_g_area_to_govt_code_map( + const boost::filesystem::path &dir) { + DBFHandle mtd_area_handle = read_dbf_file(dir / MTD_AREA_DBF); + for (int i = 0; i < DBFGetRecordCount(mtd_area_handle); i++) { + uint64_t area_id = + dbf_get_uint_by_field(mtd_area_handle, i, AREA_ID.data()); + uint64_t govt_code = + dbf_get_uint_by_field(mtd_area_handle, i, GOVT_CODE.data()); + g_area_to_govt_code_map.emplace(area_id, govt_code); + } + DBFClose(mtd_area_handle); +} + +void StreetConverter::init_g_cntry_ref_map(const boost::filesystem::path &dir) { + DBFHandle cntry_ref_handle = read_dbf_file(dir / MTD_CNTRY_REF_DBF); + for (int i = 0; i < DBFGetRecordCount(cntry_ref_handle); i++) { + uint64_t govt_code = + dbf_get_uint_by_field(cntry_ref_handle, i, GOVT_CODE.data()); + auto unit_measure = + dbf_get_string_by_field(cntry_ref_handle, i, UNTMEASURE.data()); + auto speed_limit_unit = + dbf_get_string_by_field(cntry_ref_handle, i, SPEEDLIMITUNIT.data()); + auto iso_code = + dbf_get_string_by_field(cntry_ref_handle, i, ISO_CODE.data()); + auto cntry_ref = cntry_ref_type(unit_measure, speed_limit_unit, iso_code); + g_cntry_ref_map.emplace(govt_code, cntry_ref); + } + DBFClose(cntry_ref_handle); +} + +void StreetConverter::process_way_end_nodes( + const std::vector &dirs, + const std::map> &z_level_map, + osmium::io::Writer &writer) { + for (auto &dir : dirs) { + + // parse ramp names and refs + init_ramp_names(dir); + + auto path = dir / STREETS_SHP; + auto ds = open_shape_file(path); + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(path.string())); + + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + + int linkIDField = layer->FindFieldIndex(LINK_ID.data(), true); + + // get all nodes which may be a routable crossing + for (auto &feat : *layer) { + uint64_t link_id = feat->GetFieldAsInteger(linkIDField); + // omit way end nodes with different z-levels (they have to be handled + // extra) + if (z_level_map.find(link_id) == z_level_map.end()) + process_way_end_nodes(feat, node_buffer); + } + node_buffer.commit(); + writer(std::move(node_buffer)); + g_ramps_ref_map.clear(); + } +} + +void StreetConverter::process_way_end_nodes( + OGRFeatureUniquePtr &feat, osmium::memory::Buffer &node_buffer) { + + auto ogr_ls = static_cast(feat->GetGeometryRef()); + + process_way_end_node(osmium::Location(ogr_ls->getX(0), ogr_ls->getY(0)), + node_buffer); + process_way_end_node( + osmium::Location(ogr_ls->getX(ogr_ls->getNumPoints() - 1), + ogr_ls->getY(ogr_ls->getNumPoints() - 1)), + node_buffer); +} + +void StreetConverter::process_way_end_node( + const osmium::Location &location, osmium::memory::Buffer &node_buffer) { + + auto it = g_way_end_points_map.find(location); + if (it != g_way_end_points_map.end()) + return; + + osmium::builder::NodeBuilder builder(node_buffer); + osmium::unsigned_object_id_type osm_id = build_node(location, builder); + // add ramp tags + auto ramp = g_ramps_ref_map.find(location); + if (ramp != g_ramps_ref_map.end()) { + if (ramp->second.find(0) != ramp->second.end()) { + osmium::builder::TagListBuilder tglBuilder(builder); + tglBuilder.add_tag(HIGHWAY, "motorway_junction"); + tglBuilder.add_tag("ref", ramp->second[0]); + tglBuilder.add_tag("name", to_camel_case_with_spaces(ramp->second[1])); + } + } + g_way_end_points_map.emplace(location, osm_id); +} + +void StreetConverter::init_ramp_names(const boost::filesystem::path &dir) { + // read junction names from alt_streets + auto junctionMap = read_junction_names(dir / ALT_STREETS_DBF); + + // create location ramps map + parse_ramp_names(dir / STREETS_SHP, junctionMap); +} + +std::map +StreetConverter::read_junction_names(const boost::filesystem::path &dbf_file) { + DBFHandle hwys_handle = read_dbf_file(dbf_file); + std::map junctionNames; + for (int i = 0; i < DBFGetRecordCount(hwys_handle); i++) { + + uint64_t link_id = dbf_get_uint_by_field(hwys_handle, i, LINK_ID.data()); + std::string ramp_name = + dbf_get_string_by_field(hwys_handle, i, ST_NM_BASE.data()); + + if (parse_bool(dbf_get_string_by_field(hwys_handle, i, JUNCTIONNM.data()) + .c_str())) { + junctionNames[link_id] = ramp_name; + } + } + DBFClose(hwys_handle); + + return junctionNames; +} + +void StreetConverter::parse_ramp_names( + const boost::filesystem::path &shp_file, + const std::map &junctionNames) { + + auto ds = open_shape_file(shp_file); + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(shp_file.string())); + + int exitNameField = layer->FindFieldIndex(EXITNAME.data(), true); + int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); + int baseNameField = layer->FindFieldIndex(ST_NM_BASE.data(), true); + int directionField = layer->FindFieldIndex(DIR_TRAVEL, true); + int rampField = layer->FindFieldIndex(RAMP, true); + + for (auto &feat : *layer) { + + if (!parse_bool(feat->GetFieldAsString(rampField))) { + continue; + } + + auto ogr_ls = static_cast(feat->GetGeometryRef()); + + auto location = osmium::Location(ogr_ls->getX(0), ogr_ls->getY(0)); + if (!strcmp(feat->GetFieldAsString(directionField), "T")) + location = osmium::Location(ogr_ls->getX(ogr_ls->getNumPoints() - 1), + ogr_ls->getY(ogr_ls->getNumPoints() - 1)); + + if (parse_bool(feat->GetFieldAsString(exitNameField))) { + std::string exitName = feat->GetFieldAsString(baseNameField); + + // add exit name + g_ramps_ref_map[location].emplace(0, exitName); + + // add junction name + auto it = junctionNames.find(feat->GetFieldAsInteger(linkIdField)); + if (it != junctionNames.end()) { + g_ramps_ref_map[location].emplace(1, it->second); + } + } + } +} + +void StreetConverter::process_way( + OGRFeatureUniquePtr &feat, + const std::map> &z_level_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { + + std::map node_ref_map; + + auto ogr_ls = static_cast(feat->GetGeometryRef()); + + // creates remaining nodes required for way + middle_points_preparation(ogr_ls, node_ref_map, node_buffer); + if (ogr_ls->getNumPoints() > 2) + assert(node_ref_map.size() > 0); + + uint64_t link_id = get_uint_from_feature(feat, LINK_ID.data()); + + auto it = z_level_map.find(link_id); + if (it == z_level_map.end()) { + build_way(feat, ogr_ls, node_ref_map, way_buffer, false, -5); + } else { + auto &index_z_lvl_vector = it->second; + + // way with different z_levels + auto &first_point_with_different_z_lvl = index_z_lvl_vector.front(); + auto first_index = 0; + short first_z_lvl = 0; + if (first_point_with_different_z_lvl.index == first_index) + first_z_lvl = first_point_with_different_z_lvl.z_level; + + process_end_point(true, first_z_lvl, ogr_ls, node_ref_map, node_buffer); + + auto &last_point_with_different_z_lvl = index_z_lvl_vector.back(); + auto last_index = ogr_ls->getNumPoints() - 1; + short last_z_lvl = 0; + if (last_point_with_different_z_lvl.index == last_index) + last_z_lvl = last_point_with_different_z_lvl.z_level; + + process_end_point(false, last_z_lvl, ogr_ls, node_ref_map, node_buffer); + + way_buffer.commit(); + + if (is_ferry(get_field_from_feature(feat, FERRY))) + set_ferry_z_lvls_to_zero(feat, index_z_lvl_vector); + + split_way_by_z_level(feat, ogr_ls, index_z_lvl_vector, node_ref_map, + link_id, way_buffer); + } +} + +void StreetConverter::middle_points_preparation( + OGRLineString *ogr_ls, + std::map &node_ref_map, + osmium::memory::Buffer &node_buffer) { + // creates remaining nodes required for way + for (int i = 1; i < ogr_ls->getNumPoints() - 1; ++i) { + osmium::Location location(ogr_ls->getX(i), ogr_ls->getY(i)); + node_ref_map.emplace(location, build_node(location, node_buffer)); + } + node_buffer.commit(); +} + +osmium::unsigned_object_id_type StreetConverter::build_way( + OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, + std::map &node_ref_map, + osmium::memory::Buffer &way_buffer, bool is_sub_linestring = false, + short z_lvl = -5) { + + if (is_sub_linestring) + test__z_lvl_range(z_lvl); + + osmium::builder::WayBuilder builder(way_buffer); + setObjectProperties(builder); + osmium::Location start(ogr_ls->getX(0), ogr_ls->getY(0)); + osmium::Location end(ogr_ls->getX(ogr_ls->getNumPoints() - 1), + ogr_ls->getY(ogr_ls->getNumPoints() - 1)); + + { + osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &builder); + + for (int i = 0; i < ogr_ls->getNumPoints(); i++) { + osmium::Location location(ogr_ls->getX(i), ogr_ls->getY(i)); + bool is_end_point = i == 0 || i == ogr_ls->getNumPoints() - 1; + std::map + *map_containing_node; + if (!is_sub_linestring) { + if (is_end_point) + map_containing_node = &g_way_end_points_map; + else + map_containing_node = &node_ref_map; + } else { + if (node_ref_map.find(location) != node_ref_map.end()) { + map_containing_node = &node_ref_map; + } else { + // node has to be in node_ref_map or way_end_points_map + assert(g_way_end_points_map.find(location) != + g_way_end_points_map.end()); + map_containing_node = &g_way_end_points_map; + } + } + + wnl_builder.add_node_ref( + osmium::NodeRef(map_containing_node->at(location), location)); + } + } + + build_tag_list(feat, &builder, way_buffer, z_lvl); + return builder.object().id(); +} + +uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, + osmium::builder::Builder *builder, + osmium::memory::Buffer &buf, + short z_level) { + osmium::builder::TagListBuilder tl_builder(buf, builder); + + uint64_t link_id = parse_street_tags( + &tl_builder, feat, &g_cdms_map, &g_cnd_mod_map, &g_area_to_govt_code_map, + &g_cntry_ref_map, &g_mtd_area_map, &g_route_type_map, &g_hwys_ref_map, + g_construction_set, debugMode); + + if (z_level != -5 && z_level != 0) + tl_builder.add_tag("layer", std::to_string(z_level)); + if (link_id == 0) + throw(format_error("layers column field '" + std::string(LINK_ID.data()) + + "' is missing")); + return link_id; +} + +uint64_t StreetConverter::parse_street_tags( + osmium::builder::TagListBuilder *builder, OGRFeatureUniquePtr &f, + cdms_map_type *cdms_map, cnd_mod_map_type *cnd_mod_map, + area_id_govt_code_map_type *area_govt_map, cntry_ref_map_type *cntry_map, + mtd_area_map_type *mtd_area_map, link_id_route_type_map *route_type_map, + link_id_to_names_map *names_map, + const std::set &construction_set, bool debugMode); +{ + + const char *link_id_s = get_field_from_feature(f, LINK_ID); + link_id_type link_id = std::stoul(link_id_s); + + bool ramp = parse_bool(get_field_from_feature(f, RAMP)); + + ushort route_type = 0; + if (!((std::string)get_field_from_feature(f, ROUTE)).empty()) + route_type = get_uint_from_feature(f, ROUTE); + + auto routeTypeIter = route_type_map->find(link_id); + if (routeTypeIter != route_type_map->end() && + (!route_type || routeTypeIter->second < route_type)) + route_type = routeTypeIter->second; + + // add tags for ref and int_ref to major highways + std::string ref_name = + add_highway_name_tags(builder, names_map, link_id, ramp); + + bool underConstruction = + (construction_set.find(link_id) != construction_set.end()); + + if (is_ferry(get_field_from_feature(f, FERRY))) { + add_ferry_tag(builder, f); + } else { // usual highways + add_highway_tags(builder, f, route_type, mtd_area_map, ref_name, + underConstruction); + } + + uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); + uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); + // tags which apply to highways and ferry routes + add_additional_restrictions(builder, link_id, l_area_id, r_area_id, cdms_map, + cnd_mod_map, area_govt_map, cntry_map, + mtd_area_map); + + // tag for debug purpose + if (debugMode) { + builder->add_tag(LINK_ID, link_id_s); + add_here_speed_cat_tag(builder, f); + if (parse_bool(get_field_from_feature(f, TOLLWAY))) + builder->add_tag("here:tollway", YES); + if (parse_bool(get_field_from_feature(f, URBAN))) + builder->add_tag("here:urban", YES); + if (parse_bool(get_field_from_feature(f, CONTRACC))) + builder->add_tag("here:controll_access", YES); + if (route_type) + add_uint_tag(builder, "here:route_type", route_type); + + std::string func_class = get_field_from_feature(f, FUNC_CLASS); + if (!func_class.empty()) + builder->add_tag("here:func_class", func_class.c_str()); + + add_uint_tag(builder, "here:area_code", get_area_code_l(f, mtd_area_map)); + } + return link_id; +} + +void StreetConverter::add_additional_restrictions( + osmium::builder::TagListBuilder *builder, uint64_t link_id, + uint64_t l_area_id, uint64_t r_area_id, cdms_map_type *cdms_map, + cnd_mod_map_type *cnd_mod_map, area_id_govt_code_map_type *area_govt_map, + cntry_ref_map_type *cntry_map, mtd_area_map_type *mtd_area_map) { + if (!cdms_map || !cnd_mod_map) + return; + + // default is metric units + bool imperial_units = false; + if (area_govt_map && cntry_map) { + imperial_units = + is_imperial(l_area_id, r_area_id, area_govt_map, cntry_map); + } + + uint64_t max_height = 0, max_width = 0, max_length = 0, max_weight = 0, + max_axleload = 0; + + std::vector mod_group_vector; + auto range = cdms_map->equal_range(link_id); + for (auto it = range.first; it != range.second; ++it) { + cond_pair_type cond = it->second; + if (cond.second == CT_RESTRICTED_DRIVING_MANOEUVRE || + cond.second == CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE) + continue; // TODO RESTRICTED_DRIVING_MANOEUVRE should apply as + // conditional turn restriction but not for current link id + auto it2 = cnd_mod_map->find(cond.first); + if (it2 != cnd_mod_map->end()) { + for (auto mod_group : it2->second) { + mod_group_vector.push_back(mod_group); + } + } + } + + for (auto mod_group : mod_group_vector) { + auto mod_type = mod_group.mod_type; + auto mod_val = mod_group.mod_val; + if (mod_type == MT_HEIGHT_RESTRICTION) { + if (!max_height || mod_val < max_height) + max_height = mod_val; + } else if (mod_type == MT_WIDTH_RESTRICTION) { + if (!max_width || mod_val < max_width) + max_width = mod_val; + } else if (mod_type == MT_LENGTH_RESTRICTION) { + if (!max_length || mod_val < max_length) + max_length = mod_val; + } else if (mod_type == MT_WEIGHT_RESTRICTION) { + if (!max_weight || mod_val < max_weight) + max_weight = mod_val; + } else if (mod_type == MT_WEIGHT_PER_AXLE_RESTRICTION) { + if (!max_axleload || mod_val < max_axleload) + max_axleload = mod_val; + } else if (mod_type == MT_HAZARDOUS_RESTRICTION) { + add_hazmat_tag(builder, mod_val); + } + } + + if (get_area_code_l(l_area_id, r_area_id, mtd_area_map) == 107) { + /** exceptional handling for Sweden as there are BK Roads + * + * HERE tags these roads with the most conservative values, + * which would make it unroutable for nearly every truck. + * Therefore we use the highest value and add a marker for BK2 / BK3 */ + if (max_weight == 16000 && max_axleload == 10000) { + builder->add_tag("maxweight:class", "BK2"); + max_weight = 51400; + } else if (max_weight == 12000 && max_axleload == 8000) { + builder->add_tag("maxweight:class", "BK3"); + max_weight = 37000; + } + } + + if (max_height > 0) + builder->add_tag("maxheight", imperial_units ? inch_to_feet(max_height) + : cm_to_m(max_height)); + if (max_width > 0) + builder->add_tag("maxwidth", imperial_units ? inch_to_feet(max_width) + : cm_to_m(max_width)); + if (max_length > 0) + builder->add_tag("maxlength", imperial_units ? inch_to_feet(max_length) + : cm_to_m(max_length)); + if (max_weight > 0) + builder->add_tag("maxweight", imperial_units ? lbs_to_metric_ton(max_weight) + : kg_to_t(max_weight)); + if (max_axleload > 0) + builder->add_tag("maxaxleload", imperial_units + ? lbs_to_metric_ton(max_axleload) + : kg_to_t(max_axleload)); +} + +void StreetConverter::process_end_point( + bool first, short z_lvl, OGRLineString *ogr_ls, + std::map &node_ref_map, + osmium::memory::Buffer &node_buffer) { + ushort i = first ? 0 : ogr_ls->getNumPoints() - 1; + osmium::Location location(ogr_ls->getX(i), ogr_ls->getY(i)); + + if (z_lvl != 0) { + auto node_id = std::make_pair(location, z_lvl); + auto it = g_z_lvl_nodes_map.find(node_id); + if (it != g_z_lvl_nodes_map.end()) { + node_ref_map.emplace(location, it->second); + } else { + osmium::unsigned_object_id_type osm_id = + build_node(location, node_buffer); + node_ref_map.emplace(location, osm_id); + g_z_lvl_nodes_map.emplace(node_id, osm_id); + } + } else { + // adds all zero z-level end points to g_way_end_points_map + g_way_end_points_map.emplace(location, build_node(location, node_buffer)); + } +} + +void StreetConverter::split_way_by_z_level( + OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, + const std::vector &node_z_level_vector, + std::map &node_ref_map, + uint64_t link_id, osmium::memory::Buffer &way_buffer) { + + ushort first_index = 0, last_index = ogr_ls->getNumPoints() - 1; + ushort start_index = node_z_level_vector.cbegin()->index; + if (start_index > 0) + start_index--; + + // first_index <= start_index < end_index <= last_index + assert(first_index <= start_index); + assert(start_index < last_index); + + // if (DEBUG) print_z_level_map(link_id, true); + if (first_index != start_index) { + build_sub_way_by_index(feat, ogr_ls, first_index, start_index, node_ref_map, + way_buffer, 0); + BOOST_LOG_TRIVIAL(debug) + << " 1 ## " << link_id << " ## " << first_index << "/" << last_index + << " - " << start_index << "/" << last_index << ": \tz_lvl=" << 0 + << std::endl; + } + + start_index = create_continuing_sub_ways( + feat, ogr_ls, first_index, start_index, last_index, link_id, + node_z_level_vector, node_ref_map, way_buffer); + + if (start_index < last_index) { + build_sub_way_by_index(feat, ogr_ls, start_index, last_index, node_ref_map, + way_buffer, 0); + BOOST_LOG_TRIVIAL(debug) + << " 4 ## " << link_id << " ## " << start_index << "/" << last_index + << " - " << last_index << "/" << last_index << ": \tz_lvl=" << 0 + << std::endl; + } +} + +void StreetConverter::build_sub_way_by_index( + OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, ushort start_index, + ushort end_index, + std::map &node_ref_map, + osmium::memory::Buffer &way_buffer, short z_lvl = 0) { + assert(start_index < end_index || end_index == -1); + assert(start_index < ogr_ls->getNumPoints()); + OGRLineString subLineString; + subLineString.addSubLineString(ogr_ls, start_index, end_index); + build_way(feat, &subLineString, node_ref_map, way_buffer, true, z_lvl); +} + +ushort StreetConverter::create_continuing_sub_ways( + OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, ushort first_index, + ushort start_index, ushort last_index, uint link_id, + const std::vector &node_z_level_vector, + std::map &node_ref_map, + osmium::memory::Buffer &way_buffer) { + + for (auto it = node_z_level_vector.cbegin(); it != node_z_level_vector.cend(); + ++it) { + short z_lvl = it->z_level; + test__z_lvl_range(z_lvl); + bool last_element = node_z_level_vector.cend() - 1 == it; + bool not_last_element = !last_element; + ushort index = it->index; + ushort next_index; + short next_z_lvl; + if (not_last_element) { + auto next_it = it + 1; + next_index = next_it->index; + next_z_lvl = next_it->z_level; + test__z_lvl_range(next_z_lvl); + } + BOOST_LOG_TRIVIAL(debug) + << "first_index=" << first_index << " " + << "start_index=" << start_index << " " << "last_index=" << last_index + << " " << "index=" << index << " " << "z_lvl=" << z_lvl << " " + << "next_z_lvl=" << next_z_lvl << std::endl; + + if (not_last_element) { + if (index + 2 == next_index && z_lvl == next_z_lvl) + continue; + bool not_second_last_element = it + 2 != node_z_level_vector.cend(); + if (not_second_last_element) { + ushort second_next_index = (it + 2)->index; + short second_next_z_lvl = (it + 2)->z_level; + test__z_lvl_range(second_next_z_lvl); + if (index + 2 == second_next_index && + is_superior_or_equal(second_next_z_lvl, next_z_lvl) && + z_lvl == second_next_z_lvl) { + ++it; + continue; + } + } + } + + // checks for gaps within the way + if (last_element || index + 1 < next_index || z_lvl != next_z_lvl) { + ushort from = start_index; + ushort to; + if (last_element || index + 1 < next_index || + is_superior(z_lvl, next_z_lvl)) + to = std::min((ushort)(index + 1), last_index); + else + to = index; + BOOST_LOG_TRIVIAL(debug) + << " 2 ## " << link_id << " ## " << from << "/" << last_index + << " - " << to << "/" << last_index << ": \tz_lvl=" << z_lvl + << std::endl; + if (from < to) { + build_sub_way_by_index(feat, ogr_ls, from, to, node_ref_map, way_buffer, + z_lvl); + start_index = to; + } + + if (not_last_element && to < next_index - 1) { + build_sub_way_by_index(feat, ogr_ls, to, next_index - 1, node_ref_map, + way_buffer); + BOOST_LOG_TRIVIAL(debug) + << " 3 ## " << link_id << " ## " << to << "/" << last_index + << " - " << next_index - 1 << "/" << last_index + << ": \tz_lvl=" << 0 << std::endl; + start_index = next_index - 1; + } + } + } + return start_index; +} diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp new file mode 100644 index 0000000..8eed38a --- /dev/null +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -0,0 +1,201 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef STREETCONVERTER_HPP +#define STREETCONVERTER_HPP + +#include "Converter.hpp" + +#include + +class StreetConverter : public Converter { + +public: + StreetConverter(const boost::filesystem::path &executable_path); + virtual ~StreetConverter(); + + virtual void convert(const std::vector &dirs, + osmium::io::Writer &writer); + +private: + struct z_lvl_index_type_t { + ushort index; + short z_level; + }; + + struct mod_group_type { + std::string lang_code; + uint64_t mod_type; + uint64_t mod_val; + mod_group_type(uint64_t mod_type, uint64_t mod_val, + const std::string &lang_code) { + this->lang_code = lang_code; + this->mod_type = mod_type; + this->mod_val = mod_val; + } + }; + + struct cntry_ref_type { + std::string unit_measure; + std::string speed_limit_unit; + std::string iso_code; + cntry_ref_type() {} + cntry_ref_type(const std::string &unit_measure, + const std::string &speed_limit_unit, + const std::string &iso_code) { + this->unit_measure = unit_measure; + this->speed_limit_unit = speed_limit_unit; + this->iso_code = iso_code; + } + bool operator==(cntry_ref_type rhs) { + if (this->unit_measure != rhs.unit_measure) + return false; + if (this->speed_limit_unit != rhs.speed_limit_unit) + return false; + if (this->iso_code != rhs.iso_code) + return false; + return true; + } + bool operator!=(cntry_ref_type rhs) { return !(*this == rhs); } + }; + + std::map process_alt_steets_route_types( + const std::vector &dirs); + + void add_street_shapes(const std::vector &dirs, + osmium::io::Writer &writer); + + std::map> + process_z_levels(const std::vector &dirs); + + void init_z_level_map( + boost::filesystem::path dir, + std::map> &z_level_map); + + void init_conditional_modifications(const boost::filesystem::path &dir); + void init_g_cnd_mod_map(const boost::filesystem::path &dir); + void init_g_cdms_map(const boost::filesystem::path &dir); + + void init_country_reference(const boost::filesystem::path &dir); + void init_g_area_to_govt_code_map(const boost::filesystem::path &dir); + void init_g_cntry_ref_map(const boost::filesystem::path &dir); + + // process end nodes + void process_way_end_nodes( + const std::vector &dirs, + const std::map> &z_level_map, + osmium::io::Writer &writer); + void process_way_end_nodes(OGRFeatureUniquePtr &feat, + osmium::memory::Buffer &node_buffer); + void process_way_end_node(const osmium::Location &location, + osmium::memory::Buffer &node_buffer); + + // ramp names + void init_ramp_names(const boost::filesystem::path &dir); + std::map + read_junction_names(const boost::filesystem::path &dbf_file); + void parse_ramp_names(const boost::filesystem::path &shp_file, + const std::map &junctionNames); + + void process_way( + OGRFeatureUniquePtr &feat, + const std::map> &z_level_map, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); + void middle_points_preparation( + OGRLineString *ogr_ls, + std::map &node_ref_map, + osmium::memory::Buffer &node_buffer); + + osmium::unsigned_object_id_type build_way( + OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, + std::map &node_ref_map, + osmium::memory::Buffer &way_buffer, bool is_sub_linestring, short z_lvl); + + uint64_t build_tag_list(OGRFeatureUniquePtr &feat, + osmium::builder::Builder *builder, + osmium::memory::Buffer &buf, short z_level); + + uint64_t parse_street_tags( + osmium::builder::TagListBuilder *builder, OGRFeatureUniquePtr &f, + cdms_map_type *cdms_map, cnd_mod_map_type *cnd_mod_map, + area_id_govt_code_map_type *area_govt_map, cntry_ref_map_type *cntry_map, + mtd_area_map_type *mtd_area_map, link_id_route_type_map *route_type_map, + link_id_to_names_map *names_map, + const std::set &construction_set, bool debugMode); + + void add_additional_restrictions(osmium::builder::TagListBuilder *builder, + uint64_t link_id, uint64_t l_area_id, + uint64_t r_area_id, cdms_map_type *cdms_map, + cnd_mod_map_type *cnd_mod_map, + area_id_govt_code_map_type *area_govt_map, + cntry_ref_map_type *cntry_map, + mtd_area_map_type *mtd_area_map); + + void process_end_point( + bool first, short z_lvl, OGRLineString *ogr_ls, + std::map &node_ref_map, + osmium::memory::Buffer &node_buffer); + + void split_way_by_z_level( + OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, + const std::vector &node_z_level_vector, + std::map &node_ref_map, + uint64_t link_id, osmium::memory::Buffer &way_buffer); + + void build_sub_way_by_index( + OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, ushort start_index, + ushort end_index, + std::map &node_ref_map, + osmium::memory::Buffer &way_buffer, short z_lvl); + + ushort create_continuing_sub_ways( + OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, ushort first_index, + ushort start_index, ushort last_index, uint link_id, + const std::vector &node_z_level_vector, + std::map &node_ref_map, + osmium::memory::Buffer &way_buffer); + + // CndMod types (CM) + static constexpr std::string_view CM_MOD_TYPE = "MOD_TYPE"; + static constexpr std::string_view CM_MOD_VAL = "MOD_VAL"; + + // ZLEVELS_DBF columns + static constexpr std::string_view Z_LEVEL = "Z_LEVEL"; + static constexpr std::string_view POINT_NUM = "POINT_NUM"; + + // MTD_AREA_DBF columns + static constexpr std::string_view AREA_ID = "AREA_ID"; + static constexpr std::string_view LANG_CODE = "LANG_CODE"; + static constexpr std::string_view AREA_NAME = "AREA_NAME"; + static constexpr std::string_view AREA_CODE_1 = "AREACODE_1"; + static constexpr std::string_view ADMIN_LVL = "ADMIN_LVL"; + static constexpr std::string_view GOVT_CODE = "GOVT_CODE"; + + // RDMS_DBF columns + static constexpr std::string_view COND_ID = "COND_ID"; + + static constexpr std::string_view ST_NM_BASE = "ST_NM_BASE"; + static constexpr std::string_view EXITNAME = "EXITNAME"; + static constexpr std::string_view JUNCTIONNM = "JUNCTIONNM"; + + // MTD_CNTRY_REF columns + static constexpr std::string_view UNTMEASURE = "UNTMEASURE"; + // const char* MAX_ADMINLEVEL = "MAX_ADMINLEVEL"; + static constexpr std::string_view SPEEDLIMITUNIT = "SPDLIMUNIT"; + static constexpr std::string_view ISO_CODE = "ISO_CODE"; +}; + +#endif // STREETCONVERTER_HPP diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index 410e194..19673f2 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -33,11 +33,6 @@ #define DEBUG false -static constexpr int buffer_size = 10 * 1000 * 1000; - -// maps location of way end nodes to node ids -node_map_type g_way_end_points_map; - z_lvl_nodes_map_type g_z_lvl_nodes_map; // id counter for object creation @@ -66,418 +61,6 @@ cntry_ref_map_type g_cntry_ref_map; bool debugMode = false; -/** - * \brief Dummy attributes enable josm to read output xml files. - * - * \param obj OSMObject to set attributess to. - * */ -void set_dummy_osm_object_attributes(osmium::OSMObject &obj) { - obj.set_version(VERSION); - obj.set_changeset(CHANGESET); - obj.set_uid(USERID); - obj.set_timestamp(TIMESTAMP); -} - -/** - * \brief parses and writes tags from features with builder - * \param builder builder to add tags to. - * \param z_level Sets z_level if valid (-5 is invalid default) - * \return link id of parsed feature. - */ - -link_id_type build_tag_list(OGRFeatureUniquePtr &feat, - osmium::builder::Builder *builder, - osmium::memory::Buffer &buf, short z_level) { - osmium::builder::TagListBuilder tl_builder(buf, builder); - - link_id_type link_id = parse_street_tags( - &tl_builder, feat, &g_cdms_map, &g_cnd_mod_map, &g_area_to_govt_code_map, - &g_cntry_ref_map, &g_mtd_area_map, &g_route_type_map, &g_hwys_ref_map, - g_construction_set, debugMode); - - if (z_level != -5 && z_level != 0) - tl_builder.add_tag("layer", std::to_string(z_level)); - if (link_id == 0) - throw(format_error("layers column field '" + std::string(LINK_ID) + - "' is missing")); - return link_id; -} - -/** - * \brief creates Node with given builder. - * \param location Location of Node being created. - * \param builder NodeBuilder to create Node. - * \return id of created Node. - */ -osmium::unsigned_object_id_type -build_node(const osmium::Location &location, - osmium::builder::NodeBuilder *builder) { - builder->object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder->object()); - builder->set_user(USER); - builder->object().set_location(location); - return builder->object().id(); -} - -/** - * \brief creates Node and writes it to m_buffer. - * \param location Location of Node being created. - * \return id of created Node. - */ -osmium::unsigned_object_id_type -build_node(const osmium::Location &location, - osmium::memory::Buffer &node_buffer) { - osmium::builder::NodeBuilder builder(node_buffer); - return build_node(location, &builder); -} - -/** - * \brief adds WayNode to Way. - * \param location Location of WayNode - * \param wnl_builder Builder to create WayNode - * \param node_ref_map holds Node ids suitable to given Location. - */ -void add_way_node(const osmium::Location &location, - osmium::builder::WayNodeListBuilder &wnl_builder, - node_map_type *node_ref_map) { - assert(node_ref_map); - wnl_builder.add_node_ref( - osmium::NodeRef(node_ref_map->at(location), location)); -} - -static std::set z_lvl_set = {-4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; -void test__z_lvl_range(short z_lvl) { - if (z_lvl_set.find(z_lvl) == z_lvl_set.end()) - throw(out_of_range_exception("z_lvl " + std::to_string(z_lvl) + - " is not valid")); -} - -/** - * \brief creates way with tags in m_buffer. - * \param ogr_ls provides geometry (linestring) for the way. - * \param node_ref_map provides osm_ids of Nodes to a given location. - * \param is_sub_linestring true if given linestring is a sublinestring. - * \param z_lvl z-level of way. initially invalid (-5). - * \return id of created Way. - */ -osmium::unsigned_object_id_type -build_way(OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, - node_map_type *node_ref_map, osmium::memory::Buffer &way_buffer, - bool is_sub_linestring = false, short z_lvl = -5) { - - if (is_sub_linestring) - test__z_lvl_range(z_lvl); - - osmium::builder::WayBuilder builder(way_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - - osmium::Location start(ogr_ls->getX(0), ogr_ls->getY(0)); - osmium::Location end(ogr_ls->getX(ogr_ls->getNumPoints() - 1), - ogr_ls->getY(ogr_ls->getNumPoints() - 1)); - - builder.set_user(USER); - { - osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &builder); - - for (int i = 0; i < ogr_ls->getNumPoints(); i++) { - osmium::Location location(ogr_ls->getX(i), ogr_ls->getY(i)); - bool is_end_point = i == 0 || i == ogr_ls->getNumPoints() - 1; - std::map - *map_containing_node; - if (!is_sub_linestring) { - if (is_end_point) - map_containing_node = &g_way_end_points_map; - else - map_containing_node = node_ref_map; - } else { - if (node_ref_map->find(location) != node_ref_map->end()) { - map_containing_node = node_ref_map; - } else { - // node has to be in node_ref_map or way_end_points_map - assert(g_way_end_points_map.find(location) != - g_way_end_points_map.end()); - map_containing_node = &g_way_end_points_map; - } - } - add_way_node(location, wnl_builder, map_containing_node); - } - } - - build_tag_list(feat, &builder, way_buffer, z_lvl); - return builder.object().id(); -} - -/** - * \brief creates a sublinestring from ogr_ls from range [start_index, - * end_index] inclusive \param ogr_ls Linestring from which the sublinestring - * is taken from. \param start_index Node index in ogr_ls, where sublinestring - * will begin. \param end_index Node index in ogr_ls, where sublinestring will - * end. \return sublinestring from ogr_ls [start_index, end_index] inclusive - */ -OGRLineString create_sublinestring_geometry(OGRLineString *ogr_ls, - int start_index, - int end_index = -1) { - assert(start_index < end_index || end_index == -1); - assert(start_index < ogr_ls->getNumPoints()); - OGRLineString ogr_sub_ls; - ogr_sub_ls.addSubLineString(ogr_ls, start_index, end_index); - return ogr_sub_ls; -} - -/* helpers for split_way_by_z_level */ -/** - * \brief checks if first z_level is more significant than the other. - * \param superior First z_level. - * \param than second z_level. - * \return true if superior is superior to than. - */ -bool is_superior(short superior, short than) { - if (abs(superior) > abs(than)) - return true; - return false; -} - -/** - * \brief checks if first z_level is more significant than the other or equal. - * \param superior first z_level. - * \param than second z_level. - * \return true if superior is greater or equal than. - */ -bool is_superior_or_equal(short superior, short than) { - if (abs(superior) >= abs(than)) - return true; - return false; -} - -/** - * \brief splits a OGRLinestring by index. - * \param start_index index where sub_way begins. - * \param end_index index where sub_way ends. - * \param ogr_ls geometry of index. - * \param node_ref_map provides osm_ids of Nodes to a given location. - * \param z_lvl - */ -void build_sub_way_by_index(OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, - ushort start_index, ushort end_index, - node_map_type *node_ref_map, - osmium::memory::Buffer &way_buffer, - short z_lvl = 0) { - OGRLineString subLineString = - create_sublinestring_geometry(ogr_ls, start_index, end_index); - build_way(feat, &subLineString, node_ref_map, way_buffer, true, z_lvl); -} - -/** - * \brief creates a way for each z_level change - * \param start_index starting index of next way creation - * \param end_index index where the last z_level is not 0 (not default) - * \param last_index index of the last node in given way - * \param link_id for debug only - * \param node_z_level_vector holds [index, z_level] pairs to process - * \param ogr_ls given way which has to be splitted - * \param node_ref_map location to osm_id mapping (to preserve uniqueness of - * node locations) \return start_index - */ -ushort create_continuing_sub_ways( - OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, ushort first_index, - ushort start_index, ushort last_index, uint link_id, - const index_z_lvl_vector_type &node_z_level_vector, - node_map_type *node_ref_map, osmium::memory::Buffer &way_buffer) { - - for (auto it = node_z_level_vector.cbegin(); it != node_z_level_vector.cend(); - ++it) { - short z_lvl = it->second; - test__z_lvl_range(z_lvl); - bool last_element = node_z_level_vector.cend() - 1 == it; - bool not_last_element = !last_element; - ushort index = it->first; - ushort next_index; - short next_z_lvl; - if (not_last_element) { - auto next_it = it + 1; - next_index = next_it->first; - next_z_lvl = next_it->second; - test__z_lvl_range(next_z_lvl); - } - if (DEBUG) - std::cout << "first_index=" << first_index << " " - << "start_index=" << start_index << " " - << "last_index=" << last_index << " " << "index=" << index - << " " << "z_lvl=" << z_lvl << " " - << "next_z_lvl=" << next_z_lvl << std::endl; - - if (not_last_element) { - if (index + 2 == next_index && z_lvl == next_z_lvl) - continue; - bool not_second_last_element = it + 2 != node_z_level_vector.cend(); - if (not_second_last_element) { - ushort second_next_index = (it + 2)->first; - short second_next_z_lvl = (it + 2)->second; - test__z_lvl_range(second_next_z_lvl); - if (index + 2 == second_next_index && - is_superior_or_equal(second_next_z_lvl, next_z_lvl) && - z_lvl == second_next_z_lvl) { - ++it; - continue; - } - } - } - - // checks for gaps within the way - if (last_element || index + 1 < next_index || z_lvl != next_z_lvl) { - ushort from = start_index; - ushort to; - if (last_element || index + 1 < next_index || - is_superior(z_lvl, next_z_lvl)) - to = std::min((ushort)(index + 1), last_index); - else - to = index; - if (DEBUG) - std::cout << " 2 ## " << link_id << " ## " << from << "/" << last_index - << " - " << to << "/" << last_index << ": \tz_lvl=" << z_lvl - << std::endl; - if (from < to) { - build_sub_way_by_index(feat, ogr_ls, from, to, node_ref_map, way_buffer, - z_lvl); - start_index = to; - } - - if (not_last_element && to < next_index - 1) { - build_sub_way_by_index(feat, ogr_ls, to, next_index - 1, node_ref_map, - way_buffer); - if (DEBUG) - std::cout << " 3 ## " << link_id << " ## " << to << "/" << last_index - << " - " << next_index - 1 << "/" << last_index - << ": \tz_lvl=" << 0 << std::endl; - start_index = next_index - 1; - } - } - } - return start_index; -} - -/** - * \brief splits a given linestring into sub_ways to be able to apply - * z_levels. \param ogr_ls Linestring to be splitted. \param - * node_z_level_vector holds pairs of Node indices in linestring and their - * z_level. ommited indices imply default value of 0. \param node_ref_map - * provides osm_ids of Nodes to a given location. \param link_id link_id of - * processed feature - for debug only. - */ -void split_way_by_z_level(OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, - const index_z_lvl_vector_type &node_z_level_vector, - node_map_type *node_ref_map, uint link_id, - osmium::memory::Buffer &way_buffer) { - - ushort first_index = 0, last_index = ogr_ls->getNumPoints() - 1; - ushort start_index = node_z_level_vector.cbegin()->first; - if (start_index > 0) - start_index--; - - // first_index <= start_index < end_index <= last_index - assert(first_index <= start_index); - assert(start_index < last_index); - - // if (DEBUG) print_z_level_map(link_id, true); - if (first_index != start_index) { - build_sub_way_by_index(feat, ogr_ls, first_index, start_index, node_ref_map, - way_buffer); - if (DEBUG) - std::cout << " 1 ## " << link_id << " ## " << first_index << "/" - << last_index << " - " << start_index << "/" << last_index - << ": \tz_lvl=" << 0 << std::endl; - } - - start_index = create_continuing_sub_ways( - feat, ogr_ls, first_index, start_index, last_index, link_id, - node_z_level_vector, node_ref_map, way_buffer); - - if (start_index < last_index) { - build_sub_way_by_index(feat, ogr_ls, start_index, last_index, node_ref_map, - way_buffer); - if (DEBUG) - std::cout << " 4 ## " << link_id << " ## " << start_index << "/" - << last_index << " - " << last_index << "/" << last_index - << ": \tz_lvl=" << 0 << std::endl; - } -} - -/**************************************************** - * processing input: converting from navteq to osm - * and writing it to osmium - ****************************************************/ - -/** - * \brief determines osm_id for end_point. If it doesn't exist it will be - * created. - */ - -void process_end_point(bool first, z_lvl_type z_lvl, OGRLineString *ogr_ls, - node_map_type &node_ref_map, - osmium::memory::Buffer &node_buffer) { - ushort i = first ? 0 : ogr_ls->getNumPoints() - 1; - osmium::Location location(ogr_ls->getX(i), ogr_ls->getY(i)); - - if (z_lvl != 0) { - node_id_type node_id = std::make_pair(location, z_lvl); - auto it = g_z_lvl_nodes_map.find(node_id); - if (it != g_z_lvl_nodes_map.end()) { - node_ref_map.emplace(location, it->second); - } else { - osmium::unsigned_object_id_type osm_id = - build_node(location, node_buffer); - node_ref_map.emplace(location, osm_id); - g_z_lvl_nodes_map.emplace(node_id, osm_id); - } - } else { - // adds all zero z-level end points to g_way_end_points_map - g_way_end_points_map.emplace(location, build_node(location, node_buffer)); - } -} - -void process_first_end_point(z_lvl_type z_lvl, OGRLineString *ogr_ls, - node_map_type &node_ref_map, - osmium::memory::Buffer &node_buffer) { - process_end_point(true, z_lvl, ogr_ls, node_ref_map, node_buffer); -} - -void process_last_end_point(z_lvl_type z_lvl, OGRLineString *ogr_ls, - node_map_type &node_ref_map, - osmium::memory::Buffer &node_buffer) { - process_end_point(false, z_lvl, ogr_ls, node_ref_map, node_buffer); -} - -void middle_points_preparation(OGRLineString *ogr_ls, - node_map_type &node_ref_map, - osmium::memory::Buffer &node_buffer) { - // creates remaining nodes required for way - for (int i = 1; i < ogr_ls->getNumPoints() - 1; ++i) { - osmium::Location location(ogr_ls->getX(i), ogr_ls->getY(i)); - node_ref_map.emplace(location, build_node(location, node_buffer)); - } - node_buffer.commit(); -} - -/** - * \brief replaces all z-levels by zero, which are not an endpoint - * \param z_lvl_vec vector containing pairs of [z_lvl_index, z_lvl] - */ -void set_ferry_z_lvls_to_zero(OGRFeatureUniquePtr &feat, - index_z_lvl_vector_type &z_lvl_vec) { - // erase middle z_lvls - if (z_lvl_vec.size() > 2) - z_lvl_vec.erase(z_lvl_vec.begin() + 1, z_lvl_vec.end() - 1); - // erase first z_lvl if first index references first node - if (!z_lvl_vec.empty() && z_lvl_vec.begin()->first != 0) - z_lvl_vec.erase(z_lvl_vec.begin()); - // erase last z_lvl if last index references last node - OGRLineString *ogr_ls = static_cast(feat->GetGeometryRef()); - if (!z_lvl_vec.empty() && - (z_lvl_vec.end() - 1)->first != ogr_ls->getNumPoints() - 1) - z_lvl_vec.erase(z_lvl_vec.end()); -} - /** * \brief creates interpolated house numbers alongside of a given linestring * if feature holds suitable tags \param feat feature which holds the tags @@ -607,60 +190,6 @@ void create_premium_house_numbers( } } -/** - * \brief creates Way from linestring. - * creates missing Nodes needed for Way and Way itself. - * \param ogr_ls linestring which provides the geometry. - * \param z_level_map holds z_levels to Nodes of Ways. - */ -void process_way(OGRFeatureUniquePtr &feat, z_lvl_map *z_level_map, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - - node_map_type node_ref_map; - - auto ogr_ls = static_cast(feat->GetGeometryRef()); - - // creates remaining nodes required for way - middle_points_preparation(ogr_ls, node_ref_map, node_buffer); - if (ogr_ls->getNumPoints() > 2) - assert(node_ref_map.size() > 0); - - link_id_type link_id = get_uint_from_feature(feat, LINK_ID); - - auto it = z_level_map->find(link_id); - if (it == z_level_map->end()) { - build_way(feat, ogr_ls, &node_ref_map, way_buffer); - } else { - auto &index_z_lvl_vector = it->second; - - // way with different z_levels - auto &first_point_with_different_z_lvl = index_z_lvl_vector.front(); - auto first_index = 0; - z_lvl_type first_z_lvl = 0; - if (first_point_with_different_z_lvl.first == first_index) - first_z_lvl = first_point_with_different_z_lvl.second; - - process_first_end_point(first_z_lvl, ogr_ls, node_ref_map, node_buffer); - - auto &last_point_with_different_z_lvl = index_z_lvl_vector.back(); - auto last_index = ogr_ls->getNumPoints() - 1; - z_lvl_type last_z_lvl = 0; - if (last_point_with_different_z_lvl.first == last_index) - last_z_lvl = last_point_with_different_z_lvl.second; - - process_last_end_point(last_z_lvl, ogr_ls, node_ref_map, node_buffer); - - way_buffer.commit(); - - if (is_ferry(get_field_from_feature(feat, FERRY))) - set_ferry_z_lvls_to_zero(feat, index_z_lvl_vector); - - split_way_by_z_level(feat, ogr_ls, index_z_lvl_vector, &node_ref_map, - link_id, way_buffer); - } -} - /** * \brief creates Way from linestring. * creates missing Nodes needed for Way and Way itself. @@ -686,175 +215,6 @@ void process_house_numbers( } } -// \brief writes way end node to way_end_points_map. -void process_way_end_node(const osmium::Location &location, - osmium::memory::Buffer &node_buffer) { - - auto it = g_way_end_points_map.find(location); - if (it != g_way_end_points_map.end()) - return; - - osmium::builder::NodeBuilder builder(node_buffer); - osmium::unsigned_object_id_type osm_id = build_node(location, &builder); - // add ramp tags - auto ramp = g_ramps_ref_map.find(location); - if (ramp != g_ramps_ref_map.end()) { - if (ramp->second.find(0) != ramp->second.end()) { - osmium::builder::TagListBuilder tglBuilder(builder); - tglBuilder.add_tag(HIGHWAY, "motorway_junction"); - tglBuilder.add_tag("ref", ramp->second[0]); - tglBuilder.add_tag("name", to_camel_case_with_spaces(ramp->second[1])); - } - } - g_way_end_points_map.emplace(location, osm_id); -} - -// \brief gets end nodes of linestring and processes them. -void process_way_end_nodes(OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer) { - - auto ogr_ls = static_cast(feat->GetGeometryRef()); - - process_way_end_node(osmium::Location(ogr_ls->getX(0), ogr_ls->getY(0)), - node_buffer); - process_way_end_node( - osmium::Location(ogr_ls->getX(ogr_ls->getNumPoints() - 1), - ogr_ls->getY(ogr_ls->getNumPoints() - 1)), - node_buffer); -} - -/** - * \brief creates nodes for closed ways (i.e. for administrative boundary) - * \return osm_ids of created nodes - */ -node_vector_type create_closed_way_nodes(const OGRLinearRing *ring, - osmium::memory::Buffer &node_buffer) { - node_vector_type osm_way_node_ids; - for (auto &point : *ring) { - osmium::Location location(point.getX(), point.getY()); - auto it = g_way_end_points_map.find(location); - - if (it != g_way_end_points_map.end()) { - osm_way_node_ids.emplace_back(location, it->second); - } else { - auto osm_id = build_node(location, node_buffer); - osm_way_node_ids.emplace_back(location, osm_id); - g_way_end_points_map.emplace(location, osm_id); - } - } - - // first and last node are the same in rings, hence add first node_id and - // skip last node. - if (!ring->get_IsClosed()) - throw format_error( - "admin boundary ring is invalid. First and last node don't match"); - - return osm_way_node_ids; -} - -/** - * \brief creates nodes for open ways - * \return osm_ids of created nodes - */ -node_vector_type create_open_way_nodes(const OGRLineString *line, - osmium::memory::Buffer &node_buffer) { - node_vector_type osm_way_node_ids; - - for (auto &point : *line) { - osmium::Location location(point.getX(), point.getY()); - auto it = g_way_end_points_map.find(location); - if (it != g_way_end_points_map.end()) { - osm_way_node_ids.emplace_back(location, it->second); - } else { - auto osm_id = build_node(location, node_buffer); - osm_way_node_ids.emplace_back(location, osm_id); - g_way_end_points_map.emplace(location, osm_id); - } - } - - return osm_way_node_ids; -} - -/** - * \brief creates closed ways (i.e. for administrative boundary) - * \return osm_ids of created ways - */ -osm_id_vector_type build_closed_ways(const OGRLinearRing *ring, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - node_vector_type osm_way_node_ids = - create_closed_way_nodes(ring, node_buffer); - - osm_id_vector_type osm_way_ids; - size_t i = 0; - do { - osmium::builder::WayBuilder builder(way_buffer); - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER); - osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &builder); - for (size_t j = i; - j < std::min(i + OSM_MAX_WAY_NODES, osm_way_node_ids.size()); j++) - wnl_builder.add_node_ref(osm_way_node_ids.at(j).second, - osm_way_node_ids.at(j).first); - osm_way_ids.push_back(builder.object().id()); - i += OSM_MAX_WAY_NODES - 1; - } while (i < osm_way_node_ids.size()); - return osm_way_ids; -} - -/** - * \brief adds navteq administrative boundary tags to Relation - */ - -/** - * \brief adds navteq landuse tags to Relation - */ - -void build_relation_members(osmium::builder::RelationBuilder &builder, - const osm_id_vector_type &ext_osm_way_ids, - const osm_id_vector_type &int_osm_way_ids) { - osmium::builder::RelationMemberListBuilder rml_builder(builder); - - for (osmium::unsigned_object_id_type osm_id : ext_osm_way_ids) - rml_builder.add_member(osmium::item_type::way, osm_id, "outer"); - - for (osmium::unsigned_object_id_type osm_id : int_osm_way_ids) - rml_builder.add_member(osmium::item_type::way, osm_id, "inner"); -} - -void create_polygon(const OGRPolygon *poly, - osm_id_vector_type &exterior_way_ids, - osm_id_vector_type &interior_way_ids, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - bool isExteriorRing = true; // first ring is the exterior ring - for (const OGRLinearRing *ring : *poly) { - auto tmp = build_closed_ways(ring, node_buffer, way_buffer); - if (isExteriorRing) { - std::move(tmp.begin(), tmp.end(), std::back_inserter(exterior_way_ids)); - } else { - std::move(tmp.begin(), tmp.end(), std::back_inserter(interior_way_ids)); - } - isExteriorRing = false; - } -} - -/** - * \brief handles administrative boundary multipolygons - */ -void create_multi_polygon(OGRMultiPolygon *mp, - osm_id_vector_type &mp_ext_ring_osm_ids, - osm_id_vector_type &mp_int_ring_osm_ids, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - - for (const OGRPolygon *poly : mp) { - create_polygon(poly, mp_ext_ring_osm_ids, mp_int_ring_osm_ids, node_buffer, - way_buffer); - } -} - void init_cdms_map( DBFHandle cdms_handle, std::map &cdms_map) { @@ -866,116 +226,6 @@ void init_cdms_map( } } -void init_g_cnd_mod_map(const boost::filesystem::path &dir) { - DBFHandle cnd_mod_handle = read_dbf_file(dir / CND_MOD_DBF); - for (int i = 0; i < DBFGetRecordCount(cnd_mod_handle); i++) { - cond_id_type cond_id = dbf_get_uint_by_field(cnd_mod_handle, i, COND_ID); - std::string lang_code = - dbf_get_string_by_field(cnd_mod_handle, i, LANG_CODE); - mod_typ_type mod_type = - dbf_get_uint_by_field(cnd_mod_handle, i, CM_MOD_TYPE); - mod_val_type mod_val = dbf_get_uint_by_field(cnd_mod_handle, i, CM_MOD_VAL); - - auto it2 = g_cnd_mod_map.find(cond_id); - if (it2 == g_cnd_mod_map.end()) { - mod_group_vector_type new_vector; - new_vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); - g_cnd_mod_map.emplace(cond_id, new_vector); - } else { - //(std::vector) ()’ - auto vector = it2->second; - g_cnd_mod_map.erase(it2); - vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); - g_cnd_mod_map.emplace(cond_id, vector); - } - } - DBFClose(cnd_mod_handle); -} - -void init_g_cdms_map(const boost::filesystem::path &dir) { - DBFHandle cdms_handle = read_dbf_file(dir / CDMS_DBF); - for (int i = 0; i < DBFGetRecordCount(cdms_handle); i++) { - link_id_type link_id = dbf_get_uint_by_field(cdms_handle, i, LINK_ID); - cond_id_type cond_id = dbf_get_uint_by_field(cdms_handle, i, COND_ID); - ushort cond_type = dbf_get_uint_by_field(cdms_handle, i, COND_TYPE); - g_cdms_map.emplace(link_id, cond_pair_type(cond_id, cond_type)); - } - DBFClose(cdms_handle); -} - -void init_g_area_to_govt_code_map(const boost::filesystem::path &dir) { - DBFHandle mtd_area_handle = read_dbf_file(dir / MTD_AREA_DBF); - for (int i = 0; i < DBFGetRecordCount(mtd_area_handle); i++) { - area_id_type area_id = dbf_get_uint_by_field(mtd_area_handle, i, AREA_ID); - govt_code_type govt_code = - dbf_get_uint_by_field(mtd_area_handle, i, GOVT_CODE); - g_area_to_govt_code_map.emplace(area_id, govt_code); - } - DBFClose(mtd_area_handle); -} - -void init_g_cntry_ref_map(const boost::filesystem::path &dir) { - DBFHandle cntry_ref_handle = read_dbf_file(dir / MTD_CNTRY_REF_DBF); - for (int i = 0; i < DBFGetRecordCount(cntry_ref_handle); i++) { - govt_code_type govt_code = - dbf_get_uint_by_field(cntry_ref_handle, i, GOVT_CODE); - auto unit_measure = - dbf_get_string_by_field(cntry_ref_handle, i, UNTMEASURE); - auto speed_limit_unit = - dbf_get_string_by_field(cntry_ref_handle, i, SPEEDLIMITUNIT); - auto iso_code = dbf_get_string_by_field(cntry_ref_handle, i, ISO_CODE); - auto cntry_ref = cntry_ref_type(unit_measure, speed_limit_unit, iso_code); - g_cntry_ref_map.emplace(govt_code, cntry_ref); - } - DBFClose(cntry_ref_handle); -} - -// \brief stores z_levels in z_level_map for later use. Maps link_ids to pairs -// of indices and z-levels of waypoints with z-levels not equal 0. -void init_z_level_map(boost::filesystem::path dir, z_lvl_map &z_level_map) { - - // open dbf - DBFHandle handle = read_dbf_file(dir / ZLEVELS_DBF); - - link_id_type last_link_id = 0; - index_z_lvl_vector_type v; - - for (int i = 0; i < DBFGetRecordCount(handle); i++) { - link_id_type link_id = dbf_get_uint_by_field(handle, i, LINK_ID); - ushort point_num = dbf_get_uint_by_field(handle, i, POINT_NUM) - 1; - short z_level = dbf_get_uint_by_field(handle, i, Z_LEVEL); - - if (i > 0 && last_link_id != link_id && !v.empty()) { - z_level_map.emplace(last_link_id, v); - v = index_z_lvl_vector_type(); - } - if (z_level != 0) - v.emplace_back(point_num, z_level); - last_link_id = link_id; - } - - // close dbf - DBFClose(handle); - - if (!v.empty()) - z_level_map.emplace(last_link_id, v); -} - -void init_conditional_driving_manoeuvres(const boost::filesystem::path &dir) { - if (dbf_file_exists(dir / CND_MOD_DBF) && dbf_file_exists(dir / CDMS_DBF)) { - init_g_cnd_mod_map(dir); - init_g_cdms_map(dir); - } -} - -void init_country_reference(const boost::filesystem::path &dir) { - if (dbf_file_exists(dir / MTD_AREA_DBF) && - dbf_file_exists(dir / MTD_CNTRY_REF_DBF)) { - init_g_area_to_govt_code_map(dir); - init_g_cntry_ref_map(dir); - } -} - void init_under_construction(const boost::filesystem::path &dir) { if (!dbf_file_exists(dir / CDMS_DBF)) return; @@ -1021,128 +271,6 @@ void init_highway_names(const boost::filesystem::path &dir) { parse_highway_names(dir / STREETS_DBF, true); } -void parse_ramp_names( - const boost::filesystem::path &shp_file, - const std::map &junctionNames) { - - auto ds = open_shape_file(shp_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(shp_file.string())); - - int exitNameField = layer->FindFieldIndex(EXITNAME, true); - int linkIdField = layer->FindFieldIndex(LINK_ID, true); - int baseNameField = layer->FindFieldIndex(ST_NM_BASE, true); - int directionField = layer->FindFieldIndex(DIR_TRAVEL, true); - int rampField = layer->FindFieldIndex(RAMP, true); - - for (auto &feat : *layer) { - - if (!parse_bool(feat->GetFieldAsString(rampField))) { - continue; - } - - auto ogr_ls = static_cast(feat->GetGeometryRef()); - - auto location = osmium::Location(ogr_ls->getX(0), ogr_ls->getY(0)); - if (!strcmp(feat->GetFieldAsString(directionField), "T")) - location = osmium::Location(ogr_ls->getX(ogr_ls->getNumPoints() - 1), - ogr_ls->getY(ogr_ls->getNumPoints() - 1)); - - if (parse_bool(feat->GetFieldAsString(exitNameField))) { - std::string exitName = feat->GetFieldAsString(baseNameField); - - // add exit name - g_ramps_ref_map[location].emplace(0, exitName); - - // add junction name - auto it = junctionNames.find(feat->GetFieldAsInteger(linkIdField)); - if (it != junctionNames.end()) { - g_ramps_ref_map[location].emplace(1, it->second); - } - } - } -} - -std::map -read_junction_names(const boost::filesystem::path &dbf_file) { - DBFHandle hwys_handle = read_dbf_file(dbf_file); - std::map junctionNames; - for (int i = 0; i < DBFGetRecordCount(hwys_handle); i++) { - - link_id_type link_id = dbf_get_uint_by_field(hwys_handle, i, LINK_ID); - std::string ramp_name = dbf_get_string_by_field(hwys_handle, i, ST_NM_BASE); - - if (parse_bool( - dbf_get_string_by_field(hwys_handle, i, JUNCTIONNM).c_str())) { - junctionNames[link_id] = ramp_name; - } - } - DBFClose(hwys_handle); - - return junctionNames; -} - -void init_ramp_names(const boost::filesystem::path &dir) { - // read junction names from alt_streets - auto junctionMap = read_junction_names(dir / ALT_STREETS_DBF); - - // create location ramps map - parse_ramp_names(dir / STREETS_SHP, junctionMap); -} - -z_lvl_map process_z_levels(const std::vector &dirs) { - - z_lvl_map z_level_map; - - for (auto &dir : dirs) { - auto path = dir / STREETS_SHP; - auto ds = open_shape_file(path); - - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(path.string())); - assert(layer->GetGeomType() == wkbLineString); - - init_z_level_map(dir, z_level_map); - init_conditional_driving_manoeuvres(dir); - init_country_reference(dir); - } - return z_level_map; -} - -void process_way_end_nodes(const std::vector &dirs, - z_lvl_map &z_level_map, osmium::io::Writer &writer) { - for (auto &dir : dirs) { - - // parse ramp names and refs - init_ramp_names(dir); - - auto path = dir / STREETS_SHP; - auto ds = open_shape_file(path); - - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(path.string())); - - osmium::memory::Buffer node_buffer(buffer_size); - - int linkIDField = layer->FindFieldIndex(LINK_ID, true); - - // get all nodes which may be a routable crossing - for (auto &feat : *layer) { - link_id_type link_id = feat->GetFieldAsInteger(linkIDField); - // omit way end nodes with different z-levels (they have to be handled - // extra) - if (z_level_map.find(link_id) == z_level_map.end()) - process_way_end_nodes(feat, node_buffer); - } - node_buffer.commit(); - writer(std::move(node_buffer)); - g_ramps_ref_map.clear(); - } -} - void process_way(const std::vector &dirs, z_lvl_map &z_level_map, osmium::io::Writer &writer) { for (auto &dir : dirs) { @@ -1249,85 +377,6 @@ void process_house_numbers(const std::vector &dirs, } } -/** - * \brief Parses AltStreets.dbf for route type values. - */ -void process_alt_steets_route_types( - const std::vector &dirs) { - for (auto dir : dirs) { - DBFHandle alt_streets_handle = read_dbf_file(dir / ALT_STREETS_DBF); - for (int i = 0; i < DBFGetRecordCount(alt_streets_handle); i++) { - - if (dbf_get_string_by_field(alt_streets_handle, i, ROUTE).empty()) - continue; - - osmium::unsigned_object_id_type link_id = - dbf_get_uint_by_field(alt_streets_handle, i, LINK_ID); - ushort route_type = dbf_get_uint_by_field(alt_streets_handle, i, ROUTE); - - // try to emplace pair - auto [insertion, inserted] = - g_route_type_map.emplace(link_id, route_type); - - // if its already exists update routetype - if (!inserted && insertion->second > route_type) { - // As link id's aren't unique in AltStreets.dbf - // just store the lowest route type - insertion->second = route_type; - } - } - DBFClose(alt_streets_handle); - } -} - -/**************************************************** - * adds layers to osmium: - * cur_layer and cur_feature have to be set - ****************************************************/ - -/** - * \brief adds streets to m_buffer / osmium. - * \param layer Pointer to administrative layer. - */ - -void add_street_shapes(const std::vector &dirs, - osmium::io::Writer &writer) { - - BOOST_LOG_TRIVIAL(info) << " processing z-levels"; - z_lvl_map z_level_map = process_z_levels(dirs); - - BOOST_LOG_TRIVIAL(info) << " processing way end points"; - process_way_end_nodes(dirs, z_level_map, writer); - - BOOST_LOG_TRIVIAL(info) << " processing ways"; - process_way(dirs, z_level_map, writer); - - // create house numbers - BOOST_LOG_TRIVIAL(info) << " processing house numbers"; - process_house_numbers(dirs, writer); - - BOOST_LOG_TRIVIAL(info) << " clean"; - for (auto elem : z_level_map) - elem.second.clear(); - z_level_map.clear(); - - // now we can clear some maps: - g_hwys_ref_map.clear(); - g_cdms_map.clear(); - g_cnd_mod_map.clear(); - g_area_to_govt_code_map.clear(); - g_cntry_ref_map.clear(); - g_z_lvl_nodes_map.clear(); - g_route_type_map.clear(); -} - -void add_street_shapes(const boost::filesystem::path &dir, - osmium::io::Writer &writer) { - std::vector dir_vector; - dir_vector.push_back(dir); - add_street_shapes(dir_vector, writer); -} - /**************************************************** * cleanup and assertions ****************************************************/ diff --git a/plugins/navteq/navteq2osm_tag_parser.hpp b/plugins/navteq/navteq2osm_tag_parser.hpp index 229418c..8e1c036 100644 --- a/plugins/navteq/navteq2osm_tag_parser.hpp +++ b/plugins/navteq/navteq2osm_tag_parser.hpp @@ -393,106 +393,6 @@ void add_hazmat_tag(osmium::builder::TagListBuilder *builder, /** * \brief adds maxheight, maxwidth, maxlength, maxweight and maxaxleload tags. */ -void add_additional_restrictions( - osmium::builder::TagListBuilder *builder, link_id_type link_id, - area_id_type l_area_id, area_id_type r_area_id, cdms_map_type *cdms_map, - cnd_mod_map_type *cnd_mod_map, area_id_govt_code_map_type *area_govt_map, - cntry_ref_map_type *cntry_map, mtd_area_map_type *mtd_area_map) { - if (!cdms_map || !cnd_mod_map) - return; - - // default is metric units - bool imperial_units = false; - if (area_govt_map && cntry_map) { - imperial_units = - is_imperial(l_area_id, r_area_id, area_govt_map, cntry_map); - } - - uint64_t max_height = 0, max_width = 0, max_length = 0, max_weight = 0, - max_axleload = 0; - - std::vector mod_group_vector; - auto range = cdms_map->equal_range(link_id); - for (auto it = range.first; it != range.second; ++it) { - cond_pair_type cond = it->second; - if (cond.second == CT_RESTRICTED_DRIVING_MANOEUVRE || - cond.second == CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE) - continue; // TODO RESTRICTED_DRIVING_MANOEUVRE should apply as - // conditional turn restriction but not for current link id - auto it2 = cnd_mod_map->find(cond.first); - if (it2 != cnd_mod_map->end()) { - for (auto mod_group : it2->second) { - mod_group_vector.push_back(mod_group); - } - } - } - - for (auto mod_group : mod_group_vector) { - auto mod_type = mod_group.mod_type; - auto mod_val = mod_group.mod_val; - if (mod_type == MT_HEIGHT_RESTRICTION) { - if (!max_height || mod_val < max_height) - max_height = mod_val; - } else if (mod_type == MT_WIDTH_RESTRICTION) { - if (!max_width || mod_val < max_width) - max_width = mod_val; - } else if (mod_type == MT_LENGTH_RESTRICTION) { - if (!max_length || mod_val < max_length) - max_length = mod_val; - } else if (mod_type == MT_WEIGHT_RESTRICTION) { - if (!max_weight || mod_val < max_weight) - max_weight = mod_val; - } else if (mod_type == MT_WEIGHT_PER_AXLE_RESTRICTION) { - if (!max_axleload || mod_val < max_axleload) - max_axleload = mod_val; - } else if (mod_type == MT_HAZARDOUS_RESTRICTION) { - add_hazmat_tag(builder, mod_val); - } - } - - if (get_area_code_l(l_area_id, r_area_id, mtd_area_map) == 107) { - /** exceptional handling for Sweden as there are BK Roads - * - * HERE tags these roads with the most conservative values, - * which would make it unroutable for nearly every truck. - * Therefore we use the highest value and add a marker for BK2 / BK3 */ - if (max_weight == 16000 && max_axleload == 10000) { - builder->add_tag("maxweight:class", "BK2"); - max_weight = 51400; - } else if (max_weight == 12000 && max_axleload == 8000) { - builder->add_tag("maxweight:class", "BK3"); - max_weight = 37000; - } - } - - if (max_height > 0) - builder->add_tag("maxheight", imperial_units ? inch_to_feet(max_height) - : cm_to_m(max_height)); - if (max_width > 0) - builder->add_tag("maxwidth", imperial_units ? inch_to_feet(max_width) - : cm_to_m(max_width)); - if (max_length > 0) - builder->add_tag("maxlength", imperial_units ? inch_to_feet(max_length) - : cm_to_m(max_length)); - if (max_weight > 0) - builder->add_tag("maxweight", imperial_units ? lbs_to_metric_ton(max_weight) - : kg_to_t(max_weight)); - if (max_axleload > 0) - builder->add_tag("maxaxleload", imperial_units - ? lbs_to_metric_ton(max_axleload) - : kg_to_t(max_axleload)); -} - -bool is_ferry(const char *value) { - if (!strcmp(value, "H")) - return false; // H --> not a ferry - else if (!strcmp(value, "B")) - return true; // T --> boat ferry - else if (!strcmp(value, "R")) - return true; // B --> rail ferry - throw(format_error("value '" + std::string(value) + "' for " + - std::string(FERRY) + " not valid")); -} bool only_pedestrians(OGRFeatureUniquePtr &f) { if (strcmp(get_field_from_feature(f, AR_PEDESTRIANS), "Y")) @@ -633,75 +533,6 @@ void add_highway_tags(osmium::builder::TagListBuilder *builder, builder->add_tag("4wd_only", YES); } -/** - * \brief maps navteq tags for access, tunnel, bridge, etc. to osm tags - * \return link id of processed feature. - */ -link_id_type parse_street_tags( - osmium::builder::TagListBuilder *builder, OGRFeatureUniquePtr &f, - cdms_map_type *cdms_map, cnd_mod_map_type *cnd_mod_map, - area_id_govt_code_map_type *area_govt_map, cntry_ref_map_type *cntry_map, - mtd_area_map_type *mtd_area_map, link_id_route_type_map *route_type_map, - link_id_to_names_map *names_map, - const std::set &construction_set, bool debugMode) { - - const char *link_id_s = get_field_from_feature(f, LINK_ID); - link_id_type link_id = std::stoul(link_id_s); - - bool ramp = parse_bool(get_field_from_feature(f, RAMP)); - - ushort route_type = 0; - if (!((std::string)get_field_from_feature(f, ROUTE)).empty()) - route_type = get_uint_from_feature(f, ROUTE); - - auto routeTypeIter = route_type_map->find(link_id); - if (routeTypeIter != route_type_map->end() && - (!route_type || routeTypeIter->second < route_type)) - route_type = routeTypeIter->second; - - // add tags for ref and int_ref to major highways - std::string ref_name = - add_highway_name_tags(builder, names_map, link_id, ramp); - - bool underConstruction = - (construction_set.find(link_id) != construction_set.end()); - - if (is_ferry(get_field_from_feature(f, FERRY))) { - add_ferry_tag(builder, f); - } else { // usual highways - add_highway_tags(builder, f, route_type, mtd_area_map, ref_name, - underConstruction); - } - - area_id_type l_area_id = get_uint_from_feature(f, L_AREA_ID); - area_id_type r_area_id = get_uint_from_feature(f, R_AREA_ID); - // tags which apply to highways and ferry routes - add_additional_restrictions(builder, link_id, l_area_id, r_area_id, cdms_map, - cnd_mod_map, area_govt_map, cntry_map, - mtd_area_map); - - // tag for debug purpose - if (debugMode) { - builder->add_tag(LINK_ID, link_id_s); - add_here_speed_cat_tag(builder, f); - if (parse_bool(get_field_from_feature(f, TOLLWAY))) - builder->add_tag("here:tollway", YES); - if (parse_bool(get_field_from_feature(f, URBAN))) - builder->add_tag("here:urban", YES); - if (parse_bool(get_field_from_feature(f, CONTRACC))) - builder->add_tag("here:controll_access", YES); - if (route_type) - add_uint_tag(builder, "here:route_type", route_type); - - std::string func_class = get_field_from_feature(f, FUNC_CLASS); - if (!func_class.empty()) - builder->add_tag("here:func_class", func_class.c_str()); - - add_uint_tag(builder, "here:area_code", get_area_code_l(f, mtd_area_map)); - } - return link_id; -} - std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { if (!is_in_range(navteq_admin_lvl_int, (uint)NAVTEQ_ADMIN_LVL_MIN, (uint)NAVTEQ_ADMIN_LVL_MAX)) diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 2b98fff..f366300 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -26,19 +26,15 @@ static const boost::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; static const boost::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; static const boost::filesystem::path RDMS_DBF = "Rdms.dbf"; -static const boost::filesystem::path CDMS_DBF = "Cdms.dbf"; -static const boost::filesystem::path CND_MOD_DBF = "CndMod.dbf"; -static const boost::filesystem::path ZLEVELS_DBF = "Zlevels.dbf"; + static const boost::filesystem::path MAJ_HWYS_DBF = "MajHwys.dbf"; static const boost::filesystem::path SEC_HWYS_DBF = "SecHwys.dbf"; -static const boost::filesystem::path ALT_STREETS_DBF = "AltStreets.dbf"; static const boost::filesystem::path STREETS_DBF = "Streets.dbf"; // STREETS columns const char *LINK_ID = "LINK_ID"; const char *ST_NAME = "ST_NAME"; -const char *ST_NM_BASE = "ST_NM_BASE"; const char *ADDR_TYPE = "ADDR_TYPE"; const char *L_REFADDR = "L_REFADDR"; @@ -83,25 +79,9 @@ const char *R_AREA_ID = "R_AREA_ID"; const char *L_POSTCODE = "L_POSTCODE"; const char *R_POSTCODE = "R_POSTCODE"; const char *RAMP = "RAMP"; -const char *EXITNAME = "EXITNAME"; -const char *JUNCTIONNM = "JUNCTIONNM"; // const char *AREA_NAME_LANG_CODE = "NM_LANGCD"; -// MTD_AREA_DBF columns -const char *AREA_ID = "AREA_ID"; -const char *LANG_CODE = "LANG_CODE"; -const char *AREA_NAME = "AREA_NAME"; -const char *AREA_CODE_1 = "AREACODE_1"; -const char *ADMIN_LVL = "ADMIN_LVL"; -const char *GOVT_CODE = "GOVT_CODE"; - -// MTD_CNTRY_REF columns -const char *UNTMEASURE = "UNTMEASURE"; -// const char* MAX_ADMINLEVEL = "MAX_ADMINLEVEL"; -const char *SPEEDLIMITUNIT = "SPDLIMUNIT"; -const char *ISO_CODE = "ISO_CODE"; - // RDMS_DBF columns // const char* LINK_ID = "LINK_ID"; const char *COND_ID = "COND_ID"; @@ -130,16 +110,8 @@ const char *HIGHWAY_NM = "HIGHWAY_NM"; #define MT_LENGTH_RESTRICTION 44 #define MT_WIDTH_RESTRICTION 45 -// CndMod types (CM) -const char *CM_MOD_TYPE = "MOD_TYPE"; -const char *CM_MOD_VAL = "MOD_VAL"; - #define RESTRICTED_DRIVING_MANOEUVRE 7 -// ZLEVELS_DBF columns -const char *Z_LEVEL = "Z_LEVEL"; -const char *POINT_NUM = "POINT_NUM"; - #define YES "yes" #define NO "no" diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 42e319c..5877164 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -23,6 +23,7 @@ #include "converter/LanduseConverter.hpp" #include "converter/RailwayConverter.hpp" #include "converter/RestAreaConverter.hpp" +#include "converter/StreetConverter.hpp" #include "converter/WaterConverter.hpp" #include "navteq.hpp" @@ -38,12 +39,13 @@ navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) : base_plugin::base_plugin("Navteq Plugin", executable_path) { - convetrer.emplace_back(new AdminBoundariesConverter(executable_path)); + converter.emplace_back(new AdminBoundariesConverter(executable_path)); + converter.emplace_back(new StreetConverter(executable_path)); converter.emplace_back(new LanduseConverter(executable_path)); converter.emplace_back(new CityConverter(executable_path)); converter.emplace_back(new HamletConverter(executable_path)); converter.emplace_back(new BuildingConverter(executable_path)); - converter.emplace_back(new RestAreaConverter(executable_path); + converter.emplace_back(new RestAreaConverter(executable_path)); converter.emplace_back(new RailwayConverter(executable_path)); converter.emplace_back(new WaterConverter(executable_path)); } @@ -66,8 +68,6 @@ bool navteq_plugin::check_files(const boost::filesystem::path &dir) { if (!shp_file_exists(dir / STREETS_SHP)) return false; - if (!dbf_file_exists(dir / MTD_AREA_DBF)) - return false; if (!dbf_file_exists(dir / RDMS_DBF)) return false; if (!dbf_file_exists(dir / CDMS_DBF)) @@ -197,15 +197,6 @@ void navteq_plugin::execute() { hdr.set("xml_josm_upload", "false"); osmium::io::Writer writer(outfile, hdr, osmium::io::overwrite::allow); - BOOST_LOG_TRIVIAL(info) << "Procesing Meta areas"; - preprocess_meta_areas(dataDirs); - - BOOST_LOG_TRIVIAL(info) << "Procesing alt street rout types"; - process_alt_steets_route_types(dataDirs); - - BOOST_LOG_TRIVIAL(info) << "Add street shapes"; - add_street_shapes(dataDirs, writer); - // run converters for (auto &c : converter) c->convert(dataDirs, writer); diff --git a/plugins/navteq/navteq_types.hpp b/plugins/navteq/navteq_types.hpp index 7ac4b75..c62dd13 100644 --- a/plugins/navteq/navteq_types.hpp +++ b/plugins/navteq/navteq_types.hpp @@ -20,30 +20,6 @@ typedef uint64_t mod_val_type; typedef std::pair mod_pair_type; -struct cntry_ref_type { - std::string unit_measure; - std::string speed_limit_unit; - std::string iso_code; - cntry_ref_type() {} - cntry_ref_type(const std::string &unit_measure, - const std::string &speed_limit_unit, - const std::string &iso_code) { - this->unit_measure = unit_measure; - this->speed_limit_unit = speed_limit_unit; - this->iso_code = iso_code; - } - bool operator==(cntry_ref_type rhs) { - if (this->unit_measure != rhs.unit_measure) - return false; - if (this->speed_limit_unit != rhs.speed_limit_unit) - return false; - if (this->iso_code != rhs.iso_code) - return false; - return true; - } - bool operator!=(cntry_ref_type rhs) { return !(*this == rhs); } -}; - struct mod_group_type { std::string lang_code; mod_typ_type mod_type; @@ -94,6 +70,7 @@ typedef short z_lvl_type; typedef std::pair index_z_lvl_pair_type; typedef std::vector index_z_lvl_vector_type; + // maps navteq link_ids to pairs of typedef std::map z_lvl_map; diff --git a/plugins/util.hpp b/plugins/util.hpp index 52681a7..8b48f8b 100644 --- a/plugins/util.hpp +++ b/plugins/util.hpp @@ -251,4 +251,62 @@ bool parse_bool(const char *value) { return false; } +static std::set z_lvl_set = {-4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; +void test__z_lvl_range(short z_lvl) { + if (z_lvl_set.find(z_lvl) == z_lvl_set.end()) + throw(out_of_range_exception("z_lvl " + std::to_string(z_lvl) + + " is not valid")); +} + +void set_ferry_z_lvls_to_zero(OGRFeatureUniquePtr &feat, + index_z_lvl_vector_type &z_lvl_vec) { + // erase middle z_lvls + if (z_lvl_vec.size() > 2) + z_lvl_vec.erase(z_lvl_vec.begin() + 1, z_lvl_vec.end() - 1); + // erase first z_lvl if first index references first node + if (!z_lvl_vec.empty() && z_lvl_vec.begin()->first != 0) + z_lvl_vec.erase(z_lvl_vec.begin()); + // erase last z_lvl if last index references last node + OGRLineString *ogr_ls = static_cast(feat->GetGeometryRef()); + if (!z_lvl_vec.empty() && + (z_lvl_vec.end() - 1)->first != ogr_ls->getNumPoints() - 1) + z_lvl_vec.erase(z_lvl_vec.end()); +} + +bool is_ferry(const char *value) { + if (!strcmp(value, "H")) + return false; // H --> not a ferry + else if (!strcmp(value, "B")) + return true; // T --> boat ferry + else if (!strcmp(value, "R")) + return true; // B --> rail ferry + throw(format_error("value '" + std::string(value) + "' for " + + std::string(FERRY) + " not valid")); +} + +/** + * \brief checks if first z_level is more significant than the other or equal. + * \param superior first z_level. + * \param than second z_level. + * \return true if superior is greater or equal than. + */ +bool is_superior_or_equal(short superior, short than) { + if (abs(superior) >= abs(than)) + return true; + return false; +} + +/* helpers for split_way_by_z_level */ +/** + * \brief checks if first z_level is more significant than the other. + * \param superior First z_level. + * \param than second z_level. + * \return true if superior is superior to than. + */ +bool is_superior(short superior, short than) { + if (abs(superior) > abs(than)) + return true; + return false; +} + #endif /* UTIL_HPP_ */ From 5b13a1d9411827fbd4113424e81e89495fc7f8a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 11:43:03 +0000 Subject: [PATCH 17/57] Refactor code to remove unused variables and improve code readability --- plugins/navteq/converter/StreetConverter.cpp | 97 ++++++++++++++------ plugins/navteq/converter/StreetConverter.hpp | 50 +++++++--- plugins/navteq/navteq2osm_tag_parser.hpp | 43 --------- plugins/navteq/navteq_mappings.hpp | 3 +- 4 files changed, 105 insertions(+), 88 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 7c5e6f5..a8db03d 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -498,15 +498,19 @@ uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, uint64_t StreetConverter::parse_street_tags( osmium::builder::TagListBuilder *builder, OGRFeatureUniquePtr &f, - cdms_map_type *cdms_map, cnd_mod_map_type *cnd_mod_map, - area_id_govt_code_map_type *area_govt_map, cntry_ref_map_type *cntry_map, - mtd_area_map_type *mtd_area_map, link_id_route_type_map *route_type_map, - link_id_to_names_map *names_map, - const std::set &construction_set, bool debugMode); -{ - - const char *link_id_s = get_field_from_feature(f, LINK_ID); - link_id_type link_id = std::stoul(link_id_s); + const std::multimap &cdms_map, + const std::unordered_map> + &cnd_mod_map, + const std::map &area_govt_map, + const std::map &cntry_map, + const std::map + mtd_area_map, + const std::map &route_type_map, + const std::map> &names_map, + const std::set &construction_set, bool debugMode) { + + const char *link_id_s = get_field_from_feature(f, LINK_ID.data()); + uint64_t link_id = std::stoul(link_id_s); bool ramp = parse_bool(get_field_from_feature(f, RAMP)); @@ -514,8 +518,8 @@ uint64_t StreetConverter::parse_street_tags( if (!((std::string)get_field_from_feature(f, ROUTE)).empty()) route_type = get_uint_from_feature(f, ROUTE); - auto routeTypeIter = route_type_map->find(link_id); - if (routeTypeIter != route_type_map->end() && + auto routeTypeIter = route_type_map.find(link_id); + if (routeTypeIter != route_type_map.end() && (!route_type || routeTypeIter->second < route_type)) route_type = routeTypeIter->second; @@ -533,8 +537,8 @@ uint64_t StreetConverter::parse_street_tags( underConstruction); } - uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); - uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); + uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID.data()); + uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID.data()); // tags which apply to highways and ferry routes add_additional_restrictions(builder, link_id, l_area_id, r_area_id, cdms_map, cnd_mod_map, area_govt_map, cntry_map, @@ -564,32 +568,37 @@ uint64_t StreetConverter::parse_street_tags( void StreetConverter::add_additional_restrictions( osmium::builder::TagListBuilder *builder, uint64_t link_id, - uint64_t l_area_id, uint64_t r_area_id, cdms_map_type *cdms_map, - cnd_mod_map_type *cnd_mod_map, area_id_govt_code_map_type *area_govt_map, - cntry_ref_map_type *cntry_map, mtd_area_map_type *mtd_area_map) { - if (!cdms_map || !cnd_mod_map) + uint64_t l_area_id, uint64_t r_area_id, + const std::multimap &cdms_map, + const std::unordered_map> + &cnd_mod_map, + const std::map &area_govt_map, + const std::map &cntry_map, + const std::map + &mtd_area_map) { + if (cdms_map.empty() || cnd_mod_map.empty()) return; // default is metric units - bool imperial_units = false; - if (area_govt_map && cntry_map) { - imperial_units = - is_imperial(l_area_id, r_area_id, area_govt_map, cntry_map); - } + bool imperial_units = + is_imperial(l_area_id, r_area_id, area_govt_map, cntry_map); - uint64_t max_height = 0, max_width = 0, max_length = 0, max_weight = 0, - max_axleload = 0; + uint64_t max_height = 0; + uint64_t max_width = 0; + uint64_t max_length = 0; + uint64_t max_weight = 0; + uint64_t max_axleload = 0; std::vector mod_group_vector; - auto range = cdms_map->equal_range(link_id); + auto range = cdms_map.equal_range(link_id); for (auto it = range.first; it != range.second; ++it) { - cond_pair_type cond = it->second; - if (cond.second == CT_RESTRICTED_DRIVING_MANOEUVRE || - cond.second == CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE) + auto cond = it->second; + if (cond.cond_type_type == CT_RESTRICTED_DRIVING_MANOEUVRE || + cond.cond_type_type == CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE) continue; // TODO RESTRICTED_DRIVING_MANOEUVRE should apply as // conditional turn restriction but not for current link id - auto it2 = cnd_mod_map->find(cond.first); - if (it2 != cnd_mod_map->end()) { + auto it2 = cnd_mod_map.find(cond.cond_id_type); + if (it2 != cnd_mod_map.end()) { for (auto mod_group : it2->second) { mod_group_vector.push_back(mod_group); } @@ -804,3 +813,31 @@ ushort StreetConverter::create_continuing_sub_ways( } return start_index; } + +bool StreetConverter::is_imperial( + uint64_t l_area_id, uint64_t r_area_id, + const std::map &area_govt_map, + const std::map &cntry_map) { + if (is_imperial(l_area_id, area_govt_map, cntry_map)) + return true; + if (is_imperial(r_area_id, area_govt_map, cntry_map)) + return true; + return false; +} + +bool StreetConverter::is_imperial( + uint64_t area_id, const std::map &area_govt_map, + const std::map &cntry_map) { + if (area_govt_map.find(area_id) != area_govt_map.end()) { + if (cntry_map.find(area_govt_map.at(area_id)) != cntry_map.end()) { + auto unit_measure = cntry_map.at(area_govt_map.at(area_id)).unit_measure; + if (unit_measure == "E") { + return true; + } else if (unit_measure != "M") { + format_error("unit_measure in navteq data is invalid: '" + + unit_measure + "'"); + } + } + } + return false; +} diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index 8eed38a..f11f8c7 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -36,6 +36,11 @@ class StreetConverter : public Converter { short z_level; }; + struct cond_type { + uint64_t cond_id_type; + uint64_t cond_type_type; + }; + struct mod_group_type { std::string lang_code; uint64_t mod_type; @@ -130,19 +135,27 @@ class StreetConverter : public Converter { uint64_t parse_street_tags( osmium::builder::TagListBuilder *builder, OGRFeatureUniquePtr &f, - cdms_map_type *cdms_map, cnd_mod_map_type *cnd_mod_map, - area_id_govt_code_map_type *area_govt_map, cntry_ref_map_type *cntry_map, - mtd_area_map_type *mtd_area_map, link_id_route_type_map *route_type_map, - link_id_to_names_map *names_map, - const std::set &construction_set, bool debugMode); - - void add_additional_restrictions(osmium::builder::TagListBuilder *builder, - uint64_t link_id, uint64_t l_area_id, - uint64_t r_area_id, cdms_map_type *cdms_map, - cnd_mod_map_type *cnd_mod_map, - area_id_govt_code_map_type *area_govt_map, - cntry_ref_map_type *cntry_map, - mtd_area_map_type *mtd_area_map); + const std::multimap &cdms_map, + const std::unordered_map> + &cnd_mod_map, + const std::map &area_govt_map, + const std::map &cntry_map, + const std::map + mtd_area_map, + const std::map &route_type_map, + const std::map> &names_map, + const std::set &construction_set, bool debugMode); + + void add_additional_restrictions( + osmium::builder::TagListBuilder *builder, uint64_t link_id, + uint64_t l_area_id, uint64_t r_area_id, + const std::multimap &cdms_map, + const std::unordered_map> + &cnd_mod_map, + const std::map &area_govt_map, + const std::map &cntry_map, + const std::map + &mtd_area_map); void process_end_point( bool first, short z_lvl, OGRLineString *ogr_ls, @@ -168,6 +181,14 @@ class StreetConverter : public Converter { std::map &node_ref_map, osmium::memory::Buffer &way_buffer); + bool is_imperial(uint64_t l_area_id, uint64_t r_area_id, + const std::map &area_govt_map, + const std::map &cntry_map); + + bool is_imperial(uint64_t area_id, + const std::map &area_govt_map, + const std::map &cntry_map); + // CndMod types (CM) static constexpr std::string_view CM_MOD_TYPE = "MOD_TYPE"; static constexpr std::string_view CM_MOD_VAL = "MOD_VAL"; @@ -196,6 +217,9 @@ class StreetConverter : public Converter { // const char* MAX_ADMINLEVEL = "MAX_ADMINLEVEL"; static constexpr std::string_view SPEEDLIMITUNIT = "SPDLIMUNIT"; static constexpr std::string_view ISO_CODE = "ISO_CODE"; + + static constexpr std::string_view L_AREA_ID = "L_AREA_ID"; + static constexpr std::string_view R_AREA_ID = "R_AREA_ID"; }; #endif // STREETCONVERTER_HPP diff --git a/plugins/navteq/navteq2osm_tag_parser.hpp b/plugins/navteq/navteq2osm_tag_parser.hpp index 8e1c036..8d1cec2 100644 --- a/plugins/navteq/navteq2osm_tag_parser.hpp +++ b/plugins/navteq/navteq2osm_tag_parser.hpp @@ -312,49 +312,6 @@ void add_here_speed_cat_tag(osmium::builder::TagListBuilder *builder, " is not valid."); } -/** - * \brief check if unit is imperial. area_id(Streets.dbf) -> - * govt_id(MtdArea.dbf) -> unit_measure(MtdCntryRef.dbf) \param area_id - * area_id \param area_govt_map maps area_ids to govt_codes \param cntry_map - * maps govt_codes to cntry_ref_types \return returns false if any of the - * areas contain metric units or if its unclear - */ -bool is_imperial(area_id_type area_id, - area_id_govt_code_map_type *area_govt_map, - cntry_ref_map_type *cntry_map) { - if (area_govt_map->find(area_id) != area_govt_map->end()) { - if (cntry_map->find(area_govt_map->at(area_id)) != cntry_map->end()) { - auto unit_measure = - cntry_map->at(area_govt_map->at(area_id)).unit_measure; - if (unit_measure == "E") { - return true; - } else if (unit_measure != "M") { - format_error("unit_measure in navteq data is invalid: '" + - unit_measure + "'"); - } - } - } - return false; -} - -/** - * \brief check if unit is imperial. area_id(Streets.dbf) -> - * govt_id(MtdArea.dbf) -> unit_measure(MtdCntryRef.dbf) \param l_area_id - * area_id on the left side of the link \param r_area_id area_id on the right - * side of the link \param area_govt_map maps area_ids to govt_codes \param - * cntry_map maps govt_codes to cntry_ref_types \return returns false if any - * of the areas contain metric units or if its unclear - */ -bool is_imperial(area_id_type l_area_id, area_id_type r_area_id, - area_id_govt_code_map_type *area_govt_map, - cntry_ref_map_type *cntry_map) { - if (is_imperial(l_area_id, area_govt_map, cntry_map)) - return true; - if (is_imperial(r_area_id, area_govt_map, cntry_map)) - return true; - return false; -} - void add_hazmat_tag(osmium::builder::TagListBuilder *builder, mod_val_type mod_val) { if (mod_val == 20) { // || mod_val == 21 diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index f366300..e9f97c6 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -74,8 +74,7 @@ const char *ROUTE = "ROUTE_TYPE"; const char *FOURWHLDR = "FOURWHLDR"; const char *PHYS_LANES = "PHYS_LANES"; const char *PUB_ACCESS = "PUB_ACCESS"; -const char *L_AREA_ID = "L_AREA_ID"; -const char *R_AREA_ID = "R_AREA_ID"; + const char *L_POSTCODE = "L_POSTCODE"; const char *R_POSTCODE = "R_POSTCODE"; const char *RAMP = "RAMP"; From 360b666ca9a9d15067fd33dc748f1e9513aa8a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 13:15:28 +0000 Subject: [PATCH 18/57] rfactoring --- plugins/navteq/converter/Converter.hpp | 12 +- plugins/navteq/converter/StreetConverter.cpp | 473 ++++++++++++++++++- plugins/navteq/converter/StreetConverter.hpp | 144 +++++- plugins/navteq/navteq2osm_tag_parser.hpp | 421 ----------------- plugins/navteq/navteq_mappings.hpp | 69 --- plugins/util.hpp | 41 +- 6 files changed, 625 insertions(+), 535 deletions(-) diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index bca7400..f88eb7b 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -51,9 +51,8 @@ class OGRLinearRing; class Converter { public: - Converter(const boost::filesystem::path &_executable_path) { - executable_path = _executable_path; - } + Converter(const boost::filesystem::path &_executable_path) + : executable_path(_executable_path) {} virtual ~Converter() {} virtual void convert(const std::vector &dirs, @@ -61,8 +60,6 @@ class Converter { void set_dummy_osm_object_attributes(osmium::OSMObject &obj); -protected: - // data structure to store admin boundary tags struct mtd_area_dataset { osmium::unsigned_object_id_type area_id; std::string admin_lvl; @@ -72,6 +69,9 @@ class Converter { std::vector> lang_code_2_area_name; }; +protected: + // data structure to store admin boundary tags + void build_relation_members( osmium::builder::RelationBuilder &builder, const std::vector &ext_osm_way_ids, @@ -171,7 +171,7 @@ class Converter { private: static std::map lang_code_map; - boost::filesystem::path &executable_path; + boost::filesystem::path executable_path; }; #endif // CONVERTER_HPP diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index a8db03d..ef078a1 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -49,12 +49,13 @@ std::map StreetConverter::process_alt_steets_route_types( DBFHandle alt_streets_handle = read_dbf_file(dir / ALT_STREETS_DBF); for (int i = 0; i < DBFGetRecordCount(alt_streets_handle); i++) { - if (dbf_get_string_by_field(alt_streets_handle, i, ROUTE).empty()) + if (dbf_get_string_by_field(alt_streets_handle, i, ROUTE.data()).empty()) continue; osmium::unsigned_object_id_type link_id = dbf_get_uint_by_field(alt_streets_handle, i, LINK_ID.data()); - ushort route_type = dbf_get_uint_by_field(alt_streets_handle, i, ROUTE); + ushort route_type = + dbf_get_uint_by_field(alt_streets_handle, i, ROUTE.data()); // try to emplace pair auto [insertion, inserted] = route_type_map.emplace(link_id, route_type); @@ -235,7 +236,8 @@ void StreetConverter::process_way_end_nodes( for (auto &dir : dirs) { // parse ramp names and refs - init_ramp_names(dir); + std::map> ramps_ref_map = + init_ramp_names(dir); auto path = dir / STREETS_SHP; auto ds = open_shape_file(path); @@ -258,7 +260,6 @@ void StreetConverter::process_way_end_nodes( } node_buffer.commit(); writer(std::move(node_buffer)); - g_ramps_ref_map.clear(); } } @@ -289,7 +290,7 @@ void StreetConverter::process_way_end_node( if (ramp != g_ramps_ref_map.end()) { if (ramp->second.find(0) != ramp->second.end()) { osmium::builder::TagListBuilder tglBuilder(builder); - tglBuilder.add_tag(HIGHWAY, "motorway_junction"); + tglBuilder.add_tag(HIGHWAY.data(), "motorway_junction"); tglBuilder.add_tag("ref", ramp->second[0]); tglBuilder.add_tag("name", to_camel_case_with_spaces(ramp->second[1])); } @@ -297,12 +298,17 @@ void StreetConverter::process_way_end_node( g_way_end_points_map.emplace(location, osm_id); } -void StreetConverter::init_ramp_names(const boost::filesystem::path &dir) { +std::map> +StreetConverter::init_ramp_names(const boost::filesystem::path &dir) { + + std::map> ramps_ref_map; // read junction names from alt_streets auto junctionMap = read_junction_names(dir / ALT_STREETS_DBF); // create location ramps map - parse_ramp_names(dir / STREETS_SHP, junctionMap); + parse_ramp_names(dir / STREETS_SHP, ramps_ref_map, junctionMap); + + return ramps_ref_map; } std::map @@ -327,6 +333,7 @@ StreetConverter::read_junction_names(const boost::filesystem::path &dbf_file) { void StreetConverter::parse_ramp_names( const boost::filesystem::path &shp_file, + std::map> &ramps_ref_map, const std::map &junctionNames) { auto ds = open_shape_file(shp_file); @@ -337,8 +344,8 @@ void StreetConverter::parse_ramp_names( int exitNameField = layer->FindFieldIndex(EXITNAME.data(), true); int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); int baseNameField = layer->FindFieldIndex(ST_NM_BASE.data(), true); - int directionField = layer->FindFieldIndex(DIR_TRAVEL, true); - int rampField = layer->FindFieldIndex(RAMP, true); + int directionField = layer->FindFieldIndex(DIR_TRAVEL.data(), true); + int rampField = layer->FindFieldIndex(RAMP.data(), true); for (auto &feat : *layer) { @@ -357,12 +364,12 @@ void StreetConverter::parse_ramp_names( std::string exitName = feat->GetFieldAsString(baseNameField); // add exit name - g_ramps_ref_map[location].emplace(0, exitName); + ramps_ref_map[location].emplace(0, exitName); // add junction name auto it = junctionNames.find(feat->GetFieldAsInteger(linkIdField)); if (it != junctionNames.end()) { - g_ramps_ref_map[location].emplace(1, it->second); + ramps_ref_map[location].emplace(1, it->second); } } } @@ -382,7 +389,7 @@ void StreetConverter::process_way( if (ogr_ls->getNumPoints() > 2) assert(node_ref_map.size() > 0); - uint64_t link_id = get_uint_from_feature(feat, LINK_ID.data()); + uint64_t link_id = get_uint_from_feature(feat, LINK_ID); auto it = z_level_map.find(link_id); if (it == z_level_map.end()) { @@ -484,7 +491,7 @@ uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, osmium::builder::TagListBuilder tl_builder(buf, builder); uint64_t link_id = parse_street_tags( - &tl_builder, feat, &g_cdms_map, &g_cnd_mod_map, &g_area_to_govt_code_map, + tl_builder, feat, &g_cdms_map, &g_cnd_mod_map, &g_area_to_govt_code_map, &g_cntry_ref_map, &g_mtd_area_map, &g_route_type_map, &g_hwys_ref_map, g_construction_set, debugMode); @@ -497,19 +504,19 @@ uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, } uint64_t StreetConverter::parse_street_tags( - osmium::builder::TagListBuilder *builder, OGRFeatureUniquePtr &f, + osmium::builder::TagListBuilder &builder, OGRFeatureUniquePtr &f, const std::multimap &cdms_map, const std::unordered_map> &cnd_mod_map, const std::map &area_govt_map, const std::map &cntry_map, - const std::map - mtd_area_map, + const std::map + &mtd_area_map, const std::map &route_type_map, const std::map> &names_map, const std::set &construction_set, bool debugMode) { - const char *link_id_s = get_field_from_feature(f, LINK_ID.data()); + const char *link_id_s = get_field_from_feature(f, LINK_ID); uint64_t link_id = std::stoul(link_id_s); bool ramp = parse_bool(get_field_from_feature(f, RAMP)); @@ -537,8 +544,8 @@ uint64_t StreetConverter::parse_street_tags( underConstruction); } - uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID.data()); - uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID.data()); + uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); + uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); // tags which apply to highways and ferry routes add_additional_restrictions(builder, link_id, l_area_id, r_area_id, cdms_map, cnd_mod_map, area_govt_map, cntry_map, @@ -546,20 +553,20 @@ uint64_t StreetConverter::parse_street_tags( // tag for debug purpose if (debugMode) { - builder->add_tag(LINK_ID, link_id_s); + builder.add_tag(LINK_ID.data(), link_id_s); add_here_speed_cat_tag(builder, f); if (parse_bool(get_field_from_feature(f, TOLLWAY))) - builder->add_tag("here:tollway", YES); + builder.add_tag("here:tollway", YES.data()); if (parse_bool(get_field_from_feature(f, URBAN))) - builder->add_tag("here:urban", YES); + builder.add_tag("here:urban", YES.data()); if (parse_bool(get_field_from_feature(f, CONTRACC))) - builder->add_tag("here:controll_access", YES); + builder.add_tag("here:controll_access", YES.data()); if (route_type) add_uint_tag(builder, "here:route_type", route_type); std::string func_class = get_field_from_feature(f, FUNC_CLASS); if (!func_class.empty()) - builder->add_tag("here:func_class", func_class.c_str()); + builder.add_tag("here:func_class", func_class.c_str()); add_uint_tag(builder, "here:area_code", get_area_code_l(f, mtd_area_map)); } @@ -567,14 +574,14 @@ uint64_t StreetConverter::parse_street_tags( } void StreetConverter::add_additional_restrictions( - osmium::builder::TagListBuilder *builder, uint64_t link_id, + osmium::builder::TagListBuilder &builder, uint64_t link_id, uint64_t l_area_id, uint64_t r_area_id, const std::multimap &cdms_map, const std::unordered_map> &cnd_mod_map, const std::map &area_govt_map, const std::map &cntry_map, - const std::map + const std::map &mtd_area_map) { if (cdms_map.empty() || cnd_mod_map.empty()) return; @@ -841,3 +848,417 @@ bool StreetConverter::is_imperial( } return false; } + +void StreetConverter::add_highway_tag( + osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, + ushort route_type, ushort func_class, + const std::map + &mtd_area_map, + const std::string &ref_name, bool underConstruction) { + + bool paved = parse_bool(get_field_from_feature(f, PAVED)); + bool motorized_allowed = is_motorized_allowed(f); + + std::string highwayTagName = HIGHWAY.data(); + + if (underConstruction) { + builder.add_tag(HIGHWAY.data(), CONSTRUCTION.data()); + highwayTagName = CONSTRUCTION.data(); + } + + if (!paved) { + if (!motorized_allowed) { + // unpaved + non-motorized => path + builder.add_tag(highwayTagName, PATH.data()); + } else { + // unpaved + motorized allowed => track + builder.add_tag(highwayTagName, TRACK.data()); + } + } else { + if (!motorized_allowed) { + // paved + non-motorized => footway + // it seems imposref_nameible to distinguish footways from cycle ways or + // pedestrian zones + builder.add_tag(highwayTagName, FOOTWAY.data()); + } else { + // paved + motorized allowed + bool controlled_access = parse_bool(get_field_from_feature(f, CONTRACC)); + bool urban = parse_bool(get_field_from_feature(f, URBAN)); + bool ramp = parse_bool(get_field_from_feature(f, RAMP)); + uint area_code_1 = get_area_code_l(f, mtd_area_map); + + if (controlled_access) { + // controlled_access => motorway + if (ramp) + builder.add_tag(highwayTagName, MOTORWAY_LINK.data()); + else + builder.add_tag(highwayTagName, MOTORWAY.data()); + } else if (func_class || route_type) { + std::string_view hwy_value = + get_hwy_value(route_type, func_class, area_code_1, ref_name, urban); + if (!hwy_value.empty()) { + builder.add_tag(highwayTagName, hwy_value.data()); + } else { + std::cerr << "ignoring highway_level'" << std::to_string(route_type) + << "' for " << area_code_1 << std::endl; + } + } else { + std::cerr << " highway misses route_type and func_class! " << std::endl; + } + } + } +} + +std::string_view StreetConverter::get_hwy_value(ushort route_type, + ushort func_class, + uint area_code_1, + const std::string &ref_name, + bool urban) { + /* some exceptional cases for better route type parsing */ + if (area_code_1 == 2 && route_type == 4) { /*"FRA"*/ + /* Too many different highways have route type 4 + * so we also take functional class into consideration */ + if (func_class == 2) + return PRIMARY; + else if (func_class == 3) + return SECONDARY; + else if (func_class > 3) + return TERTIARY; + } else if (area_code_1 == 5 && route_type == 3) { /*"BEL"*/ + /* N# and N## is like PRIMARY + * N### SECONDARY + * N#### TERTIARY */ + uint hwy_num = get_number_after(ref_name, "N"); + if (hwy_num > 999) + return TERTIARY; + if (hwy_num > 99) + return SECONDARY; + } else if (area_code_1 == 9) { /*"AUT"*/ + if (route_type == 4) { + return PRIMARY; // bundesstrasse + } else if (route_type == 5) { + return SECONDARY; // landesstrasse + } + } else if (area_code_1 == 23 && route_type == 2) { /*"IRL"*/ + /* N## is TRUNK if ## smaller 50 otherwise PRIMARY */ + uint hwy_num = get_number_after(ref_name, "N"); + if (hwy_num > 0 && hwy_num < 50) + return TRUNK; + } else if (area_code_1 == 109 || + area_code_1 == 110 /*UK - Wales*/ /*UK - England*/ + || area_code_1 == 112 || + area_code_1 == 22) { /*UK - Scotland*/ /*UK - Northern Ireland*/ + /* Differ between white and green shield A-Roads */ + if (route_type == 2) { + if (func_class == 2 || func_class == 1) + return TRUNK; + else + return PRIMARY; + } else if (route_type == 3 && func_class == 4) { + return SECONDARY; + } + } else if (area_code_1 == 107) { // SWE + if (func_class == 1 && route_type == 1) + return TRUNK; // func_class 1 und not controlled + } + + uint apply_func_class = func_class; + if (apply_func_class > 4 && urban) { + apply_func_class++; + } else if (func_class == 2 && (route_type == 3 || route_type == 2)) { + return PRIMARY; // primary + } + + const auto &hwy_vector = HWY_FUNC_CLASS_MAP.contains(area_code_1) + ? HWY_FUNC_CLASS_MAP.at(area_code_1) + : DEFAULT_HWY_FUNC_TYPE; + + /* default case */ + return hwy_vector.at(apply_func_class); +} + +bool StreetConverter::is_motorized_allowed(const OGRFeatureUniquePtr &f) { + if (parse_bool(get_field_from_feature(f, AR_AUTO))) + return true; + if (parse_bool(get_field_from_feature(f, AR_BUS))) + return true; + if (parse_bool(get_field_from_feature(f, AR_TAXIS))) + return true; + if (parse_bool(get_field_from_feature(f, AR_TRUCKS))) + return true; + if (parse_bool(get_field_from_feature(f, AR_DELIV))) + return true; + if (parse_bool(get_field_from_feature(f, AR_EMERVEH))) + return true; + if (parse_bool(get_field_from_feature(f, AR_MOTORCYCLES))) + return true; + + return false; +} + +void StreetConverter::add_hazmat_tag(osmium::builder::TagListBuilder &builder, + uint64_t mod_val) { + if (mod_val == 20) { // || mod_val == 21 + builder.add_tag("hazmat", "no"); + } else if (mod_val == 22) { + builder.add_tag("hazmat:water", "no"); + } else if (mod_val == 24) { + builder.add_tag("hazmat:B", "no"); + } else if (mod_val == 28) { + builder.add_tag("hazmat:C", "no"); + } else if (mod_val == 32) { + builder.add_tag("hazmat:D", "no"); + } else if (mod_val == 34) { + builder.add_tag("hazmat:E", "no"); + } else if (mod_val == 23) { + /* 23 = Explosive and Flammable */ + } else { + /** + * Do nothing for the residual values, + * which do not occur and/or have no proper OSM tagging equivalent + * 1 = Explosives + * 2 = Gas + * 3 = Flammable + * 4 = Flammable solid/Combustible + * 5 = Organic + * 6 = Poison + * 7 = Radioactive + * 8 = Corrosive + * 9 = Other + */ + BOOST_LOG_TRIVIAL(error) << "Hazardous material value " << mod_val + << " hasn't been parsed!" << std::endl; + } +} + +std::string StreetConverter::add_highway_name_tags( + osmium::builder::TagListBuilder &builder, + const std::map> &names_map, + uint64_t link_id, bool ramp) { + std::string ref_tag; + + auto it = names_map.find(link_id); + if (it != names_map.end()) { + auto &highway_names_vector = it->second; + std::string street_name; + std::string int_ref_tag; + std::string nat_ref_tag; + + for (auto highwayName : highway_names_vector) { + if (highwayName.first == 0) { + street_name = highwayName.second; + } else if (highwayName.first == 1) { + int_ref_tag = highwayName.second; + } else if (highwayName.first > 1) { + nat_ref_tag = highwayName.second; + } + } + + if (!nat_ref_tag.empty()) + ref_tag = nat_ref_tag; + else + ref_tag = int_ref_tag; + + if (!street_name.empty() && !ramp) + builder.add_tag("name", to_camel_case_with_spaces(street_name)); + if (!ref_tag.empty()) // national ref (Autobahn) + builder.add_tag("ref", ref_tag); + if (!int_ref_tag.empty()) // international ref (European street) + builder.add_tag("int_ref", int_ref_tag); + if (!nat_ref_tag.empty()) // national ref (European street) + builder.add_tag("nat_ref", nat_ref_tag); + } + + return ref_tag; +} + +void StreetConverter::add_highway_tags( + osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, + ushort route_type, + const std::map + &mtd_area_map, + const std::string &ref_name, bool underConstruction) { + + ushort func_class = 0; + std::string func_class_s = get_field_from_feature(f, FUNC_CLASS); + if (!func_class_s.empty()) + func_class = get_uint_from_feature(f, FUNC_CLASS); + + add_highway_tag(builder, f, route_type, func_class, mtd_area_map, ref_name, + underConstruction); + + add_one_way_tag(builder, get_field_from_feature(f, DIR_TRAVEL)); + add_access_tags(builder, f); + add_maxspeed_tags(builder, f); + add_lanes_tag(builder, f); + add_postcode_tag(builder, f); + + if (parse_bool(get_field_from_feature(f, PAVED))) + builder.add_tag("surface", "paved"); + if (parse_bool(get_field_from_feature(f, BRIDGE))) + builder.add_tag("bridge", YES.data()); + if (parse_bool(get_field_from_feature(f, TUNNEL))) + builder.add_tag("tunnel", YES.data()); + if (parse_bool(get_field_from_feature(f, TOLLWAY))) + builder.add_tag("toll", YES.data()); + if (parse_bool(get_field_from_feature(f, ROUNDABOUT))) + builder.add_tag("junction", "roundabout"); + if (parse_bool(get_field_from_feature(f, FOURWHLDR))) + builder.add_tag("4wd_only", YES.data()); +} + +void StreetConverter::add_one_way_tag(osmium::builder::TagListBuilder &builder, + const char *value) { + if (!strcmp(value, "F")) // F --> FROM reference node + builder.add_tag("oneway", YES.data()); + else if (!strcmp(value, "T")) // T --> TO reference node + builder.add_tag("oneway", "-1"); // todo reverse way instead using "-1" + else if (!strcmp(value, "B")) // B --> BOTH ways are allowed + return; + throw( + format_error("value '" + std::string(value) + "' for oneway not valid")); +} + +void StreetConverter::add_access_tags(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f) { + bool automobile_allowed = parse_bool(get_field_from_feature(f, AR_AUTO)); + if (!automobile_allowed) + builder.add_tag("motorcar", NO.data()); + if (!parse_bool(get_field_from_feature(f, AR_BUS))) + builder.add_tag("bus", NO.data()); + if (!parse_bool(get_field_from_feature(f, AR_TAXIS))) + builder.add_tag("taxi", NO.data()); + // if (! parse_bool(get_field_from_feature(f, AR_CARPOOL))) + // builder->add_tag("hov", NO); + if (!parse_bool(get_field_from_feature(f, AR_PEDESTRIANS))) + builder.add_tag("foot", NO.data()); + if (!parse_bool(get_field_from_feature(f, AR_TRUCKS))) { + // truck access handling: + if (!parse_bool(get_field_from_feature(f, AR_DELIV))) + builder.add_tag( + "hgv", + NO.data()); // no truck + no delivery => hgv not allowed at all + else if (!automobile_allowed) + builder.add_tag("access", + "delivery"); // no automobile + no truck but delivery + // => general access is 'delivery' + else if (automobile_allowed) + builder.add_tag("hgv", "delivery"); // automobile generally allowed => + // only truck is 'delivery' + } + if (!parse_bool(get_field_from_feature(f, AR_EMERVEH))) + builder.add_tag("emergency", NO.data()); + if (!parse_bool(get_field_from_feature(f, AR_MOTORCYCLES))) + builder.add_tag("motorcycle", NO.data()); + if (!parse_bool(get_field_from_feature(f, PUB_ACCESS)) || + parse_bool(get_field_from_feature(f, PRIVATE))) { + builder.add_tag("access", "private"); + } else if (!parse_bool(get_field_from_feature(f, AR_THROUGH_TRAFFIC))) { + builder.add_tag("access", "destination"); + } +} + +void StreetConverter::add_ferry_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f) { + const char *ferry = get_field_from_feature(f, FERRY); + builder.add_tag("route", "ferry"); + if (!strcmp(ferry, "B")) { + if (only_pedestrians(f)) { + builder.add_tag("foot", YES.data()); + } else { + builder.add_tag("foot", + parse_bool(get_field_from_feature(f, AR_PEDESTRIANS)) + ? YES.data() + : NO.data()); + builder.add_tag("motorcar", parse_bool(get_field_from_feature(f, AR_AUTO)) + ? YES.data() + : NO.data()); + } + + } else if (!strcmp(ferry, "R")) { + builder.add_tag("railway", "ferry"); + } else + throw(format_error("value '" + std::string(ferry) + "' for " + + std::string(FERRY) + " not valid")); +} + +void StreetConverter::add_maxspeed_tags( + osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f) { + char *from_speed_limit_s = strdup(get_field_from_feature(f, FR_SPEED_LIMIT)); + char *to_speed_limit_s = strdup(get_field_from_feature(f, TO_SPEED_LIMIT)); + + uint from_speed_limit = get_uint_from_feature(f, FR_SPEED_LIMIT); + uint to_speed_limit = get_uint_from_feature(f, TO_SPEED_LIMIT); + + if (from_speed_limit >= 1000 || to_speed_limit >= 1000) + throw(format_error("from_speed_limit='" + std::string(from_speed_limit_s) + + "' or to_speed_limit='" + std::string(to_speed_limit_s) + + "' is not valid (>= 1000)")); + + // 998 is a ramp without speed limit information + if (from_speed_limit == 998 || to_speed_limit == 998) + return; + + // 999 means no speed limit at all + const char *from = from_speed_limit == 999 ? "none" : from_speed_limit_s; + const char *to = to_speed_limit == 999 ? "none" : to_speed_limit_s; + + if (from_speed_limit != 0 && to_speed_limit != 0) { + if (from_speed_limit != to_speed_limit) { + builder.add_tag("maxspeed:forward", from); + builder.add_tag("maxspeed:backward", to); + } else { + builder.add_tag("maxspeed", from); + } + } else if (from_speed_limit != 0 && to_speed_limit == 0) { + builder.add_tag("maxspeed", from); + } else if (from_speed_limit == 0 && to_speed_limit != 0) { + builder.add_tag("maxspeed", to); + } + + free(from_speed_limit_s); + free(to_speed_limit_s); +} + +void StreetConverter::add_lanes_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f) { + const char *number_of_physical_lanes = get_field_from_feature(f, PHYS_LANES); + if (strcmp(number_of_physical_lanes, "0")) + builder.add_tag("lanes", number_of_physical_lanes); +} + +void StreetConverter::add_postcode_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f) { + std::string l_postcode = get_field_from_feature(f, L_POSTCODE); + std::string r_postcode = get_field_from_feature(f, R_POSTCODE); + + if (l_postcode.empty() && r_postcode.empty()) + return; + + std::string postcode; + if (l_postcode == r_postcode) + postcode = l_postcode; + else + postcode = l_postcode + ";" + r_postcode; + + builder.add_tag("addr:postcode", postcode); +} + +bool StreetConverter::only_pedestrians(const OGRFeatureUniquePtr &f) { + if (strcmp(get_field_from_feature(f, AR_PEDESTRIANS), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_AUTO), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_BUS), "Y")) + return false; + // if (! strcmp(get_field_from_feature(f, AR_CARPOOL),"Y")) return false; + if (!strcmp(get_field_from_feature(f, AR_EMERVEH), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_MOTORCYCLES), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_TAXIS), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_THROUGH_TRAFFIC), "Y")) + return false; + return true; +} \ No newline at end of file diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index f11f8c7..f6c12dc 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -109,16 +109,20 @@ class StreetConverter : public Converter { osmium::memory::Buffer &node_buffer); // ramp names - void init_ramp_names(const boost::filesystem::path &dir); + std::map> + init_ramp_names(const boost::filesystem::path &dir); std::map read_junction_names(const boost::filesystem::path &dbf_file); - void parse_ramp_names(const boost::filesystem::path &shp_file, - const std::map &junctionNames); + void parse_ramp_names( + const boost::filesystem::path &shp_file, + std::map> &ramps_ref_map, + const std::map &junctionNames); void process_way( OGRFeatureUniquePtr &feat, const std::map> &z_level_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); + void middle_points_preparation( OGRLineString *ogr_ls, std::map &node_ref_map, @@ -134,28 +138,28 @@ class StreetConverter : public Converter { osmium::memory::Buffer &buf, short z_level); uint64_t parse_street_tags( - osmium::builder::TagListBuilder *builder, OGRFeatureUniquePtr &f, + osmium::builder::TagListBuilder &builder, OGRFeatureUniquePtr &f, const std::multimap &cdms_map, const std::unordered_map> &cnd_mod_map, const std::map &area_govt_map, const std::map &cntry_map, - const std::map - mtd_area_map, + const std::map &mtd_area_map, const std::map &route_type_map, const std::map> &names_map, const std::set &construction_set, bool debugMode); void add_additional_restrictions( - osmium::builder::TagListBuilder *builder, uint64_t link_id, + osmium::builder::TagListBuilder &builder, uint64_t link_id, uint64_t l_area_id, uint64_t r_area_id, const std::multimap &cdms_map, const std::unordered_map> &cnd_mod_map, const std::map &area_govt_map, const std::map &cntry_map, - const std::map - &mtd_area_map); + const std::map &mtd_area_map); void process_end_point( bool first, short z_lvl, OGRLineString *ogr_ls, @@ -189,6 +193,55 @@ class StreetConverter : public Converter { const std::map &area_govt_map, const std::map &cntry_map); + bool is_motorized_allowed(const OGRFeatureUniquePtr &f); + + void + add_highway_tags(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f, ushort route_type, + const std::map &mtd_area_map, + const std::string &ref_name, bool underConstruction); + + void + add_highway_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f, ushort route_type, + ushort func_class, + const std::map &mtd_area_map, + const std::string &ref_name, bool underConstruction); + + std::string_view get_hwy_value(ushort route_type, ushort func_class, + uint area_code_1, const std::string &ref_name, + bool urban); + + void add_hazmat_tag(osmium::builder::TagListBuilder &builder, + uint64_t mod_val); + + std::string add_highway_name_tags( + osmium::builder::TagListBuilder &builder, + const std::map> &names_map, + uint64_t link_id, bool ramp); + + void add_ferry_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f); + + void add_one_way_tag(osmium::builder::TagListBuilder &builder, + const char *value); + + void add_access_tags(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f); + + void add_maxspeed_tags(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f); + + void add_lanes_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f); + + void add_postcode_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f); + + bool only_pedestrians(const OGRFeatureUniquePtr &f); + // CndMod types (CM) static constexpr std::string_view CM_MOD_TYPE = "MOD_TYPE"; static constexpr std::string_view CM_MOD_VAL = "MOD_VAL"; @@ -220,6 +273,79 @@ class StreetConverter : public Converter { static constexpr std::string_view L_AREA_ID = "L_AREA_ID"; static constexpr std::string_view R_AREA_ID = "R_AREA_ID"; + + static constexpr std::string_view ROUTE = "ROUTE_TYPE"; + static constexpr std::string_view FUNC_CLASS = "FUNC_CLASS"; + static constexpr std::string_view SPEED_CAT = "SPEED_CAT"; + static constexpr std::string_view FR_SPEED_LIMIT = "FR_SPD_LIM"; + static constexpr std::string_view TO_SPEED_LIMIT = "TO_SPD_LIM"; + static constexpr std::string_view DIR_TRAVEL = "DIR_TRAVEL"; + static constexpr std::string_view AR_AUTO = "AR_AUTO"; + static constexpr std::string_view AR_BUS = "AR_BUS"; + static constexpr std::string_view AR_TAXIS = "AR_TAXIS"; + // static constexpr std::string_view AR_CARPOOL = "AR_CARPOOL"; + static constexpr std::string_view AR_PEDESTRIANS = "AR_PEDEST"; + static constexpr std::string_view AR_TRUCKS = "AR_TRUCKS"; + static constexpr std::string_view AR_DELIV = "AR_DELIV"; + static constexpr std::string_view AR_EMERVEH = "AR_EMERVEH"; + static constexpr std::string_view AR_MOTORCYCLES = "AR_MOTOR"; + static constexpr std::string_view AR_THROUGH_TRAFFIC = "AR_TRAFF"; + static constexpr std::string_view PAVED = "PAVED"; + static constexpr std::string_view PRIVATE = "PRIVATE"; + static constexpr std::string_view BRIDGE = "BRIDGE"; + static constexpr std::string_view TUNNEL = "TUNNEL"; + static constexpr std::string_view TOLLWAY = "TOLLWAY"; + static constexpr std::string_view CONTRACC = "CONTRACC"; + static constexpr std::string_view ROUNDABOUT = "ROUNDABOUT"; + static constexpr std::string_view FERRY = "FERRY_TYPE"; + static constexpr std::string_view URBAN = "URBAN"; + + static constexpr std::string_view FOURWHLDR = "FOURWHLDR"; + static constexpr std::string_view PHYS_LANES = "PHYS_LANES"; + static constexpr std::string_view PUB_ACCESS = "PUB_ACCESS"; + + static constexpr std::string_view L_POSTCODE = "L_POSTCODE"; + static constexpr std::string_view R_POSTCODE = "R_POSTCODE"; + static constexpr std::string_view RAMP = "RAMP"; + + // highway OSM tags + static constexpr std::string_view MOTORWAY = "motorway"; + static constexpr std::string_view MOTORWAY_LINK = "motorway_link"; + static constexpr std::string_view TRUNK = "trunk"; + static constexpr std::string_view PRIMARY = "primary"; + static constexpr std::string_view PRIMARY_LINK = "primary_link"; + static constexpr std::string_view SECONDARY = "secondary"; + static constexpr std::string_view SECONDARY_LINK = "secondary_link"; + static constexpr std::string_view TERTIARY = "tertiary"; + static constexpr std::string_view UNCLASSIFIED = "unclassified"; + static constexpr std::string_view RESIDENTIAL = "residential"; + static constexpr std::string_view TRACK = "track"; + static constexpr std::string_view PATH = "path"; + static constexpr std::string_view FOOTWAY = "footway"; + static constexpr std::string_view HIGHWAY = "highway"; + static constexpr std::string_view CONSTRUCTION = "construction"; + + // higway classification + const std::vector DEFAULT_HWY_FUNC_TYPE = { + "", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}; + + std::map> const HWY_FUNC_CLASS_MAP = { + /* Applied with functional classes: + * 1, 2, 3, 4, 5 + + * rural, 5 + urban */ + {0 /*"DEFAULT"*/, DEFAULT_HWY_FUNC_TYPE}, + {3 /*"GER"*/, + {"", PRIMARY, SECONDARY, TERTIARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, + {8 /*"CHE"*/, + {"", PRIMARY, SECONDARY, TERTIARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, + {108 /*"DEN"*/, + {"", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, + RESIDENTIAL}}, + {107 /*"SWE"*/, + {"", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, + RESIDENTIAL}}, + {9 /*"AUT"*/, + {"", PRIMARY, PRIMARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}}; }; #endif // STREETCONVERTER_HPP diff --git a/plugins/navteq/navteq2osm_tag_parser.hpp b/plugins/navteq/navteq2osm_tag_parser.hpp index 8d1cec2..a9a0cb0 100644 --- a/plugins/navteq/navteq2osm_tag_parser.hpp +++ b/plugins/navteq/navteq2osm_tag_parser.hpp @@ -4,10 +4,6 @@ #include #include -#include "navteq_mappings.hpp" -#include "navteq_types.hpp" -#include "navteq_util.hpp" - int ctr = 0; bool fits_street_ref(const std::string &st_name) { @@ -28,275 +24,9 @@ bool fits_street_ref(const std::string &st_name) { return number_started; } -uint get_number_after(const std::string &str, const char *start_str) { - if (!str.starts_with(start_str)) - return 0; /* doesn't start with start_str */ - - /* Get number string after start_str until first non-digit appears */ - std::string end_str = str.substr(strlen(start_str)); - std::string number_str; - for (auto it = end_str.begin(); it != end_str.end(); ++it) { - if (!std::isdigit(*it)) { - /* break because B107a should return 107*/ - break; - } - number_str += *it; - } - - try { - return std::stoul(number_str); - } catch (const std::invalid_argument &) { - return 0; - } -} - -bool is_motorized_allowed(OGRFeatureUniquePtr &f) { - if (parse_bool(get_field_from_feature(f, AR_AUTO))) - return true; - if (parse_bool(get_field_from_feature(f, AR_BUS))) - return true; - if (parse_bool(get_field_from_feature(f, AR_TAXIS))) - return true; - if (parse_bool(get_field_from_feature(f, AR_TRUCKS))) - return true; - if (parse_bool(get_field_from_feature(f, AR_DELIV))) - return true; - if (parse_bool(get_field_from_feature(f, AR_EMERVEH))) - return true; - if (parse_bool(get_field_from_feature(f, AR_MOTORCYCLES))) - return true; - - return false; -} - -std::vector -get_hwy_vector(const std::map> &HWY_TYPE_MAP, - uint area_code_1) { - auto it = HWY_TYPE_MAP.find(area_code_1); - if (it != HWY_TYPE_MAP.end()) { - return it->second; - } else { - return DEFAULT_HWY_FUNC_TYPE; - } -} - -std::string get_hwy_value(ushort route_type, ushort func_class, - uint area_code_1, const std::string &ref_name, - bool urban) { - /* some exceptional cases for better route type parsing */ - if (area_code_1 == 2 && route_type == 4) { /*"FRA"*/ - /* Too many different highways have route type 4 - * so we also take functional class into consideration */ - if (func_class == 2) - return PRIMARY; - else if (func_class == 3) - return SECONDARY; - else if (func_class > 3) - return TERTIARY; - } else if (area_code_1 == 5 && route_type == 3) { /*"BEL"*/ - /* N# and N## is like PRIMARY - * N### SECONDARY - * N#### TERTIARY */ - uint hwy_num = get_number_after(ref_name, "N"); - if (hwy_num > 999) - return TERTIARY; - if (hwy_num > 99) - return SECONDARY; - } else if (area_code_1 == 9) { /*"AUT"*/ - if (route_type == 4) { - return PRIMARY; // bundesstrasse - } else if (route_type == 5) { - return SECONDARY; // landesstrasse - } - } else if (area_code_1 == 23 && route_type == 2) { /*"IRL"*/ - /* N## is TRUNK if ## smaller 50 otherwise PRIMARY */ - uint hwy_num = get_number_after(ref_name, "N"); - if (hwy_num > 0 && hwy_num < 50) - return TRUNK; - } else if (area_code_1 == 109 || - area_code_1 == 110 /*UK - Wales*/ /*UK - England*/ - || area_code_1 == 112 || - area_code_1 == 22) { /*UK - Scotland*/ /*UK - Northern Ireland*/ - /* Differ between white and green shield A-Roads */ - if (route_type == 2) { - if (func_class == 2 || func_class == 1) - return TRUNK; - else - return PRIMARY; - } else if (route_type == 3 && func_class == 4) { - return SECONDARY; - } - } else if (area_code_1 == 107) { // SWE - if (func_class == 1 && route_type == 1) - return TRUNK; // func_class 1 und not controlled - } - - uint apply_func_class = func_class; - if (apply_func_class > 4 && urban) { - apply_func_class++; - } else if (func_class == 2 && (route_type == 3 || route_type == 2)) { - return PRIMARY; // primary - } - - /* default case */ - return get_hwy_vector(HWY_FUNC_CLASS_MAP, area_code_1).at(apply_func_class); -} - -void add_highway_tag(osmium::builder::TagListBuilder *builder, - OGRFeatureUniquePtr &f, ushort route_type, - ushort func_class, mtd_area_map_type *mtd_area_map, - const std::string &ref_name, bool underConstruction) { - - bool paved = parse_bool(get_field_from_feature(f, PAVED)); - bool motorized_allowed = is_motorized_allowed(f); - - std::string highwayTagName = HIGHWAY; - - if (underConstruction) { - builder->add_tag(HIGHWAY, CONSTRUCTION); - highwayTagName = CONSTRUCTION; - } - - if (!paved) { - if (!motorized_allowed) { - // unpaved + non-motorized => path - builder->add_tag(highwayTagName, PATH); - } else { - // unpaved + motorized allowed => track - builder->add_tag(highwayTagName, TRACK); - } - } else { - if (!motorized_allowed) { - // paved + non-motorized => footway - // it seems imposref_nameible to distinguish footways from cycle ways or - // pedestrian zones - builder->add_tag(highwayTagName, FOOTWAY); - } else { - // paved + motorized allowed - bool controlled_access = parse_bool(get_field_from_feature(f, CONTRACC)); - bool urban = parse_bool(get_field_from_feature(f, URBAN)); - bool ramp = parse_bool(get_field_from_feature(f, RAMP)); - uint area_code_1 = get_area_code_l(f, mtd_area_map); - - if (controlled_access) { - // controlled_access => motorway - if (ramp) - builder->add_tag(highwayTagName, MOTORWAY_LINK); - else - builder->add_tag(highwayTagName, MOTORWAY); - } else if (func_class || route_type) { - std::string hwy_value = - get_hwy_value(route_type, func_class, area_code_1, ref_name, urban); - if (!hwy_value.empty()) { - builder->add_tag(highwayTagName, hwy_value); - } else { - std::cerr << "ignoring highway_level'" << std::to_string(route_type) - << "' for " << area_code_1 << std::endl; - } - } else { - std::cerr << " highway misses route_type and func_class! " << std::endl; - } - } - } -} - -const char *parse_one_way_tag(const char *value) { - if (!strcmp(value, "F")) // F --> FROM reference node - return YES; - else if (!strcmp(value, "T")) // T --> TO reference node - return "-1"; // todo reverse way instead using "-1" - else if (!strcmp(value, "B")) // B --> BOTH ways are allowed - return nullptr; - throw( - format_error("value '" + std::string(value) + "' for oneway not valid")); -} - -void add_one_way_tag(osmium::builder::TagListBuilder *builder, - const char *value) { - const char *one_way = "oneway"; - const char *parsed_value = parse_one_way_tag(value); - if (parsed_value) - builder->add_tag(one_way, parsed_value); -} - -void add_access_tags(osmium::builder::TagListBuilder *builder, - OGRFeatureUniquePtr &f) { - bool automobile_allowed = parse_bool(get_field_from_feature(f, AR_AUTO)); - if (!automobile_allowed) - builder->add_tag("motorcar", NO); - if (!parse_bool(get_field_from_feature(f, AR_BUS))) - builder->add_tag("bus", NO); - if (!parse_bool(get_field_from_feature(f, AR_TAXIS))) - builder->add_tag("taxi", NO); - // if (! parse_bool(get_field_from_feature(f, AR_CARPOOL))) - // builder->add_tag("hov", NO); - if (!parse_bool(get_field_from_feature(f, AR_PEDESTRIANS))) - builder->add_tag("foot", NO); - if (!parse_bool(get_field_from_feature(f, AR_TRUCKS))) { - // truck access handling: - if (!parse_bool(get_field_from_feature(f, AR_DELIV))) - builder->add_tag("hgv", - NO); // no truck + no delivery => hgv not allowed at all - else if (!automobile_allowed) - builder->add_tag("access", - "delivery"); // no automobile + no truck but delivery - // => general access is 'delivery' - else if (automobile_allowed) - builder->add_tag("hgv", "delivery"); // automobile generally allowed => - // only truck is 'delivery' - } - if (!parse_bool(get_field_from_feature(f, AR_EMERVEH))) - builder->add_tag("emergency", NO); - if (!parse_bool(get_field_from_feature(f, AR_MOTORCYCLES))) - builder->add_tag("motorcycle", NO); - if (!parse_bool(get_field_from_feature(f, PUB_ACCESS)) || - parse_bool(get_field_from_feature(f, PRIVATE))) { - builder->add_tag("access", "private"); - } else if (!parse_bool(get_field_from_feature(f, AR_THROUGH_TRAFFIC))) { - builder->add_tag("access", "destination"); - } -} - /** * \brief adds maxspeed tag */ -void add_maxspeed_tags(osmium::builder::TagListBuilder *builder, - OGRFeatureUniquePtr &f) { - char *from_speed_limit_s = strdup(get_field_from_feature(f, FR_SPEED_LIMIT)); - char *to_speed_limit_s = strdup(get_field_from_feature(f, TO_SPEED_LIMIT)); - - uint from_speed_limit = get_uint_from_feature(f, FR_SPEED_LIMIT); - uint to_speed_limit = get_uint_from_feature(f, TO_SPEED_LIMIT); - - if (from_speed_limit >= 1000 || to_speed_limit >= 1000) - throw(format_error("from_speed_limit='" + std::string(from_speed_limit_s) + - "' or to_speed_limit='" + std::string(to_speed_limit_s) + - "' is not valid (>= 1000)")); - - // 998 is a ramp without speed limit information - if (from_speed_limit == 998 || to_speed_limit == 998) - return; - - // 999 means no speed limit at all - const char *from = from_speed_limit == 999 ? "none" : from_speed_limit_s; - const char *to = to_speed_limit == 999 ? "none" : to_speed_limit_s; - - if (from_speed_limit != 0 && to_speed_limit != 0) { - if (from_speed_limit != to_speed_limit) { - builder->add_tag("maxspeed:forward", from); - builder->add_tag("maxspeed:backward", to); - } else { - builder->add_tag("maxspeed", from); - } - } else if (from_speed_limit != 0 && to_speed_limit == 0) { - builder->add_tag("maxspeed", from); - } else if (from_speed_limit == 0 && to_speed_limit != 0) { - builder->add_tag("maxspeed", to); - } - - free(from_speed_limit_s); - free(to_speed_limit_s); -} /** * \brief adds here:speed_cat tag @@ -312,64 +42,10 @@ void add_here_speed_cat_tag(osmium::builder::TagListBuilder *builder, " is not valid."); } -void add_hazmat_tag(osmium::builder::TagListBuilder *builder, - mod_val_type mod_val) { - if (mod_val == 20) { // || mod_val == 21 - builder->add_tag("hazmat", "no"); - } else if (mod_val == 22) { - builder->add_tag("hazmat:water", "no"); - } else if (mod_val == 24) { - builder->add_tag("hazmat:B", "no"); - } else if (mod_val == 28) { - builder->add_tag("hazmat:C", "no"); - } else if (mod_val == 32) { - builder->add_tag("hazmat:D", "no"); - } else if (mod_val == 34) { - builder->add_tag("hazmat:E", "no"); - } else if (mod_val == 23) { - /* 23 = Explosive and Flammable */ - } else { - /** - * Do nothing for the residual values, - * which do not occur and/or have no proper OSM tagging equivalent - * 1 = Explosives - * 2 = Gas - * 3 = Flammable - * 4 = Flammable solid/Combustible - * 5 = Organic - * 6 = Poison - * 7 = Radioactive - * 8 = Corrosive - * 9 = Other - */ - std::cerr << "Hazardous material value " << mod_val - << " hasn't been parsed!" << std::endl; - } -} - /** * \brief adds maxheight, maxwidth, maxlength, maxweight and maxaxleload tags. */ -bool only_pedestrians(OGRFeatureUniquePtr &f) { - if (strcmp(get_field_from_feature(f, AR_PEDESTRIANS), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_AUTO), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_BUS), "Y")) - return false; - // if (! strcmp(get_field_from_feature(f, AR_CARPOOL),"Y")) return false; - if (!strcmp(get_field_from_feature(f, AR_EMERVEH), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_MOTORCYCLES), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_TAXIS), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_THROUGH_TRAFFIC), "Y")) - return false; - return true; -} - void add_ferry_tag(osmium::builder::TagListBuilder *builder, OGRFeatureUniquePtr &f) { const char *ferry = get_field_from_feature(f, FERRY); @@ -393,103 +69,6 @@ void add_ferry_tag(osmium::builder::TagListBuilder *builder, std::string(FERRY) + " not valid")); } -void add_lanes_tag(osmium::builder::TagListBuilder *builder, - OGRFeatureUniquePtr &f) { - const char *number_of_physical_lanes = get_field_from_feature(f, PHYS_LANES); - if (strcmp(number_of_physical_lanes, "0")) - builder->add_tag("lanes", number_of_physical_lanes); -} - -void add_postcode_tag(osmium::builder::TagListBuilder *builder, - OGRFeatureUniquePtr &f) { - std::string l_postcode = get_field_from_feature(f, L_POSTCODE); - std::string r_postcode = get_field_from_feature(f, R_POSTCODE); - - if (l_postcode.empty() && r_postcode.empty()) - return; - - std::string postcode; - if (l_postcode == r_postcode) - postcode = l_postcode; - else - postcode = l_postcode + ";" + r_postcode; - - builder->add_tag("addr:postcode", postcode); -} - -std::string add_highway_name_tags(osmium::builder::TagListBuilder *builder, - link_id_to_names_map *names_map, - link_id_type link_id, bool ramp) { - std::string ref_tag; - - auto it = names_map->find(link_id); - if (it != names_map->end()) { - auto &highway_names_vector = it->second; - std::string street_name; - std::string int_ref_tag; - std::string nat_ref_tag; - - for (auto highwayName : highway_names_vector) { - if (highwayName.first == 0) { - street_name = highwayName.second; - } else if (highwayName.first == 1) { - int_ref_tag = highwayName.second; - } else if (highwayName.first > 1) { - nat_ref_tag = highwayName.second; - } - } - - if (!nat_ref_tag.empty()) - ref_tag = nat_ref_tag; - else - ref_tag = int_ref_tag; - - if (!street_name.empty() && !ramp) - builder->add_tag("name", to_camel_case_with_spaces(street_name)); - if (!ref_tag.empty()) // national ref (Autobahn) - builder->add_tag("ref", ref_tag); - if (!int_ref_tag.empty()) // international ref (European street) - builder->add_tag("int_ref", int_ref_tag); - if (!nat_ref_tag.empty()) // national ref (European street) - builder->add_tag("nat_ref", nat_ref_tag); - } - - return ref_tag; -} - -void add_highway_tags(osmium::builder::TagListBuilder *builder, - OGRFeatureUniquePtr &f, ushort route_type, - mtd_area_map_type *mtd_area_map, - const std::string &ref_name, bool underConstruction) { - - ushort func_class = 0; - std::string func_class_s = get_field_from_feature(f, FUNC_CLASS); - if (!func_class_s.empty()) - func_class = get_uint_from_feature(f, FUNC_CLASS); - - add_highway_tag(builder, f, route_type, func_class, mtd_area_map, ref_name, - underConstruction); - - add_one_way_tag(builder, get_field_from_feature(f, DIR_TRAVEL)); - add_access_tags(builder, f); - add_maxspeed_tags(builder, f); - add_lanes_tag(builder, f); - add_postcode_tag(builder, f); - - if (parse_bool(get_field_from_feature(f, PAVED))) - builder->add_tag("surface", "paved"); - if (parse_bool(get_field_from_feature(f, BRIDGE))) - builder->add_tag("bridge", YES); - if (parse_bool(get_field_from_feature(f, TUNNEL))) - builder->add_tag("tunnel", YES); - if (parse_bool(get_field_from_feature(f, TOLLWAY))) - builder->add_tag("toll", YES); - if (parse_bool(get_field_from_feature(f, ROUNDABOUT))) - builder->add_tag("junction", "roundabout"); - if (parse_bool(get_field_from_feature(f, FOURWHLDR))) - builder->add_tag("4wd_only", YES); -} - std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { if (!is_in_range(navteq_admin_lvl_int, (uint)NAVTEQ_ADMIN_LVL_MIN, (uint)NAVTEQ_ADMIN_LVL_MAX)) diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index e9f97c6..df6405c 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -46,39 +46,6 @@ const char *R_NREFADDR = "R_NREFADDR"; const char *R_ADDRSCH = "R_ADDRSCH"; // const char *R_ADDRFORM = "R_ADDRFORM"; -const char *FUNC_CLASS = "FUNC_CLASS"; -const char *SPEED_CAT = "SPEED_CAT"; -const char *FR_SPEED_LIMIT = "FR_SPD_LIM"; -const char *TO_SPEED_LIMIT = "TO_SPD_LIM"; -const char *DIR_TRAVEL = "DIR_TRAVEL"; -const char *AR_AUTO = "AR_AUTO"; -const char *AR_BUS = "AR_BUS"; -const char *AR_TAXIS = "AR_TAXIS"; -// const char *AR_CARPOOL = "AR_CARPOOL"; -const char *AR_PEDESTRIANS = "AR_PEDEST"; -const char *AR_TRUCKS = "AR_TRUCKS"; -const char *AR_DELIV = "AR_DELIV"; -const char *AR_EMERVEH = "AR_EMERVEH"; -const char *AR_MOTORCYCLES = "AR_MOTOR"; -const char *AR_THROUGH_TRAFFIC = "AR_TRAFF"; -const char *PAVED = "PAVED"; -const char *PRIVATE = "PRIVATE"; -const char *BRIDGE = "BRIDGE"; -const char *TUNNEL = "TUNNEL"; -const char *TOLLWAY = "TOLLWAY"; -const char *CONTRACC = "CONTRACC"; -const char *ROUNDABOUT = "ROUNDABOUT"; -const char *FERRY = "FERRY_TYPE"; -const char *URBAN = "URBAN"; -const char *ROUTE = "ROUTE_TYPE"; -const char *FOURWHLDR = "FOURWHLDR"; -const char *PHYS_LANES = "PHYS_LANES"; -const char *PUB_ACCESS = "PUB_ACCESS"; - -const char *L_POSTCODE = "L_POSTCODE"; -const char *R_POSTCODE = "R_POSTCODE"; -const char *RAMP = "RAMP"; - // const char *AREA_NAME_LANG_CODE = "NM_LANGCD"; // RDMS_DBF columns @@ -130,42 +97,6 @@ static const char *speed_cat_metric[] = { #define TIMESTAMP 1 } // namespace -// highway OSM tags -const char *MOTORWAY = "motorway"; -const char *MOTORWAY_LINK = "motorway_link"; -const char *TRUNK = "trunk"; -const char *PRIMARY = "primary"; -const char *PRIMARY_LINK = "primary_link"; -const char *SECONDARY = "secondary"; -const char *SECONDARY_LINK = "secondary_link"; -const char *TERTIARY = "tertiary"; -const char *UNCLASSIFIED = "unclassified"; -const char *RESIDENTIAL = "residential"; -const char *TRACK = "track"; -const char *PATH = "path"; -const char *FOOTWAY = "footway"; -const char *HIGHWAY = "highway"; -const char *CONSTRUCTION = "construction"; - -const std::vector DEFAULT_HWY_FUNC_TYPE = { - "", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}; - -std::map> const HWY_FUNC_CLASS_MAP = { - /* Applied with functional classes: - * 1, 2, 3, 4, 5 + - * rural, 5 + urban */ - {0 /*"DEFAULT"*/, DEFAULT_HWY_FUNC_TYPE}, - {3 /*"GER"*/, - {"", PRIMARY, SECONDARY, TERTIARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, - {8 /*"CHE"*/, - {"", PRIMARY, SECONDARY, TERTIARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, - {108 /*"DEN"*/, - {"", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, - {107 /*"SWE"*/, - {"", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, - {9 /*"AUT"*/, - {"", PRIMARY, PRIMARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}}; - const double HOUSENUMBER_CURVE_OFFSET = 0.00005; #endif /* PLUGINS_NAVTEQ_MAPPINGS_HPP_ */ diff --git a/plugins/util.hpp b/plugins/util.hpp index 8b48f8b..04fa307 100644 --- a/plugins/util.hpp +++ b/plugins/util.hpp @@ -115,13 +115,18 @@ uint64_t dbf_get_uint_by_field(DBFHandle handle, int row, * \param field field name as key * \return const char* of field value */ -const char *get_field_from_feature(const OGRFeature *feat, const char *field) { +const char *get_field_from_feature(const OGRFeatureUniquePtr &feat, + const char *field) { int field_index = feat->GetFieldIndex(field); if (field_index == -1) std::cerr << field << std::endl; return feat->GetFieldAsString(field_index); } +const char *get_field_from_feature(const OGRFeatureUniquePtr &feat, + const std::string_view &field) { + return get_field_from_feature(feat, field.data()); +} /** * \brief returns field from OGRFeature * throws exception if field_value is not @@ -129,7 +134,8 @@ const char *get_field_from_feature(const OGRFeature *feat, const char *field) { * \param field field name as key * \return field value as uint */ -uint64_t get_uint_from_feature(const OGRFeature *feat, const char *field) { +uint64_t get_uint_from_feature(const OGRFeatureUniquePtr &feat, + const char *field) { const char *value = get_field_from_feature(feat, field); assert(value); try { @@ -140,6 +146,11 @@ uint64_t get_uint_from_feature(const OGRFeature *feat, const char *field) { } } +uint64_t get_uint_from_feature(const OGRFeatureUniquePtr &feat, + const std::string_view &field) { + return get_uint_from_feature(feat, field.data()); +} + /* getting fields from OGRFeatures -- end */ template bool is_in_range(Type test, Type from, Type to) { @@ -212,11 +223,11 @@ std::string to_camel_case_with_spaces(const std::string &camel) { return to_camel_case_with_spaces(camel.c_str()); } -void add_uint_tag(osmium::builder::TagListBuilder *tl_builder, +void add_uint_tag(osmium::builder::TagListBuilder &tl_builder, const char *tag_key, uint uint_tag_val) { std::string val_s = std::to_string(uint_tag_val); if (tag_key) { - tl_builder->add_tag(tag_key, val_s); + tl_builder.add_tag(tag_key, val_s); } } @@ -309,4 +320,26 @@ bool is_superior(short superior, short than) { return false; } +uint get_number_after(const std::string &str, const char *start_str) { + if (!str.starts_with(start_str)) + return 0; /* doesn't start with start_str */ + + /* Get number string after start_str until first non-digit appears */ + std::string end_str = str.substr(strlen(start_str)); + std::string number_str; + for (auto it = end_str.begin(); it != end_str.end(); ++it) { + if (!std::isdigit(*it)) { + /* break because B107a should return 107*/ + break; + } + number_str += *it; + } + + try { + return std::stoul(number_str); + } catch (const std::invalid_argument &) { + return 0; + } +} + #endif /* UTIL_HPP_ */ From 1c08a0e045c721ece5eb459c93dbbddea0234c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 13:35:29 +0000 Subject: [PATCH 19/57] refactoring --- plugins/navteq/converter/StreetConverter.cpp | 87 +++++++++++++++++++- plugins/navteq/converter/StreetConverter.hpp | 17 ++++ plugins/navteq/navteq.hpp | 78 ------------------ plugins/navteq/navteq_mappings.hpp | 4 +- 4 files changed, 104 insertions(+), 82 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index ef078a1..c1b3e4b 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -154,7 +154,7 @@ void StreetConverter::init_g_cnd_mod_map(const boost::filesystem::path &dir) { const boost::filesystem::path CND_MOD_DBF = "CndMod.dbf"; DBFHandle cnd_mod_handle = read_dbf_file(dir / CND_MOD_DBF); for (int i = 0; i < DBFGetRecordCount(cnd_mod_handle); i++) { - uint64_t cond_id = dbf_get_uint_by_field(cnd_mod_handle, i, COND_ID); + uint64_t cond_id = dbf_get_uint_by_field(cnd_mod_handle, i, COND_ID.data()); std::string lang_code = dbf_get_string_by_field(cnd_mod_handle, i, LANG_CODE.data()); uint64_t mod_type = @@ -375,6 +375,91 @@ void StreetConverter::parse_ramp_names( } } +void StreetConverter::process_way( + const std::vector &dirs, + const std::map> &z_level_map, + osmium::io::Writer &writer) { + for (auto &dir : dirs) { + // parse highway names and refs + auto hwys_ref_map = init_highway_names(dir); + + // parse conditionals + init_under_construction(dir); + + auto path = dir / STREETS_SHP; + auto ds = open_shape_file(path); + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(path.string())); + + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + for (auto &feat : *layer) { + process_way(feat, z_level_map, node_buffer, way_buffer); + } + + node_buffer.commit(); + way_buffer.commit(); + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); + + g_hwys_ref_map.clear(); + } +} + +std::map> +StreetConverter::init_highway_names(const boost::filesystem::path &dir) { + std::map> hwys_ref_map; + if (dbf_file_exists(dir / MAJ_HWYS_DBF)) + parse_highway_names(dir / MAJ_HWYS_DBF, hwys_ref_map, false); + if (dbf_file_exists(dir / SEC_HWYS_DBF)) + parse_highway_names(dir / SEC_HWYS_DBF, hwys_ref_map, false); + if (dbf_file_exists(dir / ALT_STREETS_DBF)) + parse_highway_names(dir / ALT_STREETS_DBF, hwys_ref_map, true); + if (dbf_file_exists(dir / STREETS_DBF)) + parse_highway_names(dir / STREETS_DBF, hwys_ref_map, true); + + return hwys_ref_map; +} + +void StreetConverter::parse_highway_names( + const boost::filesystem::path &dbf_file, + std::map> &hwys_ref_map, + bool isStreetLayer) { + DBFHandle hwys_handle = read_dbf_file(dbf_file); + for (int i = 0; i < DBFGetRecordCount(hwys_handle); i++) { + + uint64_t link_id = dbf_get_uint_by_field(hwys_handle, i, LINK_ID.data()); + std::string hwy_name; + if (isStreetLayer) + hwy_name = dbf_get_string_by_field(hwys_handle, i, ST_NAME.data()); + else + hwy_name = dbf_get_string_by_field(hwys_handle, i, HIGHWAY_NM.data()); + + uint routeType = dbf_get_uint_by_field(hwys_handle, i, ROUTE.data()); + + hwys_ref_map[link_id].emplace(routeType, hwy_name); + } + DBFClose(hwys_handle); +} + +void StreetConverter::init_under_construction( + const boost::filesystem::path &dir) { + if (!dbf_file_exists(dir / CDMS_DBF)) + return; + + DBFHandle cond = read_dbf_file(dir / CDMS_DBF); + for (int i = 0; i < DBFGetRecordCount(cond); i++) { + uint64_t link_id = dbf_get_uint_by_field(cond, i, LINK_ID); + uint condType = dbf_get_uint_by_field(cond, i, COND_TYPE); + + if (condType == 3) + g_construction_set.emplace(link_id); + } + DBFClose(cond); +} + void StreetConverter::process_way( OGRFeatureUniquePtr &feat, const std::map> &z_level_map, diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index f6c12dc..7370aac 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -118,6 +118,10 @@ class StreetConverter : public Converter { std::map> &ramps_ref_map, const std::map &junctionNames); + void process_way( + const std::vector &dirs, + const std::map> &z_level_map, + osmium::io::Writer &writer); void process_way( OGRFeatureUniquePtr &feat, const std::map> &z_level_map, @@ -150,6 +154,13 @@ class StreetConverter : public Converter { const std::map> &names_map, const std::set &construction_set, bool debugMode); + std::map> + init_highway_names(const boost::filesystem::path &dir); + + void parse_highway_names( + const boost::filesystem::path &dbf_file, + std::map> &hwys_ref_map, + bool isStreetLayer); void add_additional_restrictions( osmium::builder::TagListBuilder &builder, uint64_t link_id, uint64_t l_area_id, uint64_t r_area_id, @@ -242,6 +253,8 @@ class StreetConverter : public Converter { bool only_pedestrians(const OGRFeatureUniquePtr &f); + void init_under_construction(const boost::filesystem::path &dir); + // CndMod types (CM) static constexpr std::string_view CM_MOD_TYPE = "MOD_TYPE"; static constexpr std::string_view CM_MOD_VAL = "MOD_VAL"; @@ -325,6 +338,10 @@ class StreetConverter : public Converter { static constexpr std::string_view HIGHWAY = "highway"; static constexpr std::string_view CONSTRUCTION = "construction"; + static constexpr std::string_view HIGHWAY_NM = "HIGHWAY_NM"; + static constexpr std::string_view ST_NAME = "ST_NAME"; + static constexpr std::string_view COND_TYPE = "COND_TYPE"; + // higway classification const std::vector DEFAULT_HWY_FUNC_TYPE = { "", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}; diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index 19673f2..8f57a81 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -226,84 +226,6 @@ void init_cdms_map( } } -void init_under_construction(const boost::filesystem::path &dir) { - if (!dbf_file_exists(dir / CDMS_DBF)) - return; - - DBFHandle cond = read_dbf_file(dir / CDMS_DBF); - for (int i = 0; i < DBFGetRecordCount(cond); i++) { - link_id_type link_id = dbf_get_uint_by_field(cond, i, LINK_ID); - uint condType = dbf_get_uint_by_field(cond, i, COND_TYPE); - - if (condType == 3) - g_construction_set.emplace(link_id); - } - DBFClose(cond); -} - -void parse_highway_names(const boost::filesystem::path &dbf_file, - bool isStreetLayer) { - DBFHandle hwys_handle = read_dbf_file(dbf_file); - for (int i = 0; i < DBFGetRecordCount(hwys_handle); i++) { - - link_id_type link_id = dbf_get_uint_by_field(hwys_handle, i, LINK_ID); - std::string hwy_name; - if (isStreetLayer) - hwy_name = dbf_get_string_by_field(hwys_handle, i, ST_NAME); - else - hwy_name = dbf_get_string_by_field(hwys_handle, i, HIGHWAY_NM); - - uint routeType = dbf_get_uint_by_field(hwys_handle, i, ROUTE); - - g_hwys_ref_map[link_id].emplace(routeType, hwy_name); - } - DBFClose(hwys_handle); -} - -void init_highway_names(const boost::filesystem::path &dir) { - if (dbf_file_exists(dir / MAJ_HWYS_DBF)) - parse_highway_names(dir / MAJ_HWYS_DBF, false); - if (dbf_file_exists(dir / SEC_HWYS_DBF)) - parse_highway_names(dir / SEC_HWYS_DBF, false); - if (dbf_file_exists(dir / ALT_STREETS_DBF)) - parse_highway_names(dir / ALT_STREETS_DBF, true); - if (dbf_file_exists(dir / STREETS_DBF)) - parse_highway_names(dir / STREETS_DBF, true); -} - -void process_way(const std::vector &dirs, - z_lvl_map &z_level_map, osmium::io::Writer &writer) { - for (auto &dir : dirs) { - // parse highway names and refs - init_highway_names(dir); - - // parse conditionals - init_under_construction(dir); - - auto path = dir / STREETS_SHP; - auto ds = open_shape_file(path); - - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(path.string())); - boost::timer::progress_display progress(layer->GetFeatureCount()); - - osmium::memory::Buffer node_buffer(buffer_size); - osmium::memory::Buffer way_buffer(buffer_size); - for (auto &feat : *layer) { - process_way(feat, &z_level_map, node_buffer, way_buffer); - ++progress; - } - - node_buffer.commit(); - way_buffer.commit(); - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); - - g_hwys_ref_map.clear(); - } -} - auto createPointAddressMapList(const boost::filesystem::path dir) { auto pointAddressMap = diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index df6405c..53c3dd9 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -34,7 +34,6 @@ static const boost::filesystem::path STREETS_DBF = "Streets.dbf"; // STREETS columns const char *LINK_ID = "LINK_ID"; -const char *ST_NAME = "ST_NAME"; const char *ADDR_TYPE = "ADDR_TYPE"; const char *L_REFADDR = "L_REFADDR"; @@ -53,7 +52,7 @@ const char *R_ADDRSCH = "R_ADDRSCH"; const char *COND_ID = "COND_ID"; // CDMS_DBF columns -const char *COND_TYPE = "COND_TYPE"; + // const char *COND_VAL1 = "COND_VAL1"; // const char *COND_VAL2 = "COND_VAL2"; // const char *COND_VAL3 = "COND_VAL3"; @@ -61,7 +60,6 @@ const char *COND_TYPE = "COND_TYPE"; // MAJ_HWYS columns // const char* LINK_ID = "LINK_ID"; -const char *HIGHWAY_NM = "HIGHWAY_NM"; // condition types (CT) #define CT_RESTRICTED_DRIVING_MANOEUVRE 7 From 4f77e8b23fafdc530240f5e777843e7033102e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 14:42:56 +0000 Subject: [PATCH 20/57] add housenumber --- plugins/navteq/converter/StreetConverter.cpp | 257 ++++++++++++++++++- plugins/navteq/converter/StreetConverter.hpp | 47 ++++ plugins/navteq/navteq.hpp | 218 ---------------- plugins/navteq/navteq2osm_tag_parser.hpp | 11 - plugins/navteq/navteq_mappings.hpp | 5 - plugins/util.hpp | 11 + 6 files changed, 301 insertions(+), 248 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index c1b3e4b..65a9409 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -727,30 +727,30 @@ void StreetConverter::add_additional_restrictions( * which would make it unroutable for nearly every truck. * Therefore we use the highest value and add a marker for BK2 / BK3 */ if (max_weight == 16000 && max_axleload == 10000) { - builder->add_tag("maxweight:class", "BK2"); + builder.add_tag("maxweight:class", "BK2"); max_weight = 51400; } else if (max_weight == 12000 && max_axleload == 8000) { - builder->add_tag("maxweight:class", "BK3"); + builder.add_tag("maxweight:class", "BK3"); max_weight = 37000; } } if (max_height > 0) - builder->add_tag("maxheight", imperial_units ? inch_to_feet(max_height) - : cm_to_m(max_height)); + builder.add_tag("maxheight", imperial_units ? inch_to_feet(max_height) + : cm_to_m(max_height)); if (max_width > 0) - builder->add_tag("maxwidth", imperial_units ? inch_to_feet(max_width) - : cm_to_m(max_width)); + builder.add_tag("maxwidth", imperial_units ? inch_to_feet(max_width) + : cm_to_m(max_width)); if (max_length > 0) - builder->add_tag("maxlength", imperial_units ? inch_to_feet(max_length) - : cm_to_m(max_length)); + builder.add_tag("maxlength", imperial_units ? inch_to_feet(max_length) + : cm_to_m(max_length)); if (max_weight > 0) - builder->add_tag("maxweight", imperial_units ? lbs_to_metric_ton(max_weight) - : kg_to_t(max_weight)); + builder.add_tag("maxweight", imperial_units ? lbs_to_metric_ton(max_weight) + : kg_to_t(max_weight)); if (max_axleload > 0) - builder->add_tag("maxaxleload", imperial_units - ? lbs_to_metric_ton(max_axleload) - : kg_to_t(max_axleload)); + builder.add_tag("maxaxleload", imperial_units + ? lbs_to_metric_ton(max_axleload) + : kg_to_t(max_axleload)); } void StreetConverter::process_end_point( @@ -1346,4 +1346,233 @@ bool StreetConverter::only_pedestrians(const OGRFeatureUniquePtr &f) { if (!strcmp(get_field_from_feature(f, AR_THROUGH_TRAFFIC), "Y")) return false; return true; -} \ No newline at end of file +} + +void StreetConverter::add_here_speed_cat_tag( + osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f) { + auto speed_cat = get_uint_from_feature(f, SPEED_CAT); + if (0 < speed_cat && speed_cat < speed_cat_metric.size()) + builder.add_tag("here:speed_cat", speed_cat_metric[speed_cat].data()); + else + throw format_error("SPEED_CAT=" + std::to_string(speed_cat) + + " is not valid."); +} + +void StreetConverter::create_house_numbers(const OGRFeatureUniquePtr &feat, + const OGRLineString *ogr_ls, + bool left, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer) { + const std::string_view &ref_addr = left ? L_REFADDR : R_REFADDR; + const std::string_view &nref_addr = left ? L_NREFADDR : R_NREFADDR; + const std::string_view &addr_schema = left ? L_ADDRSCH : R_ADDRSCH; + + if (!strcmp(get_field_from_feature(feat, ref_addr), "")) + return; + if (!strcmp(get_field_from_feature(feat, nref_addr), "")) + return; + if (!strcmp(get_field_from_feature(feat, addr_schema), "")) + return; + if (!strcmp(get_field_from_feature(feat, addr_schema), "M")) + return; + + std::string startNumber = + get_field_from_feature(feat, left ? ref_addr : nref_addr); + + std::string endNumber = + get_field_from_feature(feat, left ? nref_addr : ref_addr); + + std::unique_ptr offset_ogr_ls( + create_offset_curve(ogr_ls, HOUSENUMBER_CURVE_OFFSET, left)); + if (startNumber == endNumber) { + // no interpolation for signel addresses + OGRPoint midPoint; + offset_ogr_ls->Centroid(&midPoint); + { + osmium::Location location(midPoint.getX(), midPoint.getY()); + // scope node_builder + osmium::builder::NodeBuilder node_builder(node_buffer); + build_node(location, node_builder); + { + // scope tl_builder + osmium::builder::TagListBuilder tl_builder(node_builder); + tl_builder.add_tag("addr:housenumber", startNumber); + tl_builder.add_tag( + "addr:street", + to_camel_case_with_spaces(get_field_from_feature(feat, ST_NAME))); + } + } + } else { + // osm address interpolation + osmium::builder::WayBuilder way_builder(way_buffer); + setObjectProperties(way_builder); + { + // scope wnl_builder + osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &way_builder); + + for (int i = 0; i < offset_ogr_ls->getNumPoints(); i++) { + osmium::Location location(offset_ogr_ls->getX(i), + offset_ogr_ls->getY(i)); + { + // scope node_builder + osmium::builder::NodeBuilder node_builder(node_buffer); + auto node_id = build_node(location, node_builder); + { + // scope tl_builder + osmium::builder::TagListBuilder tl_builder(node_buffer, + &node_builder); + if (i == 0 || i == offset_ogr_ls->getNumPoints() - 1) { + if (i == 0) { + tl_builder.add_tag("addr:housenumber", startNumber); + } else if (i == offset_ogr_ls->getNumPoints() - 1) { + tl_builder.add_tag("addr:housenumber", endNumber); + } + tl_builder.add_tag("addr:street", + to_camel_case_with_spaces( + get_field_from_feature(feat, ST_NAME))); + } + } + + wnl_builder.add_node_ref(osmium::NodeRef(node_id, location)); + } + } + } + { + // scope tl_builder + osmium::builder::TagListBuilder tl_builder(way_buffer, &way_builder); + const char *schema = + parse_house_number_schema(get_field_from_feature(feat, addr_schema)); + tl_builder.add_tag("addr:interpolation", schema); + } + } + node_buffer.commit(); + way_buffer.commit(); +} + +void StreetConverter::create_house_numbers(const OGRFeatureUniquePtr &feat, + const OGRLineString *ogr_ls, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer) { + create_house_numbers(feat, ogr_ls, true, node_buffer, way_buffer); + create_house_numbers(feat, ogr_ls, false, node_buffer, way_buffer); +} + +void StreetConverter::create_premium_house_numbers( + const OGRFeatureUniquePtr &feat, + const std::vector> &addressList, + int linkId, osmium::memory::Buffer &node_buffer) { + + for (auto &[location, houseNo] : addressList) { + + // scope node_builder + osmium::builder::NodeBuilder node_builder(node_buffer); + build_node(location, node_builder); + { + // scope tl_builder + osmium::builder::TagListBuilder tl_builder(node_buffer, &node_builder); + tl_builder.add_tag(LINK_ID.data(), std::to_string(linkId)); + tl_builder.add_tag("addr:housenumber", houseNo); + tl_builder.add_tag( + "addr:street", + to_camel_case_with_spaces(get_field_from_feature(feat, ST_NAME))); + } + } +} + +void StreetConverter::process_house_numbers( + const std::vector &dirs, + osmium::io::Writer &writer) { + for (auto &dir : dirs) { + // create point addresses from PointAddress.dbf + auto pointMap = createPointAddressMapList(dir); + + auto path = dir / STREETS_SHP; + auto ds = open_shape_file(path); + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(path.string())); + + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + + int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); + + for (auto &feat : *layer) { + int linkId = feat->GetFieldAsInteger(linkIdField); + process_house_numbers(feat, *pointMap, linkId, node_buffer, way_buffer); + } + + node_buffer.commit(); + way_buffer.commit(); + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); + delete pointMap; + } +} +/** + * \brief creates Way from linestring. + * creates missing Nodes needed for Way and Way itself. + * \param ogr_ls linestring which provides the geometry. + * \param z_level_map holds z_levels to Nodes of Ways. + */ +void StreetConverter::process_house_numbers( + const OGRFeatureUniquePtr &feat, + const std::map>> + &pointAddresses, + int linkId, osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer) { + + auto ogr_ls = static_cast(feat->GetGeometryRef()); + + auto it = pointAddresses.find(linkId); + if (it != pointAddresses.end()) { + create_premium_house_numbers(feat, it->second, linkId, node_buffer); + } else { + if (!strcmp(get_field_from_feature(feat, ADDR_TYPE), "B")) { + create_house_numbers(feat, ogr_ls, node_buffer, way_buffer); + } + } +} + +std::map>> * +StreetConverter::createPointAddressMapList(const boost::filesystem::path &dir) { + + auto pointAddressMap = + new std::map>>(); + if (shp_file_exists(dir / POINT_ADDRESS_SHP)) { + auto ds = open_shape_file(dir / POINT_ADDRESS_SHP); + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error((dir / POINT_ADDRESS_SHP).string())); + + int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); + int latField = layer->FindFieldIndex("DISP_LAT", true); + int lonField = layer->FindFieldIndex("DISP_LON", true); + int addressField = layer->FindFieldIndex("ADDRESS", true); + + for (auto &feat : *layer) { + int linkId = feat->GetFieldAsInteger(linkIdField); + auto houseNumber = std::string(feat->GetFieldAsString(addressField)); + + double lat = 0.0; + double lon = 0.0; + + if (feat->IsFieldNull(lonField) && feat->IsFieldNull(latField)) { + auto point = static_cast(feat->GetGeometryRef()); + lat = point->getY(); + lon = point->getX(); + } else { + lon = feat->GetFieldAsDouble(lonField); + lat = feat->GetFieldAsDouble(latField); + } + + (*pointAddressMap)[linkId].emplace_back(osmium::Location(lon, lat), + houseNumber); + } + } + return pointAddressMap; +} diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index 7370aac..dc137a8 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -255,6 +255,38 @@ class StreetConverter : public Converter { void init_under_construction(const boost::filesystem::path &dir); + void add_here_speed_cat_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f); + + void create_house_numbers(const OGRFeatureUniquePtr &feat, + const OGRLineString *ogr_ls, bool left, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + void create_house_numbers(const OGRFeatureUniquePtr &feat, + const OGRLineString *ogr_ls, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + void create_premium_house_numbers( + const OGRFeatureUniquePtr &feat, + const std::vector> &addressList, + int linkId, osmium::memory::Buffer &node_buffer); + + void process_house_numbers(const std::vector &dirs, + osmium::io::Writer &writer); + + void process_house_numbers( + const OGRFeatureUniquePtr &feat, + const std::map>> + &pointAddresses, + int linkId, osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + std::map>> * + createPointAddressMapList(const boost::filesystem::path &dir); + // CndMod types (CM) static constexpr std::string_view CM_MOD_TYPE = "MOD_TYPE"; static constexpr std::string_view CM_MOD_VAL = "MOD_VAL"; @@ -342,6 +374,15 @@ class StreetConverter : public Converter { static constexpr std::string_view ST_NAME = "ST_NAME"; static constexpr std::string_view COND_TYPE = "COND_TYPE"; + static constexpr std::string_view ADDR_TYPE = "ADDR_TYPE"; + static constexpr std::string_view L_REFADDR = "L_REFADDR"; + const char *L_NREFADDR = "L_NREFADDR"; + const char *L_ADDRSCH = "L_ADDRSCH"; + // const char *L_ADDRFORM = "L_ADDRFORM"; + const char *R_REFADDR = "R_REFADDR"; + const char *R_NREFADDR = "R_NREFADDR"; + const char *R_ADDRSCH = "R_ADDRSCH"; + // higway classification const std::vector DEFAULT_HWY_FUNC_TYPE = { "", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}; @@ -363,6 +404,12 @@ class StreetConverter : public Converter { RESIDENTIAL}}, {9 /*"AUT"*/, {"", PRIMARY, PRIMARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}}; + + static constexpr std::array speed_cat_metric{ + "", ">130", "101-130", "91-100", "71-90", + "51-70", "31-50", "11-30", "<11"}; + + constexpr double HOUSENUMBER_CURVE_OFFSET = 0.00005; }; #endif // STREETCONVERTER_HPP diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp index 8f57a81..f8e7a75 100644 --- a/plugins/navteq/navteq.hpp +++ b/plugins/navteq/navteq.hpp @@ -68,152 +68,6 @@ bool debugMode = false; * \param left specifies on which side of the linestring the house numbers * will be applied */ -void create_house_numbers(const OGRFeatureUniquePtr &feat, - const OGRLineString *ogr_ls, bool left, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - const char *ref_addr = left ? L_REFADDR : R_REFADDR; - const char *nref_addr = left ? L_NREFADDR : R_NREFADDR; - const char *addr_schema = left ? L_ADDRSCH : R_ADDRSCH; - - if (!strcmp(get_field_from_feature(feat, ref_addr), "")) - return; - if (!strcmp(get_field_from_feature(feat, nref_addr), "")) - return; - if (!strcmp(get_field_from_feature(feat, addr_schema), "")) - return; - if (!strcmp(get_field_from_feature(feat, addr_schema), "M")) - return; - - std::string startNumber = - get_field_from_feature(feat, left ? ref_addr : nref_addr); - - std::string endNumber = - get_field_from_feature(feat, left ? nref_addr : ref_addr); - - std::unique_ptr offset_ogr_ls( - create_offset_curve(ogr_ls, HOUSENUMBER_CURVE_OFFSET, left)); - if (startNumber == endNumber) { - // no interpolation for signel addresses - OGRPoint midPoint; - offset_ogr_ls->Centroid(&midPoint); - { - osmium::Location location(midPoint.getX(), midPoint.getY()); - // scope node_builder - osmium::builder::NodeBuilder node_builder(node_buffer); - build_node(location, &node_builder); - { - // scope tl_builder - osmium::builder::TagListBuilder tl_builder(node_builder); - tl_builder.add_tag("addr:housenumber", startNumber); - tl_builder.add_tag( - "addr:street", - to_camel_case_with_spaces(get_field_from_feature(feat, ST_NAME))); - } - } - } else { - // osm address interpolation - osmium::builder::WayBuilder way_builder(way_buffer); - way_builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(way_builder.object()); - way_builder.set_user(USER); - { - // scope wnl_builder - osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &way_builder); - - for (int i = 0; i < offset_ogr_ls->getNumPoints(); i++) { - osmium::Location location(offset_ogr_ls->getX(i), - offset_ogr_ls->getY(i)); - { - // scope node_builder - osmium::builder::NodeBuilder node_builder(node_buffer); - auto node_id = build_node(location, &node_builder); - { - // scope tl_builder - osmium::builder::TagListBuilder tl_builder(node_buffer, - &node_builder); - if (i == 0 || i == offset_ogr_ls->getNumPoints() - 1) { - if (i == 0) { - tl_builder.add_tag("addr:housenumber", startNumber); - } else if (i == offset_ogr_ls->getNumPoints() - 1) { - tl_builder.add_tag("addr:housenumber", endNumber); - } - tl_builder.add_tag("addr:street", - to_camel_case_with_spaces( - get_field_from_feature(feat, ST_NAME))); - } - } - - wnl_builder.add_node_ref(osmium::NodeRef(node_id, location)); - } - } - } - { - // scope tl_builder - osmium::builder::TagListBuilder tl_builder(way_buffer, &way_builder); - const char *schema = - parse_house_number_schema(get_field_from_feature(feat, addr_schema)); - tl_builder.add_tag("addr:interpolation", schema); - } - } - node_buffer.commit(); - way_buffer.commit(); -} - -void create_house_numbers(const OGRFeatureUniquePtr &feat, - const OGRLineString *ogr_ls, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - create_house_numbers(feat, ogr_ls, true, node_buffer, way_buffer); - create_house_numbers(feat, ogr_ls, false, node_buffer, way_buffer); -} - -void create_premium_house_numbers( - const OGRFeatureUniquePtr &feat, - const std::vector> &addressList, - int linkId, osmium::memory::Buffer &node_buffer) { - - for (auto &address : addressList) { - - // scope node_builder - osmium::builder::NodeBuilder node_builder(node_buffer); - build_node(address.first, &node_builder); - { - // scope tl_builder - osmium::builder::TagListBuilder tl_builder(node_buffer, &node_builder); - tl_builder.add_tag(LINK_ID, std::to_string(linkId)); - tl_builder.add_tag("addr:housenumber", address.second); - tl_builder.add_tag( - "addr:street", - to_camel_case_with_spaces(get_field_from_feature(feat, ST_NAME))); - } - } -} - -/** - * \brief creates Way from linestring. - * creates missing Nodes needed for Way and Way itself. - * \param ogr_ls linestring which provides the geometry. - * \param z_level_map holds z_levels to Nodes of Ways. - */ -void process_house_numbers( - const OGRFeatureUniquePtr &feat, - std::map>> - *pointAddresses, - int linkId, osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - - auto ogr_ls = static_cast(feat->GetGeometryRef()); - - auto it = pointAddresses->find(linkId); - if (it != pointAddresses->end()) { - create_premium_house_numbers(feat, it->second, linkId, node_buffer); - } else { - if (!strcmp(get_field_from_feature(feat, ADDR_TYPE), "B")) { - create_house_numbers(feat, ogr_ls, node_buffer, way_buffer); - } - } -} void init_cdms_map( DBFHandle cdms_handle, @@ -225,78 +79,6 @@ void init_cdms_map( cdms_map.insert(std::make_pair(cond_id, cond_type)); } } - -auto createPointAddressMapList(const boost::filesystem::path dir) { - - auto pointAddressMap = - new std::map>>(); - if (shp_file_exists(dir / POINT_ADDRESS_SHP)) { - auto ds = open_shape_file(dir / POINT_ADDRESS_SHP); - - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error((dir / POINT_ADDRESS_SHP).string())); - - int linkIdField = layer->FindFieldIndex(LINK_ID, true); - int latField = layer->FindFieldIndex("DISP_LAT", true); - int lonField = layer->FindFieldIndex("DISP_LON", true); - int addressField = layer->FindFieldIndex("ADDRESS", true); - - for (auto &feat : *layer) { - int linkId = feat->GetFieldAsInteger(linkIdField); - auto houseNumber = std::string(feat->GetFieldAsString(addressField)); - - double lat = 0.0; - double lon = 0.0; - - if (feat->IsFieldNull(lonField) && feat->IsFieldNull(latField)) { - auto point = static_cast(feat->GetGeometryRef()); - lat = point->getY(); - lon = point->getX(); - } else { - lon = feat->GetFieldAsDouble(lonField); - lat = feat->GetFieldAsDouble(latField); - } - - (*pointAddressMap)[linkId].emplace_back(osmium::Location(lon, lat), - houseNumber); - } - } - return pointAddressMap; -} - -void process_house_numbers(const std::vector &dirs, - osmium::io::Writer &writer) { - for (auto &dir : dirs) { - // create point addresses from PointAddress.dbf - auto pointMap = createPointAddressMapList(dir); - - auto path = dir / STREETS_SHP; - auto ds = open_shape_file(path); - - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(path.string())); - boost::timer::progress_display progress(layer->GetFeatureCount()); - - osmium::memory::Buffer node_buffer(buffer_size); - osmium::memory::Buffer way_buffer(buffer_size); - - int linkIdField = layer->FindFieldIndex(LINK_ID, true); - - for (auto &feat : *layer) { - int linkId = feat->GetFieldAsInteger(linkIdField); - process_house_numbers(feat, pointMap, linkId, node_buffer, way_buffer); - ++progress; - } - - node_buffer.commit(); - way_buffer.commit(); - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); - delete pointMap; - } } /**************************************************** diff --git a/plugins/navteq/navteq2osm_tag_parser.hpp b/plugins/navteq/navteq2osm_tag_parser.hpp index a9a0cb0..9c2b702 100644 --- a/plugins/navteq/navteq2osm_tag_parser.hpp +++ b/plugins/navteq/navteq2osm_tag_parser.hpp @@ -86,15 +86,4 @@ std::string navteq_2_osm_admin_lvl(std::string navteq_admin_lvl) { return navteq_2_osm_admin_lvl(stoi(navteq_admin_lvl)); } -const char *parse_house_number_schema(const char *schema) { - if (!strcmp(schema, "E")) - return "even"; - if (!strcmp(schema, "O")) - return "odd"; - std::cerr << "schema = " << schema << " unsupported" << std::endl; - return ""; - throw std::runtime_error("scheme " + std::string(schema) + - " is currently not supported"); -} - #endif /* NAVTEQ2OSMTAGPARSE_HPP_ */ diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 53c3dd9..3b396d6 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -82,9 +82,6 @@ const char *COND_ID = "COND_ID"; #define NAVTEQ_ADMIN_LVL_MIN 1 #define NAVTEQ_ADMIN_LVL_MAX 7 -static const char *speed_cat_metric[] = { - "", ">130", "101-130", "91-100", "71-90", "51-70", "31-50", "11-30", "<11"}; - #define OSM_MAX_WAY_NODES 1000 // default tags for osm nodes ways and relations @@ -95,6 +92,4 @@ static const char *speed_cat_metric[] = { #define TIMESTAMP 1 } // namespace -const double HOUSENUMBER_CURVE_OFFSET = 0.00005; - #endif /* PLUGINS_NAVTEQ_MAPPINGS_HPP_ */ diff --git a/plugins/util.hpp b/plugins/util.hpp index 04fa307..857786f 100644 --- a/plugins/util.hpp +++ b/plugins/util.hpp @@ -342,4 +342,15 @@ uint get_number_after(const std::string &str, const char *start_str) { } } +const char *parse_house_number_schema(const char *schema) { + if (!strcmp(schema, "E")) + return "even"; + if (!strcmp(schema, "O")) + return "odd"; + std::cerr << "schema = " << schema << " unsupported" << std::endl; + return ""; + throw std::runtime_error("scheme " + std::string(schema) + + " is currently not supported"); +} + #endif /* UTIL_HPP_ */ From c269b05b5a8b6328f38259111ae5741a381205a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 14:44:41 +0000 Subject: [PATCH 21/57] refactor navteq.hpp to remove unused code and improve readability --- plugins/navteq/navteq.hpp | 99 --------------------------------------- 1 file changed, 99 deletions(-) delete mode 100644 plugins/navteq/navteq.hpp diff --git a/plugins/navteq/navteq.hpp b/plugins/navteq/navteq.hpp deleted file mode 100644 index f8e7a75..0000000 --- a/plugins/navteq/navteq.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/* \include - * navteq.hpp - * - * Created on: 12.06.2015 - * Author: philip - * - * Convert Shapefiles into OSM files. - */ - -#ifndef NAVTEQ_HPP_ -#define NAVTEQ_HPP_ - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../comm2osm_exceptions.hpp" -#include "../readers.hpp" -#include "navteq2osm_tag_parser.hpp" -#include "navteq_mappings.hpp" -#include "navteq_types.hpp" -#include "navteq_util.hpp" - -#define DEBUG false - -z_lvl_nodes_map_type g_z_lvl_nodes_map; - -// id counter for object creation -osmium::unsigned_object_id_type g_osm_id = 1; - -// g_route_type_map maps navteq link_ids to the lowest occurring route_type -// value -link_id_route_type_map g_route_type_map; - -// g_hwys_ref_map maps navteq link_ids to a vector of highway names -link_id_to_names_map g_hwys_ref_map; - -// g_hwys_ref_map maps navteq link_ids to a vector of highway names -std::set g_construction_set; - -// g_ramps_ref_map maps navteq link_ids to a vector of ramp names -std::map> g_ramps_ref_map; - -// map for conditional modifications -cnd_mod_map_type g_cnd_mod_map; - -// map for conditional driving manoeuvres -cdms_map_type g_cdms_map; -std::map g_area_to_govt_code_map; -cntry_ref_map_type g_cntry_ref_map; - -bool debugMode = false; - -/** - * \brief creates interpolated house numbers alongside of a given linestring - * if feature holds suitable tags \param feat feature which holds the tags - * \param ogr_ls linestring which receives the interpolated house numbers - * \param left specifies on which side of the linestring the house numbers - * will be applied - */ - -void init_cdms_map( - DBFHandle cdms_handle, - std::map &cdms_map) { - for (int i = 0; i < DBFGetRecordCount(cdms_handle); i++) { - osmium::unsigned_object_id_type cond_id = - dbf_get_uint_by_field(cdms_handle, i, COND_ID); - ushort cond_type = dbf_get_uint_by_field(cdms_handle, i, COND_TYPE); - cdms_map.insert(std::make_pair(cond_id, cond_type)); - } -} -} - -/**************************************************** - * cleanup and assertions - ****************************************************/ - -/** - * \brief clears all global variables. - */ - -void clear_all() { - g_osm_id = 1; - g_hwys_ref_map.clear(); - - g_mtd_area_map.clear(); -} - -#endif /* NAVTEQ_HPP_ */ From 2e878b58b8a4f0d088cfe9cee5dc36363fc76e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 14:46:37 +0000 Subject: [PATCH 22/57] Refactor navteq_mappings.hpp to remove unused code and improve readability --- plugins/navteq/navteq_mappings.hpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 3b396d6..a7caf62 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -32,17 +32,6 @@ static const boost::filesystem::path SEC_HWYS_DBF = "SecHwys.dbf"; static const boost::filesystem::path STREETS_DBF = "Streets.dbf"; -// STREETS columns -const char *LINK_ID = "LINK_ID"; - -const char *ADDR_TYPE = "ADDR_TYPE"; -const char *L_REFADDR = "L_REFADDR"; -const char *L_NREFADDR = "L_NREFADDR"; -const char *L_ADDRSCH = "L_ADDRSCH"; -// const char *L_ADDRFORM = "L_ADDRFORM"; -const char *R_REFADDR = "R_REFADDR"; -const char *R_NREFADDR = "R_NREFADDR"; -const char *R_ADDRSCH = "R_ADDRSCH"; // const char *R_ADDRFORM = "R_ADDRFORM"; // const char *AREA_NAME_LANG_CODE = "NM_LANGCD"; From 3940346633fcba2a9e29627730f538c5ce02efda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 17:22:26 +0000 Subject: [PATCH 23/57] Refactor navteq_plugin.hpp to remove unused code and improve readability --- plugins/navteq/navteq_mappings.hpp | 32 ----------- plugins/navteq/navteq_plugin.cpp | 88 +++-------------------------- plugins/navteq/navteq_plugin.hpp | 4 +- plugins/navteq/navteq_types.hpp | 89 ------------------------------ plugins/navteq/navteq_util.hpp | 51 ----------------- 5 files changed, 8 insertions(+), 256 deletions(-) delete mode 100644 plugins/navteq/navteq_types.hpp delete mode 100644 plugins/navteq/navteq_util.hpp diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index a7caf62..8f6c084 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -32,24 +32,6 @@ static const boost::filesystem::path SEC_HWYS_DBF = "SecHwys.dbf"; static const boost::filesystem::path STREETS_DBF = "Streets.dbf"; -// const char *R_ADDRFORM = "R_ADDRFORM"; - -// const char *AREA_NAME_LANG_CODE = "NM_LANGCD"; - -// RDMS_DBF columns -// const char* LINK_ID = "LINK_ID"; -const char *COND_ID = "COND_ID"; - -// CDMS_DBF columns - -// const char *COND_VAL1 = "COND_VAL1"; -// const char *COND_VAL2 = "COND_VAL2"; -// const char *COND_VAL3 = "COND_VAL3"; -// const char *COND_VAL4 = "COND_VAL4"; - -// MAJ_HWYS columns -// const char* LINK_ID = "LINK_ID"; - // condition types (CT) #define CT_RESTRICTED_DRIVING_MANOEUVRE 7 #define CT_TRANSPORT_ACCESS_RESTRICTION 23 @@ -65,20 +47,6 @@ const char *COND_ID = "COND_ID"; #define RESTRICTED_DRIVING_MANOEUVRE 7 -#define YES "yes" -#define NO "no" - -#define NAVTEQ_ADMIN_LVL_MIN 1 -#define NAVTEQ_ADMIN_LVL_MAX 7 - -#define OSM_MAX_WAY_NODES 1000 - -// default tags for osm nodes ways and relations -#define USER "import" -#define VERSION "1" -#define CHANGESET "1" -#define USERID "1" -#define TIMESTAMP 1 } // namespace #endif /* PLUGINS_NAVTEQ_MAPPINGS_HPP_ */ diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 5877164..6383866 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -26,9 +26,8 @@ #include "converter/StreetConverter.hpp" #include "converter/WaterConverter.hpp" -#include "navteq.hpp" +#include "../comm2osm_exceptions.hpp" #include "navteq_plugin.hpp" -#include "navteq_util.hpp" /* @@ -65,67 +64,16 @@ bool navteq_plugin::is_valid_format(std::string filename) { } bool navteq_plugin::check_files(const boost::filesystem::path &dir) { - if (!shp_file_exists(dir / STREETS_SHP)) - return false; - if (!dbf_file_exists(dir / RDMS_DBF)) - return false; - if (!dbf_file_exists(dir / CDMS_DBF)) - return false; - if (!dbf_file_exists(dir / ZLEVELS_DBF)) - return false; - if (!dbf_file_exists(dir / MAJ_HWYS_DBF)) - return false; - if (!dbf_file_exists(dir / SEC_HWYS_DBF)) - return false; - if (!dbf_file_exists(dir / ALT_STREETS_DBF)) - return false; - if (!shp_file_exists(dir / POINT_ADDRESS_SHP)) - BOOST_LOG_TRIVIAL(warning) << " point addresses are missing"; - - if (!shp_file_exists(dir / ADMINBNDY_1_SHP)) - BOOST_LOG_TRIVIAL(warning) - << " administrative boundaries level 1 are missing"; - if (!shp_file_exists(dir / ADMINBNDY_2_SHP)) - BOOST_LOG_TRIVIAL(warning) - << " administrative boundaries level 2 are missing"; - - boost::filesystem::path bbCheckFile; - - if (!shp_file_exists(dir / ADMINBNDY_3_SHP)) { - BOOST_LOG_TRIVIAL(warning) - << " administrative boundaries level 3 are missing"; - } else { - bbCheckFile = dir / ADMINBNDY_3_SHP; - } + // check if the directory contains HERE data - if (!shp_file_exists(dir / ADMINBNDY_4_SHP)) { - BOOST_LOG_TRIVIAL(warning) - << " administrative boundaries level 4 are missing"; - } else { - bbCheckFile = dir / ADMINBNDY_4_SHP; - } + // checck if the PROD.csv file exists - if (!shp_file_exists(dir / ADMINBNDY_5_SHP)) { - BOOST_LOG_TRIVIAL(warning) - << " administrative boundaries level 5 are missing"; - } else { - bbCheckFile = dir / ADMINBNDY_5_SHP; - } + // check HERE-Contrycodes - if (!shp_file_exists(dir / ADMINLINE_1_SHP)) - BOOST_LOG_TRIVIAL(warning) << " administrative lines level 1 are missing"; + // if there is a tar.gz --> use vsitar to extract the files - // check boundingbox - if (!checkInBoundingBox(boundingBox, bbCheckFile)) { - BOOST_LOG_TRIVIAL(warning) << dir.string() << " out of boundingbox"; - return false; - } - - if (!checkCountryCode(dir)) { - BOOST_LOG_TRIVIAL(info) << dir.string() << " skip country"; - return false; - } + // otherwise check id there are unpacked files return true; } @@ -257,26 +205,4 @@ void navteq_plugin::setCountries(const std::vector &countries) { countriesToConvert = countries; } -bool navteq_plugin::checkCountryCode(const boost::filesystem::path &dir) { - DBFHandle handle = read_dbf_file(dir / MTD_CNTRY_REF_DBF); - - if (countriesToConvert.empty()) - return true; - - for (int i = 0; i < DBFGetRecordCount(handle); i++) { - std::string countryCode = dbf_get_string_by_field(handle, i, ISO_CODE); - - foundCountries.insert(countryCode); - auto found = std::find(countriesToConvert.cbegin(), - countriesToConvert.cend(), countryCode); - if (found != countriesToConvert.end()) { - DBFClose(handle); - return true; - } - } - DBFClose(handle); - - return false; -} - -void navteq_plugin::setDebug(bool debug) { debugMode = debug; } \ No newline at end of file +void navteq_plugin::setDebug(bool _debug) { debug = _debug; } \ No newline at end of file diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index 9184e0d..c934e5c 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -10,7 +10,6 @@ #include "../base_plugin.hpp" #include "converter/Converter.hpp" -#include "navteq_types.hpp" #include #include #include @@ -40,8 +39,7 @@ class navteq_plugin : public base_plugin { std::vector countriesToConvert; std::set foundCountries; - - bool checkCountryCode(const boost::filesystem::path &dir); + bool debug; public: navteq_plugin(const boost::filesystem::path &executable_path); diff --git a/plugins/navteq/navteq_types.hpp b/plugins/navteq/navteq_types.hpp deleted file mode 100644 index c62dd13..0000000 --- a/plugins/navteq/navteq_types.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * navteq_types.hpp - * - * Created on: 04.11.2015 - * Author: philip - */ - -#ifndef PLUGINS_NAVTEQ_NAVTEQ_TYPES_HPP_ -#define PLUGINS_NAVTEQ_NAVTEQ_TYPES_HPP_ - -#include -#include -#include -#include -#include - -typedef uint64_t cond_id_type; -typedef uint64_t mod_typ_type; -typedef uint64_t mod_val_type; - -typedef std::pair mod_pair_type; - -struct mod_group_type { - std::string lang_code; - mod_typ_type mod_type; - mod_val_type mod_val; - mod_group_type(mod_typ_type mod_type, mod_val_type mod_val, - const std::string &lang_code) { - this->lang_code = lang_code; - this->mod_type = mod_type; - this->mod_val = mod_val; - } -}; - -typedef uint64_t area_id_type; -typedef uint64_t govt_code_type; -typedef std::map area_id_govt_code_map_type; -typedef std::map cntry_ref_map_type; - -typedef std::map admin_bndy_map_type; - -typedef uint64_t link_id_type; - -// vector of osm_ids -typedef std::vector osm_id_vector_type; - -// maps location to node ids -typedef std::map - node_map_type; - -// pair of [Location, osm_id] -typedef std::pair - loc_osmid_pair_type; -// vector of pairs of [Location, osm_id] -typedef std::vector node_vector_type; - -// maps link ids to a vector of osm_ids -typedef std::map link_id_map_type; - -typedef std::vector link_id_vector_type; - -typedef std::map> - link_id_to_names_map; - -typedef std::map link_id_route_type_map; - -/* z-level types */ -// type of z-levels (range -4 to +5) -typedef short z_lvl_type; - -typedef std::pair index_z_lvl_pair_type; -typedef std::vector index_z_lvl_vector_type; - -// maps navteq link_ids to pairs of -typedef std::map z_lvl_map; - -// pair [Location, z_level] identifies nodes precisely -typedef std::pair node_id_type; -// maps pair [Location, z_level] to osm_id. -typedef std::map - z_lvl_nodes_map_type; - -typedef uint64_t cond_type_type; -typedef std::pair cond_pair_type; -typedef std::vector mod_group_vector_type; -typedef std::unordered_map - cnd_mod_map_type; -typedef std::multimap cdms_map_type; -#endif /* PLUGINS_NAVTEQ_NAVTEQ_TYPES_HPP_ */ diff --git a/plugins/navteq/navteq_util.hpp b/plugins/navteq/navteq_util.hpp deleted file mode 100644 index 79a85c7..0000000 --- a/plugins/navteq/navteq_util.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * navteq_util.hpp - * - * Created on: 11.12.2015 - * Author: philip - */ - -#ifndef PLUGINS_NAVTEQ_NAVTEQ_UTIL_HPP_ -#define PLUGINS_NAVTEQ_NAVTEQ_UTIL_HPP_ - -#include "../util.hpp" -#include "navteq_types.hpp" -#include - -/** - * \brief returns field from OGRFeature - * aborts if feature is nullpointer or field key is invalid - * \param feat feature from which field is read - * \param field field name as key - * \return const char* of field value - */ -const char *get_field_from_feature(const OGRFeatureUniquePtr &feat, - const char *field) { - assert(feat); - int field_index = feat->GetFieldIndex(field); - if (field_index == -1) - std::cerr << field << std::endl; - assert(field_index != -1); - return feat->GetFieldAsString(field_index); -} - -/** - * \brief returns field from OGRFeature - * throws exception if field_value is not - * \param feat feature from which field is read - * \param field field name as key - * \return field value as uint - */ -uint64_t get_uint_from_feature(const OGRFeatureUniquePtr &feat, - const char *field) { - const char *value = get_field_from_feature(feat, field); - assert(value); - try { - return std::stoul(value); - } catch (const std::invalid_argument &) { - throw format_error("Could not parse field='" + std::string(field) + - "' with value='" + std::string(value) + "'"); - } -} - -#endif /* PLUGINS_NAVTEQ_NAVTEQ_UTIL_HPP_ */ From 80d1b3a5427e27c14d555631f64626974ef23ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 19:14:44 +0000 Subject: [PATCH 24/57] replace with std::fileystem --- comm2osm.cpp | 4 +- plugins/base_plugin.hpp | 26 +++---- plugins/dummy/dummy_plugin.cpp | 3 +- plugins/dummy/dummy_plugin.hpp | 5 +- .../converter/AdminBoundariesConverter.cpp | 24 +++--- .../converter/AdminBoundariesConverter.hpp | 12 +-- .../navteq/converter/BuildingConverter.cpp | 11 ++- .../navteq/converter/BuildingConverter.hpp | 6 +- plugins/navteq/converter/CityConverter.cpp | 8 +- plugins/navteq/converter/CityConverter.hpp | 6 +- plugins/navteq/converter/Converter.cpp | 10 +-- plugins/navteq/converter/Converter.hpp | 10 +-- plugins/navteq/converter/HamletConverter.cpp | 8 +- plugins/navteq/converter/HamletConverter.hpp | 6 +- plugins/navteq/converter/LanduseConverter.cpp | 11 ++- plugins/navteq/converter/LanduseConverter.hpp | 6 +- plugins/navteq/converter/RailwayConverter.cpp | 9 +-- plugins/navteq/converter/RailwayConverter.hpp | 6 +- .../navteq/converter/RestAreaConverter.cpp | 11 ++- .../navteq/converter/RestAreaConverter.hpp | 6 +- plugins/navteq/converter/StreetConverter.cpp | 53 +++++++------- plugins/navteq/converter/StreetConverter.hpp | 44 +++++------ plugins/navteq/converter/WaterConverter.cpp | 10 +-- plugins/navteq/converter/WaterConverter.hpp | 6 +- plugins/navteq/navteq_mappings.hpp | 26 +++---- plugins/navteq/navteq_plugin.cpp | 73 +++++++++++-------- plugins/navteq/navteq_plugin.hpp | 15 ++-- plugins/readers.hpp | 4 +- plugins/util.hpp | 6 +- tests/unit_test_util.cpp | 12 +-- 30 files changed, 220 insertions(+), 217 deletions(-) diff --git a/comm2osm.cpp b/comm2osm.cpp index 5d5728b..1a76f4c 100644 --- a/comm2osm.cpp +++ b/comm2osm.cpp @@ -17,7 +17,7 @@ #include "plugins/dummy/dummy_plugin.hpp" #include "plugins/navteq/navteq_plugin.hpp" -boost::filesystem::path input_path, output_file; +std::filesystem::path input_path, output_file; std::vector boundingBox; std::vector countries; static bool debug = false; @@ -99,7 +99,7 @@ int main(int argc, char *argv[]) { std::vector> plugins; - boost::filesystem::path executable_path(argv[0]); + std::filesystem::path executable_path(argv[0]); // plugins.emplace_back(std::make_unique()); plugins.emplace_back(std::make_unique(executable_path)); diff --git a/plugins/base_plugin.hpp b/plugins/base_plugin.hpp index c78a908..dd69736 100644 --- a/plugins/base_plugin.hpp +++ b/plugins/base_plugin.hpp @@ -10,21 +10,21 @@ #include #include -#include +#include #include class base_plugin { public: std::string name; - boost::filesystem::path input_path; - boost::filesystem::path output_path; - boost::filesystem::path executable_path; + std::filesystem::path input_path; + std::filesystem::path output_path; + std::filesystem::path executable_path; base_plugin() { this->name = ""; }; base_plugin(const std::string &name) { this->name = name; }; base_plugin(const std::string &name, - const boost::filesystem::path &executable_path) { + const std::filesystem::path &executable_path) { this->name = name; this->executable_path = executable_path.parent_path(); } @@ -42,14 +42,14 @@ class base_plugin { * \param inputh_path_rhs input path to set * \param output_path_rhs output path to set (may be ommited) * */ - void plugin_setup(const boost::filesystem::path &input_path_rhs, - const boost::filesystem::path &output_path_rhs = - boost::filesystem::path()) { + void plugin_setup( + const std::filesystem::path &input_path_rhs, + const std::filesystem::path &output_path_rhs = std::filesystem::path()) { input_path = input_path_rhs; - if (!boost::filesystem::is_directory(input_path)) + if (!std::filesystem::is_directory(input_path)) throw(osmium::io_error("input_path '" + input_path.string() + "' is not valid.")); - if (boost::filesystem::is_directory(output_path_rhs.parent_path())) + if (std::filesystem::is_directory(output_path_rhs.parent_path())) output_path = output_path_rhs; } @@ -74,9 +74,9 @@ class base_plugin { * * \return returns true if input is existing and valid * */ - virtual bool check_input(const boost::filesystem::path &input_path, - const boost::filesystem::path &output_path = - boost::filesystem::path("")) = 0; + virtual bool check_input( + const std::filesystem::path &input_path, + const std::filesystem::path &output_path = std::filesystem::path("")) = 0; /** * \brief Converts input to OSM files diff --git a/plugins/dummy/dummy_plugin.cpp b/plugins/dummy/dummy_plugin.cpp index 35865a8..6b708e7 100644 --- a/plugins/dummy/dummy_plugin.cpp +++ b/plugins/dummy/dummy_plugin.cpp @@ -12,8 +12,7 @@ dummy_plugin::dummy_plugin() : base_plugin::base_plugin("Dummy Plugin") {} dummy_plugin::~dummy_plugin() {} -bool dummy_plugin::check_input(boost::filesystem::path, - boost::filesystem::path) { +bool dummy_plugin::check_input(std::filesystem::path, std::filesystem::path) { return true; } diff --git a/plugins/dummy/dummy_plugin.hpp b/plugins/dummy/dummy_plugin.hpp index ca1f17b..f362640 100644 --- a/plugins/dummy/dummy_plugin.hpp +++ b/plugins/dummy/dummy_plugin.hpp @@ -15,9 +15,8 @@ class dummy_plugin : public base_plugin { dummy_plugin(); virtual ~dummy_plugin(); - bool - check_input(boost::filesystem::path input_path, - boost::filesystem::path output_path = boost::filesystem::path()); + bool check_input(std::filesystem::path input_path, + std::filesystem::path output_path = std::filesystem::path()); void execute(); }; diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index 138c648..0dadd25 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -29,19 +29,19 @@ #include "../../util.hpp" AdminBoundariesConverter::AdminBoundariesConverter( - const boost::filesystem::path &executable_path) + const std::filesystem::path &executable_path) : Converter(executable_path) {} AdminBoundariesConverter::~AdminBoundariesConverter() {} void AdminBoundariesConverter::convert( - const std::vector &dirs, + const std::vector &dirs, osmium::io::Writer &writer) { - const boost::filesystem::path ADMINBNDY_2_SHP = "Adminbndy2.shp"; - const boost::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; - const boost::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; - const boost::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; + const std::filesystem::path ADMINBNDY_2_SHP = "Adminbndy2.shp"; + const std::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; + const std::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; + const std::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; std::map g_way_end_points_map; @@ -57,13 +57,13 @@ void AdminBoundariesConverter::convert( } void AdminBoundariesConverter::addLevel1Boundaries( - const std::vector &dirs, + const std::vector &dirs, std::map &g_way_end_points_map, osmium::io::Writer &writer) { - const boost::filesystem::path ADMINLINE_1_SHP = "AdminLine1.shp"; - const boost::filesystem::path ADMINBNDY_1_SHP = "Adminbndy1.shp"; + const std::filesystem::path ADMINLINE_1_SHP = "AdminLine1.shp"; + const std::filesystem::path ADMINBNDY_1_SHP = "Adminbndy1.shp"; std::map, std::vector>> @@ -98,7 +98,7 @@ void AdminBoundariesConverter::addLevel1Boundaries( } void AdminBoundariesConverter::add_admin_shape( - boost::filesystem::path admin_shape_file, + std::filesystem::path admin_shape_file, std::map &g_way_end_points_map, osmium::io::Writer &writer, @@ -125,7 +125,7 @@ void AdminBoundariesConverter::add_admin_shape( std::map> AdminBoundariesConverter::add_admin_lines( - boost::filesystem::path admin_line_shape_file, + std::filesystem::path admin_line_shape_file, std::map &g_way_end_points_map, osmium::io::Writer &writer) { @@ -262,7 +262,7 @@ AdminBoundariesConverter::build_admin_boundary_relation_with_tags( } void AdminBoundariesConverter::addLevelNBoundaries( - boost::filesystem::path dir, + std::filesystem::path dir, std::map &g_way_end_points_map, osmium::io::Writer &writer, uint level) { diff --git a/plugins/navteq/converter/AdminBoundariesConverter.hpp b/plugins/navteq/converter/AdminBoundariesConverter.hpp index de0e09d..16a9589 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.hpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.hpp @@ -33,21 +33,21 @@ class Builder; class AdminBoundariesConverter : public Converter { public: - AdminBoundariesConverter(const boost::filesystem::path &executable_path); + AdminBoundariesConverter(const std::filesystem::path &executable_path); virtual ~AdminBoundariesConverter(); - virtual void convert(const std::vector &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: void addLevel1Boundaries( - const std::vector &dirs, + const std::vector &dirs, std::map &g_way_end_points_map, osmium::io::Writer &writer); void add_admin_shape( - boost::filesystem::path admin_shape_file, + std::filesystem::path admin_shape_file, std::map &g_way_end_points_map, osmium::io::Writer &writer, @@ -56,7 +56,7 @@ class AdminBoundariesConverter : public Converter { &adminLineMap); std::map> - add_admin_lines(boost::filesystem::path admin_line_shape_file, + add_admin_lines(std::filesystem::path admin_line_shape_file, std::map &g_way_end_points_map, osmium::io::Writer &writer); @@ -91,7 +91,7 @@ class AdminBoundariesConverter : public Converter { osmium::memory::Buffer &rel_buffer); void addLevelNBoundaries( - boost::filesystem::path dir, + std::filesystem::path dir, std::map &g_way_end_points_map, osmium::io::Writer &writer, uint level); diff --git a/plugins/navteq/converter/BuildingConverter.cpp b/plugins/navteq/converter/BuildingConverter.cpp index 7433bde..f54a50a 100644 --- a/plugins/navteq/converter/BuildingConverter.cpp +++ b/plugins/navteq/converter/BuildingConverter.cpp @@ -28,16 +28,15 @@ #include "../../util.hpp" BuildingConverter::BuildingConverter( - const boost::filesystem::path &executable_path) + const std::filesystem::path &executable_path) : Converter(executable_path) {} BuildingConverter::~BuildingConverter() {} -void BuildingConverter::convert( - const std::vector &dirs, - osmium::io::Writer &writer) { +void BuildingConverter::convert(const std::vector &dirs, + osmium::io::Writer &writer) { - static const boost::filesystem::path LANDMARK_SHP = "Landmark.shp"; + static const std::filesystem::path LANDMARK_SHP = "Landmark.shp"; for (auto dir : dirs) { add_building_shape(dir / LANDMARK_SHP, writer); @@ -45,7 +44,7 @@ void BuildingConverter::convert( } void BuildingConverter::add_building_shape( - boost::filesystem::path landmark_shape_file, osmium::io::Writer &writer) { + std::filesystem::path landmark_shape_file, osmium::io::Writer &writer) { auto ds = GDALDatasetUniquePtr(GDALDataset::Open(landmark_shape_file.c_str())); diff --git a/plugins/navteq/converter/BuildingConverter.hpp b/plugins/navteq/converter/BuildingConverter.hpp index 54ac794..de5acf7 100644 --- a/plugins/navteq/converter/BuildingConverter.hpp +++ b/plugins/navteq/converter/BuildingConverter.hpp @@ -24,14 +24,14 @@ class BuildingConverter : public Converter { public: - BuildingConverter(const boost::filesystem::path &executable_path); + BuildingConverter(const std::filesystem::path &executable_path); virtual ~BuildingConverter(); - virtual void convert(const std::vector &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: - void add_building_shape(boost::filesystem::path landmark_shape_file, + void add_building_shape(std::filesystem::path landmark_shape_file, osmium::io::Writer &writer); void diff --git a/plugins/navteq/converter/CityConverter.cpp b/plugins/navteq/converter/CityConverter.cpp index 3b7fe0c..f60b317 100644 --- a/plugins/navteq/converter/CityConverter.cpp +++ b/plugins/navteq/converter/CityConverter.cpp @@ -26,22 +26,22 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -CityConverter::CityConverter(const boost::filesystem::path &executable_path) +CityConverter::CityConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} CityConverter::~CityConverter() {} -void CityConverter::convert(const std::vector &dirs, +void CityConverter::convert(const std::vector &dirs, osmium::io::Writer &writer) { - const boost::filesystem::path NAMED_PLC_SHP = "NamedPlc.shp"; + const std::filesystem::path NAMED_PLC_SHP = "NamedPlc.shp"; for (auto dir : dirs) { add_city_shape(dir / NAMED_PLC_SHP, writer); } } -void CityConverter::add_city_shape(boost::filesystem::path city_shape_file, +void CityConverter::add_city_shape(std::filesystem::path city_shape_file, osmium::io::Writer &writer) { auto ds = GDALDatasetUniquePtr(GDALDataset::Open(city_shape_file.c_str())); diff --git a/plugins/navteq/converter/CityConverter.hpp b/plugins/navteq/converter/CityConverter.hpp index f95d608..c5ced18 100644 --- a/plugins/navteq/converter/CityConverter.hpp +++ b/plugins/navteq/converter/CityConverter.hpp @@ -24,14 +24,14 @@ class CityConverter : public Converter { public: - CityConverter(const boost::filesystem::path &executable_path); + CityConverter(const std::filesystem::path &executable_path); virtual ~CityConverter(); - virtual void convert(const std::vector &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: - void add_city_shape(boost::filesystem::path city_shape_file, + void add_city_shape(std::filesystem::path city_shape_file, osmium::io::Writer &writer); void process_city(const OGRFeatureUniquePtr &feat, uint fac_type, diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 54283ad..1c9685f 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -249,14 +249,14 @@ std::string Converter::navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { // ISO-639 conversion void Converter::parse_lang_code_file() { - const boost::filesystem::path PLUGINS_NAVTEQ_ISO_639_2_UTF_8_TXT( + const std::filesystem::path PLUGINS_NAVTEQ_ISO_639_2_UTF_8_TXT( "plugins/navteq/ISO-639-2_utf-8.txt"); if (executable_path.empty()) throw(std::runtime_error("executable_path is empty")); - boost::filesystem::path iso_file(executable_path / - PLUGINS_NAVTEQ_ISO_639_2_UTF_8_TXT); + std::filesystem::path iso_file(executable_path / + PLUGINS_NAVTEQ_ISO_639_2_UTF_8_TXT); std::ifstream file(iso_file.string()); assert(file.is_open()); std::string line; @@ -296,8 +296,8 @@ std::string Converter::parse_lang_code(std::string lang_code) { } std::map -Converter::process_meta_areas(boost::filesystem::path dir) { - const boost::filesystem::path MTD_AREA_DBF = "MtdArea.dbf"; +Converter::process_meta_areas(std::filesystem::path dir) { + const std::filesystem::path MTD_AREA_DBF = "MtdArea.dbf"; std::map mtd_area_map; diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index f88eb7b..4ec6f45 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -17,7 +17,7 @@ #ifndef CONVERTER_HPP #define CONVERTER_HPP -#include +#include #include #include #include @@ -51,11 +51,11 @@ class OGRLinearRing; class Converter { public: - Converter(const boost::filesystem::path &_executable_path) + Converter(const std::filesystem::path &_executable_path) : executable_path(_executable_path) {} virtual ~Converter() {} - virtual void convert(const std::vector &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer) = 0; void set_dummy_osm_object_attributes(osmium::OSMObject &obj); @@ -128,7 +128,7 @@ class Converter { std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int); std::map - process_meta_areas(boost::filesystem::path dir); + process_meta_areas(std::filesystem::path dir); uint get_area_code_l(uint64_t l_area_id, uint64_t r_area_id, const std::map lang_code_map; - boost::filesystem::path executable_path; + std::filesystem::path executable_path; }; #endif // CONVERTER_HPP diff --git a/plugins/navteq/converter/HamletConverter.cpp b/plugins/navteq/converter/HamletConverter.cpp index 304ac57..f6d3d62 100644 --- a/plugins/navteq/converter/HamletConverter.cpp +++ b/plugins/navteq/converter/HamletConverter.cpp @@ -26,22 +26,22 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -HamletConverter::HamletConverter(const boost::filesystem::path &executable_path) +HamletConverter::HamletConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} HamletConverter::~HamletConverter() {} -void HamletConverter::convert(const std::vector &dirs, +void HamletConverter::convert(const std::vector &dirs, osmium::io::Writer &writer) { - const boost::filesystem::path HAMLET_SHP = "Hamlet.shp"; + const std::filesystem::path HAMLET_SHP = "Hamlet.shp"; for (const auto &dir : dirs) { add_hamlet(dir / HAMLET_SHP, writer); } } -void HamletConverter::add_hamlet(boost::filesystem::path hamlet_file, +void HamletConverter::add_hamlet(std::filesystem::path hamlet_file, osmium::io::Writer &writer) { auto ds = GDALDatasetUniquePtr(GDALDataset::Open(hamlet_file.c_str())); diff --git a/plugins/navteq/converter/HamletConverter.hpp b/plugins/navteq/converter/HamletConverter.hpp index 20ca57b..e78010a 100644 --- a/plugins/navteq/converter/HamletConverter.hpp +++ b/plugins/navteq/converter/HamletConverter.hpp @@ -24,14 +24,14 @@ class HamletConverter : public Converter { public: - HamletConverter(const boost::filesystem::path &executable_path); + HamletConverter(const std::filesystem::path &executable_path); virtual ~HamletConverter(); - virtual void convert(const std::vector &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: - void add_hamlet(boost::filesystem::path hamlet_file, + void add_hamlet(std::filesystem::path hamlet_file, osmium::io::Writer &writer); void process_hamlets(const OGRFeatureUniquePtr &feat, diff --git a/plugins/navteq/converter/LanduseConverter.cpp b/plugins/navteq/converter/LanduseConverter.cpp index ed6f7a7..d994992 100644 --- a/plugins/navteq/converter/LanduseConverter.cpp +++ b/plugins/navteq/converter/LanduseConverter.cpp @@ -26,16 +26,15 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -LanduseConverter::LanduseConverter( - const boost::filesystem::path &executable_path) +LanduseConverter::LanduseConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} LanduseConverter::~LanduseConverter() {} -void LanduseConverter::convert(const std::vector &dirs, +void LanduseConverter::convert(const std::vector &dirs, osmium::io::Writer &writer) { - const boost::filesystem::path LAND_USE_A_SHP = "LandUseA.shp"; - const boost::filesystem::path LAND_USE_B_SHP = "LandUseB.shp"; + const std::filesystem::path LAND_USE_A_SHP = "LandUseA.shp"; + const std::filesystem::path LAND_USE_B_SHP = "LandUseB.shp"; for (auto dir : dirs) { add_landuse_shape(dir / LAND_USE_A_SHP, writer); @@ -44,7 +43,7 @@ void LanduseConverter::convert(const std::vector &dirs, } void LanduseConverter::add_landuse_shape( - boost::filesystem::path landuse_shape_file, osmium::io::Writer &writer) { + std::filesystem::path landuse_shape_file, osmium::io::Writer &writer) { std::map g_way_end_points_map; auto ds = GDALDatasetUniquePtr(GDALDataset::Open(landuse_shape_file.c_str())); diff --git a/plugins/navteq/converter/LanduseConverter.hpp b/plugins/navteq/converter/LanduseConverter.hpp index 372db5a..34c5b50 100644 --- a/plugins/navteq/converter/LanduseConverter.hpp +++ b/plugins/navteq/converter/LanduseConverter.hpp @@ -24,14 +24,14 @@ class LanduseConverter : public Converter { public: - LanduseConverter(const boost::filesystem::path &executable_path); + LanduseConverter(const std::filesystem::path &executable_path); virtual ~LanduseConverter(); - virtual void convert(const std::vector &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: - void add_landuse_shape(boost::filesystem::path landuse_shape_file, + void add_landuse_shape(std::filesystem::path landuse_shape_file, osmium::io::Writer &writer); void diff --git a/plugins/navteq/converter/RailwayConverter.cpp b/plugins/navteq/converter/RailwayConverter.cpp index 2152b3d..2fd4f12 100644 --- a/plugins/navteq/converter/RailwayConverter.cpp +++ b/plugins/navteq/converter/RailwayConverter.cpp @@ -26,16 +26,15 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -RailwayConverter::RailwayConverter( - const boost::filesystem::path &executable_path) +RailwayConverter::RailwayConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} RailwayConverter::~RailwayConverter() {} -void RailwayConverter::convert(const std::vector &dirs, +void RailwayConverter::convert(const std::vector &dirs, osmium::io::Writer &writer) { - const boost::filesystem::path RAILWAYS_POLY_SHP = "RailRds.shp"; + const std::filesystem::path RAILWAYS_POLY_SHP = "RailRds.shp"; for (auto dir : dirs) { add_railways_shape(dir / RAILWAYS_POLY_SHP, writer); @@ -43,7 +42,7 @@ void RailwayConverter::convert(const std::vector &dirs, } void RailwayConverter::add_railways_shape( - boost::filesystem::path railway_shape_file, osmium::io::Writer &writer) { + std::filesystem::path railway_shape_file, osmium::io::Writer &writer) { auto ds = GDALDatasetUniquePtr(GDALDataset::Open(railway_shape_file.c_str())); if (!ds) { diff --git a/plugins/navteq/converter/RailwayConverter.hpp b/plugins/navteq/converter/RailwayConverter.hpp index 31e9291..b1e0d05 100644 --- a/plugins/navteq/converter/RailwayConverter.hpp +++ b/plugins/navteq/converter/RailwayConverter.hpp @@ -24,14 +24,14 @@ class RailwayConverter : public Converter { public: - RailwayConverter(const boost::filesystem::path &executable_path); + RailwayConverter(const std::filesystem::path &executable_path); virtual ~RailwayConverter(); - virtual void convert(const std::vector &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: - void add_railways_shape(boost::filesystem::path railway_shape_file, + void add_railways_shape(std::filesystem::path railway_shape_file, osmium::io::Writer &writer); void diff --git a/plugins/navteq/converter/RestAreaConverter.cpp b/plugins/navteq/converter/RestAreaConverter.cpp index 25273aa..b8e3327 100644 --- a/plugins/navteq/converter/RestAreaConverter.cpp +++ b/plugins/navteq/converter/RestAreaConverter.cpp @@ -27,22 +27,21 @@ #include "../../util.hpp" RestAreaConverter::RestAreaConverter( - const boost::filesystem::path &executable_path) + const std::filesystem::path &executable_path) : Converter(executable_path) {} RestAreaConverter::~RestAreaConverter() {} -void RestAreaConverter::convert( - const std::vector &dirs, - osmium::io::Writer &writer) { +void RestAreaConverter::convert(const std::vector &dirs, + osmium::io::Writer &writer) { - const boost::filesystem::path TRAVDEST_SHP = "TravDest.shp"; + const std::filesystem::path TRAVDEST_SHP = "TravDest.shp"; for (auto dir : dirs) { add_rest_area(dir / TRAVDEST_SHP, writer); } } -void RestAreaConverter::add_rest_area(boost::filesystem::path rest_area_file, +void RestAreaConverter::add_rest_area(std::filesystem::path rest_area_file, osmium::io::Writer &writer) { auto ds = GDALDatasetUniquePtr(GDALDataset::Open(rest_area_file.c_str())); diff --git a/plugins/navteq/converter/RestAreaConverter.hpp b/plugins/navteq/converter/RestAreaConverter.hpp index 3333945..b2af999 100644 --- a/plugins/navteq/converter/RestAreaConverter.hpp +++ b/plugins/navteq/converter/RestAreaConverter.hpp @@ -24,14 +24,14 @@ class RestAreaConverter : public Converter { public: - RestAreaConverter(const boost::filesystem::path &executable_path); + RestAreaConverter(const std::filesystem::path &executable_path); virtual ~RestAreaConverter(); - virtual void convert(const std::vector &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: - void add_rest_area(boost::filesystem::path rest_area_file, + void add_rest_area(std::filesystem::path rest_area_file, osmium::io::Writer &writer); void process_rest_area(const OGRFeatureUniquePtr &feat, diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 65a9409..62eea78 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -26,12 +26,12 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -StreetConverter::StreetConverter(const boost::filesystem::path &executable_path) +StreetConverter::StreetConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} StreetConverter::~StreetConverter() {} -void StreetConverter::convert(const std::vector &dirs, +void StreetConverter::convert(const std::vector &dirs, osmium::io::Writer &writer) { auto route_type_map = process_alt_steets_route_types(dirs); @@ -40,11 +40,11 @@ void StreetConverter::convert(const std::vector &dirs, } std::map StreetConverter::process_alt_steets_route_types( - const std::vector &dirs) { + const std::vector &dirs) { std::map route_type_map; - const boost::filesystem::path ALT_STREETS_DBF = "AltStreets.dbf"; + const std::filesystem::path ALT_STREETS_DBF = "AltStreets.dbf"; for (auto dir : dirs) { DBFHandle alt_streets_handle = read_dbf_file(dir / ALT_STREETS_DBF); for (int i = 0; i < DBFGetRecordCount(alt_streets_handle); i++) { @@ -74,7 +74,7 @@ std::map StreetConverter::process_alt_steets_route_types( } void StreetConverter::add_street_shapes( - const std::vector &dirs, + const std::vector &dirs, osmium::io::Writer &writer) { BOOST_LOG_TRIVIAL(info) << " processing z-levels"; @@ -93,7 +93,7 @@ void StreetConverter::add_street_shapes( std::map> StreetConverter::process_z_levels( - const std::vector &dirs) { + const std::vector &dirs) { std::map> z_level_map; for (auto &dir : dirs) { @@ -113,10 +113,10 @@ StreetConverter::process_z_levels( } void StreetConverter::init_z_level_map( - boost::filesystem::path dir, + std::filesystem::path dir, std::map> &z_level_map) { - const boost::filesystem::path ZLEVELS_DBF = "Zlevels.dbf"; + const std::filesystem::path ZLEVELS_DBF = "Zlevels.dbf"; // open dbf DBFHandle handle = read_dbf_file(dir / ZLEVELS_DBF); @@ -145,13 +145,13 @@ void StreetConverter::init_z_level_map( } void StreetConverter::init_conditional_modifications( - const boost::filesystem::path &dir) { + const std::filesystem::path &dir) { init_g_cnd_mod_map(dir); init_g_cdms_map(dir); } -void StreetConverter::init_g_cnd_mod_map(const boost::filesystem::path &dir) { - const boost::filesystem::path CND_MOD_DBF = "CndMod.dbf"; +void StreetConverter::init_g_cnd_mod_map(const std::filesystem::path &dir) { + const std::filesystem::path CND_MOD_DBF = "CndMod.dbf"; DBFHandle cnd_mod_handle = read_dbf_file(dir / CND_MOD_DBF); for (int i = 0; i < DBFGetRecordCount(cnd_mod_handle); i++) { uint64_t cond_id = dbf_get_uint_by_field(cnd_mod_handle, i, COND_ID.data()); @@ -178,8 +178,8 @@ void StreetConverter::init_g_cnd_mod_map(const boost::filesystem::path &dir) { DBFClose(cnd_mod_handle); } -void StreetConverter::init_g_cdms_map(const boost::filesystem::path &dir) { - const boost::filesystem::path CDMS_DBF = "Cdms.dbf"; +void StreetConverter::init_g_cdms_map(const std::filesystem::path &dir) { + const std::filesystem::path CDMS_DBF = "Cdms.dbf"; DBFHandle cdms_handle = read_dbf_file(dir / CDMS_DBF); for (int i = 0; i < DBFGetRecordCount(cdms_handle); i++) { uint64_t link_id = dbf_get_uint_by_field(cdms_handle, i, LINK_ID.data()); @@ -190,8 +190,7 @@ void StreetConverter::init_g_cdms_map(const boost::filesystem::path &dir) { DBFClose(cdms_handle); } -void StreetConverter::init_country_reference( - const boost::filesystem::path &dir) { +void StreetConverter::init_country_reference(const std::filesystem::path &dir) { if (dbf_file_exists(dir / MTD_AREA_DBF) && dbf_file_exists(dir / MTD_CNTRY_REF_DBF)) { init_g_area_to_govt_code_map(dir); @@ -200,7 +199,7 @@ void StreetConverter::init_country_reference( } void StreetConverter::init_g_area_to_govt_code_map( - const boost::filesystem::path &dir) { + const std::filesystem::path &dir) { DBFHandle mtd_area_handle = read_dbf_file(dir / MTD_AREA_DBF); for (int i = 0; i < DBFGetRecordCount(mtd_area_handle); i++) { uint64_t area_id = @@ -212,7 +211,7 @@ void StreetConverter::init_g_area_to_govt_code_map( DBFClose(mtd_area_handle); } -void StreetConverter::init_g_cntry_ref_map(const boost::filesystem::path &dir) { +void StreetConverter::init_g_cntry_ref_map(const std::filesystem::path &dir) { DBFHandle cntry_ref_handle = read_dbf_file(dir / MTD_CNTRY_REF_DBF); for (int i = 0; i < DBFGetRecordCount(cntry_ref_handle); i++) { uint64_t govt_code = @@ -230,7 +229,7 @@ void StreetConverter::init_g_cntry_ref_map(const boost::filesystem::path &dir) { } void StreetConverter::process_way_end_nodes( - const std::vector &dirs, + const std::vector &dirs, const std::map> &z_level_map, osmium::io::Writer &writer) { for (auto &dir : dirs) { @@ -299,7 +298,7 @@ void StreetConverter::process_way_end_node( } std::map> -StreetConverter::init_ramp_names(const boost::filesystem::path &dir) { +StreetConverter::init_ramp_names(const std::filesystem::path &dir) { std::map> ramps_ref_map; // read junction names from alt_streets @@ -312,7 +311,7 @@ StreetConverter::init_ramp_names(const boost::filesystem::path &dir) { } std::map -StreetConverter::read_junction_names(const boost::filesystem::path &dbf_file) { +StreetConverter::read_junction_names(const std::filesystem::path &dbf_file) { DBFHandle hwys_handle = read_dbf_file(dbf_file); std::map junctionNames; for (int i = 0; i < DBFGetRecordCount(hwys_handle); i++) { @@ -332,7 +331,7 @@ StreetConverter::read_junction_names(const boost::filesystem::path &dbf_file) { } void StreetConverter::parse_ramp_names( - const boost::filesystem::path &shp_file, + const std::filesystem::path &shp_file, std::map> &ramps_ref_map, const std::map &junctionNames) { @@ -376,7 +375,7 @@ void StreetConverter::parse_ramp_names( } void StreetConverter::process_way( - const std::vector &dirs, + const std::vector &dirs, const std::map> &z_level_map, osmium::io::Writer &writer) { for (auto &dir : dirs) { @@ -409,7 +408,7 @@ void StreetConverter::process_way( } std::map> -StreetConverter::init_highway_names(const boost::filesystem::path &dir) { +StreetConverter::init_highway_names(const std::filesystem::path &dir) { std::map> hwys_ref_map; if (dbf_file_exists(dir / MAJ_HWYS_DBF)) parse_highway_names(dir / MAJ_HWYS_DBF, hwys_ref_map, false); @@ -424,7 +423,7 @@ StreetConverter::init_highway_names(const boost::filesystem::path &dir) { } void StreetConverter::parse_highway_names( - const boost::filesystem::path &dbf_file, + const std::filesystem::path &dbf_file, std::map> &hwys_ref_map, bool isStreetLayer) { DBFHandle hwys_handle = read_dbf_file(dbf_file); @@ -445,7 +444,7 @@ void StreetConverter::parse_highway_names( } void StreetConverter::init_under_construction( - const boost::filesystem::path &dir) { + const std::filesystem::path &dir) { if (!dbf_file_exists(dir / CDMS_DBF)) return; @@ -1480,7 +1479,7 @@ void StreetConverter::create_premium_house_numbers( } void StreetConverter::process_house_numbers( - const std::vector &dirs, + const std::vector &dirs, osmium::io::Writer &writer) { for (auto &dir : dirs) { // create point addresses from PointAddress.dbf @@ -1537,7 +1536,7 @@ void StreetConverter::process_house_numbers( } std::map>> * -StreetConverter::createPointAddressMapList(const boost::filesystem::path &dir) { +StreetConverter::createPointAddressMapList(const std::filesystem::path &dir) { auto pointAddressMap = new std::map &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: @@ -78,29 +78,29 @@ class StreetConverter : public Converter { }; std::map process_alt_steets_route_types( - const std::vector &dirs); + const std::vector &dirs); - void add_street_shapes(const std::vector &dirs, + void add_street_shapes(const std::vector &dirs, osmium::io::Writer &writer); std::map> - process_z_levels(const std::vector &dirs); + process_z_levels(const std::vector &dirs); void init_z_level_map( - boost::filesystem::path dir, + std::filesystem::path dir, std::map> &z_level_map); - void init_conditional_modifications(const boost::filesystem::path &dir); - void init_g_cnd_mod_map(const boost::filesystem::path &dir); - void init_g_cdms_map(const boost::filesystem::path &dir); + void init_conditional_modifications(const std::filesystem::path &dir); + void init_g_cnd_mod_map(const std::filesystem::path &dir); + void init_g_cdms_map(const std::filesystem::path &dir); - void init_country_reference(const boost::filesystem::path &dir); - void init_g_area_to_govt_code_map(const boost::filesystem::path &dir); - void init_g_cntry_ref_map(const boost::filesystem::path &dir); + void init_country_reference(const std::filesystem::path &dir); + void init_g_area_to_govt_code_map(const std::filesystem::path &dir); + void init_g_cntry_ref_map(const std::filesystem::path &dir); // process end nodes void process_way_end_nodes( - const std::vector &dirs, + const std::vector &dirs, const std::map> &z_level_map, osmium::io::Writer &writer); void process_way_end_nodes(OGRFeatureUniquePtr &feat, @@ -110,16 +110,16 @@ class StreetConverter : public Converter { // ramp names std::map> - init_ramp_names(const boost::filesystem::path &dir); + init_ramp_names(const std::filesystem::path &dir); std::map - read_junction_names(const boost::filesystem::path &dbf_file); + read_junction_names(const std::filesystem::path &dbf_file); void parse_ramp_names( - const boost::filesystem::path &shp_file, + const std::filesystem::path &shp_file, std::map> &ramps_ref_map, const std::map &junctionNames); void process_way( - const std::vector &dirs, + const std::vector &dirs, const std::map> &z_level_map, osmium::io::Writer &writer); void process_way( @@ -155,10 +155,10 @@ class StreetConverter : public Converter { const std::set &construction_set, bool debugMode); std::map> - init_highway_names(const boost::filesystem::path &dir); + init_highway_names(const std::filesystem::path &dir); void parse_highway_names( - const boost::filesystem::path &dbf_file, + const std::filesystem::path &dbf_file, std::map> &hwys_ref_map, bool isStreetLayer); void add_additional_restrictions( @@ -253,7 +253,7 @@ class StreetConverter : public Converter { bool only_pedestrians(const OGRFeatureUniquePtr &f); - void init_under_construction(const boost::filesystem::path &dir); + void init_under_construction(const std::filesystem::path &dir); void add_here_speed_cat_tag(osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f); @@ -273,7 +273,7 @@ class StreetConverter : public Converter { const std::vector> &addressList, int linkId, osmium::memory::Buffer &node_buffer); - void process_house_numbers(const std::vector &dirs, + void process_house_numbers(const std::vector &dirs, osmium::io::Writer &writer); void process_house_numbers( @@ -285,7 +285,7 @@ class StreetConverter : public Converter { osmium::memory::Buffer &way_buffer); std::map>> * - createPointAddressMapList(const boost::filesystem::path &dir); + createPointAddressMapList(const std::filesystem::path &dir); // CndMod types (CM) static constexpr std::string_view CM_MOD_TYPE = "MOD_TYPE"; diff --git a/plugins/navteq/converter/WaterConverter.cpp b/plugins/navteq/converter/WaterConverter.cpp index b58a81b..ee441b9 100644 --- a/plugins/navteq/converter/WaterConverter.cpp +++ b/plugins/navteq/converter/WaterConverter.cpp @@ -25,16 +25,16 @@ #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" -WaterConverter::WaterConverter(const boost::filesystem::path &executable_path) +WaterConverter::WaterConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} WaterConverter::~WaterConverter() {} -void WaterConverter::convert(const std::vector &dirs, +void WaterConverter::convert(const std::vector &dirs, osmium::io::Writer &writer) { - const boost::filesystem::path WATER_SEG_SHP = "WaterSeg.shp"; - const boost::filesystem::path WATER_POLY_SHP = "WaterPoly.shp"; + const std::filesystem::path WATER_SEG_SHP = "WaterSeg.shp"; + const std::filesystem::path WATER_POLY_SHP = "WaterPoly.shp"; for (auto dir : dirs) { add_water_shape(dir / WATER_POLY_SHP, writer); @@ -42,7 +42,7 @@ void WaterConverter::convert(const std::vector &dirs, } } -void WaterConverter::add_water_shape(boost::filesystem::path water_shape_file, +void WaterConverter::add_water_shape(std::filesystem::path water_shape_file, osmium::io::Writer &writer) { auto ds = GDALDatasetUniquePtr(GDALDataset::Open(water_shape_file.c_str())); diff --git a/plugins/navteq/converter/WaterConverter.hpp b/plugins/navteq/converter/WaterConverter.hpp index 20d1bf9..19b7016 100644 --- a/plugins/navteq/converter/WaterConverter.hpp +++ b/plugins/navteq/converter/WaterConverter.hpp @@ -39,14 +39,14 @@ class OGRLineString; class WaterConverter : public Converter { public: - WaterConverter(const boost::filesystem::path &executable_path); + WaterConverter(const std::filesystem::path &executable_path); virtual ~WaterConverter(); - virtual void convert(const std::vector &dirs, + virtual void convert(const std::vector &dirs, osmium::io::Writer &writer); private: - void add_water_shape(boost::filesystem::path water_shape_file, + void add_water_shape(std::filesystem::path water_shape_file, osmium::io::Writer &writer); void process_water(const OGRFeatureUniquePtr &feat, diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 8f6c084..8026bbb 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -13,24 +13,24 @@ namespace { -static const boost::filesystem::path STREETS_SHP = "Streets.shp"; -static const boost::filesystem::path ADMINLINE_1_SHP = "AdminLine1.shp"; -static const boost::filesystem::path ADMINBNDY_1_SHP = "Adminbndy1.shp"; -static const boost::filesystem::path ADMINBNDY_2_SHP = "Adminbndy2.shp"; -static const boost::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; -static const boost::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; -static const boost::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; +static const std::filesystem::path STREETS_SHP = "Streets.shp"; +static const std::filesystem::path ADMINLINE_1_SHP = "AdminLine1.shp"; +static const std::filesystem::path ADMINBNDY_1_SHP = "Adminbndy1.shp"; +static const std::filesystem::path ADMINBNDY_2_SHP = "Adminbndy2.shp"; +static const std::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; +static const std::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; +static const std::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; -static const boost::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; +static const std::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; -static const boost::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; +static const std::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; -static const boost::filesystem::path RDMS_DBF = "Rdms.dbf"; +static const std::filesystem::path RDMS_DBF = "Rdms.dbf"; -static const boost::filesystem::path MAJ_HWYS_DBF = "MajHwys.dbf"; -static const boost::filesystem::path SEC_HWYS_DBF = "SecHwys.dbf"; +static const std::filesystem::path MAJ_HWYS_DBF = "MajHwys.dbf"; +static const std::filesystem::path SEC_HWYS_DBF = "SecHwys.dbf"; -static const boost::filesystem::path STREETS_DBF = "Streets.dbf"; +static const std::filesystem::path STREETS_DBF = "Streets.dbf"; // condition types (CT) #define CT_RESTRICTED_DRIVING_MANOEUVRE 7 diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 6383866..604fe79 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -6,15 +6,16 @@ */ #include -#include #include #include #include #include +#include #include #include #include #include +#include #include "converter/AdminBoundariesConverter.hpp" #include "converter/BuildingConverter.hpp" @@ -35,7 +36,7 @@ */ -navteq_plugin::navteq_plugin(const boost::filesystem::path &executable_path) +navteq_plugin::navteq_plugin(const std::filesystem::path &executable_path) : base_plugin::base_plugin("Navteq Plugin", executable_path) { converter.emplace_back(new AdminBoundariesConverter(executable_path)); @@ -63,11 +64,33 @@ bool navteq_plugin::is_valid_format(std::string filename) { return false; } -bool navteq_plugin::check_files(const boost::filesystem::path &dir) { +std::optional +navteq_plugin::check_files(const std::filesystem::path &dir) { + + bool isHereDatatDir = false; + bool hasPackedData = false; + std::filesystem::path tarFile; + for (const auto &entry : std::filesystem::directory_iterator(dir) | + std::views::filter([](auto &entry) { + return entry.is_regular_file(); + })) { + if (entry.path().extension() == ".PROD.csv") { + isHereDatatDir = true; + } + + if (entry.path().extension() == ".tar.gz") { + hasPackedData = true; + tarFile = entry.path(); + } + } - // check if the directory contains HERE data + if (!isHereDatatDir) + return std::nullopt; - // checck if the PROD.csv file exists + if (hasPackedData) + return std::optional(tarFile / "vsitar"); + + // check if the PROD.csv file exists // check HERE-Contrycodes @@ -75,37 +98,18 @@ bool navteq_plugin::check_files(const boost::filesystem::path &dir) { // otherwise check id there are unpacked files - return true; -} - -/** - * \brief Checks wether there is a subdirectory containinig valid data. - * \param dir directory from which to start recursion - * \param recur if set non-directories within the root directory are ignored - * \return Existance of valid data in a subdirectory. - */ - -void navteq_plugin::recurse_dir(const boost::filesystem::path &dir) { - if (check_files(dir)) - dataDirs.push_back(dir); - - for (auto &itr : boost::make_iterator_range( - boost::filesystem::directory_iterator(dir), {})) { - if (boost::filesystem::is_directory(itr)) { - recurse_dir(itr); - } - } + return std::nullopt; } -bool navteq_plugin::check_input(const boost::filesystem::path &input_path, - const boost::filesystem::path &output_file) { - if (!boost::filesystem::is_directory(input_path)) +bool navteq_plugin::check_input(const std::filesystem::path &input_path, + const std::filesystem::path &output_file) { + if (!std::filesystem::is_directory(input_path)) throw(std::runtime_error("directory " + input_path.string() + " does not exist")); if (!output_file.empty()) { - boost::filesystem::path output_path = output_file.parent_path(); - if (!boost::filesystem::is_directory(output_path)) + std::filesystem::path output_path = output_file.parent_path(); + if (!std::filesystem::is_directory(output_path)) throw(std::runtime_error("output directory " + output_path.string() + " does not exist")); if (!is_valid_format(output_file.string())) @@ -113,7 +117,12 @@ bool navteq_plugin::check_input(const boost::filesystem::path &input_path, output_file.string())); } - recurse_dir(input_path); + for (const auto &entry : + std::filesystem::recursive_directory_iterator(input_path) | + std::views::filter( + [](auto &entry) { return entry.is_directory(); })) { + check_files(entry).and_then([&](auto &path) { dataDirs.push_back(path); }); + } if (!foundCountries.empty()) { BOOST_LOG_TRIVIAL(info) @@ -181,7 +190,7 @@ void navteq_plugin::sortPBF() { writer.close(); - boost::filesystem::remove(output_path.parent_path().append("tmp.pbf")); + std::filesystem::remove(output_path.parent_path().append("tmp.pbf")); } void navteq_plugin::copyType(osmium::io::Writer &writer, osmium::io::File &file, diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index c934e5c..d6f37bd 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -10,9 +10,10 @@ #include "../base_plugin.hpp" #include "converter/Converter.hpp" -#include +#include #include #include + namespace osmium { namespace io { class Writer; @@ -23,15 +24,15 @@ class File; class navteq_plugin : public base_plugin { private: bool is_valid_format(std::string format); - void recurse_dir(const boost::filesystem::path &dir); - bool check_files(const boost::filesystem::path &dir); + std::optional + check_files(const std::filesystem::path &dir); void write_output(); void sortPBF(); void copyType(osmium::io::Writer &writer, osmium::io::File &file, osmium::osm_entity_bits::type bits); - std::vector dataDirs; + std::vector dataDirs; std::vector> converter; @@ -42,12 +43,12 @@ class navteq_plugin : public base_plugin { bool debug; public: - navteq_plugin(const boost::filesystem::path &executable_path); + navteq_plugin(const std::filesystem::path &executable_path); virtual ~navteq_plugin(); bool check_input( - const boost::filesystem::path &input_path, - const boost::filesystem::path &output_path = boost::filesystem::path()); + const std::filesystem::path &input_path, + const std::filesystem::path &output_file = std::filesystem::path()); void execute(); void setBoundingBox(double minX, double minY, double maxX, double maxY); diff --git a/plugins/readers.hpp b/plugins/readers.hpp index 1a80a5e..4e370b5 100644 --- a/plugins/readers.hpp +++ b/plugins/readers.hpp @@ -15,7 +15,7 @@ #include "comm2osm_exceptions.hpp" -GDALDatasetUniquePtr open_shape_file(boost::filesystem::path shp_file) { +GDALDatasetUniquePtr open_shape_file(std::filesystem::path shp_file) { BOOST_LOG_TRIVIAL(debug) << "\treading " << shp_file; auto input_data_source = @@ -26,7 +26,7 @@ GDALDatasetUniquePtr open_shape_file(boost::filesystem::path shp_file) { return input_data_source; } -DBFHandle read_dbf_file(boost::filesystem::path dbf_file) { +DBFHandle read_dbf_file(std::filesystem::path dbf_file) { BOOST_LOG_TRIVIAL(debug) << "\treading " << dbf_file; DBFHandle handle = DBFOpen(dbf_file.c_str(), "rb"); if (handle == nullptr) diff --git a/plugins/util.hpp b/plugins/util.hpp index 857786f..874e89f 100644 --- a/plugins/util.hpp +++ b/plugins/util.hpp @@ -47,7 +47,7 @@ bool shp_file_exists(const std::string &shp_file) { return input_data_source != nullptr; } -bool shp_file_exists(boost::filesystem::path shp_file) { +bool shp_file_exists(std::filesystem::path shp_file) { return shp_file_exists(shp_file.string()); } @@ -65,7 +65,7 @@ bool dbf_file_exists(const std::string &dbf_file) { return true; } -bool dbf_file_exists(const boost::filesystem::path &dbf_file) { +bool dbf_file_exists(const std::filesystem::path &dbf_file) { return dbf_file_exists(dbf_file.string()); } @@ -232,7 +232,7 @@ void add_uint_tag(osmium::builder::TagListBuilder &tl_builder, } bool checkInBoundingBox(const OGREnvelope &boundingBox, - const boost::filesystem::path &shp_file) { + const std::filesystem::path &shp_file) { if (!boundingBox.IsInit()) return true; diff --git a/tests/unit_test_util.cpp b/tests/unit_test_util.cpp index 596447e..2ef0f6a 100644 --- a/tests/unit_test_util.cpp +++ b/tests/unit_test_util.cpp @@ -16,11 +16,11 @@ TEST_CASE("Shapefile exists", "[SHP exist]") { CHECK(shp_file_exists( std::string("tests/testdata/faroe-islands-latest/???")) == false); - CHECK(shp_file_exists(boost::filesystem::path( + CHECK(shp_file_exists(std::filesystem::path( "tests/testdata/faroe-islands-latest/roads.shp")) == true); - CHECK(shp_file_exists(boost::filesystem::path( + CHECK(shp_file_exists(std::filesystem::path( "tests/testdata/faroe-islands-latest/README")) == false); - CHECK(shp_file_exists(boost::filesystem::path( + CHECK(shp_file_exists(std::filesystem::path( "tests/testdata/faroe-islands-latest/???")) == false); } @@ -37,11 +37,11 @@ TEST_CASE("DBF exists", "[DBF exist]") { CHECK(dbf_file_exists( std::string("tests/testdata/faroe-islands-latest/???")) == false); - CHECK(dbf_file_exists(boost::filesystem::path( + CHECK(dbf_file_exists(std::filesystem::path( "tests/testdata/faroe-islands-latest/roads.dbf")) == true); - CHECK(dbf_file_exists(boost::filesystem::path( + CHECK(dbf_file_exists(std::filesystem::path( "tests/testdata/faroe-islands-latest/README")) == false); - CHECK(dbf_file_exists(boost::filesystem::path( + CHECK(dbf_file_exists(std::filesystem::path( "tests/testdata/faroe-islands-latest/???")) == false); } From fcc282ebd23633d39c896176b24b88582678d3f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 19:24:57 +0000 Subject: [PATCH 25/57] Refactor StreetConverter to remove unused code and improve readability --- plugins/navteq/converter/StreetConverter.cpp | 16 ++++++++++++++++ plugins/navteq/converter/StreetConverter.hpp | 20 +++++++++++++++++++- plugins/navteq/navteq_mappings.hpp | 15 --------------- plugins/util.hpp | 18 +----------------- 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 62eea78..bc673bb 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -1575,3 +1575,19 @@ StreetConverter::createPointAddressMapList(const std::filesystem::path &dir) { } return pointAddressMap; } + +void StreetConverter::set_ferry_z_lvls_to_zero( + const OGRFeatureUniquePtr &feat, + std::vector &z_lvl_vec) { + // erase middle z_lvls + if (z_lvl_vec.size() > 2) + z_lvl_vec.erase(z_lvl_vec.begin() + 1, z_lvl_vec.end() - 1); + // erase first z_lvl if first index references first node + if (!z_lvl_vec.empty() && z_lvl_vec.begin()->index != 0) + z_lvl_vec.erase(z_lvl_vec.begin()); + // erase last z_lvl if last index references last node + OGRLineString *ogr_ls = static_cast(feat->GetGeometryRef()); + if (!z_lvl_vec.empty() && + (z_lvl_vec.end() - 1)->index != ogr_ls->getNumPoints() - 1) + z_lvl_vec.erase(z_lvl_vec.end()); +} diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index 067b68f..0fd906b 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -90,6 +90,9 @@ class StreetConverter : public Converter { std::filesystem::path dir, std::map> &z_level_map); + void set_ferry_z_lvls_to_zero(const OGRFeatureUniquePtr &feat, + std::vector &z_lvl_vec); + void init_conditional_modifications(const std::filesystem::path &dir); void init_g_cnd_mod_map(const std::filesystem::path &dir); void init_g_cdms_map(const std::filesystem::path &dir); @@ -409,7 +412,22 @@ class StreetConverter : public Converter { "", ">130", "101-130", "91-100", "71-90", "51-70", "31-50", "11-30", "<11"}; - constexpr double HOUSENUMBER_CURVE_OFFSET = 0.00005; + const double HOUSENUMBER_CURVE_OFFSET = 0.00005; + + // condition types (CT) + const ushort CT_RESTRICTED_DRIVING_MANOEUVRE = 7; + const ushort CT_TRANSPORT_ACCESS_RESTRICTION = 23; + const ushort CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE = 26; + + // modifier types (MT) + const ushort MT_HAZARDOUS_RESTRICTION = 39; + const ushort MT_HEIGHT_RESTRICTION = 41; + const ushort MT_WEIGHT_RESTRICTION = 42; + const ushort MT_WEIGHT_PER_AXLE_RESTRICTION = 43; + const ushort MT_LENGTH_RESTRICTION = 44; + const ushort MT_WIDTH_RESTRICTION = 45; + + const ushort RESTRICTED_DRIVING_MANOEUVRE = 7; }; #endif // STREETCONVERTER_HPP diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 8026bbb..4149dea 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -32,21 +32,6 @@ static const std::filesystem::path SEC_HWYS_DBF = "SecHwys.dbf"; static const std::filesystem::path STREETS_DBF = "Streets.dbf"; -// condition types (CT) -#define CT_RESTRICTED_DRIVING_MANOEUVRE 7 -#define CT_TRANSPORT_ACCESS_RESTRICTION 23 -#define CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE 26 - -// modifier types (MT) -#define MT_HAZARDOUS_RESTRICTION 39 -#define MT_HEIGHT_RESTRICTION 41 -#define MT_WEIGHT_RESTRICTION 42 -#define MT_WEIGHT_PER_AXLE_RESTRICTION 43 -#define MT_LENGTH_RESTRICTION 44 -#define MT_WIDTH_RESTRICTION 45 - -#define RESTRICTED_DRIVING_MANOEUVRE 7 - } // namespace #endif /* PLUGINS_NAVTEQ_MAPPINGS_HPP_ */ diff --git a/plugins/util.hpp b/plugins/util.hpp index 874e89f..6d8b013 100644 --- a/plugins/util.hpp +++ b/plugins/util.hpp @@ -269,21 +269,6 @@ void test__z_lvl_range(short z_lvl) { " is not valid")); } -void set_ferry_z_lvls_to_zero(OGRFeatureUniquePtr &feat, - index_z_lvl_vector_type &z_lvl_vec) { - // erase middle z_lvls - if (z_lvl_vec.size() > 2) - z_lvl_vec.erase(z_lvl_vec.begin() + 1, z_lvl_vec.end() - 1); - // erase first z_lvl if first index references first node - if (!z_lvl_vec.empty() && z_lvl_vec.begin()->first != 0) - z_lvl_vec.erase(z_lvl_vec.begin()); - // erase last z_lvl if last index references last node - OGRLineString *ogr_ls = static_cast(feat->GetGeometryRef()); - if (!z_lvl_vec.empty() && - (z_lvl_vec.end() - 1)->first != ogr_ls->getNumPoints() - 1) - z_lvl_vec.erase(z_lvl_vec.end()); -} - bool is_ferry(const char *value) { if (!strcmp(value, "H")) return false; // H --> not a ferry @@ -291,8 +276,7 @@ bool is_ferry(const char *value) { return true; // T --> boat ferry else if (!strcmp(value, "R")) return true; // B --> rail ferry - throw(format_error("value '" + std::string(value) + "' for " + - std::string(FERRY) + " not valid")); + throw(format_error("value '" + std::string(value) + "' for FERRY not valid")); } /** From bee78f4d025cd040742ca0a45c1f906b83514a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 19:44:33 +0000 Subject: [PATCH 26/57] use gdal to access dbf files --- plugins/navteq/converter/CityConverter.cpp | 9 ++--- plugins/navteq/converter/Converter.cpp | 37 ++++++++++++++------ plugins/navteq/converter/Converter.hpp | 13 +++++++ plugins/navteq/converter/StreetConverter.hpp | 9 ----- 4 files changed, 41 insertions(+), 27 deletions(-) diff --git a/plugins/navteq/converter/CityConverter.cpp b/plugins/navteq/converter/CityConverter.cpp index f60b317..7d6a7f7 100644 --- a/plugins/navteq/converter/CityConverter.cpp +++ b/plugins/navteq/converter/CityConverter.cpp @@ -44,14 +44,9 @@ void CityConverter::convert(const std::vector &dirs, void CityConverter::add_city_shape(std::filesystem::path city_shape_file, osmium::io::Writer &writer) { - auto ds = GDALDatasetUniquePtr(GDALDataset::Open(city_shape_file.c_str())); - if (!ds) { - BOOST_LOG_TRIVIAL(debug) << "No city shp found in " << city_shape_file; - return; - } - auto layer = ds->GetLayer(0); + auto layer = openDataSource(city_shape_file).value_or(nullptr); if (!layer) - throw(shp_empty_error(city_shape_file.string())); + return; osmium::memory::Buffer node_buffer(BUFFER_SIZE); diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 1c9685f..68defc1 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -9,6 +9,7 @@ #include #include "../../comm2osm_exceptions.hpp" +#include "../../util.hpp" osmium::unsigned_object_id_type Converter::g_osm_id = 1; @@ -301,12 +302,13 @@ Converter::process_meta_areas(std::filesystem::path dir) { std::map mtd_area_map; - DBFHandle handle = read_dbf_file(dir / MTD_AREA_DBF); - - for (int i = 0; i < DBFGetRecordCount(handle); i++) { + auto layer = openDataSource(dir / MTD_AREA_DBF).or_else([]() -> OGRLayer * { + throw(std::runtime_error("could not open MtdArea.dbf")); + }); + for (auto &feat : *layer) { osmium::unsigned_object_id_type area_id = - dbf_get_uint_by_field(handle, i, AREA_ID); + get_uint_from_feature(feat, AREA_ID); // find or create a new area data set mtd_area_dataset &data = mtd_area_map[area_id]; @@ -314,7 +316,7 @@ Converter::process_meta_areas(std::filesystem::path dir) { data.area_id = area_id; std::string admin_lvl = - std::to_string(dbf_get_uint_by_field(handle, i, ADMIN_LVL)); + std::to_string(get_uint_from_feature(feat, ADMIN_LVL)); if (data.admin_lvl.empty()) { data.admin_lvl = admin_lvl; } else if (data.admin_lvl != admin_lvl) { @@ -323,24 +325,23 @@ Converter::process_meta_areas(std::filesystem::path dir) { << " has multiple admin_lvls:" << data.admin_lvl << ", " << admin_lvl; } - std::string lang_code = dbf_get_string_by_field(handle, i, LANG_CODE); - std::string area_name = dbf_get_string_by_field(handle, i, AREA_NAME); + std::string lang_code = get_field_from_feature(feat, LANG_CODE); + std::string area_name = get_field_from_feature(feat, AREA_NAME); - std::string area_type = dbf_get_string_by_field(handle, i, "AREA_TYPE"); + std::string area_type = get_field_from_feature(feat, "AREA_TYPE"); if (area_type == "B") { data.name = to_camel_case_with_spaces(area_name); data.lang_code_2_area_name.emplace_back( lang_code, to_camel_case_with_spaces(area_name)); - data.area_code_1 = dbf_get_uint_by_field(handle, i, AREA_CODE_1); + data.area_code_1 = get_uint_from_feature(feat, AREA_CODE_1); } else if (area_type == "A") { data.short_name = to_camel_case_with_spaces(area_name); } else { data.lang_code_2_area_name.emplace_back( lang_code, to_camel_case_with_spaces(area_name)); - data.area_code_1 = dbf_get_uint_by_field(handle, i, AREA_CODE_1); + data.area_code_1 = get_uint_from_feature(feat, AREA_CODE_1); } } - DBFClose(handle); return mtd_area_map; } @@ -370,3 +371,17 @@ uint Converter::get_area_code_l( return get_area_code_l(l_area_id, r_area_id, mtd_area_map); } + +std::optional +openDataSource(const std::filesystem::path &shape_file) { + auto ds = GDALDatasetUniquePtr(GDALDataset::Open(shape_file.c_str())); + if (!ds) { + BOOST_LOG_TRIVIAL(debug) << "No shp found in " << shape_file; + return std::nullopt; + } + auto layer = ds->GetLayer(0); + if (!layer) + throw(shp_empty_error(shape_file.string())); + + return std::optional(layer); +} diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 4ec6f45..983e9fc 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -142,6 +143,9 @@ class Converter { std::string parse_lang_code(std::string lang_code); + std::optional + openDataSource(const std::filesystem::path &shape_file); + static constexpr int BUFFER_SIZE = 10 * 1000 * 1000; static constexpr int OSM_MAX_WAY_NODES = 1000; @@ -166,6 +170,15 @@ class Converter { static constexpr std::string_view LINK_ID = "LINK_ID"; + // MTD_AREA_DBF columns + static constexpr std::string_view LANG_CODE = "LANG_CODE"; + static constexpr std::string_view AREA_NAME = "AREA_NAME"; + static constexpr std::string_view AREA_CODE_1 = "AREACODE_1"; + static constexpr std::string_view L_AREA_ID = "L_AREA_ID"; + static constexpr std::string_view R_AREA_ID = "R_AREA_ID"; + static constexpr std::string_view ADMIN_LVL = "ADMIN_LVL"; + static constexpr std::string_view AREA_ID = "AREA_ID"; + static constexpr int NAVTEQ_ADMIN_LVL_MIN = 1; static constexpr int NAVTEQ_ADMIN_LVL_MAX = 7; diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index 0fd906b..6ee5fe7 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -298,12 +298,6 @@ class StreetConverter : public Converter { static constexpr std::string_view Z_LEVEL = "Z_LEVEL"; static constexpr std::string_view POINT_NUM = "POINT_NUM"; - // MTD_AREA_DBF columns - static constexpr std::string_view AREA_ID = "AREA_ID"; - static constexpr std::string_view LANG_CODE = "LANG_CODE"; - static constexpr std::string_view AREA_NAME = "AREA_NAME"; - static constexpr std::string_view AREA_CODE_1 = "AREACODE_1"; - static constexpr std::string_view ADMIN_LVL = "ADMIN_LVL"; static constexpr std::string_view GOVT_CODE = "GOVT_CODE"; // RDMS_DBF columns @@ -319,9 +313,6 @@ class StreetConverter : public Converter { static constexpr std::string_view SPEEDLIMITUNIT = "SPDLIMUNIT"; static constexpr std::string_view ISO_CODE = "ISO_CODE"; - static constexpr std::string_view L_AREA_ID = "L_AREA_ID"; - static constexpr std::string_view R_AREA_ID = "R_AREA_ID"; - static constexpr std::string_view ROUTE = "ROUTE_TYPE"; static constexpr std::string_view FUNC_CLASS = "FUNC_CLASS"; static constexpr std::string_view SPEED_CAT = "SPEED_CAT"; From c5c62451f2a40a5d6552edb87aa0f235a0de2bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 15 Jul 2024 19:44:44 +0000 Subject: [PATCH 27/57] refactor: Remove boost-filesystem dependency and use std::filesystem instead --- .devcontainer/vcpkg.json | 1 - CMakeLists.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.devcontainer/vcpkg.json b/.devcontainer/vcpkg.json index 8ef0e0d..a422703 100644 --- a/.devcontainer/vcpkg.json +++ b/.devcontainer/vcpkg.json @@ -2,7 +2,6 @@ "dependencies": [ "boost-log", "boost-program-options", - "boost-filesystem", "icu", "boost-timer", "shapelib", diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b32eed..fc28a39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ ENDIF() set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) -find_package(Boost REQUIRED COMPONENTS system filesystem log program_options) +find_package(Boost REQUIRED COMPONENTS system log program_options) find_package(GDAL REQUIRED) find_package(geos REQUIRED) find_path(OSMIUM_INCLUDE_DIRS "osmium/version.hpp") From 6f62681f570870530c36dc52bafdfb389fe85c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Tue, 16 Jul 2024 06:54:20 +0000 Subject: [PATCH 28/57] Refactor Converter class to handle navteq admin level as string --- .../converter/AdminBoundariesConverter.cpp | 37 ++++++++++++++----- .../converter/AdminBoundariesConverter.hpp | 15 ++++++-- plugins/navteq/converter/Converter.cpp | 7 ++++ plugins/navteq/converter/Converter.hpp | 2 + plugins/navteq/navteq_plugin.cpp | 2 +- 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index 0dadd25..d8d1a2d 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -46,13 +46,22 @@ void AdminBoundariesConverter::convert( std::map g_way_end_points_map; - addLevel1Boundaries(dirs, g_way_end_points_map, writer); + std::map + area_map; + + addLevel1Boundaries(dirs, g_way_end_points_map, area_map, writer); for (auto dir : dirs) { - addLevelNBoundaries(dir / ADMINBNDY_2_SHP, g_way_end_points_map, writer, 2); - addLevelNBoundaries(dir / ADMINBNDY_3_SHP, g_way_end_points_map, writer, 3); - addLevelNBoundaries(dir / ADMINBNDY_4_SHP, g_way_end_points_map, writer, 4); - addLevelNBoundaries(dir / ADMINBNDY_5_SHP, g_way_end_points_map, writer, 5); + auto mtd_area_map = process_meta_areas(dir); + + addLevelNBoundaries(dir / ADMINBNDY_2_SHP, g_way_end_points_map, + mtd_area_map, writer, 2); + addLevelNBoundaries(dir / ADMINBNDY_3_SHP, g_way_end_points_map, + mtd_area_map, writer, 3); + addLevelNBoundaries(dir / ADMINBNDY_4_SHP, g_way_end_points_map, + mtd_area_map, writer, 4); + addLevelNBoundaries(dir / ADMINBNDY_5_SHP, g_way_end_points_map, + mtd_area_map, writer, 5); } } @@ -60,6 +69,8 @@ void AdminBoundariesConverter::addLevel1Boundaries( const std::vector &dirs, std::map &g_way_end_points_map, + const std::map + &mtd_area_map, osmium::io::Writer &writer) { const std::filesystem::path ADMINLINE_1_SHP = "AdminLine1.shp"; @@ -91,7 +102,7 @@ void AdminBoundariesConverter::addLevel1Boundaries( build_admin_boundary_relation_with_tags( adminBoundary.first, adminBoundary.second.first, - adminBoundary.second.second, rel_buffer, 1); + adminBoundary.second.second, mtd_area_map, rel_buffer, 1); } rel_buffer.commit(); writer(std::move(rel_buffer)); @@ -240,10 +251,12 @@ AdminBoundariesConverter::build_admin_boundary_relation_with_tags( osmium::unsigned_object_id_type area_id, const std::vector &ext_osm_way_ids, const std::vector &int_osm_way_ids, + const std::map + &mtd_area_map, osmium::memory::Buffer &rel_buffer, uint level) { osmium::builder::RelationBuilder builder(rel_buffer); setObjectProperties(builder); - build_admin_boundary_taglist(builder, area_id, level); + build_admin_boundary_taglist(builder, area_id, mtd_area_map, level); build_relation_members(builder, ext_osm_way_ids, int_osm_way_ids); return builder.object().id(); } @@ -265,6 +278,8 @@ void AdminBoundariesConverter::addLevelNBoundaries( std::filesystem::path dir, std::map &g_way_end_points_map, + const std::map + &mtd_area_map, osmium::io::Writer &writer, uint level) { std::map, std::vector>> @@ -277,7 +292,7 @@ void AdminBoundariesConverter::addLevelNBoundaries( build_admin_boundary_relation_with_tags( adminBoundary.first, adminBoundary.second.first, - adminBoundary.second.second, rel_buffer, level); + adminBoundary.second.second, mtd_area_map, rel_buffer, level); } rel_buffer.commit(); writer(std::move(rel_buffer)); @@ -285,6 +300,8 @@ void AdminBoundariesConverter::addLevelNBoundaries( void AdminBoundariesConverter::build_admin_boundary_taglist( osmium::builder::Builder &builder, osmium::unsigned_object_id_type area_id, + const std::map + &mtd_area_map, uint level) { osmium::builder::TagListBuilder tl_builder(builder); // Mind tl_builder scope in calling method! @@ -297,8 +314,8 @@ void AdminBoundariesConverter::build_admin_boundary_taglist( tl_builder.add_tag("boundary", "administrative"); } - auto it = g_mtd_area_map.find(area_id); - if (it != g_mtd_area_map.end()) { + auto it = mtd_area_map.find(area_id); + if (it != mtd_area_map.end()) { auto d = it->second; if (!d.admin_lvl.empty()) tl_builder.add_tag("navteq_admin_level", d.admin_lvl); diff --git a/plugins/navteq/converter/AdminBoundariesConverter.hpp b/plugins/navteq/converter/AdminBoundariesConverter.hpp index 16a9589..168197d 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.hpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.hpp @@ -44,6 +44,8 @@ class AdminBoundariesConverter : public Converter { const std::vector &dirs, std::map &g_way_end_points_map, + const std::map &mtd_area_map, osmium::io::Writer &writer); void add_admin_shape( @@ -82,6 +84,8 @@ class AdminBoundariesConverter : public Converter { osmium::unsigned_object_id_type area_id, const std::vector &ext_osm_way_ids, const std::vector &int_osm_way_ids, + const std::map &mtd_area_map, osmium::memory::Buffer &rel_buffer, uint level); osmium::unsigned_object_id_type build_admin_boundary_relation_with_tags( @@ -94,11 +98,16 @@ class AdminBoundariesConverter : public Converter { std::filesystem::path dir, std::map &g_way_end_points_map, + const std::map &mtd_area_map, osmium::io::Writer &writer, uint level); - void build_admin_boundary_taglist(osmium::builder::Builder &builder, - osmium::unsigned_object_id_type area_id, - uint level); + void build_admin_boundary_taglist( + osmium::builder::Builder &builder, + osmium::unsigned_object_id_type area_id, + const std::map &mtd_area_map, + uint level); void build_admin_boundary_taglist(osmium::builder::Builder &builder, const OGRFeatureUniquePtr &feat); diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 68defc1..6e3f7e7 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -245,6 +245,13 @@ std::string Converter::navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { return std::to_string(2 * navteq_admin_lvl_int); } +std::string Converter::navteq_2_osm_admin_lvl(std::string navteq_admin_lvl) { + if (string_is_not_unsigned_integer(navteq_admin_lvl)) + throw std::runtime_error("admin level contains invalid character"); + + return navteq_2_osm_admin_lvl(stoi(navteq_admin_lvl)); +} + // matching from http://www.loc.gov/standards/iso639-2/php/code_list.php // http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt // ISO-639 conversion diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 983e9fc..570e266 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -128,6 +128,8 @@ class Converter { std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int); + std::string navteq_2_osm_admin_lvl(std::string navteq_admin_lvl); + std::map process_meta_areas(std::filesystem::path dir); diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 604fe79..79a658b 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -40,7 +40,7 @@ navteq_plugin::navteq_plugin(const std::filesystem::path &executable_path) : base_plugin::base_plugin("Navteq Plugin", executable_path) { converter.emplace_back(new AdminBoundariesConverter(executable_path)); - converter.emplace_back(new StreetConverter(executable_path)); + // converter.emplace_back(new StreetConverter(executable_path)); converter.emplace_back(new LanduseConverter(executable_path)); converter.emplace_back(new CityConverter(executable_path)); converter.emplace_back(new HamletConverter(executable_path)); From e2bafd38c894553ef56bfda85e51cb928e8390e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Tue, 16 Jul 2024 08:57:03 +0000 Subject: [PATCH 29/57] remove helper --- .../converter/AdminBoundariesConverter.cpp | 33 +- .../navteq/converter/BuildingConverter.cpp | 20 +- plugins/navteq/converter/CityConverter.cpp | 3 - plugins/navteq/converter/Converter.cpp | 101 +++++- plugins/navteq/converter/Converter.hpp | 33 +- plugins/navteq/converter/HamletConverter.cpp | 3 - plugins/navteq/converter/LanduseConverter.cpp | 3 - plugins/navteq/converter/RailwayConverter.cpp | 3 - .../navteq/converter/RestAreaConverter.cpp | 3 - ...reetConverter.cpp => StreetConverter.cpp_} | 156 ++++++++ ...reetConverter.hpp => StreetConverter.hpp_} | 0 plugins/navteq/converter/WaterConverter.cpp | 3 - plugins/navteq/navteq2osm_tag_parser.hpp | 89 ----- plugins/navteq/navteq_plugin.cpp | 16 +- plugins/readers.hpp | 37 -- plugins/util.hpp | 340 ------------------ 16 files changed, 301 insertions(+), 542 deletions(-) rename plugins/navteq/converter/{StreetConverter.cpp => StreetConverter.cpp_} (93%) rename plugins/navteq/converter/{StreetConverter.hpp => StreetConverter.hpp_} (100%) delete mode 100644 plugins/navteq/navteq2osm_tag_parser.hpp delete mode 100644 plugins/readers.hpp delete mode 100644 plugins/util.hpp diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index d8d1a2d..5328e12 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -25,9 +25,6 @@ #include #include -#include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" - AdminBoundariesConverter::AdminBoundariesConverter( const std::filesystem::path &executable_path) : Converter(executable_path) {} @@ -49,6 +46,7 @@ void AdminBoundariesConverter::convert( std::map area_map; + // TODO: calculate in loop? addLevel1Boundaries(dirs, g_way_end_points_map, area_map, writer); for (auto dir : dirs) { @@ -83,7 +81,7 @@ void AdminBoundariesConverter::addLevel1Boundaries( for (auto dir : dirs) { // for some countries the Adminbndy1.shp doesn't contain the whole country // border therefore we additionally add the links from AdminLine1.shp - if (shp_file_exists(dir / ADMINLINE_1_SHP)) { + if (std::filesystem::exists(dir / ADMINLINE_1_SHP)) { auto adminLine = add_admin_lines(dir / ADMINLINE_1_SHP, g_way_end_points_map, writer); // merge maps @@ -91,7 +89,7 @@ void AdminBoundariesConverter::addLevel1Boundaries( std::ranges::copy(mapEntry.second, std::back_inserter(map[mapEntry.first].first)); } - } else if (shp_file_exists(dir / ADMINBNDY_1_SHP)) { + } else if (std::filesystem::exists(dir / ADMINBNDY_1_SHP)) { add_admin_shape(dir / ADMINBNDY_1_SHP, g_way_end_points_map, writer, map); } } @@ -99,7 +97,6 @@ void AdminBoundariesConverter::addLevel1Boundaries( // create relations for admin boundary 1 osmium::memory::Buffer rel_buffer(BUFFER_SIZE); for (auto &adminBoundary : map) { - build_admin_boundary_relation_with_tags( adminBoundary.first, adminBoundary.second.first, adminBoundary.second.second, mtd_area_map, rel_buffer, 1); @@ -117,10 +114,14 @@ void AdminBoundariesConverter::add_admin_shape( std::vector>> &adminLineMap) { - auto ds = open_shape_file(admin_shape_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(admin_shape_file.string())); + auto layer = + openDataSource(admin_shape_file) + .or_else([&] -> std::optional { + throw std::runtime_error("Could not open data source for " + + admin_shape_file.string()); + }) + .value(); + assert(layer->GetGeomType() == wkbPolygon); osmium::memory::Buffer node_buffer(BUFFER_SIZE); osmium::memory::Buffer way_buffer(BUFFER_SIZE); @@ -142,10 +143,14 @@ AdminBoundariesConverter::add_admin_lines( osmium::io::Writer &writer) { std::map> result; - auto ds = open_shape_file(admin_line_shape_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(admin_line_shape_file.string())); + auto layer = + openDataSource(admin_line_shape_file) + .or_else([&] -> std::optional { + throw std::runtime_error("Could not open data source for " + + admin_line_shape_file.string()); + }) + .value(); + assert(layer->GetGeomType() == wkbLineString); osmium::memory::Buffer node_buffer(BUFFER_SIZE); osmium::memory::Buffer way_buffer(BUFFER_SIZE); diff --git a/plugins/navteq/converter/BuildingConverter.cpp b/plugins/navteq/converter/BuildingConverter.cpp index f54a50a..4557b93 100644 --- a/plugins/navteq/converter/BuildingConverter.cpp +++ b/plugins/navteq/converter/BuildingConverter.cpp @@ -24,9 +24,6 @@ #include #include -#include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" - BuildingConverter::BuildingConverter( const std::filesystem::path &executable_path) : Converter(executable_path) {} @@ -46,17 +43,12 @@ void BuildingConverter::convert(const std::vector &dirs, void BuildingConverter::add_building_shape( std::filesystem::path landmark_shape_file, osmium::io::Writer &writer) { - auto ds = - GDALDatasetUniquePtr(GDALDataset::Open(landmark_shape_file.c_str())); - if (!ds) { - BOOST_LOG_TRIVIAL(debug) - << "No building shp found in " << landmark_shape_file; - return; - } - auto layer = ds->GetLayer(0); - if (!layer) { - throw(shp_empty_error(landmark_shape_file.string())); - } + auto layer = openDataSource(landmark_shape_file) + .or_else([&]() -> std::optional { + throw(std::runtime_error("could not open " + + landmark_shape_file.string())); + }) + .value(); assert(layer->GetGeomType() == wkbPolygon || layer->GetGeomType() == wkbLineString); diff --git a/plugins/navteq/converter/CityConverter.cpp b/plugins/navteq/converter/CityConverter.cpp index 7d6a7f7..1faf871 100644 --- a/plugins/navteq/converter/CityConverter.cpp +++ b/plugins/navteq/converter/CityConverter.cpp @@ -23,9 +23,6 @@ #include #include -#include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" - CityConverter::CityConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 6e3f7e7..35f560f 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -7,12 +7,12 @@ #include #include #include - -#include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" +#include osmium::unsigned_object_id_type Converter::g_osm_id = 1; +std::map Converter::lang_code_map; + /** * \brief Dummy attributes enable josm to read output xml files. * @@ -224,17 +224,6 @@ Converter::build_node(const osmium::Location &location, return builder.object().id(); } -/** - * \brief Sets object properties. - * - * \param builder Builder to set properties to. - * */ -template void Converter::setObjectProperties(T &builder) { - builder.object().set_id(g_osm_id++); - set_dummy_osm_object_attributes(builder.object()); - builder.set_user(USER.data()); -} - std::string Converter::navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { if (NAVTEQ_ADMIN_LVL_MIN > navteq_admin_lvl_int || navteq_admin_lvl_int > NAVTEQ_ADMIN_LVL_MAX) @@ -309,9 +298,11 @@ Converter::process_meta_areas(std::filesystem::path dir) { std::map mtd_area_map; - auto layer = openDataSource(dir / MTD_AREA_DBF).or_else([]() -> OGRLayer * { - throw(std::runtime_error("could not open MtdArea.dbf")); - }); + auto layer = openDataSource(dir / MTD_AREA_DBF) + .or_else([&]() -> std::optional { + throw(std::runtime_error("could not open MtdArea.dbf")); + }) + .value(); for (auto &feat : *layer) { osmium::unsigned_object_id_type area_id = @@ -380,7 +371,7 @@ uint Converter::get_area_code_l( } std::optional -openDataSource(const std::filesystem::path &shape_file) { +Converter::openDataSource(const std::filesystem::path &shape_file) { auto ds = GDALDatasetUniquePtr(GDALDataset::Open(shape_file.c_str())); if (!ds) { BOOST_LOG_TRIVIAL(debug) << "No shp found in " << shape_file; @@ -392,3 +383,77 @@ openDataSource(const std::filesystem::path &shape_file) { return std::optional(layer); } + +std::string Converter::to_camel_case_with_spaces(const char *camel) { + + std::string titleString; + icu::UnicodeString ustr(camel); + ustr.toTitle(nullptr); + ustr.toUTF8String(titleString); + + return titleString; +} + +std::string Converter::to_camel_case_with_spaces(const std::string &camel) { + return to_camel_case_with_spaces(camel.c_str()); +} + +void Converter::add_uint_tag(osmium::builder::TagListBuilder &tl_builder, + const char *tag_key, uint uint_tag_val) { + std::string val_s = std::to_string(uint_tag_val); + if (tag_key) { + tl_builder.add_tag(tag_key, val_s); + } +} + +bool Converter::parse_bool(const char *value) { + if (!strcmp(value, "Y")) + return true; + return false; +} + +/** + * \brief returns field from OGRFeature + * aborts if feature is nullpointer or field key is invalid + * \param feat feature from which field is read + * \param field field name as key + * \return const char* of field value + */ +const char *Converter::get_field_from_feature(const OGRFeatureUniquePtr &feat, + const std::string_view &field) { + int field_index = feat->GetFieldIndex(field.data()); + if (field_index == -1) + BOOST_LOG_TRIVIAL(error) << field << std::endl; + return feat->GetFieldAsString(field_index); +} +/** + * \brief returns field from OGRFeature + * throws exception if field_value is not + * \param feat feature from which field is read + * \param field field name as key + * \return field value as uint + */ +uint64_t Converter::get_uint_from_feature(const OGRFeatureUniquePtr &feat, + const std::string_view &field) { + const char *value = get_field_from_feature(feat, field.data()); + assert(value); + try { + return std::stoul(value); + } catch (const std::invalid_argument &) { + throw format_error("Could not parse field='" + std::string(field) + + "' with value='" + std::string(value) + "'"); + } +} + +bool Converter::string_is_unsigned_integer(const std::string &s) { + if (s.empty()) + return false; + for (auto i : s) + if (!isdigit(i)) + return false; + return true; +} + +bool Converter::string_is_not_unsigned_integer(const std::string &s) { + return !string_is_unsigned_integer(s); +} \ No newline at end of file diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 570e266..a41c00e 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -21,10 +21,13 @@ #include #include #include +#include #include #include #include +#include "../../comm2osm_exceptions.hpp" + namespace osmium { class OSMObject; class Location; @@ -33,12 +36,6 @@ namespace io { class Writer; } // namespace io -namespace builder { -class RelationBuilder; -class NodeBuilder; -class WayBuilder; -} // namespace builder - namespace memory { class Buffer; } // namespace memory @@ -124,7 +121,11 @@ class Converter { build_node(const osmium::Location &location, osmium::builder::NodeBuilder &builder); - template void setObjectProperties(T &builder); + template void setObjectProperties(T &builder) { + builder.object().set_id(g_osm_id++); + set_dummy_osm_object_attributes(builder.object()); + builder.set_user(USER.data()); + } std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int); @@ -148,6 +149,24 @@ class Converter { std::optional openDataSource(const std::filesystem::path &shape_file); + std::string to_camel_case_with_spaces(const char *camel); + + std::string to_camel_case_with_spaces(const std::string &camel); + + void add_uint_tag(osmium::builder::TagListBuilder &tl_builder, + const char *tag_key, uint uint_tag_val); + + bool parse_bool(const char *value); + + const char *get_field_from_feature(const OGRFeatureUniquePtr &feat, + const std::string_view &field); + + uint64_t get_uint_from_feature(const OGRFeatureUniquePtr &feat, + const std::string_view &field); + + bool string_is_unsigned_integer(const std::string &s); + bool string_is_not_unsigned_integer(const std::string &s); + static constexpr int BUFFER_SIZE = 10 * 1000 * 1000; static constexpr int OSM_MAX_WAY_NODES = 1000; diff --git a/plugins/navteq/converter/HamletConverter.cpp b/plugins/navteq/converter/HamletConverter.cpp index f6d3d62..3bbe554 100644 --- a/plugins/navteq/converter/HamletConverter.cpp +++ b/plugins/navteq/converter/HamletConverter.cpp @@ -23,9 +23,6 @@ #include #include -#include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" - HamletConverter::HamletConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} diff --git a/plugins/navteq/converter/LanduseConverter.cpp b/plugins/navteq/converter/LanduseConverter.cpp index d994992..92b7e67 100644 --- a/plugins/navteq/converter/LanduseConverter.cpp +++ b/plugins/navteq/converter/LanduseConverter.cpp @@ -23,9 +23,6 @@ #include #include -#include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" - LanduseConverter::LanduseConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} diff --git a/plugins/navteq/converter/RailwayConverter.cpp b/plugins/navteq/converter/RailwayConverter.cpp index 2fd4f12..e2ac6e1 100644 --- a/plugins/navteq/converter/RailwayConverter.cpp +++ b/plugins/navteq/converter/RailwayConverter.cpp @@ -23,9 +23,6 @@ #include #include -#include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" - RailwayConverter::RailwayConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} diff --git a/plugins/navteq/converter/RestAreaConverter.cpp b/plugins/navteq/converter/RestAreaConverter.cpp index b8e3327..7aa5cb1 100644 --- a/plugins/navteq/converter/RestAreaConverter.cpp +++ b/plugins/navteq/converter/RestAreaConverter.cpp @@ -23,9 +23,6 @@ #include #include -#include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" - RestAreaConverter::RestAreaConverter( const std::filesystem::path &executable_path) : Converter(executable_path) {} diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp_ similarity index 93% rename from plugins/navteq/converter/StreetConverter.cpp rename to plugins/navteq/converter/StreetConverter.cpp_ index bc673bb..782859e 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp_ @@ -23,6 +23,7 @@ #include #include + #include "../../comm2osm_exceptions.hpp" #include "../../util.hpp" @@ -1591,3 +1592,158 @@ void StreetConverter::set_ferry_z_lvls_to_zero( (z_lvl_vec.end() - 1)->index != ogr_ls->getNumPoints() - 1) z_lvl_vec.erase(z_lvl_vec.end()); } + + +// TODO + + +static std::set z_lvl_set = {-4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; +void test__z_lvl_range(short z_lvl) { + if (z_lvl_set.find(z_lvl) == z_lvl_set.end()) + throw(out_of_range_exception("z_lvl " + std::to_string(z_lvl) + + " is not valid")); +} + +bool is_ferry(const char *value) { + if (!strcmp(value, "H")) + return false; // H --> not a ferry + else if (!strcmp(value, "B")) + return true; // T --> boat ferry + else if (!strcmp(value, "R")) + return true; // B --> rail ferry + throw(format_error("value '" + std::string(value) + "' for FERRY not valid")); +} + +/** + * \brief checks if first z_level is more significant than the other or equal. + * \param superior first z_level. + * \param than second z_level. + * \return true if superior is greater or equal than. + */ +bool is_superior_or_equal(short superior, short than) { + if (abs(superior) >= abs(than)) + return true; + return false; +} + +/* helpers for split_way_by_z_level */ +/** + * \brief checks if first z_level is more significant than the other. + * \param superior First z_level. + * \param than second z_level. + * \return true if superior is superior to than. + */ +bool is_superior(short superior, short than) { + if (abs(superior) > abs(than)) + return true; + return false; +} + +uint get_number_after(const std::string &str, const char *start_str) { + if (!str.starts_with(start_str)) + return 0; /* doesn't start with start_str */ + + /* Get number string after start_str until first non-digit appears */ + std::string end_str = str.substr(strlen(start_str)); + std::string number_str; + for (auto it = end_str.begin(); it != end_str.end(); ++it) { + if (!std::isdigit(*it)) { + /* break because B107a should return 107*/ + break; + } + number_str += *it; + } + + try { + return std::stoul(number_str); + } catch (const std::invalid_argument &) { + return 0; + } +} + +const char *parse_house_number_schema(const char *schema) { + if (!strcmp(schema, "E")) + return "even"; + if (!strcmp(schema, "O")) + return "odd"; + BOOST_LOG_TRIVIAL(error) << "schema = " << schema << " unsupported" + << std::endl; + return ""; + throw std::runtime_error("scheme " + std::string(schema) + + " is currently not supported"); +} + +/** + * \brief converts pounds to metric tons + */ +std::string lbs_to_metric_ton(double lbs) { + double short_ton = lbs / (double)POUND_BASE; + double metric_ton = short_ton * SHORT_TON; + std::stringstream stream; + stream << metric_ton; + return stream.str(); +} + +/** + * \brief converts kilogram to tons + */ +template std::string kg_to_t(T kilo) { + return std::to_string(kilo / 1000.0f); +} +/** + * \brief converts centimeter to meters + */ +template std::string cm_to_m(T meter) { + return std::to_string(meter / 100.0f); +} +/** + * \brief converts inches to feet + */ +std::string inch_to_feet(unsigned int inches) { + return std::to_string((unsigned int)floor(inches / INCH_BASE)) + "'" + + std::to_string(inches % INCH_BASE) + "\""; +} + + +const int INCH_BASE = 12; +const int POUND_BASE = 2000; +// short ton in metric tons (source: +// http://wiki.openstreetmap.org/wiki/Key:maxweight) +const double SHORT_TON = 0.90718474; + +/** + * \brief returns index of a given field in a DBFHandle + * \param handle DBFHandle + * \param field_name field of DBFhandle + * \return index of given field + */ + +int dbf_get_field_index(DBFHandle handle, const char *field_name) { + assert(handle); + assert(field_name); + // if (row >= DBFGetRecordCount(handle)) throw(std::runtime_error("row=" + + // std::to_string(row) + " is out of bounds.")); + int index = DBFGetFieldIndex(handle, field_name); + if (index == -1) + throw(std::runtime_error("DBFfile doesnt contain " + + std::string(field_name))); + return index; +} + +/** + * \brief get field of a given DBFHandle as string + */ +std::string dbf_get_string_by_field(DBFHandle handle, int row, + const char *field_name) { + return DBFReadStringAttribute(handle, row, + dbf_get_field_index(handle, field_name)); +} + +/** + * \brief get field of a given DBFHandle as uint64_t + */ +uint64_t dbf_get_uint_by_field(DBFHandle handle, int row, + const char *field_name) { + return DBFReadIntegerAttribute(handle, row, + dbf_get_field_index(handle, field_name)); +} \ No newline at end of file diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp_ similarity index 100% rename from plugins/navteq/converter/StreetConverter.hpp rename to plugins/navteq/converter/StreetConverter.hpp_ diff --git a/plugins/navteq/converter/WaterConverter.cpp b/plugins/navteq/converter/WaterConverter.cpp index ee441b9..fb1b76b 100644 --- a/plugins/navteq/converter/WaterConverter.cpp +++ b/plugins/navteq/converter/WaterConverter.cpp @@ -22,9 +22,6 @@ #include #include -#include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" - WaterConverter::WaterConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} diff --git a/plugins/navteq/navteq2osm_tag_parser.hpp b/plugins/navteq/navteq2osm_tag_parser.hpp deleted file mode 100644 index 9c2b702..0000000 --- a/plugins/navteq/navteq2osm_tag_parser.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef NAVTEQ2OSMTAGPARSE_HPP_ -#define NAVTEQ2OSMTAGPARSE_HPP_ - -#include -#include - -int ctr = 0; - -bool fits_street_ref(const std::string &st_name) { - if (st_name.empty()) - return false; - if (st_name.size() > 6) - return false; - - bool number_started = false; - for (auto it = st_name.begin(); it != st_name.end(); ++it) { - if (std::isdigit(*it)) { - number_started = true; - } else if (number_started) { - return false; - } - } - - return number_started; -} - -/** - * \brief adds maxspeed tag - */ - -/** - * \brief adds here:speed_cat tag - */ -void add_here_speed_cat_tag(osmium::builder::TagListBuilder *builder, - OGRFeatureUniquePtr &f) { - auto speed_cat = get_uint_from_feature(f, SPEED_CAT); - if (0 < speed_cat && - speed_cat < (sizeof(speed_cat_metric) / sizeof(const char *))) - builder->add_tag("here:speed_cat", speed_cat_metric[speed_cat]); - else - throw format_error("SPEED_CAT=" + std::to_string(speed_cat) + - " is not valid."); -} - -/** - * \brief adds maxheight, maxwidth, maxlength, maxweight and maxaxleload tags. - */ - -void add_ferry_tag(osmium::builder::TagListBuilder *builder, - OGRFeatureUniquePtr &f) { - const char *ferry = get_field_from_feature(f, FERRY); - builder->add_tag("route", "ferry"); - if (!strcmp(ferry, "B")) { - if (only_pedestrians(f)) { - builder->add_tag("foot", YES); - } else { - builder->add_tag( - "foot", - parse_bool(get_field_from_feature(f, AR_PEDESTRIANS)) ? YES : NO); - builder->add_tag("motorcar", - parse_bool(get_field_from_feature(f, AR_AUTO)) ? YES - : NO); - } - - } else if (!strcmp(ferry, "R")) { - builder->add_tag("railway", "ferry"); - } else - throw(format_error("value '" + std::string(ferry) + "' for " + - std::string(FERRY) + " not valid")); -} - -std::string navteq_2_osm_admin_lvl(uint navteq_admin_lvl_int) { - if (!is_in_range(navteq_admin_lvl_int, (uint)NAVTEQ_ADMIN_LVL_MIN, - (uint)NAVTEQ_ADMIN_LVL_MAX)) - throw std::runtime_error("invalid admin level. admin level '" + - std::to_string(navteq_admin_lvl_int) + - "' is out of range."); - - return std::to_string(2 * navteq_admin_lvl_int); -} - -std::string navteq_2_osm_admin_lvl(std::string navteq_admin_lvl) { - if (string_is_not_unsigned_integer(navteq_admin_lvl)) - throw std::runtime_error("admin level contains invalid character"); - - return navteq_2_osm_admin_lvl(stoi(navteq_admin_lvl)); -} - -#endif /* NAVTEQ2OSMTAGPARSE_HPP_ */ diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 79a658b..2133916 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -17,14 +17,14 @@ #include #include -#include "converter/AdminBoundariesConverter.hpp" +// #include "converter/AdminBoundariesConverter.hpp" #include "converter/BuildingConverter.hpp" #include "converter/CityConverter.hpp" #include "converter/HamletConverter.hpp" #include "converter/LanduseConverter.hpp" #include "converter/RailwayConverter.hpp" #include "converter/RestAreaConverter.hpp" -#include "converter/StreetConverter.hpp" +// #include "converter/StreetConverter.hpp" #include "converter/WaterConverter.hpp" #include "../comm2osm_exceptions.hpp" @@ -39,8 +39,8 @@ navteq_plugin::navteq_plugin(const std::filesystem::path &executable_path) : base_plugin::base_plugin("Navteq Plugin", executable_path) { - converter.emplace_back(new AdminBoundariesConverter(executable_path)); - // converter.emplace_back(new StreetConverter(executable_path)); + // converter.emplace_back(new AdminBoundariesConverter(executable_path)); + // converter.emplace_back(new StreetConverter(executable_path)); converter.emplace_back(new LanduseConverter(executable_path)); converter.emplace_back(new CityConverter(executable_path)); converter.emplace_back(new HamletConverter(executable_path)); @@ -121,7 +121,13 @@ bool navteq_plugin::check_input(const std::filesystem::path &input_path, std::filesystem::recursive_directory_iterator(input_path) | std::views::filter( [](auto &entry) { return entry.is_directory(); })) { - check_files(entry).and_then([&](auto &path) { dataDirs.push_back(path); }); + + // add path to dataDirs + check_files(entry.path()) + .and_then([&](auto path) -> std::optional { + dataDirs.push_back(path); + return std::nullopt; + }); } if (!foundCountries.empty()) { diff --git a/plugins/readers.hpp b/plugins/readers.hpp deleted file mode 100644 index 4e370b5..0000000 --- a/plugins/readers.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * readers.hpp - * - * Created on: 17.06.2015 - * Author: philip - */ - -#ifndef PLUGINS_READERS_HPP_ -#define PLUGINS_READERS_HPP_ - -#include -#include -#include -#include - -#include "comm2osm_exceptions.hpp" - -GDALDatasetUniquePtr open_shape_file(std::filesystem::path shp_file) { - BOOST_LOG_TRIVIAL(debug) << "\treading " << shp_file; - - auto input_data_source = - GDALDatasetUniquePtr(GDALDataset::Open(shp_file.c_str())); - if (!input_data_source) - throw(shp_error(shp_file.string())); - - return input_data_source; -} - -DBFHandle read_dbf_file(std::filesystem::path dbf_file) { - BOOST_LOG_TRIVIAL(debug) << "\treading " << dbf_file; - DBFHandle handle = DBFOpen(dbf_file.c_str(), "rb"); - if (handle == nullptr) - throw(dbf_error(dbf_file.string())); - return handle; -} - -#endif /* PLUGINS_READERS_HPP_ */ diff --git a/plugins/util.hpp b/plugins/util.hpp deleted file mode 100644 index 6d8b013..0000000 --- a/plugins/util.hpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * util.hpp - * - * Created on: 17.06.2015 - * Author: philip - */ - -#ifndef UTIL_HPP_ -#define UTIL_HPP_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../plugins/comm2osm_exceptions.hpp" -#include "ogr_util.hpp" -#include "readers.hpp" - -const int INCH_BASE = 12; -const int POUND_BASE = 2000; -// short ton in metric tons (source: -// http://wiki.openstreetmap.org/wiki/Key:maxweight) -const double SHORT_TON = 0.90718474; - -/** - - * helpers to check for file existance and validity - * */ - -/** - * \brief Checks shapefile existance and validity - * \param shp_file path of SHP file - * \return Returns true if existing and valid - * */ - -bool shp_file_exists(const std::string &shp_file) { - auto input_data_source = - GDALDatasetUniquePtr(GDALDataset::Open(shp_file.c_str())); - return input_data_source != nullptr; -} - -bool shp_file_exists(std::filesystem::path shp_file) { - return shp_file_exists(shp_file.string()); -} - -/** - * \brief Checks DBF file existance and validity - * \param dbf_file path of DBF file - * \return Returns true if existing and valid - * */ -bool dbf_file_exists(const std::string &dbf_file) { - DBFHandle handle = DBFOpen(dbf_file.c_str(), "rb"); - if (handle == nullptr) { - return false; - } - DBFClose(handle); - return true; -} - -bool dbf_file_exists(const std::filesystem::path &dbf_file) { - return dbf_file_exists(dbf_file.string()); -} - -/** - * \brief returns index of a given field in a DBFHandle - * \param handle DBFHandle - * \param field_name field of DBFhandle - * \return index of given field - */ - -int dbf_get_field_index(DBFHandle handle, const char *field_name) { - assert(handle); - assert(field_name); - // if (row >= DBFGetRecordCount(handle)) throw(std::runtime_error("row=" + - // std::to_string(row) + " is out of bounds.")); - int index = DBFGetFieldIndex(handle, field_name); - if (index == -1) - throw(std::runtime_error("DBFfile doesnt contain " + - std::string(field_name))); - return index; -} - -/** - * \brief get field of a given DBFHandle as string - */ -std::string dbf_get_string_by_field(DBFHandle handle, int row, - const char *field_name) { - return DBFReadStringAttribute(handle, row, - dbf_get_field_index(handle, field_name)); -} - -/** - * \brief get field of a given DBFHandle as uint64_t - */ -uint64_t dbf_get_uint_by_field(DBFHandle handle, int row, - const char *field_name) { - return DBFReadIntegerAttribute(handle, row, - dbf_get_field_index(handle, field_name)); -} - -/* getting fields from OGRFeatures -- begin */ - -/** - * \brief returns field from OGRFeature - * aborts if feature is nullpointer or field key is invalid - * \param feat feature from which field is read - * \param field field name as key - * \return const char* of field value - */ -const char *get_field_from_feature(const OGRFeatureUniquePtr &feat, - const char *field) { - int field_index = feat->GetFieldIndex(field); - if (field_index == -1) - std::cerr << field << std::endl; - return feat->GetFieldAsString(field_index); -} - -const char *get_field_from_feature(const OGRFeatureUniquePtr &feat, - const std::string_view &field) { - return get_field_from_feature(feat, field.data()); -} -/** - * \brief returns field from OGRFeature - * throws exception if field_value is not - * \param feat feature from which field is read - * \param field field name as key - * \return field value as uint - */ -uint64_t get_uint_from_feature(const OGRFeatureUniquePtr &feat, - const char *field) { - const char *value = get_field_from_feature(feat, field); - assert(value); - try { - return std::stoul(value); - } catch (const std::invalid_argument &) { - throw format_error("Could not parse field='" + std::string(field) + - "' with value='" + std::string(value) + "'"); - } -} - -uint64_t get_uint_from_feature(const OGRFeatureUniquePtr &feat, - const std::string_view &field) { - return get_uint_from_feature(feat, field.data()); -} - -/* getting fields from OGRFeatures -- end */ - -template bool is_in_range(Type test, Type from, Type to) { - if (test < from || test > to) - return false; - return true; -} - -bool string_is_unsigned_integer(const std::string &s) { - if (s.empty()) - return false; - for (auto i : s) - if (!isdigit(i)) - return false; - return true; -} - -bool string_is_not_unsigned_integer(const std::string &s) { - return !string_is_unsigned_integer(s); -} - -/** - * \brief converts kilogram to tons - */ -template std::string kg_to_t(T kilo) { - return std::to_string(kilo / 1000.0f); -} -/** - * \brief converts centimeter to meters - */ -template std::string cm_to_m(T meter) { - return std::to_string(meter / 100.0f); -} -/** - * \brief converts inches to feet - */ -std::string inch_to_feet(unsigned int inches) { - return std::to_string((unsigned int)floor(inches / INCH_BASE)) + "'" + - std::to_string(inches % INCH_BASE) + "\""; -} - -/** - * \brief converts pounds to metric tons - */ -std::string lbs_to_metric_ton(double lbs) { - double short_ton = lbs / (double)POUND_BASE; - double metric_ton = short_ton * SHORT_TON; - std::stringstream stream; - stream << metric_ton; - return stream.str(); -} - -/** - * \brief duplicate const char* value to change - */ -std::string to_camel_case_with_spaces(const char *camel) { - - std::string titleString; - icu::UnicodeString ustr(camel); - ustr.toTitle(nullptr); - ustr.toUTF8String(titleString); - - return titleString; -} - -/** - * \brief apply camel case with spaces to string - */ -std::string to_camel_case_with_spaces(const std::string &camel) { - return to_camel_case_with_spaces(camel.c_str()); -} - -void add_uint_tag(osmium::builder::TagListBuilder &tl_builder, - const char *tag_key, uint uint_tag_val) { - std::string val_s = std::to_string(uint_tag_val); - if (tag_key) { - tl_builder.add_tag(tag_key, val_s); - } -} - -bool checkInBoundingBox(const OGREnvelope &boundingBox, - const std::filesystem::path &shp_file) { - - if (!boundingBox.IsInit()) - return true; - - auto ds = open_shape_file(shp_file); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(shp_file.string())); - - OGREnvelope layerEnvelop; - - if (layer->GetExtent(&layerEnvelop) != OGRERR_NONE) { - return false; - } - - bool result = false; - if (boundingBox.Intersects(layerEnvelop)) { - result = true; - } - - return result; -} - -bool parse_bool(const char *value) { - if (!strcmp(value, "Y")) - return true; - return false; -} - -static std::set z_lvl_set = {-4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; -void test__z_lvl_range(short z_lvl) { - if (z_lvl_set.find(z_lvl) == z_lvl_set.end()) - throw(out_of_range_exception("z_lvl " + std::to_string(z_lvl) + - " is not valid")); -} - -bool is_ferry(const char *value) { - if (!strcmp(value, "H")) - return false; // H --> not a ferry - else if (!strcmp(value, "B")) - return true; // T --> boat ferry - else if (!strcmp(value, "R")) - return true; // B --> rail ferry - throw(format_error("value '" + std::string(value) + "' for FERRY not valid")); -} - -/** - * \brief checks if first z_level is more significant than the other or equal. - * \param superior first z_level. - * \param than second z_level. - * \return true if superior is greater or equal than. - */ -bool is_superior_or_equal(short superior, short than) { - if (abs(superior) >= abs(than)) - return true; - return false; -} - -/* helpers for split_way_by_z_level */ -/** - * \brief checks if first z_level is more significant than the other. - * \param superior First z_level. - * \param than second z_level. - * \return true if superior is superior to than. - */ -bool is_superior(short superior, short than) { - if (abs(superior) > abs(than)) - return true; - return false; -} - -uint get_number_after(const std::string &str, const char *start_str) { - if (!str.starts_with(start_str)) - return 0; /* doesn't start with start_str */ - - /* Get number string after start_str until first non-digit appears */ - std::string end_str = str.substr(strlen(start_str)); - std::string number_str; - for (auto it = end_str.begin(); it != end_str.end(); ++it) { - if (!std::isdigit(*it)) { - /* break because B107a should return 107*/ - break; - } - number_str += *it; - } - - try { - return std::stoul(number_str); - } catch (const std::invalid_argument &) { - return 0; - } -} - -const char *parse_house_number_schema(const char *schema) { - if (!strcmp(schema, "E")) - return "even"; - if (!strcmp(schema, "O")) - return "odd"; - std::cerr << "schema = " << schema << " unsupported" << std::endl; - return ""; - throw std::runtime_error("scheme " + std::string(schema) + - " is currently not supported"); -} - -#endif /* UTIL_HPP_ */ From 705852afaa3fe6b75161086e21aad5d2ff068845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Tue, 16 Jul 2024 09:42:07 +0000 Subject: [PATCH 30/57] fix datasource --- .../converter/AdminBoundariesConverter.cpp | 32 +++++++++++-------- .../navteq/converter/BuildingConverter.cpp | 15 +++++---- plugins/navteq/converter/CityConverter.cpp | 10 ++++-- plugins/navteq/converter/Converter.cpp | 28 +++++++++------- plugins/navteq/converter/Converter.hpp | 3 +- plugins/navteq/converter/LanduseConverter.cpp | 12 +++---- plugins/navteq/navteq_plugin.cpp | 22 +++++++------ 7 files changed, 69 insertions(+), 53 deletions(-) diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index 5328e12..89221e1 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -114,13 +114,15 @@ void AdminBoundariesConverter::add_admin_shape( std::vector>> &adminLineMap) { - auto layer = - openDataSource(admin_shape_file) - .or_else([&] -> std::optional { - throw std::runtime_error("Could not open data source for " + - admin_shape_file.string()); - }) - .value(); + auto ds = openDataSource(admin_shape_file); + if (!ds) { + return; + } + + auto layer = ds->GetLayer(0); + if (!layer) { + throw(shp_empty_error(admin_shape_file)); + } assert(layer->GetGeomType() == wkbPolygon); osmium::memory::Buffer node_buffer(BUFFER_SIZE); @@ -143,13 +145,15 @@ AdminBoundariesConverter::add_admin_lines( osmium::io::Writer &writer) { std::map> result; - auto layer = - openDataSource(admin_line_shape_file) - .or_else([&] -> std::optional { - throw std::runtime_error("Could not open data source for " + - admin_line_shape_file.string()); - }) - .value(); + auto ds = openDataSource(admin_line_shape_file); + if (!ds) { + return result; + } + + auto layer = ds->GetLayer(0); + if (!layer) { + throw(shp_empty_error(admin_line_shape_file)); + } assert(layer->GetGeomType() == wkbLineString); osmium::memory::Buffer node_buffer(BUFFER_SIZE); diff --git a/plugins/navteq/converter/BuildingConverter.cpp b/plugins/navteq/converter/BuildingConverter.cpp index 4557b93..a7c9c47 100644 --- a/plugins/navteq/converter/BuildingConverter.cpp +++ b/plugins/navteq/converter/BuildingConverter.cpp @@ -43,12 +43,15 @@ void BuildingConverter::convert(const std::vector &dirs, void BuildingConverter::add_building_shape( std::filesystem::path landmark_shape_file, osmium::io::Writer &writer) { - auto layer = openDataSource(landmark_shape_file) - .or_else([&]() -> std::optional { - throw(std::runtime_error("could not open " + - landmark_shape_file.string())); - }) - .value(); + auto ds = openDataSource(landmark_shape_file); + if (!ds) { + return; + } + + auto layer = ds->GetLayer(0); + if (!layer) { + throw(shp_empty_error(landmark_shape_file)); + } assert(layer->GetGeomType() == wkbPolygon || layer->GetGeomType() == wkbLineString); diff --git a/plugins/navteq/converter/CityConverter.cpp b/plugins/navteq/converter/CityConverter.cpp index 1faf871..45c9df5 100644 --- a/plugins/navteq/converter/CityConverter.cpp +++ b/plugins/navteq/converter/CityConverter.cpp @@ -41,9 +41,15 @@ void CityConverter::convert(const std::vector &dirs, void CityConverter::add_city_shape(std::filesystem::path city_shape_file, osmium::io::Writer &writer) { - auto layer = openDataSource(city_shape_file).value_or(nullptr); - if (!layer) + auto ds = openDataSource(city_shape_file); + if (!ds) { return; + } + + auto layer = ds->GetLayer(0); + if (!layer) { + throw(shp_empty_error(city_shape_file)); + } osmium::memory::Buffer node_buffer(BUFFER_SIZE); diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 35f560f..e3bbfb7 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -298,11 +298,10 @@ Converter::process_meta_areas(std::filesystem::path dir) { std::map mtd_area_map; - auto layer = openDataSource(dir / MTD_AREA_DBF) - .or_else([&]() -> std::optional { - throw(std::runtime_error("could not open MtdArea.dbf")); - }) - .value(); + auto ds = openDataSource(dir / MTD_AREA_DBF); + auto layer = ds->GetLayer(0); + if (!layer) + throw(shp_empty_error(dir / MTD_AREA_DBF)); for (auto &feat : *layer) { osmium::unsigned_object_id_type area_id = @@ -370,18 +369,23 @@ uint Converter::get_area_code_l( return get_area_code_l(l_area_id, r_area_id, mtd_area_map); } -std::optional +GDALDatasetUniquePtr Converter::openDataSource(const std::filesystem::path &shape_file) { - auto ds = GDALDatasetUniquePtr(GDALDataset::Open(shape_file.c_str())); + + std::string shape_file_str = shape_file.string(); + + // handle tar.gz files + if (shape_file.parent_path().string().ends_with(".tar.gz")) { + shape_file_str = "/vsitar/" + shape_file_str; + } + + auto ds = GDALDatasetUniquePtr(GDALDataset::Open(shape_file_str.c_str())); if (!ds) { BOOST_LOG_TRIVIAL(debug) << "No shp found in " << shape_file; - return std::nullopt; + return nullptr; } - auto layer = ds->GetLayer(0); - if (!layer) - throw(shp_empty_error(shape_file.string())); - return std::optional(layer); + return ds; } std::string Converter::to_camel_case_with_spaces(const char *camel) { diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index a41c00e..1ebb78a 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -146,8 +146,7 @@ class Converter { std::string parse_lang_code(std::string lang_code); - std::optional - openDataSource(const std::filesystem::path &shape_file); + GDALDatasetUniquePtr openDataSource(const std::filesystem::path &shape_file); std::string to_camel_case_with_spaces(const char *camel); diff --git a/plugins/navteq/converter/LanduseConverter.cpp b/plugins/navteq/converter/LanduseConverter.cpp index 92b7e67..5b87dc6 100644 --- a/plugins/navteq/converter/LanduseConverter.cpp +++ b/plugins/navteq/converter/LanduseConverter.cpp @@ -43,15 +43,13 @@ void LanduseConverter::add_landuse_shape( std::filesystem::path landuse_shape_file, osmium::io::Writer &writer) { std::map g_way_end_points_map; - auto ds = GDALDatasetUniquePtr(GDALDataset::Open(landuse_shape_file.c_str())); - if (ds == nullptr) { - BOOST_LOG_TRIVIAL(debug) - << "No landuse shp found in " << landuse_shape_file; + auto ds = openDataSource(landuse_shape_file); + if (!ds) return; - } auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(landuse_shape_file.string())); + if (!layer) + throw(shp_empty_error(landuse_shape_file)); + assert(layer->GetGeomType() == wkbPolygon); osmium::memory::Buffer node_buffer(BUFFER_SIZE); osmium::memory::Buffer way_buffer(BUFFER_SIZE); diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 2133916..582e8f6 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -42,12 +42,12 @@ navteq_plugin::navteq_plugin(const std::filesystem::path &executable_path) // converter.emplace_back(new AdminBoundariesConverter(executable_path)); // converter.emplace_back(new StreetConverter(executable_path)); converter.emplace_back(new LanduseConverter(executable_path)); - converter.emplace_back(new CityConverter(executable_path)); - converter.emplace_back(new HamletConverter(executable_path)); - converter.emplace_back(new BuildingConverter(executable_path)); - converter.emplace_back(new RestAreaConverter(executable_path)); - converter.emplace_back(new RailwayConverter(executable_path)); - converter.emplace_back(new WaterConverter(executable_path)); + // converter.emplace_back(new CityConverter(executable_path)); + // converter.emplace_back(new HamletConverter(executable_path)); + // converter.emplace_back(new BuildingConverter(executable_path)); + // converter.emplace_back(new RestAreaConverter(executable_path)); + // converter.emplace_back(new RailwayConverter(executable_path)); + // converter.emplace_back(new WaterConverter(executable_path)); } navteq_plugin::~navteq_plugin() {} @@ -74,11 +74,12 @@ navteq_plugin::check_files(const std::filesystem::path &dir) { std::views::filter([](auto &entry) { return entry.is_regular_file(); })) { - if (entry.path().extension() == ".PROD.csv") { + + if (entry.path().filename().string().ends_with(".PROD.csv")) { isHereDatatDir = true; } - if (entry.path().extension() == ".tar.gz") { + if (entry.path().filename().string().ends_with(".tar.gz")) { hasPackedData = true; tarFile = entry.path(); } @@ -87,8 +88,9 @@ navteq_plugin::check_files(const std::filesystem::path &dir) { if (!isHereDatatDir) return std::nullopt; - if (hasPackedData) - return std::optional(tarFile / "vsitar"); + if (hasPackedData) { + return std::optional(tarFile); + } // check if the PROD.csv file exists From a525bf9d8b82416337323d1df13df8fe6237348b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Tue, 16 Jul 2024 11:01:07 +0000 Subject: [PATCH 31/57] convert everything except streets --- .../converter/AdminBoundariesConverter.cpp | 34 ++++++++----------- .../converter/AdminBoundariesConverter.hpp | 2 +- plugins/navteq/converter/Converter.cpp | 4 +-- plugins/navteq/converter/HamletConverter.cpp | 3 +- plugins/navteq/converter/RailwayConverter.cpp | 12 +++---- .../navteq/converter/RestAreaConverter.cpp | 3 +- plugins/navteq/converter/WaterConverter.cpp | 4 +-- plugins/navteq/navteq_plugin.cpp | 16 ++++----- 8 files changed, 34 insertions(+), 44 deletions(-) diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index 89221e1..0f8e800 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -43,15 +43,11 @@ void AdminBoundariesConverter::convert( std::map g_way_end_points_map; - std::map - area_map; - - // TODO: calculate in loop? - addLevel1Boundaries(dirs, g_way_end_points_map, area_map, writer); - for (auto dir : dirs) { auto mtd_area_map = process_meta_areas(dir); + addLevel1Boundaries(dir, g_way_end_points_map, mtd_area_map, writer); + addLevelNBoundaries(dir / ADMINBNDY_2_SHP, g_way_end_points_map, mtd_area_map, writer, 2); addLevelNBoundaries(dir / ADMINBNDY_3_SHP, g_way_end_points_map, @@ -64,7 +60,7 @@ void AdminBoundariesConverter::convert( } void AdminBoundariesConverter::addLevel1Boundaries( - const std::vector &dirs, + const std::filesystem::path &dir, std::map &g_way_end_points_map, const std::map @@ -78,20 +74,18 @@ void AdminBoundariesConverter::addLevel1Boundaries( std::vector>> map; - for (auto dir : dirs) { - // for some countries the Adminbndy1.shp doesn't contain the whole country - // border therefore we additionally add the links from AdminLine1.shp - if (std::filesystem::exists(dir / ADMINLINE_1_SHP)) { - auto adminLine = - add_admin_lines(dir / ADMINLINE_1_SHP, g_way_end_points_map, writer); - // merge maps - for (auto &mapEntry : adminLine) { - std::ranges::copy(mapEntry.second, - std::back_inserter(map[mapEntry.first].first)); - } - } else if (std::filesystem::exists(dir / ADMINBNDY_1_SHP)) { - add_admin_shape(dir / ADMINBNDY_1_SHP, g_way_end_points_map, writer, map); + // for some countries the Adminbndy1.shp doesn't contain the whole country + // border therefore we additionally add the links from AdminLine1.shp + auto adminLine = + add_admin_lines(dir / ADMINLINE_1_SHP, g_way_end_points_map, writer); + if (!adminLine.empty()) { + // merge maps + for (auto &mapEntry : adminLine) { + std::ranges::copy(mapEntry.second, + std::back_inserter(map[mapEntry.first].first)); } + } else { + add_admin_shape(dir / ADMINBNDY_1_SHP, g_way_end_points_map, writer, map); } // create relations for admin boundary 1 diff --git a/plugins/navteq/converter/AdminBoundariesConverter.hpp b/plugins/navteq/converter/AdminBoundariesConverter.hpp index 168197d..c7a7246 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.hpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.hpp @@ -41,7 +41,7 @@ class AdminBoundariesConverter : public Converter { private: void addLevel1Boundaries( - const std::vector &dirs, + const std::filesystem::path &dir, std::map &g_way_end_points_map, const std::map &dirs, void HamletConverter::add_hamlet(std::filesystem::path hamlet_file, osmium::io::Writer &writer) { - auto ds = GDALDatasetUniquePtr(GDALDataset::Open(hamlet_file.c_str())); + auto ds = openDataSource(hamlet_file); if (!ds) { - BOOST_LOG_TRIVIAL(debug) << "No hamlet shp found in " << hamlet_file; return; } auto layer = ds->GetLayer(0); diff --git a/plugins/navteq/converter/RailwayConverter.cpp b/plugins/navteq/converter/RailwayConverter.cpp index e2ac6e1..5c65c74 100644 --- a/plugins/navteq/converter/RailwayConverter.cpp +++ b/plugins/navteq/converter/RailwayConverter.cpp @@ -41,16 +41,14 @@ void RailwayConverter::convert(const std::vector &dirs, void RailwayConverter::add_railways_shape( std::filesystem::path railway_shape_file, osmium::io::Writer &writer) { - auto ds = GDALDatasetUniquePtr(GDALDataset::Open(railway_shape_file.c_str())); - if (!ds) { - BOOST_LOG_TRIVIAL(debug) - << "No railway shp found in " << railway_shape_file; + auto ds = openDataSource(railway_shape_file); + if (!ds) return; - } + auto layer = ds->GetLayer(0); - if (!layer) { + if (!layer) throw(shp_empty_error(railway_shape_file.string())); - } + assert(layer->GetGeomType() == OGRwkbGeometryType::wkbPolygon || layer->GetGeomType() == OGRwkbGeometryType::wkbLineString); osmium::memory::Buffer node_buffer(BUFFER_SIZE); diff --git a/plugins/navteq/converter/RestAreaConverter.cpp b/plugins/navteq/converter/RestAreaConverter.cpp index 7aa5cb1..aed67ea 100644 --- a/plugins/navteq/converter/RestAreaConverter.cpp +++ b/plugins/navteq/converter/RestAreaConverter.cpp @@ -41,9 +41,8 @@ void RestAreaConverter::convert(const std::vector &dirs, void RestAreaConverter::add_rest_area(std::filesystem::path rest_area_file, osmium::io::Writer &writer) { - auto ds = GDALDatasetUniquePtr(GDALDataset::Open(rest_area_file.c_str())); + auto ds = openDataSource(rest_area_file); if (!ds) { - BOOST_LOG_TRIVIAL(debug) << "No rest area shp found in " << rest_area_file; return; } auto layer = ds->GetLayer(0); diff --git a/plugins/navteq/converter/WaterConverter.cpp b/plugins/navteq/converter/WaterConverter.cpp index fb1b76b..b004284 100644 --- a/plugins/navteq/converter/WaterConverter.cpp +++ b/plugins/navteq/converter/WaterConverter.cpp @@ -42,11 +42,11 @@ void WaterConverter::convert(const std::vector &dirs, void WaterConverter::add_water_shape(std::filesystem::path water_shape_file, osmium::io::Writer &writer) { - auto ds = GDALDatasetUniquePtr(GDALDataset::Open(water_shape_file.c_str())); + auto ds = openDataSource(water_shape_file); if (!ds) { - BOOST_LOG_TRIVIAL(debug) << "No water shp found in " << water_shape_file; return; } + auto layer = ds->GetLayer(0); if (layer == nullptr) { throw(shp_empty_error(water_shape_file.string())); diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 582e8f6..9f43b64 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -17,7 +17,7 @@ #include #include -// #include "converter/AdminBoundariesConverter.hpp" +#include "converter/AdminBoundariesConverter.hpp" #include "converter/BuildingConverter.hpp" #include "converter/CityConverter.hpp" #include "converter/HamletConverter.hpp" @@ -39,15 +39,15 @@ navteq_plugin::navteq_plugin(const std::filesystem::path &executable_path) : base_plugin::base_plugin("Navteq Plugin", executable_path) { - // converter.emplace_back(new AdminBoundariesConverter(executable_path)); + converter.emplace_back(new AdminBoundariesConverter(executable_path)); // converter.emplace_back(new StreetConverter(executable_path)); converter.emplace_back(new LanduseConverter(executable_path)); - // converter.emplace_back(new CityConverter(executable_path)); - // converter.emplace_back(new HamletConverter(executable_path)); - // converter.emplace_back(new BuildingConverter(executable_path)); - // converter.emplace_back(new RestAreaConverter(executable_path)); - // converter.emplace_back(new RailwayConverter(executable_path)); - // converter.emplace_back(new WaterConverter(executable_path)); + converter.emplace_back(new CityConverter(executable_path)); + converter.emplace_back(new HamletConverter(executable_path)); + converter.emplace_back(new BuildingConverter(executable_path)); + converter.emplace_back(new RestAreaConverter(executable_path)); + converter.emplace_back(new RailwayConverter(executable_path)); + converter.emplace_back(new WaterConverter(executable_path)); } navteq_plugin::~navteq_plugin() {} From 41cd71ac797e7c80075018ef0cd102aa4e879ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Tue, 16 Jul 2024 12:04:49 +0000 Subject: [PATCH 32/57] single directory in the converter --- .../converter/AdminBoundariesConverter.cpp | 27 +++++++++---------- .../converter/AdminBoundariesConverter.hpp | 4 +-- .../navteq/converter/BuildingConverter.cpp | 7 ++--- .../navteq/converter/BuildingConverter.hpp | 4 +-- plugins/navteq/converter/CityConverter.cpp | 7 ++--- plugins/navteq/converter/CityConverter.hpp | 4 +-- plugins/navteq/converter/Converter.hpp | 2 +- plugins/navteq/converter/HamletConverter.cpp | 6 ++--- plugins/navteq/converter/HamletConverter.hpp | 4 +-- plugins/navteq/converter/LanduseConverter.cpp | 8 +++--- plugins/navteq/converter/LanduseConverter.hpp | 4 +-- plugins/navteq/converter/RailwayConverter.cpp | 6 ++--- plugins/navteq/converter/RailwayConverter.hpp | 4 +-- .../navteq/converter/RestAreaConverter.cpp | 7 +++-- .../navteq/converter/RestAreaConverter.hpp | 4 +-- plugins/navteq/converter/WaterConverter.cpp | 8 +++--- plugins/navteq/converter/WaterConverter.hpp | 4 +-- plugins/navteq/navteq_plugin.cpp | 7 +++-- 18 files changed, 51 insertions(+), 66 deletions(-) diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index 0f8e800..d6cab23 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -31,9 +31,8 @@ AdminBoundariesConverter::AdminBoundariesConverter( AdminBoundariesConverter::~AdminBoundariesConverter() {} -void AdminBoundariesConverter::convert( - const std::vector &dirs, - osmium::io::Writer &writer) { +void AdminBoundariesConverter::convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) { const std::filesystem::path ADMINBNDY_2_SHP = "Adminbndy2.shp"; const std::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; @@ -43,20 +42,18 @@ void AdminBoundariesConverter::convert( std::map g_way_end_points_map; - for (auto dir : dirs) { - auto mtd_area_map = process_meta_areas(dir); + auto mtd_area_map = process_meta_areas(dir); - addLevel1Boundaries(dir, g_way_end_points_map, mtd_area_map, writer); + addLevel1Boundaries(dir, g_way_end_points_map, mtd_area_map, writer); - addLevelNBoundaries(dir / ADMINBNDY_2_SHP, g_way_end_points_map, - mtd_area_map, writer, 2); - addLevelNBoundaries(dir / ADMINBNDY_3_SHP, g_way_end_points_map, - mtd_area_map, writer, 3); - addLevelNBoundaries(dir / ADMINBNDY_4_SHP, g_way_end_points_map, - mtd_area_map, writer, 4); - addLevelNBoundaries(dir / ADMINBNDY_5_SHP, g_way_end_points_map, - mtd_area_map, writer, 5); - } + addLevelNBoundaries(dir / ADMINBNDY_2_SHP, g_way_end_points_map, mtd_area_map, + writer, 2); + addLevelNBoundaries(dir / ADMINBNDY_3_SHP, g_way_end_points_map, mtd_area_map, + writer, 3); + addLevelNBoundaries(dir / ADMINBNDY_4_SHP, g_way_end_points_map, mtd_area_map, + writer, 4); + addLevelNBoundaries(dir / ADMINBNDY_5_SHP, g_way_end_points_map, mtd_area_map, + writer, 5); } void AdminBoundariesConverter::addLevel1Boundaries( diff --git a/plugins/navteq/converter/AdminBoundariesConverter.hpp b/plugins/navteq/converter/AdminBoundariesConverter.hpp index c7a7246..d732cd5 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.hpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.hpp @@ -36,8 +36,8 @@ class AdminBoundariesConverter : public Converter { AdminBoundariesConverter(const std::filesystem::path &executable_path); virtual ~AdminBoundariesConverter(); - virtual void convert(const std::vector &dirs, - osmium::io::Writer &writer); + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; private: void addLevel1Boundaries( diff --git a/plugins/navteq/converter/BuildingConverter.cpp b/plugins/navteq/converter/BuildingConverter.cpp index a7c9c47..e62c26c 100644 --- a/plugins/navteq/converter/BuildingConverter.cpp +++ b/plugins/navteq/converter/BuildingConverter.cpp @@ -30,14 +30,11 @@ BuildingConverter::BuildingConverter( BuildingConverter::~BuildingConverter() {} -void BuildingConverter::convert(const std::vector &dirs, +void BuildingConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { static const std::filesystem::path LANDMARK_SHP = "Landmark.shp"; - - for (auto dir : dirs) { - add_building_shape(dir / LANDMARK_SHP, writer); - } + add_building_shape(dir / LANDMARK_SHP, writer); } void BuildingConverter::add_building_shape( diff --git a/plugins/navteq/converter/BuildingConverter.hpp b/plugins/navteq/converter/BuildingConverter.hpp index de5acf7..4b14088 100644 --- a/plugins/navteq/converter/BuildingConverter.hpp +++ b/plugins/navteq/converter/BuildingConverter.hpp @@ -27,8 +27,8 @@ class BuildingConverter : public Converter { BuildingConverter(const std::filesystem::path &executable_path); virtual ~BuildingConverter(); - virtual void convert(const std::vector &dirs, - osmium::io::Writer &writer); + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; private: void add_building_shape(std::filesystem::path landmark_shape_file, diff --git a/plugins/navteq/converter/CityConverter.cpp b/plugins/navteq/converter/CityConverter.cpp index 45c9df5..40a8cd7 100644 --- a/plugins/navteq/converter/CityConverter.cpp +++ b/plugins/navteq/converter/CityConverter.cpp @@ -28,14 +28,11 @@ CityConverter::CityConverter(const std::filesystem::path &executable_path) CityConverter::~CityConverter() {} -void CityConverter::convert(const std::vector &dirs, +void CityConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { const std::filesystem::path NAMED_PLC_SHP = "NamedPlc.shp"; - - for (auto dir : dirs) { - add_city_shape(dir / NAMED_PLC_SHP, writer); - } + add_city_shape(dir / NAMED_PLC_SHP, writer); } void CityConverter::add_city_shape(std::filesystem::path city_shape_file, diff --git a/plugins/navteq/converter/CityConverter.hpp b/plugins/navteq/converter/CityConverter.hpp index c5ced18..9c552ca 100644 --- a/plugins/navteq/converter/CityConverter.hpp +++ b/plugins/navteq/converter/CityConverter.hpp @@ -27,8 +27,8 @@ class CityConverter : public Converter { CityConverter(const std::filesystem::path &executable_path); virtual ~CityConverter(); - virtual void convert(const std::vector &dirs, - osmium::io::Writer &writer); + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; private: void add_city_shape(std::filesystem::path city_shape_file, diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 1ebb78a..0bf77a0 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -53,7 +53,7 @@ class Converter { : executable_path(_executable_path) {} virtual ~Converter() {} - virtual void convert(const std::vector &dirs, + virtual void convert(const std::filesystem::path &dir, osmium::io::Writer &writer) = 0; void set_dummy_osm_object_attributes(osmium::OSMObject &obj); diff --git a/plugins/navteq/converter/HamletConverter.cpp b/plugins/navteq/converter/HamletConverter.cpp index 7a1c58a..cde8ffc 100644 --- a/plugins/navteq/converter/HamletConverter.cpp +++ b/plugins/navteq/converter/HamletConverter.cpp @@ -28,14 +28,12 @@ HamletConverter::HamletConverter(const std::filesystem::path &executable_path) HamletConverter::~HamletConverter() {} -void HamletConverter::convert(const std::vector &dirs, +void HamletConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { const std::filesystem::path HAMLET_SHP = "Hamlet.shp"; - for (const auto &dir : dirs) { - add_hamlet(dir / HAMLET_SHP, writer); - } + add_hamlet(dir / HAMLET_SHP, writer); } void HamletConverter::add_hamlet(std::filesystem::path hamlet_file, diff --git a/plugins/navteq/converter/HamletConverter.hpp b/plugins/navteq/converter/HamletConverter.hpp index e78010a..4661238 100644 --- a/plugins/navteq/converter/HamletConverter.hpp +++ b/plugins/navteq/converter/HamletConverter.hpp @@ -27,8 +27,8 @@ class HamletConverter : public Converter { HamletConverter(const std::filesystem::path &executable_path); virtual ~HamletConverter(); - virtual void convert(const std::vector &dirs, - osmium::io::Writer &writer); + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; private: void add_hamlet(std::filesystem::path hamlet_file, diff --git a/plugins/navteq/converter/LanduseConverter.cpp b/plugins/navteq/converter/LanduseConverter.cpp index 5b87dc6..752bd0f 100644 --- a/plugins/navteq/converter/LanduseConverter.cpp +++ b/plugins/navteq/converter/LanduseConverter.cpp @@ -28,15 +28,13 @@ LanduseConverter::LanduseConverter(const std::filesystem::path &executable_path) LanduseConverter::~LanduseConverter() {} -void LanduseConverter::convert(const std::vector &dirs, +void LanduseConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { const std::filesystem::path LAND_USE_A_SHP = "LandUseA.shp"; const std::filesystem::path LAND_USE_B_SHP = "LandUseB.shp"; - for (auto dir : dirs) { - add_landuse_shape(dir / LAND_USE_A_SHP, writer); - add_landuse_shape(dir / LAND_USE_B_SHP, writer); - } + add_landuse_shape(dir / LAND_USE_A_SHP, writer); + add_landuse_shape(dir / LAND_USE_B_SHP, writer); } void LanduseConverter::add_landuse_shape( diff --git a/plugins/navteq/converter/LanduseConverter.hpp b/plugins/navteq/converter/LanduseConverter.hpp index 34c5b50..c426372 100644 --- a/plugins/navteq/converter/LanduseConverter.hpp +++ b/plugins/navteq/converter/LanduseConverter.hpp @@ -27,8 +27,8 @@ class LanduseConverter : public Converter { LanduseConverter(const std::filesystem::path &executable_path); virtual ~LanduseConverter(); - virtual void convert(const std::vector &dirs, - osmium::io::Writer &writer); + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; private: void add_landuse_shape(std::filesystem::path landuse_shape_file, diff --git a/plugins/navteq/converter/RailwayConverter.cpp b/plugins/navteq/converter/RailwayConverter.cpp index 5c65c74..d8cf65d 100644 --- a/plugins/navteq/converter/RailwayConverter.cpp +++ b/plugins/navteq/converter/RailwayConverter.cpp @@ -28,14 +28,12 @@ RailwayConverter::RailwayConverter(const std::filesystem::path &executable_path) RailwayConverter::~RailwayConverter() {} -void RailwayConverter::convert(const std::vector &dirs, +void RailwayConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { const std::filesystem::path RAILWAYS_POLY_SHP = "RailRds.shp"; - for (auto dir : dirs) { - add_railways_shape(dir / RAILWAYS_POLY_SHP, writer); - } + add_railways_shape(dir / RAILWAYS_POLY_SHP, writer); } void RailwayConverter::add_railways_shape( diff --git a/plugins/navteq/converter/RailwayConverter.hpp b/plugins/navteq/converter/RailwayConverter.hpp index b1e0d05..60021c4 100644 --- a/plugins/navteq/converter/RailwayConverter.hpp +++ b/plugins/navteq/converter/RailwayConverter.hpp @@ -27,8 +27,8 @@ class RailwayConverter : public Converter { RailwayConverter(const std::filesystem::path &executable_path); virtual ~RailwayConverter(); - virtual void convert(const std::vector &dirs, - osmium::io::Writer &writer); + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; private: void add_railways_shape(std::filesystem::path railway_shape_file, diff --git a/plugins/navteq/converter/RestAreaConverter.cpp b/plugins/navteq/converter/RestAreaConverter.cpp index aed67ea..1137981 100644 --- a/plugins/navteq/converter/RestAreaConverter.cpp +++ b/plugins/navteq/converter/RestAreaConverter.cpp @@ -29,13 +29,12 @@ RestAreaConverter::RestAreaConverter( RestAreaConverter::~RestAreaConverter() {} -void RestAreaConverter::convert(const std::vector &dirs, +void RestAreaConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { const std::filesystem::path TRAVDEST_SHP = "TravDest.shp"; - for (auto dir : dirs) { - add_rest_area(dir / TRAVDEST_SHP, writer); - } + + add_rest_area(dir / TRAVDEST_SHP, writer); } void RestAreaConverter::add_rest_area(std::filesystem::path rest_area_file, diff --git a/plugins/navteq/converter/RestAreaConverter.hpp b/plugins/navteq/converter/RestAreaConverter.hpp index b2af999..4e3bdb7 100644 --- a/plugins/navteq/converter/RestAreaConverter.hpp +++ b/plugins/navteq/converter/RestAreaConverter.hpp @@ -27,8 +27,8 @@ class RestAreaConverter : public Converter { RestAreaConverter(const std::filesystem::path &executable_path); virtual ~RestAreaConverter(); - virtual void convert(const std::vector &dirs, - osmium::io::Writer &writer); + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; private: void add_rest_area(std::filesystem::path rest_area_file, diff --git a/plugins/navteq/converter/WaterConverter.cpp b/plugins/navteq/converter/WaterConverter.cpp index b004284..83b1afa 100644 --- a/plugins/navteq/converter/WaterConverter.cpp +++ b/plugins/navteq/converter/WaterConverter.cpp @@ -27,16 +27,14 @@ WaterConverter::WaterConverter(const std::filesystem::path &executable_path) WaterConverter::~WaterConverter() {} -void WaterConverter::convert(const std::vector &dirs, +void WaterConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { const std::filesystem::path WATER_SEG_SHP = "WaterSeg.shp"; const std::filesystem::path WATER_POLY_SHP = "WaterPoly.shp"; - for (auto dir : dirs) { - add_water_shape(dir / WATER_POLY_SHP, writer); - add_water_shape(dir / WATER_SEG_SHP, writer); - } + add_water_shape(dir / WATER_POLY_SHP, writer); + add_water_shape(dir / WATER_SEG_SHP, writer); } void WaterConverter::add_water_shape(std::filesystem::path water_shape_file, diff --git a/plugins/navteq/converter/WaterConverter.hpp b/plugins/navteq/converter/WaterConverter.hpp index 19b7016..914e6b4 100644 --- a/plugins/navteq/converter/WaterConverter.hpp +++ b/plugins/navteq/converter/WaterConverter.hpp @@ -42,8 +42,8 @@ class WaterConverter : public Converter { WaterConverter(const std::filesystem::path &executable_path); virtual ~WaterConverter(); - virtual void convert(const std::vector &dirs, - osmium::io::Writer &writer); + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; private: void add_water_shape(std::filesystem::path water_shape_file, diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 9f43b64..4d653c4 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -163,8 +163,11 @@ void navteq_plugin::execute() { osmium::io::Writer writer(outfile, hdr, osmium::io::overwrite::allow); // run converters - for (auto &c : converter) - c->convert(dataDirs, writer); + for (auto &dir : dataDirs) { + BOOST_LOG_TRIVIAL(info) << "Processing " << dir; + for (auto &c : converter) + c->convert(dir, writer); + } writer.close(); From 80c92fa0973d644d6814f28a956028cc0ee624c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Tue, 16 Jul 2024 12:34:04 +0000 Subject: [PATCH 33/57] use Here to ISO mapping to determine the region to convert --- comm2osm.cpp | 3 ++- plugins/base_plugin.hpp | 3 ++- plugins/navteq/navteq_plugin.cpp | 32 +++++++++++++++++++++----------- plugins/navteq/navteq_plugin.hpp | 9 +++++++-- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/comm2osm.cpp b/comm2osm.cpp index 1a76f4c..d782c8c 100644 --- a/comm2osm.cpp +++ b/comm2osm.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "plugins/base_plugin.hpp" @@ -19,7 +20,7 @@ std::filesystem::path input_path, output_file; std::vector boundingBox; -std::vector countries; +std::set countries; static bool debug = false; void check_args_and_setup(int argc, char *argv[]) { diff --git a/plugins/base_plugin.hpp b/plugins/base_plugin.hpp index dd69736..a5d8739 100644 --- a/plugins/base_plugin.hpp +++ b/plugins/base_plugin.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -92,7 +93,7 @@ class base_plugin { virtual void setBoundingBox(double minX, double minY, double maxX, double maxY) = 0; - virtual void setCountries(const std::vector &_countries) = 0; + virtual void setCountries(const std::set &_countries) = 0; virtual void setDebug(bool debug) = 0; }; diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 4d653c4..713463e 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -88,19 +88,29 @@ navteq_plugin::check_files(const std::filesystem::path &dir) { if (!isHereDatatDir) return std::nullopt; - if (hasPackedData) { - return std::optional(tarFile); - } - - // check if the PROD.csv file exists - // check HERE-Contrycodes + if (!countriesToConvert.empty()) { + // get the 2 leading chars of the directory + std::string country = dir.filename().string().substr(0, 2); + auto isoContryCode = HERE_REGION_ISO_MAPPING.find(country); + if (isoContryCode == HERE_REGION_ISO_MAPPING.end()) { + BOOST_LOG_TRIVIAL(error) + << "Country code not found in mapping: " << country; + return std::nullopt; + } - // if there is a tar.gz --> use vsitar to extract the files - - // otherwise check id there are unpacked files + if (countriesToConvert.contains(isoContryCode->second)) { + foundCountries.insert(isoContryCode->second); + } else { + return std::nullopt; + } + } - return std::nullopt; + if (hasPackedData) { + return std::optional(tarFile); + } else { + return std::optional(dir); + } } bool navteq_plugin::check_input(const std::filesystem::path &input_path, @@ -221,7 +231,7 @@ void navteq_plugin::setBoundingBox(double minX, double minY, double maxX, boundingBox.MaxY = maxY; } -void navteq_plugin::setCountries(const std::vector &countries) { +void navteq_plugin::setCountries(const std::set &countries) { countriesToConvert = countries; } diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index d6f37bd..b75152d 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -11,6 +11,7 @@ #include "../base_plugin.hpp" #include "converter/Converter.hpp" #include +#include #include #include @@ -38,10 +39,14 @@ class navteq_plugin : public base_plugin { OGREnvelope boundingBox; - std::vector countriesToConvert; + std::set countriesToConvert; std::set foundCountries; bool debug; + const std::map HERE_REGION_ISO_MAPPING = { + {"M2", "SLO"}, {"M3", "ALB"}, {"M4", "MKD"}, {"M5", "SRB"}, + {"M6", "BIH"}, {"M7", "BLR"}, {"M9", "MLT"}}; + public: navteq_plugin(const std::filesystem::path &executable_path); virtual ~navteq_plugin(); @@ -53,7 +58,7 @@ class navteq_plugin : public base_plugin { void setBoundingBox(double minX, double minY, double maxX, double maxY); - void setCountries(const std::vector &_countries); + void setCountries(const std::set &_countries); void setDebug(bool debug); }; From 76d0abf7c2511ae482409c5017894ebbd46e5bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Tue, 16 Jul 2024 13:33:18 +0000 Subject: [PATCH 34/57] activate streetconverter again --- ...reetConverter.cpp_ => StreetConverter.cpp} | 577 ++++++++---------- ...reetConverter.hpp_ => StreetConverter.hpp} | 76 ++- plugins/navteq/navteq_mappings.hpp | 9 - plugins/navteq/navteq_plugin.cpp | 4 +- 4 files changed, 328 insertions(+), 338 deletions(-) rename plugins/navteq/converter/{StreetConverter.cpp_ => StreetConverter.cpp} (80%) rename plugins/navteq/converter/{StreetConverter.hpp_ => StreetConverter.hpp} (89%) diff --git a/plugins/navteq/converter/StreetConverter.cpp_ b/plugins/navteq/converter/StreetConverter.cpp similarity index 80% rename from plugins/navteq/converter/StreetConverter.cpp_ rename to plugins/navteq/converter/StreetConverter.cpp index 782859e..7c1fb3a 100644 --- a/plugins/navteq/converter/StreetConverter.cpp_ +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -23,113 +23,120 @@ #include #include - #include "../../comm2osm_exceptions.hpp" -#include "../../util.hpp" +#include "../../ogr_util.hpp" StreetConverter::StreetConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} StreetConverter::~StreetConverter() {} -void StreetConverter::convert(const std::vector &dirs, +void StreetConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { - auto route_type_map = process_alt_steets_route_types(dirs); + auto route_type_map = process_alt_steets_route_types(dir); - add_street_shapes(dirs, writer); + add_street_shapes(dir, writer); } std::map StreetConverter::process_alt_steets_route_types( - const std::vector &dirs) { + const std::filesystem::path &dir) { std::map route_type_map; - const std::filesystem::path ALT_STREETS_DBF = "AltStreets.dbf"; - for (auto dir : dirs) { - DBFHandle alt_streets_handle = read_dbf_file(dir / ALT_STREETS_DBF); - for (int i = 0; i < DBFGetRecordCount(alt_streets_handle); i++) { + auto ds = openDataSource(dir / ALT_STREETS_DBF); + if (!ds) + return route_type_map; - if (dbf_get_string_by_field(alt_streets_handle, i, ROUTE.data()).empty()) - continue; + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error((dir / ALT_STREETS_DBF).string())); - osmium::unsigned_object_id_type link_id = - dbf_get_uint_by_field(alt_streets_handle, i, LINK_ID.data()); - ushort route_type = - dbf_get_uint_by_field(alt_streets_handle, i, ROUTE.data()); + for (auto &feat : *layer) { + + std::string route = get_field_from_feature(feat, ROUTE); + if (route.empty()) + continue; - // try to emplace pair - auto [insertion, inserted] = route_type_map.emplace(link_id, route_type); + osmium::unsigned_object_id_type link_id = + get_uint_from_feature(feat, LINK_ID); + ushort route_type = get_uint_from_feature(feat, ROUTE); - // if its already exists update routetype - if (!inserted && insertion->second > route_type) { - // As link id's aren't unique in AltStreets.dbf - // just store the lowest route type - insertion->second = route_type; - } + // try to emplace pair + auto [insertion, inserted] = route_type_map.emplace(link_id, route_type); + + // if its already exists update routetype + if (!inserted && insertion->second > route_type) { + // As link id's aren't unique in AltStreets.dbf + // just store the lowest route type + insertion->second = route_type; } - DBFClose(alt_streets_handle); } return route_type_map; } -void StreetConverter::add_street_shapes( - const std::vector &dirs, - osmium::io::Writer &writer) { +void StreetConverter::add_street_shapes(const std::filesystem::path &dir, + osmium::io::Writer &writer) { BOOST_LOG_TRIVIAL(info) << " processing z-levels"; - auto z_level_map = process_z_levels(dirs); + auto z_level_map = process_z_levels(dir); BOOST_LOG_TRIVIAL(info) << " processing way end points"; - process_way_end_nodes(dirs, z_level_map, writer); + process_way_end_nodes(dir, z_level_map, writer); BOOST_LOG_TRIVIAL(info) << " processing ways"; - process_way(dirs, z_level_map, writer); + process_way(dir, z_level_map, writer); // create house numbers BOOST_LOG_TRIVIAL(info) << " processing house numbers"; - process_house_numbers(dirs, writer); + process_house_numbers(dir, writer); } -std::map> -StreetConverter::process_z_levels( - const std::vector &dirs) { +std::map> +StreetConverter::process_z_levels(const std::filesystem::path &dir) { + std::map> z_level_map; - for (auto &dir : dirs) { - auto path = dir / STREETS_SHP; - auto ds = open_shape_file(path); + auto ds = openDataSource(dir / STREETS_SHP); + if (!ds) + throw(shp_error(dir / STREETS_SHP)); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(path.string())); - assert(layer->GetGeomType() == wkbLineString); + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(dir / STREETS_SHP)); + assert(layer->GetGeomType() == wkbLineString); + + init_z_level_map(dir, z_level_map); + init_conditional_modifications(dir); + init_country_reference(dir); - init_z_level_map(dir, z_level_map); - init_conditional_modifications(dir); - init_country_reference(dir); - } return z_level_map; } void StreetConverter::init_z_level_map( - std::filesystem::path dir, + const std::filesystem::path &dir, std::map> &z_level_map) { const std::filesystem::path ZLEVELS_DBF = "Zlevels.dbf"; - // open dbf - DBFHandle handle = read_dbf_file(dir / ZLEVELS_DBF); + + auto ds = openDataSource(dir / ZLEVELS_DBF); + if (!ds) + throw(shp_error(dir / ZLEVELS_DBF)); + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(dir / ZLEVELS_DBF)); uint64_t last_link_id = 0; std::vector v; - for (int i = 0; i < DBFGetRecordCount(handle); i++) { - uint64_t link_id = dbf_get_uint_by_field(handle, i, LINK_ID.data()); - ushort point_num = dbf_get_uint_by_field(handle, i, POINT_NUM.data()) - 1; - short z_level = dbf_get_uint_by_field(handle, i, Z_LEVEL.data()); + for (auto &feat : *layer) { + uint64_t link_id = get_uint_from_feature(feat, LINK_ID); + ushort point_num = get_uint_from_feature(feat, POINT_NUM) - 1; + short z_level = get_uint_from_feature(feat, Z_LEVEL); - if (i > 0 && last_link_id != link_id && !v.empty()) { + if (last_link_id != link_id && !v.empty()) { z_level_map.emplace(last_link_id, v); v = std::vector(); } @@ -138,9 +145,6 @@ void StreetConverter::init_z_level_map( last_link_id = link_id; } - // close dbf - DBFClose(handle); - if (!v.empty()) z_level_map.emplace(last_link_id, v); } @@ -153,15 +157,20 @@ void StreetConverter::init_conditional_modifications( void StreetConverter::init_g_cnd_mod_map(const std::filesystem::path &dir) { const std::filesystem::path CND_MOD_DBF = "CndMod.dbf"; - DBFHandle cnd_mod_handle = read_dbf_file(dir / CND_MOD_DBF); - for (int i = 0; i < DBFGetRecordCount(cnd_mod_handle); i++) { - uint64_t cond_id = dbf_get_uint_by_field(cnd_mod_handle, i, COND_ID.data()); - std::string lang_code = - dbf_get_string_by_field(cnd_mod_handle, i, LANG_CODE.data()); - uint64_t mod_type = - dbf_get_uint_by_field(cnd_mod_handle, i, CM_MOD_TYPE.data()); - uint64_t mod_val = - dbf_get_uint_by_field(cnd_mod_handle, i, CM_MOD_VAL.data()); + + auto ds = openDataSource(dir / CND_MOD_DBF); + if (!ds) + return; + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(dir / CND_MOD_DBF)); + + for (auto &feat : *layer) { + uint64_t cond_id = get_uint_from_feature(feat, COND_ID); + std::string lang_code = get_field_from_feature(feat, LANG_CODE); + uint64_t mod_type = get_uint_from_feature(feat, CM_MOD_TYPE); + uint64_t mod_val = get_uint_from_feature(feat, CM_MOD_VAL); auto it2 = g_cnd_mod_map.find(cond_id); if (it2 == g_cnd_mod_map.end()) { @@ -169,98 +178,114 @@ void StreetConverter::init_g_cnd_mod_map(const std::filesystem::path &dir) { new_vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); g_cnd_mod_map.emplace(cond_id, new_vector); } else { - //(std::vector) ()’ auto vector = it2->second; g_cnd_mod_map.erase(it2); vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); g_cnd_mod_map.emplace(cond_id, vector); } } - DBFClose(cnd_mod_handle); } void StreetConverter::init_g_cdms_map(const std::filesystem::path &dir) { const std::filesystem::path CDMS_DBF = "Cdms.dbf"; - DBFHandle cdms_handle = read_dbf_file(dir / CDMS_DBF); - for (int i = 0; i < DBFGetRecordCount(cdms_handle); i++) { - uint64_t link_id = dbf_get_uint_by_field(cdms_handle, i, LINK_ID.data()); - uint64_t cond_id = dbf_get_uint_by_field(cdms_handle, i, COND_ID.data()); - ushort cond_type = dbf_get_uint_by_field(cdms_handle, i, COND_TYPE); + auto ds = openDataSource(dir / CDMS_DBF); + if (!ds) + return; + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(dir / CDMS_DBF)); + + for (auto &feat : *layer) { + uint64_t link_id = get_uint_from_feature(feat, LINK_ID); + uint64_t cond_id = get_uint_from_feature(feat, COND_ID); + ushort cond_type = get_uint_from_feature(feat, COND_TYPE); g_cdms_map.emplace(link_id, cond_pair_type(cond_id, cond_type)); + if (cond_type == 3) + g_construction_set.emplace(link_id); } - DBFClose(cdms_handle); } void StreetConverter::init_country_reference(const std::filesystem::path &dir) { - if (dbf_file_exists(dir / MTD_AREA_DBF) && - dbf_file_exists(dir / MTD_CNTRY_REF_DBF)) { - init_g_area_to_govt_code_map(dir); - init_g_cntry_ref_map(dir); - } + init_g_area_to_govt_code_map(dir); + init_g_cntry_ref_map(dir); } void StreetConverter::init_g_area_to_govt_code_map( const std::filesystem::path &dir) { - DBFHandle mtd_area_handle = read_dbf_file(dir / MTD_AREA_DBF); - for (int i = 0; i < DBFGetRecordCount(mtd_area_handle); i++) { - uint64_t area_id = - dbf_get_uint_by_field(mtd_area_handle, i, AREA_ID.data()); - uint64_t govt_code = - dbf_get_uint_by_field(mtd_area_handle, i, GOVT_CODE.data()); + + const std::filesystem::path MTD_AREA_DBF = "MtdArea.dbf"; + + auto ds = openDataSource(dir / MTD_AREA_DBF); + if (!ds) + return; + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(dir / MTD_AREA_DBF)); + + for (auto &feat : *layer) { + uint64_t area_id = get_uint_from_feature(feat, AREA_ID); + uint64_t govt_code = get_uint_from_feature(feat, GOVT_CODE); g_area_to_govt_code_map.emplace(area_id, govt_code); } - DBFClose(mtd_area_handle); } void StreetConverter::init_g_cntry_ref_map(const std::filesystem::path &dir) { - DBFHandle cntry_ref_handle = read_dbf_file(dir / MTD_CNTRY_REF_DBF); - for (int i = 0; i < DBFGetRecordCount(cntry_ref_handle); i++) { - uint64_t govt_code = - dbf_get_uint_by_field(cntry_ref_handle, i, GOVT_CODE.data()); - auto unit_measure = - dbf_get_string_by_field(cntry_ref_handle, i, UNTMEASURE.data()); - auto speed_limit_unit = - dbf_get_string_by_field(cntry_ref_handle, i, SPEEDLIMITUNIT.data()); - auto iso_code = - dbf_get_string_by_field(cntry_ref_handle, i, ISO_CODE.data()); - auto cntry_ref = cntry_ref_type(unit_measure, speed_limit_unit, iso_code); + + static const std::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; + + auto ds = openDataSource(dir / MTD_CNTRY_REF_DBF); + if (!ds) + return; + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(dir / MTD_CNTRY_REF_DBF)); + + for (auto &feat : *layer) { + uint64_t govt_code = get_uint_from_feature(feat, GOVT_CODE); + std::string unit_measure = get_field_from_feature(feat, UNTMEASURE); + std::string speed_limit_unit = get_field_from_feature(feat, SPEEDLIMITUNIT); + std::string iso_code = get_field_from_feature(feat, ISO_CODE); + cntry_ref_type cntry_ref(unit_measure, speed_limit_unit, iso_code); g_cntry_ref_map.emplace(govt_code, cntry_ref); } - DBFClose(cntry_ref_handle); } void StreetConverter::process_way_end_nodes( - const std::vector &dirs, - const std::map> &z_level_map, + const std::filesystem::path &dir, + const std::map> + &z_level_map, osmium::io::Writer &writer) { - for (auto &dir : dirs) { - // parse ramp names and refs - std::map> ramps_ref_map = - init_ramp_names(dir); + // parse ramp names and refs + std::map> ramps_ref_map = + init_ramp_names(dir); - auto path = dir / STREETS_SHP; - auto ds = open_shape_file(path); + auto path = dir / STREETS_SHP; + auto ds = openDataSource(path); + if (!ds) + throw(shp_error(path.string())); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(path.string())); + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(path.string())); - osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer node_buffer(BUFFER_SIZE); - int linkIDField = layer->FindFieldIndex(LINK_ID.data(), true); + int linkIDField = layer->FindFieldIndex(LINK_ID.data(), true); - // get all nodes which may be a routable crossing - for (auto &feat : *layer) { - uint64_t link_id = feat->GetFieldAsInteger(linkIDField); - // omit way end nodes with different z-levels (they have to be handled - // extra) - if (z_level_map.find(link_id) == z_level_map.end()) - process_way_end_nodes(feat, node_buffer); - } - node_buffer.commit(); - writer(std::move(node_buffer)); + // get all nodes which may be a routable crossing + for (auto &feat : *layer) { + uint64_t link_id = feat->GetFieldAsInteger(linkIDField); + // omit way end nodes with different z-levels (they have to be handled + // extra) + if (z_level_map.find(link_id) == z_level_map.end()) + process_way_end_nodes(feat, node_buffer); } + node_buffer.commit(); + writer(std::move(node_buffer)); } void StreetConverter::process_way_end_nodes( @@ -313,20 +338,23 @@ StreetConverter::init_ramp_names(const std::filesystem::path &dir) { std::map StreetConverter::read_junction_names(const std::filesystem::path &dbf_file) { - DBFHandle hwys_handle = read_dbf_file(dbf_file); - std::map junctionNames; - for (int i = 0; i < DBFGetRecordCount(hwys_handle); i++) { - uint64_t link_id = dbf_get_uint_by_field(hwys_handle, i, LINK_ID.data()); - std::string ramp_name = - dbf_get_string_by_field(hwys_handle, i, ST_NM_BASE.data()); + auto ds = openDataSource(dbf_file); + if (!ds) + throw(shp_error(dbf_file.string())); - if (parse_bool(dbf_get_string_by_field(hwys_handle, i, JUNCTIONNM.data()) - .c_str())) { - junctionNames[link_id] = ramp_name; + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(dbf_file.string())); + + std::map junctionNames; + + for (auto &feat : *layer) { + if (parse_bool(get_field_from_feature(feat, JUNCTIONNM))) { + uint64_t link_id = get_uint_from_feature(feat, LINK_ID); + junctionNames[link_id] = get_field_from_feature(feat, ST_NM_BASE); } } - DBFClose(hwys_handle); return junctionNames; } @@ -336,7 +364,10 @@ void StreetConverter::parse_ramp_names( std::map> &ramps_ref_map, const std::map &junctionNames) { - auto ds = open_shape_file(shp_file); + auto ds = openDataSource(shp_file); + if (!ds) + return; + auto layer = ds->GetLayer(0); if (layer == nullptr) throw(shp_empty_error(shp_file.string())); @@ -376,49 +407,46 @@ void StreetConverter::parse_ramp_names( } void StreetConverter::process_way( - const std::vector &dirs, - const std::map> &z_level_map, + const std::filesystem::path &dir, + std::map> &z_level_map, osmium::io::Writer &writer) { - for (auto &dir : dirs) { - // parse highway names and refs - auto hwys_ref_map = init_highway_names(dir); - - // parse conditionals - init_under_construction(dir); - - auto path = dir / STREETS_SHP; - auto ds = open_shape_file(path); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(path.string())); + // parse highway names and refs + auto hwys_ref_map = init_highway_names(dir); - osmium::memory::Buffer node_buffer(BUFFER_SIZE); - osmium::memory::Buffer way_buffer(BUFFER_SIZE); - for (auto &feat : *layer) { - process_way(feat, z_level_map, node_buffer, way_buffer); - } + auto path = dir / STREETS_SHP; + auto ds = openDataSource(path); + if (!ds) + throw(shp_error(path.string())); - node_buffer.commit(); - way_buffer.commit(); - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(path.string())); - g_hwys_ref_map.clear(); + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + for (auto &feat : *layer) { + process_way(feat, z_level_map, node_buffer, way_buffer); } + + node_buffer.commit(); + way_buffer.commit(); + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); } std::map> StreetConverter::init_highway_names(const std::filesystem::path &dir) { + + static const std::filesystem::path MAJ_HWYS_DBF = "MajHwys.dbf"; + static const std::filesystem::path SEC_HWYS_DBF = "SecHwys.dbf"; + static const std::filesystem::path STREETS_DBF = "Streets.dbf"; + std::map> hwys_ref_map; - if (dbf_file_exists(dir / MAJ_HWYS_DBF)) - parse_highway_names(dir / MAJ_HWYS_DBF, hwys_ref_map, false); - if (dbf_file_exists(dir / SEC_HWYS_DBF)) - parse_highway_names(dir / SEC_HWYS_DBF, hwys_ref_map, false); - if (dbf_file_exists(dir / ALT_STREETS_DBF)) - parse_highway_names(dir / ALT_STREETS_DBF, hwys_ref_map, true); - if (dbf_file_exists(dir / STREETS_DBF)) - parse_highway_names(dir / STREETS_DBF, hwys_ref_map, true); + parse_highway_names(dir / MAJ_HWYS_DBF, hwys_ref_map, false); + parse_highway_names(dir / SEC_HWYS_DBF, hwys_ref_map, false); + parse_highway_names(dir / ALT_STREETS_DBF, hwys_ref_map, true); + parse_highway_names(dir / STREETS_DBF, hwys_ref_map, true); return hwys_ref_map; } @@ -427,42 +455,30 @@ void StreetConverter::parse_highway_names( const std::filesystem::path &dbf_file, std::map> &hwys_ref_map, bool isStreetLayer) { - DBFHandle hwys_handle = read_dbf_file(dbf_file); - for (int i = 0; i < DBFGetRecordCount(hwys_handle); i++) { - uint64_t link_id = dbf_get_uint_by_field(hwys_handle, i, LINK_ID.data()); + auto ds = openDataSource(dbf_file); + if (!ds) + return; + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(dbf_file.string())); + + for (auto &feat : *layer) { + uint64_t link_id = get_uint_from_feature(feat, LINK_ID); std::string hwy_name; if (isStreetLayer) - hwy_name = dbf_get_string_by_field(hwys_handle, i, ST_NAME.data()); + hwy_name = get_field_from_feature(feat, ST_NAME); else - hwy_name = dbf_get_string_by_field(hwys_handle, i, HIGHWAY_NM.data()); - - uint routeType = dbf_get_uint_by_field(hwys_handle, i, ROUTE.data()); - + hwy_name = get_field_from_feature(feat, HIGHWAY_NM); + uint routeType = get_uint_from_feature(feat, ROUTE); hwys_ref_map[link_id].emplace(routeType, hwy_name); } - DBFClose(hwys_handle); -} - -void StreetConverter::init_under_construction( - const std::filesystem::path &dir) { - if (!dbf_file_exists(dir / CDMS_DBF)) - return; - - DBFHandle cond = read_dbf_file(dir / CDMS_DBF); - for (int i = 0; i < DBFGetRecordCount(cond); i++) { - uint64_t link_id = dbf_get_uint_by_field(cond, i, LINK_ID); - uint condType = dbf_get_uint_by_field(cond, i, COND_TYPE); - - if (condType == 3) - g_construction_set.emplace(link_id); - } - DBFClose(cond); } void StreetConverter::process_way( OGRFeatureUniquePtr &feat, - const std::map> &z_level_map, + std::map> &z_level_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { std::map node_ref_map; @@ -984,11 +1000,13 @@ void StreetConverter::add_highway_tag( if (!hwy_value.empty()) { builder.add_tag(highwayTagName, hwy_value.data()); } else { - std::cerr << "ignoring highway_level'" << std::to_string(route_type) - << "' for " << area_code_1 << std::endl; + BOOST_LOG_TRIVIAL(error) + << "ignoring highway_level'" << std::to_string(route_type) + << "' for " << area_code_1 << std::endl; } } else { - std::cerr << " highway misses route_type and func_class! " << std::endl; + BOOST_LOG_TRIVIAL(error) + << " highway misses route_type and func_class! " << std::endl; } } } @@ -1479,36 +1497,36 @@ void StreetConverter::create_premium_house_numbers( } } -void StreetConverter::process_house_numbers( - const std::vector &dirs, - osmium::io::Writer &writer) { - for (auto &dir : dirs) { - // create point addresses from PointAddress.dbf - auto pointMap = createPointAddressMapList(dir); +void StreetConverter::process_house_numbers(const std::filesystem::path &dir, + osmium::io::Writer &writer) { - auto path = dir / STREETS_SHP; - auto ds = open_shape_file(path); + // create point addresses from PointAddress.dbf + auto pointMap = createPointAddressMapList(dir); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(path.string())); + auto path = dir / STREETS_SHP; + auto ds = openDataSource(path); + if (!ds) + throw(shp_error(path.string())); - osmium::memory::Buffer node_buffer(BUFFER_SIZE); - osmium::memory::Buffer way_buffer(BUFFER_SIZE); + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(path.string())); - int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); - for (auto &feat : *layer) { - int linkId = feat->GetFieldAsInteger(linkIdField); - process_house_numbers(feat, *pointMap, linkId, node_buffer, way_buffer); - } + int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); - node_buffer.commit(); - way_buffer.commit(); - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); - delete pointMap; + for (auto &feat : *layer) { + int linkId = feat->GetFieldAsInteger(linkIdField); + process_house_numbers(feat, *pointMap, linkId, node_buffer, way_buffer); } + + node_buffer.commit(); + way_buffer.commit(); + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); + delete pointMap; } /** * \brief creates Way from linestring. @@ -1542,38 +1560,42 @@ StreetConverter::createPointAddressMapList(const std::filesystem::path &dir) { auto pointAddressMap = new std::map>>(); - if (shp_file_exists(dir / POINT_ADDRESS_SHP)) { - auto ds = open_shape_file(dir / POINT_ADDRESS_SHP); - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error((dir / POINT_ADDRESS_SHP).string())); + static const std::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; - int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); - int latField = layer->FindFieldIndex("DISP_LAT", true); - int lonField = layer->FindFieldIndex("DISP_LON", true); - int addressField = layer->FindFieldIndex("ADDRESS", true); + auto ds = openDataSource(dir / POINT_ADDRESS_SHP); + if (!ds) + return pointAddressMap; - for (auto &feat : *layer) { - int linkId = feat->GetFieldAsInteger(linkIdField); - auto houseNumber = std::string(feat->GetFieldAsString(addressField)); + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error((dir / POINT_ADDRESS_SHP).string())); - double lat = 0.0; - double lon = 0.0; + int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); + int latField = layer->FindFieldIndex("DISP_LAT", true); + int lonField = layer->FindFieldIndex("DISP_LON", true); + int addressField = layer->FindFieldIndex("ADDRESS", true); - if (feat->IsFieldNull(lonField) && feat->IsFieldNull(latField)) { - auto point = static_cast(feat->GetGeometryRef()); - lat = point->getY(); - lon = point->getX(); - } else { - lon = feat->GetFieldAsDouble(lonField); - lat = feat->GetFieldAsDouble(latField); - } + for (auto &feat : *layer) { + int linkId = feat->GetFieldAsInteger(linkIdField); + auto houseNumber = std::string(feat->GetFieldAsString(addressField)); + + double lat = 0.0; + double lon = 0.0; - (*pointAddressMap)[linkId].emplace_back(osmium::Location(lon, lat), - houseNumber); + if (feat->IsFieldNull(lonField) && feat->IsFieldNull(latField)) { + auto point = static_cast(feat->GetGeometryRef()); + lat = point->getY(); + lon = point->getX(); + } else { + lon = feat->GetFieldAsDouble(lonField); + lat = feat->GetFieldAsDouble(latField); } + + (*pointAddressMap)[linkId].emplace_back(osmium::Location(lon, lat), + houseNumber); } + return pointAddressMap; } @@ -1593,18 +1615,16 @@ void StreetConverter::set_ferry_z_lvls_to_zero( z_lvl_vec.erase(z_lvl_vec.end()); } - // TODO - static std::set z_lvl_set = {-4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; -void test__z_lvl_range(short z_lvl) { +void StreetConverter::test__z_lvl_range(short z_lvl) { if (z_lvl_set.find(z_lvl) == z_lvl_set.end()) throw(out_of_range_exception("z_lvl " + std::to_string(z_lvl) + " is not valid")); } -bool is_ferry(const char *value) { +bool StreetConverter::is_ferry(const char *value) { if (!strcmp(value, "H")) return false; // H --> not a ferry else if (!strcmp(value, "B")) @@ -1620,7 +1640,7 @@ bool is_ferry(const char *value) { * \param than second z_level. * \return true if superior is greater or equal than. */ -bool is_superior_or_equal(short superior, short than) { +bool StreetConverter::is_superior_or_equal(short superior, short than) { if (abs(superior) >= abs(than)) return true; return false; @@ -1633,13 +1653,14 @@ bool is_superior_or_equal(short superior, short than) { * \param than second z_level. * \return true if superior is superior to than. */ -bool is_superior(short superior, short than) { +bool StreetConverter::is_superior(short superior, short than) { if (abs(superior) > abs(than)) return true; return false; } -uint get_number_after(const std::string &str, const char *start_str) { +uint StreetConverter::get_number_after(const std::string &str, + const char *start_str) { if (!str.starts_with(start_str)) return 0; /* doesn't start with start_str */ @@ -1661,7 +1682,7 @@ uint get_number_after(const std::string &str, const char *start_str) { } } -const char *parse_house_number_schema(const char *schema) { +const char *StreetConverter::parse_house_number_schema(const char *schema) { if (!strcmp(schema, "E")) return "even"; if (!strcmp(schema, "O")) @@ -1676,7 +1697,7 @@ const char *parse_house_number_schema(const char *schema) { /** * \brief converts pounds to metric tons */ -std::string lbs_to_metric_ton(double lbs) { +std::string StreetConverter::lbs_to_metric_ton(double lbs) { double short_ton = lbs / (double)POUND_BASE; double metric_ton = short_ton * SHORT_TON; std::stringstream stream; @@ -1684,66 +1705,10 @@ std::string lbs_to_metric_ton(double lbs) { return stream.str(); } -/** - * \brief converts kilogram to tons - */ -template std::string kg_to_t(T kilo) { - return std::to_string(kilo / 1000.0f); -} -/** - * \brief converts centimeter to meters - */ -template std::string cm_to_m(T meter) { - return std::to_string(meter / 100.0f); -} /** * \brief converts inches to feet */ -std::string inch_to_feet(unsigned int inches) { +std::string StreetConverter::inch_to_feet(unsigned int inches) { return std::to_string((unsigned int)floor(inches / INCH_BASE)) + "'" + std::to_string(inches % INCH_BASE) + "\""; } - - -const int INCH_BASE = 12; -const int POUND_BASE = 2000; -// short ton in metric tons (source: -// http://wiki.openstreetmap.org/wiki/Key:maxweight) -const double SHORT_TON = 0.90718474; - -/** - * \brief returns index of a given field in a DBFHandle - * \param handle DBFHandle - * \param field_name field of DBFhandle - * \return index of given field - */ - -int dbf_get_field_index(DBFHandle handle, const char *field_name) { - assert(handle); - assert(field_name); - // if (row >= DBFGetRecordCount(handle)) throw(std::runtime_error("row=" + - // std::to_string(row) + " is out of bounds.")); - int index = DBFGetFieldIndex(handle, field_name); - if (index == -1) - throw(std::runtime_error("DBFfile doesnt contain " + - std::string(field_name))); - return index; -} - -/** - * \brief get field of a given DBFHandle as string - */ -std::string dbf_get_string_by_field(DBFHandle handle, int row, - const char *field_name) { - return DBFReadStringAttribute(handle, row, - dbf_get_field_index(handle, field_name)); -} - -/** - * \brief get field of a given DBFHandle as uint64_t - */ -uint64_t dbf_get_uint_by_field(DBFHandle handle, int row, - const char *field_name) { - return DBFReadIntegerAttribute(handle, row, - dbf_get_field_index(handle, field_name)); -} \ No newline at end of file diff --git a/plugins/navteq/converter/StreetConverter.hpp_ b/plugins/navteq/converter/StreetConverter.hpp similarity index 89% rename from plugins/navteq/converter/StreetConverter.hpp_ rename to plugins/navteq/converter/StreetConverter.hpp index 6ee5fe7..d15d917 100644 --- a/plugins/navteq/converter/StreetConverter.hpp_ +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -27,15 +27,15 @@ class StreetConverter : public Converter { StreetConverter(const std::filesystem::path &executable_path); virtual ~StreetConverter(); - virtual void convert(const std::vector &dirs, - osmium::io::Writer &writer); + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; -private: struct z_lvl_index_type_t { ushort index; short z_level; }; +private: struct cond_type { uint64_t cond_id_type; uint64_t cond_type_type; @@ -77,22 +77,24 @@ class StreetConverter : public Converter { bool operator!=(cntry_ref_type rhs) { return !(*this == rhs); } }; - std::map process_alt_steets_route_types( - const std::vector &dirs); + std::map + process_alt_steets_route_types(const std::filesystem::path &dir); - void add_street_shapes(const std::vector &dirs, + void add_street_shapes(const std::filesystem::path &dir, osmium::io::Writer &writer); std::map> - process_z_levels(const std::vector &dirs); + process_z_levels(const std::filesystem::path &dir); void init_z_level_map( - std::filesystem::path dir, + const std::filesystem::path &dir, std::map> &z_level_map); void set_ferry_z_lvls_to_zero(const OGRFeatureUniquePtr &feat, std::vector &z_lvl_vec); + void test__z_lvl_range(short z_lvl); + void init_conditional_modifications(const std::filesystem::path &dir); void init_g_cnd_mod_map(const std::filesystem::path &dir); void init_g_cdms_map(const std::filesystem::path &dir); @@ -103,8 +105,9 @@ class StreetConverter : public Converter { // process end nodes void process_way_end_nodes( - const std::vector &dirs, - const std::map> &z_level_map, + const std::filesystem::path &dir, + const std::map> + &z_level_map, osmium::io::Writer &writer); void process_way_end_nodes(OGRFeatureUniquePtr &feat, osmium::memory::Buffer &node_buffer); @@ -121,14 +124,15 @@ class StreetConverter : public Converter { std::map> &ramps_ref_map, const std::map &junctionNames); - void process_way( - const std::vector &dirs, - const std::map> &z_level_map, - osmium::io::Writer &writer); - void process_way( - OGRFeatureUniquePtr &feat, - const std::map> &z_level_map, - osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); + void + process_way(const std::filesystem::path &dirs, + std::map> &z_level_map, + osmium::io::Writer &writer); + void + process_way(OGRFeatureUniquePtr &feat, + std::map> &z_level_map, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); void middle_points_preparation( OGRLineString *ogr_ls, @@ -256,8 +260,6 @@ class StreetConverter : public Converter { bool only_pedestrians(const OGRFeatureUniquePtr &f); - void init_under_construction(const std::filesystem::path &dir); - void add_here_speed_cat_tag(osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f); @@ -276,7 +278,7 @@ class StreetConverter : public Converter { const std::vector> &addressList, int linkId, osmium::memory::Buffer &node_buffer); - void process_house_numbers(const std::vector &dirs, + void process_house_numbers(const std::filesystem::path &dirs, osmium::io::Writer &writer); void process_house_numbers( @@ -290,6 +292,28 @@ class StreetConverter : public Converter { std::map>> * createPointAddressMapList(const std::filesystem::path &dir); + bool is_ferry(const char *value); + + bool is_superior_or_equal(short superior, short than); + + bool is_superior(short superior, short than); + + uint get_number_after(const std::string &str, const char *start_str); + + const char *parse_house_number_schema(const char *schema); + + std::string lbs_to_metric_ton(double lbs); + + std::string inch_to_feet(unsigned int inches); + + template std::string kg_to_t(T kilo) { + return std::to_string(kilo / 1000.0f); + } + + template std::string cm_to_m(T meter) { + return std::to_string(meter / 100.0f); + } + // CndMod types (CM) static constexpr std::string_view CM_MOD_TYPE = "MOD_TYPE"; static constexpr std::string_view CM_MOD_VAL = "MOD_VAL"; @@ -419,6 +443,16 @@ class StreetConverter : public Converter { const ushort MT_WIDTH_RESTRICTION = 45; const ushort RESTRICTED_DRIVING_MANOEUVRE = 7; + + const int INCH_BASE = 12; + const int POUND_BASE = 2000; + // short ton in metric tons (source: + // http://wiki.openstreetmap.org/wiki/Key:maxweight) + const double SHORT_TON = 0.90718474; + + const std::filesystem::path STREETS_SHP = "Streets.shp"; + + const std::filesystem::path ALT_STREETS_DBF = "AltStreets.dbf"; }; #endif // STREETCONVERTER_HPP diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp index 4149dea..6845729 100644 --- a/plugins/navteq/navteq_mappings.hpp +++ b/plugins/navteq/navteq_mappings.hpp @@ -21,17 +21,8 @@ static const std::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; static const std::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; static const std::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; -static const std::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; - -static const std::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; - static const std::filesystem::path RDMS_DBF = "Rdms.dbf"; -static const std::filesystem::path MAJ_HWYS_DBF = "MajHwys.dbf"; -static const std::filesystem::path SEC_HWYS_DBF = "SecHwys.dbf"; - -static const std::filesystem::path STREETS_DBF = "Streets.dbf"; - } // namespace #endif /* PLUGINS_NAVTEQ_MAPPINGS_HPP_ */ diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 713463e..5112b06 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -24,7 +24,7 @@ #include "converter/LanduseConverter.hpp" #include "converter/RailwayConverter.hpp" #include "converter/RestAreaConverter.hpp" -// #include "converter/StreetConverter.hpp" +#include "converter/StreetConverter.hpp" #include "converter/WaterConverter.hpp" #include "../comm2osm_exceptions.hpp" @@ -40,7 +40,7 @@ navteq_plugin::navteq_plugin(const std::filesystem::path &executable_path) : base_plugin::base_plugin("Navteq Plugin", executable_path) { converter.emplace_back(new AdminBoundariesConverter(executable_path)); - // converter.emplace_back(new StreetConverter(executable_path)); + converter.emplace_back(new StreetConverter(executable_path)); converter.emplace_back(new LanduseConverter(executable_path)); converter.emplace_back(new CityConverter(executable_path)); converter.emplace_back(new HamletConverter(executable_path)); From 1ace21bc2e8b9c405b52e8b29dfe27d2f156d43e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Tue, 16 Jul 2024 13:36:10 +0000 Subject: [PATCH 35/57] refactor: Remove navteq_mappings.hpp file --- plugins/navteq/navteq_mappings.hpp | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 plugins/navteq/navteq_mappings.hpp diff --git a/plugins/navteq/navteq_mappings.hpp b/plugins/navteq/navteq_mappings.hpp deleted file mode 100644 index 6845729..0000000 --- a/plugins/navteq/navteq_mappings.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * navteq_mappings.hpp - * - * Created on: 22.06.2015 - * Author: philip - */ - -#ifndef PLUGINS_NAVTEQ_NAME_MAPPING_HPP_ -#define PLUGINS_NAVTEQ_NAME_MAPPING_HPP_ - -#include -#include - -namespace { - -static const std::filesystem::path STREETS_SHP = "Streets.shp"; -static const std::filesystem::path ADMINLINE_1_SHP = "AdminLine1.shp"; -static const std::filesystem::path ADMINBNDY_1_SHP = "Adminbndy1.shp"; -static const std::filesystem::path ADMINBNDY_2_SHP = "Adminbndy2.shp"; -static const std::filesystem::path ADMINBNDY_3_SHP = "Adminbndy3.shp"; -static const std::filesystem::path ADMINBNDY_4_SHP = "Adminbndy4.shp"; -static const std::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; - -static const std::filesystem::path RDMS_DBF = "Rdms.dbf"; - -} // namespace - -#endif /* PLUGINS_NAVTEQ_MAPPINGS_HPP_ */ From 4c7984752bad37987856832a7ea821a2904a8fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 06:45:56 +0000 Subject: [PATCH 36/57] extract OSMTagger and housenumber creation --- plugins/navteq/converter/StreetConverter.cpp | 880 +----------------- plugins/navteq/converter/StreetConverter.hpp | 2 +- .../converter/StreetConverterHouseNumber.cpp | 245 +++++ .../converter/StreetConverterOSMTagger.cpp | 687 ++++++++++++++ 4 files changed, 934 insertions(+), 880 deletions(-) create mode 100644 plugins/navteq/converter/StreetConverterHouseNumber.cpp create mode 100644 plugins/navteq/converter/StreetConverterOSMTagger.cpp diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 7c1fb3a..7e786e5 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -24,7 +24,6 @@ #include #include "../../comm2osm_exceptions.hpp" -#include "../../ogr_util.hpp" StreetConverter::StreetConverter(const std::filesystem::path &executable_path) : Converter(executable_path) {} @@ -581,194 +580,10 @@ osmium::unsigned_object_id_type StreetConverter::build_way( } } - build_tag_list(feat, &builder, way_buffer, z_lvl); + build_tag_list(feat, builder, way_buffer, z_lvl); return builder.object().id(); } -uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, - osmium::builder::Builder *builder, - osmium::memory::Buffer &buf, - short z_level) { - osmium::builder::TagListBuilder tl_builder(buf, builder); - - uint64_t link_id = parse_street_tags( - tl_builder, feat, &g_cdms_map, &g_cnd_mod_map, &g_area_to_govt_code_map, - &g_cntry_ref_map, &g_mtd_area_map, &g_route_type_map, &g_hwys_ref_map, - g_construction_set, debugMode); - - if (z_level != -5 && z_level != 0) - tl_builder.add_tag("layer", std::to_string(z_level)); - if (link_id == 0) - throw(format_error("layers column field '" + std::string(LINK_ID.data()) + - "' is missing")); - return link_id; -} - -uint64_t StreetConverter::parse_street_tags( - osmium::builder::TagListBuilder &builder, OGRFeatureUniquePtr &f, - const std::multimap &cdms_map, - const std::unordered_map> - &cnd_mod_map, - const std::map &area_govt_map, - const std::map &cntry_map, - const std::map - &mtd_area_map, - const std::map &route_type_map, - const std::map> &names_map, - const std::set &construction_set, bool debugMode) { - - const char *link_id_s = get_field_from_feature(f, LINK_ID); - uint64_t link_id = std::stoul(link_id_s); - - bool ramp = parse_bool(get_field_from_feature(f, RAMP)); - - ushort route_type = 0; - if (!((std::string)get_field_from_feature(f, ROUTE)).empty()) - route_type = get_uint_from_feature(f, ROUTE); - - auto routeTypeIter = route_type_map.find(link_id); - if (routeTypeIter != route_type_map.end() && - (!route_type || routeTypeIter->second < route_type)) - route_type = routeTypeIter->second; - - // add tags for ref and int_ref to major highways - std::string ref_name = - add_highway_name_tags(builder, names_map, link_id, ramp); - - bool underConstruction = - (construction_set.find(link_id) != construction_set.end()); - - if (is_ferry(get_field_from_feature(f, FERRY))) { - add_ferry_tag(builder, f); - } else { // usual highways - add_highway_tags(builder, f, route_type, mtd_area_map, ref_name, - underConstruction); - } - - uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); - uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); - // tags which apply to highways and ferry routes - add_additional_restrictions(builder, link_id, l_area_id, r_area_id, cdms_map, - cnd_mod_map, area_govt_map, cntry_map, - mtd_area_map); - - // tag for debug purpose - if (debugMode) { - builder.add_tag(LINK_ID.data(), link_id_s); - add_here_speed_cat_tag(builder, f); - if (parse_bool(get_field_from_feature(f, TOLLWAY))) - builder.add_tag("here:tollway", YES.data()); - if (parse_bool(get_field_from_feature(f, URBAN))) - builder.add_tag("here:urban", YES.data()); - if (parse_bool(get_field_from_feature(f, CONTRACC))) - builder.add_tag("here:controll_access", YES.data()); - if (route_type) - add_uint_tag(builder, "here:route_type", route_type); - - std::string func_class = get_field_from_feature(f, FUNC_CLASS); - if (!func_class.empty()) - builder.add_tag("here:func_class", func_class.c_str()); - - add_uint_tag(builder, "here:area_code", get_area_code_l(f, mtd_area_map)); - } - return link_id; -} - -void StreetConverter::add_additional_restrictions( - osmium::builder::TagListBuilder &builder, uint64_t link_id, - uint64_t l_area_id, uint64_t r_area_id, - const std::multimap &cdms_map, - const std::unordered_map> - &cnd_mod_map, - const std::map &area_govt_map, - const std::map &cntry_map, - const std::map - &mtd_area_map) { - if (cdms_map.empty() || cnd_mod_map.empty()) - return; - - // default is metric units - bool imperial_units = - is_imperial(l_area_id, r_area_id, area_govt_map, cntry_map); - - uint64_t max_height = 0; - uint64_t max_width = 0; - uint64_t max_length = 0; - uint64_t max_weight = 0; - uint64_t max_axleload = 0; - - std::vector mod_group_vector; - auto range = cdms_map.equal_range(link_id); - for (auto it = range.first; it != range.second; ++it) { - auto cond = it->second; - if (cond.cond_type_type == CT_RESTRICTED_DRIVING_MANOEUVRE || - cond.cond_type_type == CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE) - continue; // TODO RESTRICTED_DRIVING_MANOEUVRE should apply as - // conditional turn restriction but not for current link id - auto it2 = cnd_mod_map.find(cond.cond_id_type); - if (it2 != cnd_mod_map.end()) { - for (auto mod_group : it2->second) { - mod_group_vector.push_back(mod_group); - } - } - } - - for (auto mod_group : mod_group_vector) { - auto mod_type = mod_group.mod_type; - auto mod_val = mod_group.mod_val; - if (mod_type == MT_HEIGHT_RESTRICTION) { - if (!max_height || mod_val < max_height) - max_height = mod_val; - } else if (mod_type == MT_WIDTH_RESTRICTION) { - if (!max_width || mod_val < max_width) - max_width = mod_val; - } else if (mod_type == MT_LENGTH_RESTRICTION) { - if (!max_length || mod_val < max_length) - max_length = mod_val; - } else if (mod_type == MT_WEIGHT_RESTRICTION) { - if (!max_weight || mod_val < max_weight) - max_weight = mod_val; - } else if (mod_type == MT_WEIGHT_PER_AXLE_RESTRICTION) { - if (!max_axleload || mod_val < max_axleload) - max_axleload = mod_val; - } else if (mod_type == MT_HAZARDOUS_RESTRICTION) { - add_hazmat_tag(builder, mod_val); - } - } - - if (get_area_code_l(l_area_id, r_area_id, mtd_area_map) == 107) { - /** exceptional handling for Sweden as there are BK Roads - * - * HERE tags these roads with the most conservative values, - * which would make it unroutable for nearly every truck. - * Therefore we use the highest value and add a marker for BK2 / BK3 */ - if (max_weight == 16000 && max_axleload == 10000) { - builder.add_tag("maxweight:class", "BK2"); - max_weight = 51400; - } else if (max_weight == 12000 && max_axleload == 8000) { - builder.add_tag("maxweight:class", "BK3"); - max_weight = 37000; - } - } - - if (max_height > 0) - builder.add_tag("maxheight", imperial_units ? inch_to_feet(max_height) - : cm_to_m(max_height)); - if (max_width > 0) - builder.add_tag("maxwidth", imperial_units ? inch_to_feet(max_width) - : cm_to_m(max_width)); - if (max_length > 0) - builder.add_tag("maxlength", imperial_units ? inch_to_feet(max_length) - : cm_to_m(max_length)); - if (max_weight > 0) - builder.add_tag("maxweight", imperial_units ? lbs_to_metric_ton(max_weight) - : kg_to_t(max_weight)); - if (max_axleload > 0) - builder.add_tag("maxaxleload", imperial_units - ? lbs_to_metric_ton(max_axleload) - : kg_to_t(max_axleload)); -} - void StreetConverter::process_end_point( bool first, short z_lvl, OGRLineString *ogr_ls, std::map &node_ref_map, @@ -950,655 +765,6 @@ bool StreetConverter::is_imperial( return false; } -void StreetConverter::add_highway_tag( - osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, - ushort route_type, ushort func_class, - const std::map - &mtd_area_map, - const std::string &ref_name, bool underConstruction) { - - bool paved = parse_bool(get_field_from_feature(f, PAVED)); - bool motorized_allowed = is_motorized_allowed(f); - - std::string highwayTagName = HIGHWAY.data(); - - if (underConstruction) { - builder.add_tag(HIGHWAY.data(), CONSTRUCTION.data()); - highwayTagName = CONSTRUCTION.data(); - } - - if (!paved) { - if (!motorized_allowed) { - // unpaved + non-motorized => path - builder.add_tag(highwayTagName, PATH.data()); - } else { - // unpaved + motorized allowed => track - builder.add_tag(highwayTagName, TRACK.data()); - } - } else { - if (!motorized_allowed) { - // paved + non-motorized => footway - // it seems imposref_nameible to distinguish footways from cycle ways or - // pedestrian zones - builder.add_tag(highwayTagName, FOOTWAY.data()); - } else { - // paved + motorized allowed - bool controlled_access = parse_bool(get_field_from_feature(f, CONTRACC)); - bool urban = parse_bool(get_field_from_feature(f, URBAN)); - bool ramp = parse_bool(get_field_from_feature(f, RAMP)); - uint area_code_1 = get_area_code_l(f, mtd_area_map); - - if (controlled_access) { - // controlled_access => motorway - if (ramp) - builder.add_tag(highwayTagName, MOTORWAY_LINK.data()); - else - builder.add_tag(highwayTagName, MOTORWAY.data()); - } else if (func_class || route_type) { - std::string_view hwy_value = - get_hwy_value(route_type, func_class, area_code_1, ref_name, urban); - if (!hwy_value.empty()) { - builder.add_tag(highwayTagName, hwy_value.data()); - } else { - BOOST_LOG_TRIVIAL(error) - << "ignoring highway_level'" << std::to_string(route_type) - << "' for " << area_code_1 << std::endl; - } - } else { - BOOST_LOG_TRIVIAL(error) - << " highway misses route_type and func_class! " << std::endl; - } - } - } -} - -std::string_view StreetConverter::get_hwy_value(ushort route_type, - ushort func_class, - uint area_code_1, - const std::string &ref_name, - bool urban) { - /* some exceptional cases for better route type parsing */ - if (area_code_1 == 2 && route_type == 4) { /*"FRA"*/ - /* Too many different highways have route type 4 - * so we also take functional class into consideration */ - if (func_class == 2) - return PRIMARY; - else if (func_class == 3) - return SECONDARY; - else if (func_class > 3) - return TERTIARY; - } else if (area_code_1 == 5 && route_type == 3) { /*"BEL"*/ - /* N# and N## is like PRIMARY - * N### SECONDARY - * N#### TERTIARY */ - uint hwy_num = get_number_after(ref_name, "N"); - if (hwy_num > 999) - return TERTIARY; - if (hwy_num > 99) - return SECONDARY; - } else if (area_code_1 == 9) { /*"AUT"*/ - if (route_type == 4) { - return PRIMARY; // bundesstrasse - } else if (route_type == 5) { - return SECONDARY; // landesstrasse - } - } else if (area_code_1 == 23 && route_type == 2) { /*"IRL"*/ - /* N## is TRUNK if ## smaller 50 otherwise PRIMARY */ - uint hwy_num = get_number_after(ref_name, "N"); - if (hwy_num > 0 && hwy_num < 50) - return TRUNK; - } else if (area_code_1 == 109 || - area_code_1 == 110 /*UK - Wales*/ /*UK - England*/ - || area_code_1 == 112 || - area_code_1 == 22) { /*UK - Scotland*/ /*UK - Northern Ireland*/ - /* Differ between white and green shield A-Roads */ - if (route_type == 2) { - if (func_class == 2 || func_class == 1) - return TRUNK; - else - return PRIMARY; - } else if (route_type == 3 && func_class == 4) { - return SECONDARY; - } - } else if (area_code_1 == 107) { // SWE - if (func_class == 1 && route_type == 1) - return TRUNK; // func_class 1 und not controlled - } - - uint apply_func_class = func_class; - if (apply_func_class > 4 && urban) { - apply_func_class++; - } else if (func_class == 2 && (route_type == 3 || route_type == 2)) { - return PRIMARY; // primary - } - - const auto &hwy_vector = HWY_FUNC_CLASS_MAP.contains(area_code_1) - ? HWY_FUNC_CLASS_MAP.at(area_code_1) - : DEFAULT_HWY_FUNC_TYPE; - - /* default case */ - return hwy_vector.at(apply_func_class); -} - -bool StreetConverter::is_motorized_allowed(const OGRFeatureUniquePtr &f) { - if (parse_bool(get_field_from_feature(f, AR_AUTO))) - return true; - if (parse_bool(get_field_from_feature(f, AR_BUS))) - return true; - if (parse_bool(get_field_from_feature(f, AR_TAXIS))) - return true; - if (parse_bool(get_field_from_feature(f, AR_TRUCKS))) - return true; - if (parse_bool(get_field_from_feature(f, AR_DELIV))) - return true; - if (parse_bool(get_field_from_feature(f, AR_EMERVEH))) - return true; - if (parse_bool(get_field_from_feature(f, AR_MOTORCYCLES))) - return true; - - return false; -} - -void StreetConverter::add_hazmat_tag(osmium::builder::TagListBuilder &builder, - uint64_t mod_val) { - if (mod_val == 20) { // || mod_val == 21 - builder.add_tag("hazmat", "no"); - } else if (mod_val == 22) { - builder.add_tag("hazmat:water", "no"); - } else if (mod_val == 24) { - builder.add_tag("hazmat:B", "no"); - } else if (mod_val == 28) { - builder.add_tag("hazmat:C", "no"); - } else if (mod_val == 32) { - builder.add_tag("hazmat:D", "no"); - } else if (mod_val == 34) { - builder.add_tag("hazmat:E", "no"); - } else if (mod_val == 23) { - /* 23 = Explosive and Flammable */ - } else { - /** - * Do nothing for the residual values, - * which do not occur and/or have no proper OSM tagging equivalent - * 1 = Explosives - * 2 = Gas - * 3 = Flammable - * 4 = Flammable solid/Combustible - * 5 = Organic - * 6 = Poison - * 7 = Radioactive - * 8 = Corrosive - * 9 = Other - */ - BOOST_LOG_TRIVIAL(error) << "Hazardous material value " << mod_val - << " hasn't been parsed!" << std::endl; - } -} - -std::string StreetConverter::add_highway_name_tags( - osmium::builder::TagListBuilder &builder, - const std::map> &names_map, - uint64_t link_id, bool ramp) { - std::string ref_tag; - - auto it = names_map.find(link_id); - if (it != names_map.end()) { - auto &highway_names_vector = it->second; - std::string street_name; - std::string int_ref_tag; - std::string nat_ref_tag; - - for (auto highwayName : highway_names_vector) { - if (highwayName.first == 0) { - street_name = highwayName.second; - } else if (highwayName.first == 1) { - int_ref_tag = highwayName.second; - } else if (highwayName.first > 1) { - nat_ref_tag = highwayName.second; - } - } - - if (!nat_ref_tag.empty()) - ref_tag = nat_ref_tag; - else - ref_tag = int_ref_tag; - - if (!street_name.empty() && !ramp) - builder.add_tag("name", to_camel_case_with_spaces(street_name)); - if (!ref_tag.empty()) // national ref (Autobahn) - builder.add_tag("ref", ref_tag); - if (!int_ref_tag.empty()) // international ref (European street) - builder.add_tag("int_ref", int_ref_tag); - if (!nat_ref_tag.empty()) // national ref (European street) - builder.add_tag("nat_ref", nat_ref_tag); - } - - return ref_tag; -} - -void StreetConverter::add_highway_tags( - osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, - ushort route_type, - const std::map - &mtd_area_map, - const std::string &ref_name, bool underConstruction) { - - ushort func_class = 0; - std::string func_class_s = get_field_from_feature(f, FUNC_CLASS); - if (!func_class_s.empty()) - func_class = get_uint_from_feature(f, FUNC_CLASS); - - add_highway_tag(builder, f, route_type, func_class, mtd_area_map, ref_name, - underConstruction); - - add_one_way_tag(builder, get_field_from_feature(f, DIR_TRAVEL)); - add_access_tags(builder, f); - add_maxspeed_tags(builder, f); - add_lanes_tag(builder, f); - add_postcode_tag(builder, f); - - if (parse_bool(get_field_from_feature(f, PAVED))) - builder.add_tag("surface", "paved"); - if (parse_bool(get_field_from_feature(f, BRIDGE))) - builder.add_tag("bridge", YES.data()); - if (parse_bool(get_field_from_feature(f, TUNNEL))) - builder.add_tag("tunnel", YES.data()); - if (parse_bool(get_field_from_feature(f, TOLLWAY))) - builder.add_tag("toll", YES.data()); - if (parse_bool(get_field_from_feature(f, ROUNDABOUT))) - builder.add_tag("junction", "roundabout"); - if (parse_bool(get_field_from_feature(f, FOURWHLDR))) - builder.add_tag("4wd_only", YES.data()); -} - -void StreetConverter::add_one_way_tag(osmium::builder::TagListBuilder &builder, - const char *value) { - if (!strcmp(value, "F")) // F --> FROM reference node - builder.add_tag("oneway", YES.data()); - else if (!strcmp(value, "T")) // T --> TO reference node - builder.add_tag("oneway", "-1"); // todo reverse way instead using "-1" - else if (!strcmp(value, "B")) // B --> BOTH ways are allowed - return; - throw( - format_error("value '" + std::string(value) + "' for oneway not valid")); -} - -void StreetConverter::add_access_tags(osmium::builder::TagListBuilder &builder, - const OGRFeatureUniquePtr &f) { - bool automobile_allowed = parse_bool(get_field_from_feature(f, AR_AUTO)); - if (!automobile_allowed) - builder.add_tag("motorcar", NO.data()); - if (!parse_bool(get_field_from_feature(f, AR_BUS))) - builder.add_tag("bus", NO.data()); - if (!parse_bool(get_field_from_feature(f, AR_TAXIS))) - builder.add_tag("taxi", NO.data()); - // if (! parse_bool(get_field_from_feature(f, AR_CARPOOL))) - // builder->add_tag("hov", NO); - if (!parse_bool(get_field_from_feature(f, AR_PEDESTRIANS))) - builder.add_tag("foot", NO.data()); - if (!parse_bool(get_field_from_feature(f, AR_TRUCKS))) { - // truck access handling: - if (!parse_bool(get_field_from_feature(f, AR_DELIV))) - builder.add_tag( - "hgv", - NO.data()); // no truck + no delivery => hgv not allowed at all - else if (!automobile_allowed) - builder.add_tag("access", - "delivery"); // no automobile + no truck but delivery - // => general access is 'delivery' - else if (automobile_allowed) - builder.add_tag("hgv", "delivery"); // automobile generally allowed => - // only truck is 'delivery' - } - if (!parse_bool(get_field_from_feature(f, AR_EMERVEH))) - builder.add_tag("emergency", NO.data()); - if (!parse_bool(get_field_from_feature(f, AR_MOTORCYCLES))) - builder.add_tag("motorcycle", NO.data()); - if (!parse_bool(get_field_from_feature(f, PUB_ACCESS)) || - parse_bool(get_field_from_feature(f, PRIVATE))) { - builder.add_tag("access", "private"); - } else if (!parse_bool(get_field_from_feature(f, AR_THROUGH_TRAFFIC))) { - builder.add_tag("access", "destination"); - } -} - -void StreetConverter::add_ferry_tag(osmium::builder::TagListBuilder &builder, - const OGRFeatureUniquePtr &f) { - const char *ferry = get_field_from_feature(f, FERRY); - builder.add_tag("route", "ferry"); - if (!strcmp(ferry, "B")) { - if (only_pedestrians(f)) { - builder.add_tag("foot", YES.data()); - } else { - builder.add_tag("foot", - parse_bool(get_field_from_feature(f, AR_PEDESTRIANS)) - ? YES.data() - : NO.data()); - builder.add_tag("motorcar", parse_bool(get_field_from_feature(f, AR_AUTO)) - ? YES.data() - : NO.data()); - } - - } else if (!strcmp(ferry, "R")) { - builder.add_tag("railway", "ferry"); - } else - throw(format_error("value '" + std::string(ferry) + "' for " + - std::string(FERRY) + " not valid")); -} - -void StreetConverter::add_maxspeed_tags( - osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f) { - char *from_speed_limit_s = strdup(get_field_from_feature(f, FR_SPEED_LIMIT)); - char *to_speed_limit_s = strdup(get_field_from_feature(f, TO_SPEED_LIMIT)); - - uint from_speed_limit = get_uint_from_feature(f, FR_SPEED_LIMIT); - uint to_speed_limit = get_uint_from_feature(f, TO_SPEED_LIMIT); - - if (from_speed_limit >= 1000 || to_speed_limit >= 1000) - throw(format_error("from_speed_limit='" + std::string(from_speed_limit_s) + - "' or to_speed_limit='" + std::string(to_speed_limit_s) + - "' is not valid (>= 1000)")); - - // 998 is a ramp without speed limit information - if (from_speed_limit == 998 || to_speed_limit == 998) - return; - - // 999 means no speed limit at all - const char *from = from_speed_limit == 999 ? "none" : from_speed_limit_s; - const char *to = to_speed_limit == 999 ? "none" : to_speed_limit_s; - - if (from_speed_limit != 0 && to_speed_limit != 0) { - if (from_speed_limit != to_speed_limit) { - builder.add_tag("maxspeed:forward", from); - builder.add_tag("maxspeed:backward", to); - } else { - builder.add_tag("maxspeed", from); - } - } else if (from_speed_limit != 0 && to_speed_limit == 0) { - builder.add_tag("maxspeed", from); - } else if (from_speed_limit == 0 && to_speed_limit != 0) { - builder.add_tag("maxspeed", to); - } - - free(from_speed_limit_s); - free(to_speed_limit_s); -} - -void StreetConverter::add_lanes_tag(osmium::builder::TagListBuilder &builder, - const OGRFeatureUniquePtr &f) { - const char *number_of_physical_lanes = get_field_from_feature(f, PHYS_LANES); - if (strcmp(number_of_physical_lanes, "0")) - builder.add_tag("lanes", number_of_physical_lanes); -} - -void StreetConverter::add_postcode_tag(osmium::builder::TagListBuilder &builder, - const OGRFeatureUniquePtr &f) { - std::string l_postcode = get_field_from_feature(f, L_POSTCODE); - std::string r_postcode = get_field_from_feature(f, R_POSTCODE); - - if (l_postcode.empty() && r_postcode.empty()) - return; - - std::string postcode; - if (l_postcode == r_postcode) - postcode = l_postcode; - else - postcode = l_postcode + ";" + r_postcode; - - builder.add_tag("addr:postcode", postcode); -} - -bool StreetConverter::only_pedestrians(const OGRFeatureUniquePtr &f) { - if (strcmp(get_field_from_feature(f, AR_PEDESTRIANS), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_AUTO), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_BUS), "Y")) - return false; - // if (! strcmp(get_field_from_feature(f, AR_CARPOOL),"Y")) return false; - if (!strcmp(get_field_from_feature(f, AR_EMERVEH), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_MOTORCYCLES), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_TAXIS), "Y")) - return false; - if (!strcmp(get_field_from_feature(f, AR_THROUGH_TRAFFIC), "Y")) - return false; - return true; -} - -void StreetConverter::add_here_speed_cat_tag( - osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f) { - auto speed_cat = get_uint_from_feature(f, SPEED_CAT); - if (0 < speed_cat && speed_cat < speed_cat_metric.size()) - builder.add_tag("here:speed_cat", speed_cat_metric[speed_cat].data()); - else - throw format_error("SPEED_CAT=" + std::to_string(speed_cat) + - " is not valid."); -} - -void StreetConverter::create_house_numbers(const OGRFeatureUniquePtr &feat, - const OGRLineString *ogr_ls, - bool left, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - const std::string_view &ref_addr = left ? L_REFADDR : R_REFADDR; - const std::string_view &nref_addr = left ? L_NREFADDR : R_NREFADDR; - const std::string_view &addr_schema = left ? L_ADDRSCH : R_ADDRSCH; - - if (!strcmp(get_field_from_feature(feat, ref_addr), "")) - return; - if (!strcmp(get_field_from_feature(feat, nref_addr), "")) - return; - if (!strcmp(get_field_from_feature(feat, addr_schema), "")) - return; - if (!strcmp(get_field_from_feature(feat, addr_schema), "M")) - return; - - std::string startNumber = - get_field_from_feature(feat, left ? ref_addr : nref_addr); - - std::string endNumber = - get_field_from_feature(feat, left ? nref_addr : ref_addr); - - std::unique_ptr offset_ogr_ls( - create_offset_curve(ogr_ls, HOUSENUMBER_CURVE_OFFSET, left)); - if (startNumber == endNumber) { - // no interpolation for signel addresses - OGRPoint midPoint; - offset_ogr_ls->Centroid(&midPoint); - { - osmium::Location location(midPoint.getX(), midPoint.getY()); - // scope node_builder - osmium::builder::NodeBuilder node_builder(node_buffer); - build_node(location, node_builder); - { - // scope tl_builder - osmium::builder::TagListBuilder tl_builder(node_builder); - tl_builder.add_tag("addr:housenumber", startNumber); - tl_builder.add_tag( - "addr:street", - to_camel_case_with_spaces(get_field_from_feature(feat, ST_NAME))); - } - } - } else { - // osm address interpolation - osmium::builder::WayBuilder way_builder(way_buffer); - setObjectProperties(way_builder); - { - // scope wnl_builder - osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &way_builder); - - for (int i = 0; i < offset_ogr_ls->getNumPoints(); i++) { - osmium::Location location(offset_ogr_ls->getX(i), - offset_ogr_ls->getY(i)); - { - // scope node_builder - osmium::builder::NodeBuilder node_builder(node_buffer); - auto node_id = build_node(location, node_builder); - { - // scope tl_builder - osmium::builder::TagListBuilder tl_builder(node_buffer, - &node_builder); - if (i == 0 || i == offset_ogr_ls->getNumPoints() - 1) { - if (i == 0) { - tl_builder.add_tag("addr:housenumber", startNumber); - } else if (i == offset_ogr_ls->getNumPoints() - 1) { - tl_builder.add_tag("addr:housenumber", endNumber); - } - tl_builder.add_tag("addr:street", - to_camel_case_with_spaces( - get_field_from_feature(feat, ST_NAME))); - } - } - - wnl_builder.add_node_ref(osmium::NodeRef(node_id, location)); - } - } - } - { - // scope tl_builder - osmium::builder::TagListBuilder tl_builder(way_buffer, &way_builder); - const char *schema = - parse_house_number_schema(get_field_from_feature(feat, addr_schema)); - tl_builder.add_tag("addr:interpolation", schema); - } - } - node_buffer.commit(); - way_buffer.commit(); -} - -void StreetConverter::create_house_numbers(const OGRFeatureUniquePtr &feat, - const OGRLineString *ogr_ls, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - create_house_numbers(feat, ogr_ls, true, node_buffer, way_buffer); - create_house_numbers(feat, ogr_ls, false, node_buffer, way_buffer); -} - -void StreetConverter::create_premium_house_numbers( - const OGRFeatureUniquePtr &feat, - const std::vector> &addressList, - int linkId, osmium::memory::Buffer &node_buffer) { - - for (auto &[location, houseNo] : addressList) { - - // scope node_builder - osmium::builder::NodeBuilder node_builder(node_buffer); - build_node(location, node_builder); - { - // scope tl_builder - osmium::builder::TagListBuilder tl_builder(node_buffer, &node_builder); - tl_builder.add_tag(LINK_ID.data(), std::to_string(linkId)); - tl_builder.add_tag("addr:housenumber", houseNo); - tl_builder.add_tag( - "addr:street", - to_camel_case_with_spaces(get_field_from_feature(feat, ST_NAME))); - } - } -} - -void StreetConverter::process_house_numbers(const std::filesystem::path &dir, - osmium::io::Writer &writer) { - - // create point addresses from PointAddress.dbf - auto pointMap = createPointAddressMapList(dir); - - auto path = dir / STREETS_SHP; - auto ds = openDataSource(path); - if (!ds) - throw(shp_error(path.string())); - - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(path.string())); - - osmium::memory::Buffer node_buffer(BUFFER_SIZE); - osmium::memory::Buffer way_buffer(BUFFER_SIZE); - - int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); - - for (auto &feat : *layer) { - int linkId = feat->GetFieldAsInteger(linkIdField); - process_house_numbers(feat, *pointMap, linkId, node_buffer, way_buffer); - } - - node_buffer.commit(); - way_buffer.commit(); - writer(std::move(node_buffer)); - writer(std::move(way_buffer)); - delete pointMap; -} -/** - * \brief creates Way from linestring. - * creates missing Nodes needed for Way and Way itself. - * \param ogr_ls linestring which provides the geometry. - * \param z_level_map holds z_levels to Nodes of Ways. - */ -void StreetConverter::process_house_numbers( - const OGRFeatureUniquePtr &feat, - const std::map>> - &pointAddresses, - int linkId, osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { - - auto ogr_ls = static_cast(feat->GetGeometryRef()); - - auto it = pointAddresses.find(linkId); - if (it != pointAddresses.end()) { - create_premium_house_numbers(feat, it->second, linkId, node_buffer); - } else { - if (!strcmp(get_field_from_feature(feat, ADDR_TYPE), "B")) { - create_house_numbers(feat, ogr_ls, node_buffer, way_buffer); - } - } -} - -std::map>> * -StreetConverter::createPointAddressMapList(const std::filesystem::path &dir) { - - auto pointAddressMap = - new std::map>>(); - - static const std::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; - - auto ds = openDataSource(dir / POINT_ADDRESS_SHP); - if (!ds) - return pointAddressMap; - - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error((dir / POINT_ADDRESS_SHP).string())); - - int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); - int latField = layer->FindFieldIndex("DISP_LAT", true); - int lonField = layer->FindFieldIndex("DISP_LON", true); - int addressField = layer->FindFieldIndex("ADDRESS", true); - - for (auto &feat : *layer) { - int linkId = feat->GetFieldAsInteger(linkIdField); - auto houseNumber = std::string(feat->GetFieldAsString(addressField)); - - double lat = 0.0; - double lon = 0.0; - - if (feat->IsFieldNull(lonField) && feat->IsFieldNull(latField)) { - auto point = static_cast(feat->GetGeometryRef()); - lat = point->getY(); - lon = point->getX(); - } else { - lon = feat->GetFieldAsDouble(lonField); - lat = feat->GetFieldAsDouble(latField); - } - - (*pointAddressMap)[linkId].emplace_back(osmium::Location(lon, lat), - houseNumber); - } - - return pointAddressMap; -} - void StreetConverter::set_ferry_z_lvls_to_zero( const OGRFeatureUniquePtr &feat, std::vector &z_lvl_vec) { @@ -1615,8 +781,6 @@ void StreetConverter::set_ferry_z_lvls_to_zero( z_lvl_vec.erase(z_lvl_vec.end()); } -// TODO - static std::set z_lvl_set = {-4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; void StreetConverter::test__z_lvl_range(short z_lvl) { if (z_lvl_set.find(z_lvl) == z_lvl_set.end()) @@ -1659,29 +823,6 @@ bool StreetConverter::is_superior(short superior, short than) { return false; } -uint StreetConverter::get_number_after(const std::string &str, - const char *start_str) { - if (!str.starts_with(start_str)) - return 0; /* doesn't start with start_str */ - - /* Get number string after start_str until first non-digit appears */ - std::string end_str = str.substr(strlen(start_str)); - std::string number_str; - for (auto it = end_str.begin(); it != end_str.end(); ++it) { - if (!std::isdigit(*it)) { - /* break because B107a should return 107*/ - break; - } - number_str += *it; - } - - try { - return std::stoul(number_str); - } catch (const std::invalid_argument &) { - return 0; - } -} - const char *StreetConverter::parse_house_number_schema(const char *schema) { if (!strcmp(schema, "E")) return "even"; @@ -1693,22 +834,3 @@ const char *StreetConverter::parse_house_number_schema(const char *schema) { throw std::runtime_error("scheme " + std::string(schema) + " is currently not supported"); } - -/** - * \brief converts pounds to metric tons - */ -std::string StreetConverter::lbs_to_metric_ton(double lbs) { - double short_ton = lbs / (double)POUND_BASE; - double metric_ton = short_ton * SHORT_TON; - std::stringstream stream; - stream << metric_ton; - return stream.str(); -} - -/** - * \brief converts inches to feet - */ -std::string StreetConverter::inch_to_feet(unsigned int inches) { - return std::to_string((unsigned int)floor(inches / INCH_BASE)) + "'" + - std::to_string(inches % INCH_BASE) + "\""; -} diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index d15d917..df8bbcb 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -145,7 +145,7 @@ class StreetConverter : public Converter { osmium::memory::Buffer &way_buffer, bool is_sub_linestring, short z_lvl); uint64_t build_tag_list(OGRFeatureUniquePtr &feat, - osmium::builder::Builder *builder, + osmium::builder::Builder &builder, osmium::memory::Buffer &buf, short z_level); uint64_t parse_street_tags( diff --git a/plugins/navteq/converter/StreetConverterHouseNumber.cpp b/plugins/navteq/converter/StreetConverterHouseNumber.cpp new file mode 100644 index 0000000..9d08860 --- /dev/null +++ b/plugins/navteq/converter/StreetConverterHouseNumber.cpp @@ -0,0 +1,245 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "StreetConverter.hpp" + +#include + +#include "../../ogr_util.hpp" + +void StreetConverter::process_house_numbers(const std::filesystem::path &dir, + osmium::io::Writer &writer) { + + // create point addresses from PointAddress.dbf + auto pointMap = createPointAddressMapList(dir); + + auto path = dir / STREETS_SHP; + auto ds = openDataSource(path); + if (!ds) + throw(shp_error(path.string())); + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(path.string())); + + osmium::memory::Buffer node_buffer(BUFFER_SIZE); + osmium::memory::Buffer way_buffer(BUFFER_SIZE); + + int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); + + for (auto &feat : *layer) { + int linkId = feat->GetFieldAsInteger(linkIdField); + process_house_numbers(feat, *pointMap, linkId, node_buffer, way_buffer); + } + + node_buffer.commit(); + way_buffer.commit(); + writer(std::move(node_buffer)); + writer(std::move(way_buffer)); + delete pointMap; +} + +/** + * \brief creates Way from linestring. + * creates missing Nodes needed for Way and Way itself. + * \param ogr_ls linestring which provides the geometry. + * \param z_level_map holds z_levels to Nodes of Ways. + */ +void StreetConverter::process_house_numbers( + const OGRFeatureUniquePtr &feat, + const std::map>> + &pointAddresses, + int linkId, osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer) { + + auto ogr_ls = static_cast(feat->GetGeometryRef()); + + auto it = pointAddresses.find(linkId); + if (it != pointAddresses.end()) { + create_premium_house_numbers(feat, it->second, linkId, node_buffer); + } else { + if (!strcmp(get_field_from_feature(feat, ADDR_TYPE), "B")) { + create_house_numbers(feat, ogr_ls, node_buffer, way_buffer); + } + } +} + +std::map>> * +StreetConverter::createPointAddressMapList(const std::filesystem::path &dir) { + + auto pointAddressMap = + new std::map>>(); + + static const std::filesystem::path POINT_ADDRESS_SHP = "PointAddress.shp"; + + auto ds = openDataSource(dir / POINT_ADDRESS_SHP); + if (!ds) + return pointAddressMap; + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error((dir / POINT_ADDRESS_SHP).string())); + + int linkIdField = layer->FindFieldIndex(LINK_ID.data(), true); + int latField = layer->FindFieldIndex("DISP_LAT", true); + int lonField = layer->FindFieldIndex("DISP_LON", true); + int addressField = layer->FindFieldIndex("ADDRESS", true); + + for (auto &feat : *layer) { + int linkId = feat->GetFieldAsInteger(linkIdField); + auto houseNumber = std::string(feat->GetFieldAsString(addressField)); + + double lat = 0.0; + double lon = 0.0; + + if (feat->IsFieldNull(lonField) && feat->IsFieldNull(latField)) { + auto point = static_cast(feat->GetGeometryRef()); + lat = point->getY(); + lon = point->getX(); + } else { + lon = feat->GetFieldAsDouble(lonField); + lat = feat->GetFieldAsDouble(latField); + } + + (*pointAddressMap)[linkId].emplace_back(osmium::Location(lon, lat), + houseNumber); + } + + return pointAddressMap; +} + +void StreetConverter::create_house_numbers(const OGRFeatureUniquePtr &feat, + const OGRLineString *ogr_ls, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer) { + create_house_numbers(feat, ogr_ls, true, node_buffer, way_buffer); + create_house_numbers(feat, ogr_ls, false, node_buffer, way_buffer); +} + +void StreetConverter::create_premium_house_numbers( + const OGRFeatureUniquePtr &feat, + const std::vector> &addressList, + int linkId, osmium::memory::Buffer &node_buffer) { + + for (auto &[location, houseNo] : addressList) { + + // scope node_builder + osmium::builder::NodeBuilder node_builder(node_buffer); + build_node(location, node_builder); + { + // scope tl_builder + osmium::builder::TagListBuilder tl_builder(node_buffer, &node_builder); + tl_builder.add_tag(LINK_ID.data(), std::to_string(linkId)); + tl_builder.add_tag("addr:housenumber", houseNo); + tl_builder.add_tag( + "addr:street", + to_camel_case_with_spaces(get_field_from_feature(feat, ST_NAME))); + } + } +} + +void StreetConverter::create_house_numbers(const OGRFeatureUniquePtr &feat, + const OGRLineString *ogr_ls, + bool left, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer) { + const std::string_view &ref_addr = left ? L_REFADDR : R_REFADDR; + const std::string_view &nref_addr = left ? L_NREFADDR : R_NREFADDR; + const std::string_view &addr_schema = left ? L_ADDRSCH : R_ADDRSCH; + + if (!strcmp(get_field_from_feature(feat, ref_addr), "")) + return; + if (!strcmp(get_field_from_feature(feat, nref_addr), "")) + return; + if (!strcmp(get_field_from_feature(feat, addr_schema), "")) + return; + if (!strcmp(get_field_from_feature(feat, addr_schema), "M")) + return; + + std::string startNumber = + get_field_from_feature(feat, left ? ref_addr : nref_addr); + + std::string endNumber = + get_field_from_feature(feat, left ? nref_addr : ref_addr); + + std::unique_ptr offset_ogr_ls( + create_offset_curve(ogr_ls, HOUSENUMBER_CURVE_OFFSET, left)); + if (startNumber == endNumber) { + // no interpolation for signel addresses + OGRPoint midPoint; + offset_ogr_ls->Centroid(&midPoint); + { + osmium::Location location(midPoint.getX(), midPoint.getY()); + // scope node_builder + osmium::builder::NodeBuilder node_builder(node_buffer); + build_node(location, node_builder); + { + // scope tl_builder + osmium::builder::TagListBuilder tl_builder(node_builder); + tl_builder.add_tag("addr:housenumber", startNumber); + tl_builder.add_tag( + "addr:street", + to_camel_case_with_spaces(get_field_from_feature(feat, ST_NAME))); + } + } + } else { + // osm address interpolation + osmium::builder::WayBuilder way_builder(way_buffer); + setObjectProperties(way_builder); + { + // scope wnl_builder + osmium::builder::WayNodeListBuilder wnl_builder(way_buffer, &way_builder); + + for (int i = 0; i < offset_ogr_ls->getNumPoints(); i++) { + osmium::Location location(offset_ogr_ls->getX(i), + offset_ogr_ls->getY(i)); + { + // scope node_builder + osmium::builder::NodeBuilder node_builder(node_buffer); + auto node_id = build_node(location, node_builder); + { + // scope tl_builder + osmium::builder::TagListBuilder tl_builder(node_buffer, + &node_builder); + if (i == 0 || i == offset_ogr_ls->getNumPoints() - 1) { + if (i == 0) { + tl_builder.add_tag("addr:housenumber", startNumber); + } else if (i == offset_ogr_ls->getNumPoints() - 1) { + tl_builder.add_tag("addr:housenumber", endNumber); + } + tl_builder.add_tag("addr:street", + to_camel_case_with_spaces( + get_field_from_feature(feat, ST_NAME))); + } + } + + wnl_builder.add_node_ref(osmium::NodeRef(node_id, location)); + } + } + } + { + // scope tl_builder + osmium::builder::TagListBuilder tl_builder(way_buffer, &way_builder); + const char *schema = + parse_house_number_schema(get_field_from_feature(feat, addr_schema)); + tl_builder.add_tag("addr:interpolation", schema); + } + } + node_buffer.commit(); + way_buffer.commit(); +} diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp new file mode 100644 index 0000000..477925c --- /dev/null +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -0,0 +1,687 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#include "StreetConverter.hpp" + +#include + +uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, + osmium::builder::Builder &builder, + osmium::memory::Buffer &buf, + short z_level) { + osmium::builder::TagListBuilder tl_builder(buf, builder); + + uint64_t link_id = parse_street_tags( + tl_builder, feat, &g_cdms_map, &g_cnd_mod_map, &g_area_to_govt_code_map, + &g_cntry_ref_map, &g_mtd_area_map, &g_route_type_map, &g_hwys_ref_map, + g_construction_set, debugMode); + + if (z_level != -5 && z_level != 0) + tl_builder.add_tag("layer", std::to_string(z_level)); + if (link_id == 0) + throw(format_error("layers column field '" + std::string(LINK_ID.data()) + + "' is missing")); + return link_id; +} + +uint64_t StreetConverter::parse_street_tags( + osmium::builder::TagListBuilder &builder, OGRFeatureUniquePtr &f, + const std::multimap &cdms_map, + const std::unordered_map> + &cnd_mod_map, + const std::map &area_govt_map, + const std::map &cntry_map, + const std::map + &mtd_area_map, + const std::map &route_type_map, + const std::map> &names_map, + const std::set &construction_set, bool debugMode) { + + const char *link_id_s = get_field_from_feature(f, LINK_ID); + uint64_t link_id = std::stoul(link_id_s); + + bool ramp = parse_bool(get_field_from_feature(f, RAMP)); + + ushort route_type = 0; + if (!((std::string)get_field_from_feature(f, ROUTE)).empty()) + route_type = get_uint_from_feature(f, ROUTE); + + auto routeTypeIter = route_type_map.find(link_id); + if (routeTypeIter != route_type_map.end() && + (!route_type || routeTypeIter->second < route_type)) + route_type = routeTypeIter->second; + + // add tags for ref and int_ref to major highways + std::string ref_name = + add_highway_name_tags(builder, names_map, link_id, ramp); + + bool underConstruction = + (construction_set.find(link_id) != construction_set.end()); + + if (is_ferry(get_field_from_feature(f, FERRY))) { + add_ferry_tag(builder, f); + } else { // usual highways + add_highway_tags(builder, f, route_type, mtd_area_map, ref_name, + underConstruction); + } + + uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); + uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); + // tags which apply to highways and ferry routes + add_additional_restrictions(builder, link_id, l_area_id, r_area_id, cdms_map, + cnd_mod_map, area_govt_map, cntry_map, + mtd_area_map); + + // tag for debug purpose + if (debugMode) { + builder.add_tag(LINK_ID.data(), link_id_s); + add_here_speed_cat_tag(builder, f); + if (parse_bool(get_field_from_feature(f, TOLLWAY))) + builder.add_tag("here:tollway", YES.data()); + if (parse_bool(get_field_from_feature(f, URBAN))) + builder.add_tag("here:urban", YES.data()); + if (parse_bool(get_field_from_feature(f, CONTRACC))) + builder.add_tag("here:controll_access", YES.data()); + if (route_type) + add_uint_tag(builder, "here:route_type", route_type); + + std::string func_class = get_field_from_feature(f, FUNC_CLASS); + if (!func_class.empty()) + builder.add_tag("here:func_class", func_class.c_str()); + + add_uint_tag(builder, "here:area_code", get_area_code_l(f, mtd_area_map)); + } + return link_id; +} + +/** + * \brief converts pounds to metric tons + */ +std::string StreetConverter::lbs_to_metric_ton(double lbs) { + double short_ton = lbs / (double)POUND_BASE; + double metric_ton = short_ton * SHORT_TON; + std::stringstream stream; + stream << metric_ton; + return stream.str(); +} + +bool StreetConverter::only_pedestrians(const OGRFeatureUniquePtr &f) { + if (strcmp(get_field_from_feature(f, AR_PEDESTRIANS), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_AUTO), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_BUS), "Y")) + return false; + // if (! strcmp(get_field_from_feature(f, AR_CARPOOL),"Y")) return false; + if (!strcmp(get_field_from_feature(f, AR_EMERVEH), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_MOTORCYCLES), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_TAXIS), "Y")) + return false; + if (!strcmp(get_field_from_feature(f, AR_THROUGH_TRAFFIC), "Y")) + return false; + return true; +} + +void StreetConverter::add_lanes_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f) { + const char *number_of_physical_lanes = get_field_from_feature(f, PHYS_LANES); + if (strcmp(number_of_physical_lanes, "0")) + builder.add_tag("lanes", number_of_physical_lanes); +} + +void StreetConverter::add_postcode_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f) { + std::string l_postcode = get_field_from_feature(f, L_POSTCODE); + std::string r_postcode = get_field_from_feature(f, R_POSTCODE); + + if (l_postcode.empty() && r_postcode.empty()) + return; + + std::string postcode; + if (l_postcode == r_postcode) + postcode = l_postcode; + else + postcode = l_postcode + ";" + r_postcode; + + builder.add_tag("addr:postcode", postcode); +} + +void StreetConverter::add_maxspeed_tags( + osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f) { + char *from_speed_limit_s = strdup(get_field_from_feature(f, FR_SPEED_LIMIT)); + char *to_speed_limit_s = strdup(get_field_from_feature(f, TO_SPEED_LIMIT)); + + uint from_speed_limit = get_uint_from_feature(f, FR_SPEED_LIMIT); + uint to_speed_limit = get_uint_from_feature(f, TO_SPEED_LIMIT); + + if (from_speed_limit >= 1000 || to_speed_limit >= 1000) + throw(format_error("from_speed_limit='" + std::string(from_speed_limit_s) + + "' or to_speed_limit='" + std::string(to_speed_limit_s) + + "' is not valid (>= 1000)")); + + // 998 is a ramp without speed limit information + if (from_speed_limit == 998 || to_speed_limit == 998) + return; + + // 999 means no speed limit at all + const char *from = from_speed_limit == 999 ? "none" : from_speed_limit_s; + const char *to = to_speed_limit == 999 ? "none" : to_speed_limit_s; + + if (from_speed_limit != 0 && to_speed_limit != 0) { + if (from_speed_limit != to_speed_limit) { + builder.add_tag("maxspeed:forward", from); + builder.add_tag("maxspeed:backward", to); + } else { + builder.add_tag("maxspeed", from); + } + } else if (from_speed_limit != 0 && to_speed_limit == 0) { + builder.add_tag("maxspeed", from); + } else if (from_speed_limit == 0 && to_speed_limit != 0) { + builder.add_tag("maxspeed", to); + } + + free(from_speed_limit_s); + free(to_speed_limit_s); +} + +void StreetConverter::add_ferry_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f) { + const char *ferry = get_field_from_feature(f, FERRY); + builder.add_tag("route", "ferry"); + if (!strcmp(ferry, "B")) { + if (only_pedestrians(f)) { + builder.add_tag("foot", YES.data()); + } else { + builder.add_tag("foot", + parse_bool(get_field_from_feature(f, AR_PEDESTRIANS)) + ? YES.data() + : NO.data()); + builder.add_tag("motorcar", parse_bool(get_field_from_feature(f, AR_AUTO)) + ? YES.data() + : NO.data()); + } + + } else if (!strcmp(ferry, "R")) { + builder.add_tag("railway", "ferry"); + } else + throw(format_error("value '" + std::string(ferry) + "' for " + + std::string(FERRY) + " not valid")); +} + +void StreetConverter::add_highway_tags( + osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, + ushort route_type, + const std::map + &mtd_area_map, + const std::string &ref_name, bool underConstruction) { + + ushort func_class = 0; + std::string func_class_s = get_field_from_feature(f, FUNC_CLASS); + if (!func_class_s.empty()) + func_class = get_uint_from_feature(f, FUNC_CLASS); + + add_highway_tag(builder, f, route_type, func_class, mtd_area_map, ref_name, + underConstruction); + + add_one_way_tag(builder, get_field_from_feature(f, DIR_TRAVEL)); + add_access_tags(builder, f); + add_maxspeed_tags(builder, f); + add_lanes_tag(builder, f); + add_postcode_tag(builder, f); + + if (parse_bool(get_field_from_feature(f, PAVED))) + builder.add_tag("surface", "paved"); + if (parse_bool(get_field_from_feature(f, BRIDGE))) + builder.add_tag("bridge", YES.data()); + if (parse_bool(get_field_from_feature(f, TUNNEL))) + builder.add_tag("tunnel", YES.data()); + if (parse_bool(get_field_from_feature(f, TOLLWAY))) + builder.add_tag("toll", YES.data()); + if (parse_bool(get_field_from_feature(f, ROUNDABOUT))) + builder.add_tag("junction", "roundabout"); + if (parse_bool(get_field_from_feature(f, FOURWHLDR))) + builder.add_tag("4wd_only", YES.data()); +} + +void StreetConverter::add_one_way_tag(osmium::builder::TagListBuilder &builder, + const char *value) { + if (!strcmp(value, "F")) // F --> FROM reference node + builder.add_tag("oneway", YES.data()); + else if (!strcmp(value, "T")) // T --> TO reference node + builder.add_tag("oneway", "-1"); // todo reverse way instead using "-1" + else if (!strcmp(value, "B")) // B --> BOTH ways are allowed + return; + throw( + format_error("value '" + std::string(value) + "' for oneway not valid")); +} + +void StreetConverter::add_access_tags(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f) { + bool automobile_allowed = parse_bool(get_field_from_feature(f, AR_AUTO)); + if (!automobile_allowed) + builder.add_tag("motorcar", NO.data()); + if (!parse_bool(get_field_from_feature(f, AR_BUS))) + builder.add_tag("bus", NO.data()); + if (!parse_bool(get_field_from_feature(f, AR_TAXIS))) + builder.add_tag("taxi", NO.data()); + // if (! parse_bool(get_field_from_feature(f, AR_CARPOOL))) + // builder->add_tag("hov", NO); + if (!parse_bool(get_field_from_feature(f, AR_PEDESTRIANS))) + builder.add_tag("foot", NO.data()); + if (!parse_bool(get_field_from_feature(f, AR_TRUCKS))) { + // truck access handling: + if (!parse_bool(get_field_from_feature(f, AR_DELIV))) + builder.add_tag( + "hgv", + NO.data()); // no truck + no delivery => hgv not allowed at all + else if (!automobile_allowed) + builder.add_tag("access", + "delivery"); // no automobile + no truck but delivery + // => general access is 'delivery' + else if (automobile_allowed) + builder.add_tag("hgv", "delivery"); // automobile generally allowed => + // only truck is 'delivery' + } + if (!parse_bool(get_field_from_feature(f, AR_EMERVEH))) + builder.add_tag("emergency", NO.data()); + if (!parse_bool(get_field_from_feature(f, AR_MOTORCYCLES))) + builder.add_tag("motorcycle", NO.data()); + if (!parse_bool(get_field_from_feature(f, PUB_ACCESS)) || + parse_bool(get_field_from_feature(f, PRIVATE))) { + builder.add_tag("access", "private"); + } else if (!parse_bool(get_field_from_feature(f, AR_THROUGH_TRAFFIC))) { + builder.add_tag("access", "destination"); + } +} + +std::string StreetConverter::add_highway_name_tags( + osmium::builder::TagListBuilder &builder, + const std::map> &names_map, + uint64_t link_id, bool ramp) { + std::string ref_tag; + + auto it = names_map.find(link_id); + if (it != names_map.end()) { + auto &highway_names_vector = it->second; + std::string street_name; + std::string int_ref_tag; + std::string nat_ref_tag; + + for (auto highwayName : highway_names_vector) { + if (highwayName.first == 0) { + street_name = highwayName.second; + } else if (highwayName.first == 1) { + int_ref_tag = highwayName.second; + } else if (highwayName.first > 1) { + nat_ref_tag = highwayName.second; + } + } + + if (!nat_ref_tag.empty()) + ref_tag = nat_ref_tag; + else + ref_tag = int_ref_tag; + + if (!street_name.empty() && !ramp) + builder.add_tag("name", to_camel_case_with_spaces(street_name)); + if (!ref_tag.empty()) // national ref (Autobahn) + builder.add_tag("ref", ref_tag); + if (!int_ref_tag.empty()) // international ref (European street) + builder.add_tag("int_ref", int_ref_tag); + if (!nat_ref_tag.empty()) // national ref (European street) + builder.add_tag("nat_ref", nat_ref_tag); + } + + return ref_tag; +} + +/** + * \brief converts inches to feet + */ +std::string StreetConverter::inch_to_feet(unsigned int inches) { + return std::to_string((unsigned int)floor(inches / INCH_BASE)) + "'" + + std::to_string(inches % INCH_BASE) + "\""; +} + +void StreetConverter::add_here_speed_cat_tag( + osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f) { + auto speed_cat = get_uint_from_feature(f, SPEED_CAT); + if (0 < speed_cat && speed_cat < speed_cat_metric.size()) + builder.add_tag("here:speed_cat", speed_cat_metric[speed_cat].data()); + else + throw format_error("SPEED_CAT=" + std::to_string(speed_cat) + + " is not valid."); +} + +bool StreetConverter::is_motorized_allowed(const OGRFeatureUniquePtr &f) { + if (parse_bool(get_field_from_feature(f, AR_AUTO))) + return true; + if (parse_bool(get_field_from_feature(f, AR_BUS))) + return true; + if (parse_bool(get_field_from_feature(f, AR_TAXIS))) + return true; + if (parse_bool(get_field_from_feature(f, AR_TRUCKS))) + return true; + if (parse_bool(get_field_from_feature(f, AR_DELIV))) + return true; + if (parse_bool(get_field_from_feature(f, AR_EMERVEH))) + return true; + if (parse_bool(get_field_from_feature(f, AR_MOTORCYCLES))) + return true; + + return false; +} + +void StreetConverter::add_hazmat_tag(osmium::builder::TagListBuilder &builder, + uint64_t mod_val) { + if (mod_val == 20) { // || mod_val == 21 + builder.add_tag("hazmat", "no"); + } else if (mod_val == 22) { + builder.add_tag("hazmat:water", "no"); + } else if (mod_val == 24) { + builder.add_tag("hazmat:B", "no"); + } else if (mod_val == 28) { + builder.add_tag("hazmat:C", "no"); + } else if (mod_val == 32) { + builder.add_tag("hazmat:D", "no"); + } else if (mod_val == 34) { + builder.add_tag("hazmat:E", "no"); + } else if (mod_val == 23) { + /* 23 = Explosive and Flammable */ + } else { + /** + * Do nothing for the residual values, + * which do not occur and/or have no proper OSM tagging equivalent + * 1 = Explosives + * 2 = Gas + * 3 = Flammable + * 4 = Flammable solid/Combustible + * 5 = Organic + * 6 = Poison + * 7 = Radioactive + * 8 = Corrosive + * 9 = Other + */ + BOOST_LOG_TRIVIAL(error) << "Hazardous material value " << mod_val + << " hasn't been parsed!" << std::endl; + } +} + +void StreetConverter::add_highway_tag( + osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, + ushort route_type, ushort func_class, + const std::map + &mtd_area_map, + const std::string &ref_name, bool underConstruction) { + + bool paved = parse_bool(get_field_from_feature(f, PAVED)); + bool motorized_allowed = is_motorized_allowed(f); + + std::string highwayTagName = HIGHWAY.data(); + + if (underConstruction) { + builder.add_tag(HIGHWAY.data(), CONSTRUCTION.data()); + highwayTagName = CONSTRUCTION.data(); + } + + if (!paved) { + if (!motorized_allowed) { + // unpaved + non-motorized => path + builder.add_tag(highwayTagName, PATH.data()); + } else { + // unpaved + motorized allowed => track + builder.add_tag(highwayTagName, TRACK.data()); + } + } else { + if (!motorized_allowed) { + // paved + non-motorized => footway + // it seems imposref_nameible to distinguish footways from cycle ways or + // pedestrian zones + builder.add_tag(highwayTagName, FOOTWAY.data()); + } else { + // paved + motorized allowed + bool controlled_access = parse_bool(get_field_from_feature(f, CONTRACC)); + bool urban = parse_bool(get_field_from_feature(f, URBAN)); + bool ramp = parse_bool(get_field_from_feature(f, RAMP)); + uint area_code_1 = get_area_code_l(f, mtd_area_map); + + if (controlled_access) { + // controlled_access => motorway + if (ramp) + builder.add_tag(highwayTagName, MOTORWAY_LINK.data()); + else + builder.add_tag(highwayTagName, MOTORWAY.data()); + } else if (func_class || route_type) { + std::string_view hwy_value = + get_hwy_value(route_type, func_class, area_code_1, ref_name, urban); + if (!hwy_value.empty()) { + builder.add_tag(highwayTagName, hwy_value.data()); + } else { + BOOST_LOG_TRIVIAL(error) + << "ignoring highway_level'" << std::to_string(route_type) + << "' for " << area_code_1 << std::endl; + } + } else { + BOOST_LOG_TRIVIAL(error) + << " highway misses route_type and func_class! " << std::endl; + } + } + } +} + +std::string_view StreetConverter::get_hwy_value(ushort route_type, + ushort func_class, + uint area_code_1, + const std::string &ref_name, + bool urban) { + /* some exceptional cases for better route type parsing */ + if (area_code_1 == 2 && route_type == 4) { /*"FRA"*/ + /* Too many different highways have route type 4 + * so we also take functional class into consideration */ + if (func_class == 2) + return PRIMARY; + else if (func_class == 3) + return SECONDARY; + else if (func_class > 3) + return TERTIARY; + } else if (area_code_1 == 5 && route_type == 3) { /*"BEL"*/ + /* N# and N## is like PRIMARY + * N### SECONDARY + * N#### TERTIARY */ + uint hwy_num = get_number_after(ref_name, "N"); + if (hwy_num > 999) + return TERTIARY; + if (hwy_num > 99) + return SECONDARY; + } else if (area_code_1 == 9) { /*"AUT"*/ + if (route_type == 4) { + return PRIMARY; // bundesstrasse + } else if (route_type == 5) { + return SECONDARY; // landesstrasse + } + } else if (area_code_1 == 23 && route_type == 2) { /*"IRL"*/ + /* N## is TRUNK if ## smaller 50 otherwise PRIMARY */ + uint hwy_num = get_number_after(ref_name, "N"); + if (hwy_num > 0 && hwy_num < 50) + return TRUNK; + } else if (area_code_1 == 109 || + area_code_1 == 110 /*UK - Wales*/ /*UK - England*/ + || area_code_1 == 112 || + area_code_1 == 22) { /*UK - Scotland*/ /*UK - Northern Ireland*/ + /* Differ between white and green shield A-Roads */ + if (route_type == 2) { + if (func_class == 2 || func_class == 1) + return TRUNK; + else + return PRIMARY; + } else if (route_type == 3 && func_class == 4) { + return SECONDARY; + } + } else if (area_code_1 == 107) { // SWE + if (func_class == 1 && route_type == 1) + return TRUNK; // func_class 1 und not controlled + } + + uint apply_func_class = func_class; + if (apply_func_class > 4 && urban) { + apply_func_class++; + } else if (func_class == 2 && (route_type == 3 || route_type == 2)) { + return PRIMARY; // primary + } + + const auto &hwy_vector = HWY_FUNC_CLASS_MAP.contains(area_code_1) + ? HWY_FUNC_CLASS_MAP.at(area_code_1) + : DEFAULT_HWY_FUNC_TYPE; + + /* default case */ + return hwy_vector.at(apply_func_class); +} + +void StreetConverter::add_additional_restrictions( + osmium::builder::TagListBuilder &builder, uint64_t link_id, + uint64_t l_area_id, uint64_t r_area_id, + const std::multimap &cdms_map, + const std::unordered_map> + &cnd_mod_map, + const std::map &area_govt_map, + const std::map &cntry_map, + const std::map + &mtd_area_map) { + if (cdms_map.empty() || cnd_mod_map.empty()) + return; + + // default is metric units + bool imperial_units = + is_imperial(l_area_id, r_area_id, area_govt_map, cntry_map); + + uint64_t max_height = 0; + uint64_t max_width = 0; + uint64_t max_length = 0; + uint64_t max_weight = 0; + uint64_t max_axleload = 0; + + std::vector mod_group_vector; + auto range = cdms_map.equal_range(link_id); + for (auto it = range.first; it != range.second; ++it) { + auto cond = it->second; + if (cond.cond_type_type == CT_RESTRICTED_DRIVING_MANOEUVRE || + cond.cond_type_type == CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE) + continue; // TODO RESTRICTED_DRIVING_MANOEUVRE should apply as + // conditional turn restriction but not for current link id + auto it2 = cnd_mod_map.find(cond.cond_id_type); + if (it2 != cnd_mod_map.end()) { + for (auto mod_group : it2->second) { + mod_group_vector.push_back(mod_group); + } + } + } + + for (auto mod_group : mod_group_vector) { + auto mod_type = mod_group.mod_type; + auto mod_val = mod_group.mod_val; + if (mod_type == MT_HEIGHT_RESTRICTION) { + if (!max_height || mod_val < max_height) + max_height = mod_val; + } else if (mod_type == MT_WIDTH_RESTRICTION) { + if (!max_width || mod_val < max_width) + max_width = mod_val; + } else if (mod_type == MT_LENGTH_RESTRICTION) { + if (!max_length || mod_val < max_length) + max_length = mod_val; + } else if (mod_type == MT_WEIGHT_RESTRICTION) { + if (!max_weight || mod_val < max_weight) + max_weight = mod_val; + } else if (mod_type == MT_WEIGHT_PER_AXLE_RESTRICTION) { + if (!max_axleload || mod_val < max_axleload) + max_axleload = mod_val; + } else if (mod_type == MT_HAZARDOUS_RESTRICTION) { + add_hazmat_tag(builder, mod_val); + } + } + + if (get_area_code_l(l_area_id, r_area_id, mtd_area_map) == 107) { + /** exceptional handling for Sweden as there are BK Roads + * + * HERE tags these roads with the most conservative values, + * which would make it unroutable for nearly every truck. + * Therefore we use the highest value and add a marker for BK2 / BK3 */ + if (max_weight == 16000 && max_axleload == 10000) { + builder.add_tag("maxweight:class", "BK2"); + max_weight = 51400; + } else if (max_weight == 12000 && max_axleload == 8000) { + builder.add_tag("maxweight:class", "BK3"); + max_weight = 37000; + } + } + + if (max_height > 0) + builder.add_tag("maxheight", imperial_units ? inch_to_feet(max_height) + : cm_to_m(max_height)); + if (max_width > 0) + builder.add_tag("maxwidth", imperial_units ? inch_to_feet(max_width) + : cm_to_m(max_width)); + if (max_length > 0) + builder.add_tag("maxlength", imperial_units ? inch_to_feet(max_length) + : cm_to_m(max_length)); + if (max_weight > 0) + builder.add_tag("maxweight", imperial_units ? lbs_to_metric_ton(max_weight) + : kg_to_t(max_weight)); + if (max_axleload > 0) + builder.add_tag("maxaxleload", imperial_units + ? lbs_to_metric_ton(max_axleload) + : kg_to_t(max_axleload)); +} + +uint StreetConverter::get_number_after(const std::string &str, + const char *start_str) { + if (!str.starts_with(start_str)) + return 0; /* doesn't start with start_str */ + + /* Get number string after start_str until first non-digit appears */ + std::string end_str = str.substr(strlen(start_str)); + std::string number_str; + for (auto it = end_str.begin(); it != end_str.end(); ++it) { + if (!std::isdigit(*it)) { + /* break because B107a should return 107*/ + break; + } + number_str += *it; + } + + uint StreetConverter::get_number_after(const std::string &str, + const char *start_str) { + if (!str.starts_with(start_str)) + return 0; /* doesn't start with start_str */ + + /* Get number string after start_str until first non-digit appears */ + std::string end_str = str.substr(strlen(start_str)); + std::string number_str; + for (auto it = end_str.begin(); it != end_str.end(); ++it) { + if (!std::isdigit(*it)) { + /* break because B107a should return 107*/ + break; + } + number_str += *it; + } + + try { + return std::stoul(number_str); + } catch (const std::invalid_argument &) { + return 0; + } + } \ No newline at end of file From dcf5a6b956f5141072481db2566fc9a2bceda71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 06:53:50 +0000 Subject: [PATCH 37/57] more extraction --- plugins/navteq/converter/StreetConverter.cpp | 14 +-- plugins/navteq/converter/StreetConverter.hpp | 65 +------------ .../converter/StreetConverterHouseNumber.cpp | 13 +++ .../converter/StreetConverterOSMTagger.cpp | 91 ++++++++++++++----- 4 files changed, 83 insertions(+), 100 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 7e786e5..69f8523 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -580,7 +580,7 @@ osmium::unsigned_object_id_type StreetConverter::build_way( } } - build_tag_list(feat, builder, way_buffer, z_lvl); + build_tag_list(feat, builder, z_lvl); return builder.object().id(); } @@ -822,15 +822,3 @@ bool StreetConverter::is_superior(short superior, short than) { return true; return false; } - -const char *StreetConverter::parse_house_number_schema(const char *schema) { - if (!strcmp(schema, "E")) - return "even"; - if (!strcmp(schema, "O")) - return "odd"; - BOOST_LOG_TRIVIAL(error) << "schema = " << schema << " unsupported" - << std::endl; - return ""; - throw std::runtime_error("scheme " + std::string(schema) + - " is currently not supported"); -} diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index df8bbcb..bce7e21 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -145,8 +145,7 @@ class StreetConverter : public Converter { osmium::memory::Buffer &way_buffer, bool is_sub_linestring, short z_lvl); uint64_t build_tag_list(OGRFeatureUniquePtr &feat, - osmium::builder::Builder &builder, - osmium::memory::Buffer &buf, short z_level); + osmium::builder::Builder &builder, short z_level); uint64_t parse_street_tags( osmium::builder::TagListBuilder &builder, OGRFeatureUniquePtr &f, @@ -372,21 +371,8 @@ class StreetConverter : public Converter { static constexpr std::string_view RAMP = "RAMP"; // highway OSM tags - static constexpr std::string_view MOTORWAY = "motorway"; - static constexpr std::string_view MOTORWAY_LINK = "motorway_link"; - static constexpr std::string_view TRUNK = "trunk"; - static constexpr std::string_view PRIMARY = "primary"; - static constexpr std::string_view PRIMARY_LINK = "primary_link"; - static constexpr std::string_view SECONDARY = "secondary"; - static constexpr std::string_view SECONDARY_LINK = "secondary_link"; - static constexpr std::string_view TERTIARY = "tertiary"; - static constexpr std::string_view UNCLASSIFIED = "unclassified"; - static constexpr std::string_view RESIDENTIAL = "residential"; - static constexpr std::string_view TRACK = "track"; - static constexpr std::string_view PATH = "path"; - static constexpr std::string_view FOOTWAY = "footway"; + static constexpr std::string_view HIGHWAY = "highway"; - static constexpr std::string_view CONSTRUCTION = "construction"; static constexpr std::string_view HIGHWAY_NM = "HIGHWAY_NM"; static constexpr std::string_view ST_NAME = "ST_NAME"; @@ -401,55 +387,8 @@ class StreetConverter : public Converter { const char *R_NREFADDR = "R_NREFADDR"; const char *R_ADDRSCH = "R_ADDRSCH"; - // higway classification - const std::vector DEFAULT_HWY_FUNC_TYPE = { - "", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}; - - std::map> const HWY_FUNC_CLASS_MAP = { - /* Applied with functional classes: - * 1, 2, 3, 4, 5 + - * rural, 5 + urban */ - {0 /*"DEFAULT"*/, DEFAULT_HWY_FUNC_TYPE}, - {3 /*"GER"*/, - {"", PRIMARY, SECONDARY, TERTIARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, - {8 /*"CHE"*/, - {"", PRIMARY, SECONDARY, TERTIARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, - {108 /*"DEN"*/, - {"", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, - RESIDENTIAL}}, - {107 /*"SWE"*/, - {"", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, - RESIDENTIAL}}, - {9 /*"AUT"*/, - {"", PRIMARY, PRIMARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}}; - - static constexpr std::array speed_cat_metric{ - "", ">130", "101-130", "91-100", "71-90", - "51-70", "31-50", "11-30", "<11"}; - const double HOUSENUMBER_CURVE_OFFSET = 0.00005; - // condition types (CT) - const ushort CT_RESTRICTED_DRIVING_MANOEUVRE = 7; - const ushort CT_TRANSPORT_ACCESS_RESTRICTION = 23; - const ushort CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE = 26; - - // modifier types (MT) - const ushort MT_HAZARDOUS_RESTRICTION = 39; - const ushort MT_HEIGHT_RESTRICTION = 41; - const ushort MT_WEIGHT_RESTRICTION = 42; - const ushort MT_WEIGHT_PER_AXLE_RESTRICTION = 43; - const ushort MT_LENGTH_RESTRICTION = 44; - const ushort MT_WIDTH_RESTRICTION = 45; - - const ushort RESTRICTED_DRIVING_MANOEUVRE = 7; - - const int INCH_BASE = 12; - const int POUND_BASE = 2000; - // short ton in metric tons (source: - // http://wiki.openstreetmap.org/wiki/Key:maxweight) - const double SHORT_TON = 0.90718474; - const std::filesystem::path STREETS_SHP = "Streets.shp"; const std::filesystem::path ALT_STREETS_DBF = "AltStreets.dbf"; diff --git a/plugins/navteq/converter/StreetConverterHouseNumber.cpp b/plugins/navteq/converter/StreetConverterHouseNumber.cpp index 9d08860..3b26a78 100644 --- a/plugins/navteq/converter/StreetConverterHouseNumber.cpp +++ b/plugins/navteq/converter/StreetConverterHouseNumber.cpp @@ -16,6 +16,7 @@ #include "StreetConverter.hpp" +#include #include #include "../../ogr_util.hpp" @@ -243,3 +244,15 @@ void StreetConverter::create_house_numbers(const OGRFeatureUniquePtr &feat, node_buffer.commit(); way_buffer.commit(); } + +const char *StreetConverter::parse_house_number_schema(const char *schema) { + if (!strcmp(schema, "E")) + return "even"; + if (!strcmp(schema, "O")) + return "odd"; + BOOST_LOG_TRIVIAL(error) << "schema = " << schema << " unsupported" + << std::endl; + return ""; + throw std::runtime_error("scheme " + std::string(schema) + + " is currently not supported"); +} \ No newline at end of file diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 477925c..95f11ef 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -18,11 +18,70 @@ #include +// condition types (CT) +const ushort CT_RESTRICTED_DRIVING_MANOEUVRE = 7; +const ushort CT_TRANSPORT_ACCESS_RESTRICTION = 23; +const ushort CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE = 26; + +// modifier types (MT) +const ushort MT_HAZARDOUS_RESTRICTION = 39; +const ushort MT_HEIGHT_RESTRICTION = 41; +const ushort MT_WEIGHT_RESTRICTION = 42; +const ushort MT_WEIGHT_PER_AXLE_RESTRICTION = 43; +const ushort MT_LENGTH_RESTRICTION = 44; +const ushort MT_WIDTH_RESTRICTION = 45; + +const ushort RESTRICTED_DRIVING_MANOEUVRE = 7; + +const int INCH_BASE = 12; +const int POUND_BASE = 2000; +// short ton in metric tons (source: +// http://wiki.openstreetmap.org/wiki/Key:maxweight) +const double SHORT_TON = 0.90718474; + +static constexpr std::string_view MOTORWAY = "motorway"; +static constexpr std::string_view MOTORWAY_LINK = "motorway_link"; +static constexpr std::string_view TRUNK = "trunk"; +static constexpr std::string_view PRIMARY = "primary"; +static constexpr std::string_view PRIMARY_LINK = "primary_link"; +static constexpr std::string_view SECONDARY = "secondary"; +static constexpr std::string_view SECONDARY_LINK = "secondary_link"; +static constexpr std::string_view TERTIARY = "tertiary"; +static constexpr std::string_view UNCLASSIFIED = "unclassified"; +static constexpr std::string_view RESIDENTIAL = "residential"; +static constexpr std::string_view TRACK = "track"; +static constexpr std::string_view PATH = "path"; +static constexpr std::string_view FOOTWAY = "footway"; + +static constexpr std::string_view CONSTRUCTION = "construction"; + +// higway classification +const std::vector DEFAULT_HWY_FUNC_TYPE = { + "", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}; + +std::map> const HWY_FUNC_CLASS_MAP = { + /* Applied with functional classes: + * 1, 2, 3, 4, 5 + + * rural, 5 + urban */ + {0 /*"DEFAULT"*/, DEFAULT_HWY_FUNC_TYPE}, + {3 /*"GER"*/, + {"", PRIMARY, SECONDARY, TERTIARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, + {8 /*"CHE"*/, + {"", PRIMARY, SECONDARY, TERTIARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, + {108 /*"DEN"*/, + {"", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, + {107 /*"SWE"*/, + {"", PRIMARY, SECONDARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}, + {9 /*"AUT"*/, + {"", PRIMARY, PRIMARY, SECONDARY, TERTIARY, UNCLASSIFIED, RESIDENTIAL}}}; + +static constexpr std::array speed_cat_metric{ + "", ">130", "101-130", "91-100", "71-90", "51-70", "31-50", "11-30", "<11"}; + uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, osmium::builder::Builder &builder, - osmium::memory::Buffer &buf, short z_level) { - osmium::builder::TagListBuilder tl_builder(buf, builder); + osmium::builder::TagListBuilder tl_builder(builder); uint64_t link_id = parse_street_tags( tl_builder, feat, &g_cdms_map, &g_cnd_mod_map, &g_area_to_govt_code_map, @@ -663,25 +722,9 @@ uint StreetConverter::get_number_after(const std::string &str, number_str += *it; } - uint StreetConverter::get_number_after(const std::string &str, - const char *start_str) { - if (!str.starts_with(start_str)) - return 0; /* doesn't start with start_str */ - - /* Get number string after start_str until first non-digit appears */ - std::string end_str = str.substr(strlen(start_str)); - std::string number_str; - for (auto it = end_str.begin(); it != end_str.end(); ++it) { - if (!std::isdigit(*it)) { - /* break because B107a should return 107*/ - break; - } - number_str += *it; - } - - try { - return std::stoul(number_str); - } catch (const std::invalid_argument &) { - return 0; - } - } \ No newline at end of file + try { + return std::stoul(number_str); + } catch (const std::invalid_argument &) { + return 0; + } +} \ No newline at end of file From b8490e6c3ebc3b5897758a08379cce910b6976e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 07:40:30 +0000 Subject: [PATCH 38/57] remove global under construction map --- .../converter/StreetConverterOSMTagger.cpp | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 95f11ef..d2a0e97 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -17,8 +17,10 @@ #include "StreetConverter.hpp" #include +#include // condition types (CT) +const ushort CT_CONSTRUCTION_STATUS_CLOSED = 3; const ushort CT_RESTRICTED_DRIVING_MANOEUVRE = 7; const ushort CT_TRANSPORT_ACCESS_RESTRICTION = 23; const ushort CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE = 26; @@ -86,7 +88,7 @@ uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, uint64_t link_id = parse_street_tags( tl_builder, feat, &g_cdms_map, &g_cnd_mod_map, &g_area_to_govt_code_map, &g_cntry_ref_map, &g_mtd_area_map, &g_route_type_map, &g_hwys_ref_map, - g_construction_set, debugMode); + debugMode); if (z_level != -5 && z_level != 0) tl_builder.add_tag("layer", std::to_string(z_level)); @@ -107,7 +109,7 @@ uint64_t StreetConverter::parse_street_tags( &mtd_area_map, const std::map &route_type_map, const std::map> &names_map, - const std::set &construction_set, bool debugMode) { + bool debugMode) { const char *link_id_s = get_field_from_feature(f, LINK_ID); uint64_t link_id = std::stoul(link_id_s); @@ -123,16 +125,21 @@ uint64_t StreetConverter::parse_street_tags( (!route_type || routeTypeIter->second < route_type)) route_type = routeTypeIter->second; - // add tags for ref and int_ref to major highways - std::string ref_name = - add_highway_name_tags(builder, names_map, link_id, ramp); - - bool underConstruction = - (construction_set.find(link_id) != construction_set.end()); - if (is_ferry(get_field_from_feature(f, FERRY))) { add_ferry_tag(builder, f); } else { // usual highways + + // add tags for ref and int_ref to major highways + std::string ref_name = + add_highway_name_tags(builder, names_map, link_id, ramp); + + // get under construction condition + auto itPair = cdms_map.equal_range(link_id); + bool underConstruction = + (std::find_if(itPair.first, itPair.second, [&](cond_type &cndt) { + return cndt.cond_type_type == CT_CONSTRUCTION_STATUS_CLOSED; + }) != itPair.second); + add_highway_tags(builder, f, route_type, mtd_area_map, ref_name, underConstruction); } @@ -642,6 +649,7 @@ void StreetConverter::add_additional_restrictions( cond.cond_type_type == CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE) continue; // TODO RESTRICTED_DRIVING_MANOEUVRE should apply as // conditional turn restriction but not for current link id + auto it2 = cnd_mod_map.find(cond.cond_id_type); if (it2 != cnd_mod_map.end()) { for (auto mod_group : it2->second) { From 988f50bb604449302fc4529d584786bd09f81887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 08:19:28 +0000 Subject: [PATCH 39/57] refactor: replace global maps --- plugins/navteq/converter/StreetConverter.cpp | 108 ++++++++++-------- plugins/navteq/converter/StreetConverter.hpp | 35 +++--- .../converter/StreetConverterOSMTagger.cpp | 6 - 3 files changed, 80 insertions(+), 69 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 69f8523..1053f58 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -79,7 +79,15 @@ void StreetConverter::add_street_shapes(const std::filesystem::path &dir, osmium::io::Writer &writer) { BOOST_LOG_TRIVIAL(info) << " processing z-levels"; - auto z_level_map = process_z_levels(dir); + auto z_level_map = init_z_level_map(dir); + + BOOST_LOG_TRIVIAL(info) << " processing conditional modifications "; + auto cdms_map = init_g_cdms_map(dir); + auto cnd_mod_map = init_g_cnd_mod_map(cdms_map, dir); + + BOOST_LOG_TRIVIAL(info) << " processing country reference"; + auto area_to_govt_code_map = init_g_area_to_govt_code_map(dir); + auto g_cntry_ref_map = init_g_cntry_ref_map(dir); BOOST_LOG_TRIVIAL(info) << " processing way end points"; process_way_end_nodes(dir, z_level_map, writer); @@ -93,30 +101,10 @@ void StreetConverter::add_street_shapes(const std::filesystem::path &dir, } std::map> -StreetConverter::process_z_levels(const std::filesystem::path &dir) { +StreetConverter::init_z_level_map(const std::filesystem::path &dir) { std::map> z_level_map; - auto ds = openDataSource(dir / STREETS_SHP); - if (!ds) - throw(shp_error(dir / STREETS_SHP)); - - auto layer = ds->GetLayer(0); - if (layer == nullptr) - throw(shp_empty_error(dir / STREETS_SHP)); - assert(layer->GetGeomType() == wkbLineString); - - init_z_level_map(dir, z_level_map); - init_conditional_modifications(dir); - init_country_reference(dir); - - return z_level_map; -} - -void StreetConverter::init_z_level_map( - const std::filesystem::path &dir, - std::map> &z_level_map) { - const std::filesystem::path ZLEVELS_DBF = "Zlevels.dbf"; auto ds = openDataSource(dir / ZLEVELS_DBF); @@ -146,20 +134,26 @@ void StreetConverter::init_z_level_map( if (!v.empty()) z_level_map.emplace(last_link_id, v); -} -void StreetConverter::init_conditional_modifications( - const std::filesystem::path &dir) { - init_g_cnd_mod_map(dir); - init_g_cdms_map(dir); + return z_level_map; } -void StreetConverter::init_g_cnd_mod_map(const std::filesystem::path &dir) { +std::unordered_map> +StreetConverter::init_g_cnd_mod_map( + const std::multimap &cdms_map, + const std::filesystem::path &dir) { const std::filesystem::path CND_MOD_DBF = "CndMod.dbf"; + std::unordered_map> cnd_mod_map; + + std::set cond_ids; + for (const auto &[_, cond] : cdms_map) { + cond_ids.insert(cond.cond_id_type); + } + auto ds = openDataSource(dir / CND_MOD_DBF); if (!ds) - return; + return cnd_mod_map; auto layer = ds->GetLayer(0); if (layer == nullptr) @@ -167,29 +161,40 @@ void StreetConverter::init_g_cnd_mod_map(const std::filesystem::path &dir) { for (auto &feat : *layer) { uint64_t cond_id = get_uint_from_feature(feat, COND_ID); + + // only process conditional modifications for the given cond_ids + if (cond_ids.find(cond_id) == cond_ids.end()) + continue; + std::string lang_code = get_field_from_feature(feat, LANG_CODE); uint64_t mod_type = get_uint_from_feature(feat, CM_MOD_TYPE); uint64_t mod_val = get_uint_from_feature(feat, CM_MOD_VAL); - auto it2 = g_cnd_mod_map.find(cond_id); - if (it2 == g_cnd_mod_map.end()) { + auto it2 = cnd_mod_map.find(cond_id); + if (it2 == cnd_mod_map.end()) { std::vector new_vector; new_vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); - g_cnd_mod_map.emplace(cond_id, new_vector); + cnd_mod_map.emplace(cond_id, new_vector); } else { auto vector = it2->second; - g_cnd_mod_map.erase(it2); + cnd_mod_map.erase(it2); vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); - g_cnd_mod_map.emplace(cond_id, vector); + cnd_mod_map.emplace(cond_id, vector); } } + + return cnd_mod_map; } -void StreetConverter::init_g_cdms_map(const std::filesystem::path &dir) { +std::multimap +StreetConverter::init_g_cdms_map(const std::filesystem::path &dir) { + + std::multimap cdms_map; + const std::filesystem::path CDMS_DBF = "Cdms.dbf"; auto ds = openDataSource(dir / CDMS_DBF); if (!ds) - return; + return cdms_map; auto layer = ds->GetLayer(0); if (layer == nullptr) @@ -199,25 +204,23 @@ void StreetConverter::init_g_cdms_map(const std::filesystem::path &dir) { uint64_t link_id = get_uint_from_feature(feat, LINK_ID); uint64_t cond_id = get_uint_from_feature(feat, COND_ID); ushort cond_type = get_uint_from_feature(feat, COND_TYPE); - g_cdms_map.emplace(link_id, cond_pair_type(cond_id, cond_type)); - if (cond_type == 3) - g_construction_set.emplace(link_id); + + cdms_map.emplace(link_id, StreetConverter::cond_type{cond_id, cond_type}); } -} -void StreetConverter::init_country_reference(const std::filesystem::path &dir) { - init_g_area_to_govt_code_map(dir); - init_g_cntry_ref_map(dir); + return cdms_map; } -void StreetConverter::init_g_area_to_govt_code_map( +std::map StreetConverter::init_g_area_to_govt_code_map( const std::filesystem::path &dir) { + std::map area_to_govt_code_map; + const std::filesystem::path MTD_AREA_DBF = "MtdArea.dbf"; auto ds = openDataSource(dir / MTD_AREA_DBF); if (!ds) - return; + return area_to_govt_code_map; auto layer = ds->GetLayer(0); if (layer == nullptr) @@ -226,17 +229,22 @@ void StreetConverter::init_g_area_to_govt_code_map( for (auto &feat : *layer) { uint64_t area_id = get_uint_from_feature(feat, AREA_ID); uint64_t govt_code = get_uint_from_feature(feat, GOVT_CODE); - g_area_to_govt_code_map.emplace(area_id, govt_code); + area_to_govt_code_map.emplace(area_id, govt_code); } + + return area_to_govt_code_map; } -void StreetConverter::init_g_cntry_ref_map(const std::filesystem::path &dir) { +std::map +StreetConverter::init_g_cntry_ref_map(const std::filesystem::path &dir) { + + std::map cntry_ref_map; static const std::filesystem::path MTD_CNTRY_REF_DBF = "MtdCntryRef.dbf"; auto ds = openDataSource(dir / MTD_CNTRY_REF_DBF); if (!ds) - return; + return cntry_ref_map; auto layer = ds->GetLayer(0); if (layer == nullptr) @@ -248,8 +256,10 @@ void StreetConverter::init_g_cntry_ref_map(const std::filesystem::path &dir) { std::string speed_limit_unit = get_field_from_feature(feat, SPEEDLIMITUNIT); std::string iso_code = get_field_from_feature(feat, ISO_CODE); cntry_ref_type cntry_ref(unit_measure, speed_limit_unit, iso_code); - g_cntry_ref_map.emplace(govt_code, cntry_ref); + cntry_ref_map.emplace(govt_code, cntry_ref); } + + return cntry_ref_map; } void StreetConverter::process_way_end_nodes( diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index bce7e21..6dc1d38 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -35,7 +35,6 @@ class StreetConverter : public Converter { short z_level; }; -private: struct cond_type { uint64_t cond_id_type; uint64_t cond_type_type; @@ -77,31 +76,33 @@ class StreetConverter : public Converter { bool operator!=(cntry_ref_type rhs) { return !(*this == rhs); } }; +private: std::map process_alt_steets_route_types(const std::filesystem::path &dir); void add_street_shapes(const std::filesystem::path &dir, osmium::io::Writer &writer); - std::map> - process_z_levels(const std::filesystem::path &dir); - - void init_z_level_map( - const std::filesystem::path &dir, - std::map> &z_level_map); + std::map> + init_z_level_map(const std::filesystem::path &dir); void set_ferry_z_lvls_to_zero(const OGRFeatureUniquePtr &feat, std::vector &z_lvl_vec); void test__z_lvl_range(short z_lvl); - void init_conditional_modifications(const std::filesystem::path &dir); - void init_g_cnd_mod_map(const std::filesystem::path &dir); - void init_g_cdms_map(const std::filesystem::path &dir); + std::unordered_map> + init_g_cnd_mod_map( + const std::multimap &cdms_map, + const std::filesystem::path &dir); + + std::multimap + init_g_cdms_map(const std::filesystem::path &dir); - void init_country_reference(const std::filesystem::path &dir); - void init_g_area_to_govt_code_map(const std::filesystem::path &dir); - void init_g_cntry_ref_map(const std::filesystem::path &dir); + std::map + init_g_area_to_govt_code_map(const std::filesystem::path &dir); + std::map + init_g_cntry_ref_map(const std::filesystem::path &dir); // process end nodes void process_way_end_nodes( @@ -158,7 +159,7 @@ class StreetConverter : public Converter { Converter::mtd_area_dataset> &mtd_area_map, const std::map &route_type_map, const std::map> &names_map, - const std::set &construction_set, bool debugMode); + bool debugMode); std::map> init_highway_names(const std::filesystem::path &dir); @@ -392,6 +393,12 @@ class StreetConverter : public Converter { const std::filesystem::path STREETS_SHP = "Streets.shp"; const std::filesystem::path ALT_STREETS_DBF = "AltStreets.dbf"; + + // condition types (CT) + const ushort CT_CONSTRUCTION_STATUS_CLOSED = 3; + const ushort CT_RESTRICTED_DRIVING_MANOEUVRE = 7; + const ushort CT_TRANSPORT_ACCESS_RESTRICTION = 23; + const ushort CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE = 26; }; #endif // STREETCONVERTER_HPP diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index d2a0e97..5439c64 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -19,12 +19,6 @@ #include #include -// condition types (CT) -const ushort CT_CONSTRUCTION_STATUS_CLOSED = 3; -const ushort CT_RESTRICTED_DRIVING_MANOEUVRE = 7; -const ushort CT_TRANSPORT_ACCESS_RESTRICTION = 23; -const ushort CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE = 26; - // modifier types (MT) const ushort MT_HAZARDOUS_RESTRICTION = 39; const ushort MT_HEIGHT_RESTRICTION = 41; From 45cc7038029e7a50ae5769ff68854c41673c9b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 08:30:27 +0000 Subject: [PATCH 40/57] Extract Housenumber conversion into its on converter --- ...useNumber.cpp => HouseNumberConverter.cpp} | 43 ++++++---- .../navteq/converter/HouseNumberConverter.hpp | 80 +++++++++++++++++++ plugins/navteq/converter/StreetConverter.cpp | 4 - plugins/navteq/converter/StreetConverter.hpp | 42 ---------- plugins/navteq/navteq_plugin.cpp | 2 + 5 files changed, 109 insertions(+), 62 deletions(-) rename plugins/navteq/converter/{StreetConverterHouseNumber.cpp => HouseNumberConverter.cpp} (87%) create mode 100644 plugins/navteq/converter/HouseNumberConverter.hpp diff --git a/plugins/navteq/converter/StreetConverterHouseNumber.cpp b/plugins/navteq/converter/HouseNumberConverter.cpp similarity index 87% rename from plugins/navteq/converter/StreetConverterHouseNumber.cpp rename to plugins/navteq/converter/HouseNumberConverter.cpp index 3b26a78..c788fcb 100644 --- a/plugins/navteq/converter/StreetConverterHouseNumber.cpp +++ b/plugins/navteq/converter/HouseNumberConverter.cpp @@ -14,15 +14,27 @@ * along with Morituri. If not, see . */ -#include "StreetConverter.hpp" +#include "HouseNumberConverter.hpp" #include #include #include "../../ogr_util.hpp" -void StreetConverter::process_house_numbers(const std::filesystem::path &dir, - osmium::io::Writer &writer) { +HouseNumberConverter::HouseNumberConverter( + const std::filesystem::path &executable_path) + : Converter(executable_path) {} + +HouseNumberConverter::~HouseNumberConverter() {} + +void HouseNumberConverter::convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) { + + process_house_numbers(dir, writer); +} + +void HouseNumberConverter::process_house_numbers( + const std::filesystem::path &dir, osmium::io::Writer &writer) { // create point addresses from PointAddress.dbf auto pointMap = createPointAddressMapList(dir); @@ -59,7 +71,7 @@ void StreetConverter::process_house_numbers(const std::filesystem::path &dir, * \param ogr_ls linestring which provides the geometry. * \param z_level_map holds z_levels to Nodes of Ways. */ -void StreetConverter::process_house_numbers( +void HouseNumberConverter::process_house_numbers( const OGRFeatureUniquePtr &feat, const std::map>> @@ -80,7 +92,8 @@ void StreetConverter::process_house_numbers( } std::map>> * -StreetConverter::createPointAddressMapList(const std::filesystem::path &dir) { +HouseNumberConverter::createPointAddressMapList( + const std::filesystem::path &dir) { auto pointAddressMap = new std::map> &addressList, int linkId, osmium::memory::Buffer &node_buffer) { @@ -154,11 +166,9 @@ void StreetConverter::create_premium_house_numbers( } } -void StreetConverter::create_house_numbers(const OGRFeatureUniquePtr &feat, - const OGRLineString *ogr_ls, - bool left, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer) { +void HouseNumberConverter::create_house_numbers( + const OGRFeatureUniquePtr &feat, const OGRLineString *ogr_ls, bool left, + osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { const std::string_view &ref_addr = left ? L_REFADDR : R_REFADDR; const std::string_view &nref_addr = left ? L_NREFADDR : R_NREFADDR; const std::string_view &addr_schema = left ? L_ADDRSCH : R_ADDRSCH; @@ -245,7 +255,8 @@ void StreetConverter::create_house_numbers(const OGRFeatureUniquePtr &feat, way_buffer.commit(); } -const char *StreetConverter::parse_house_number_schema(const char *schema) { +const char * +HouseNumberConverter::parse_house_number_schema(const char *schema) { if (!strcmp(schema, "E")) return "even"; if (!strcmp(schema, "O")) diff --git a/plugins/navteq/converter/HouseNumberConverter.hpp b/plugins/navteq/converter/HouseNumberConverter.hpp new file mode 100644 index 0000000..8a14c45 --- /dev/null +++ b/plugins/navteq/converter/HouseNumberConverter.hpp @@ -0,0 +1,80 @@ +/* + * This file is part of the Morituri project. + * Morituri is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Morituri is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Morituri. If not, see . + */ + +#ifndef HOUSENUMBERCONVERTER_HPP +#define HOUSENUMBERCONVERTER_HPP + +#include "Converter.hpp" + +class HouseNumberConverter : public Converter { + +public: + HouseNumberConverter(const std::filesystem::path &executable_path); + virtual ~HouseNumberConverter(); + + virtual void convert(const std::filesystem::path &dir, + osmium::io::Writer &writer) override; + +private: + void create_house_numbers(const OGRFeatureUniquePtr &feat, + const OGRLineString *ogr_ls, bool left, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + void create_house_numbers(const OGRFeatureUniquePtr &feat, + const OGRLineString *ogr_ls, + osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + void create_premium_house_numbers( + const OGRFeatureUniquePtr &feat, + const std::vector> &addressList, + int linkId, osmium::memory::Buffer &node_buffer); + + void process_house_numbers(const std::filesystem::path &dirs, + osmium::io::Writer &writer); + + void process_house_numbers( + const OGRFeatureUniquePtr &feat, + const std::map>> + &pointAddresses, + int linkId, osmium::memory::Buffer &node_buffer, + osmium::memory::Buffer &way_buffer); + + std::map>> * + createPointAddressMapList(const std::filesystem::path &dir); + + const char *parse_house_number_schema(const char *schema); + + const std::filesystem::path STREETS_SHP = "Streets.shp"; + + static constexpr std::string_view ST_NAME = "ST_NAME"; + + static constexpr std::string_view ADDR_TYPE = "ADDR_TYPE"; + + static constexpr std::string_view L_REFADDR = "L_REFADDR"; + const char *L_NREFADDR = "L_NREFADDR"; + const char *L_ADDRSCH = "L_ADDRSCH"; + // const char *L_ADDRFORM = "L_ADDRFORM"; + const char *R_REFADDR = "R_REFADDR"; + const char *R_NREFADDR = "R_NREFADDR"; + const char *R_ADDRSCH = "R_ADDRSCH"; + + const double HOUSENUMBER_CURVE_OFFSET = 0.00005; +}; + +#endif // HOUSENUMBERCONVERTER_HPP \ No newline at end of file diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 1053f58..1ad0552 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -94,10 +94,6 @@ void StreetConverter::add_street_shapes(const std::filesystem::path &dir, BOOST_LOG_TRIVIAL(info) << " processing ways"; process_way(dir, z_level_map, writer); - - // create house numbers - BOOST_LOG_TRIVIAL(info) << " processing house numbers"; - process_house_numbers(dir, writer); } std::map> diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index 6dc1d38..152d844 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -263,35 +263,6 @@ class StreetConverter : public Converter { void add_here_speed_cat_tag(osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f); - void create_house_numbers(const OGRFeatureUniquePtr &feat, - const OGRLineString *ogr_ls, bool left, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer); - - void create_house_numbers(const OGRFeatureUniquePtr &feat, - const OGRLineString *ogr_ls, - osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer); - - void create_premium_house_numbers( - const OGRFeatureUniquePtr &feat, - const std::vector> &addressList, - int linkId, osmium::memory::Buffer &node_buffer); - - void process_house_numbers(const std::filesystem::path &dirs, - osmium::io::Writer &writer); - - void process_house_numbers( - const OGRFeatureUniquePtr &feat, - const std::map>> - &pointAddresses, - int linkId, osmium::memory::Buffer &node_buffer, - osmium::memory::Buffer &way_buffer); - - std::map>> * - createPointAddressMapList(const std::filesystem::path &dir); - bool is_ferry(const char *value); bool is_superior_or_equal(short superior, short than); @@ -300,8 +271,6 @@ class StreetConverter : public Converter { uint get_number_after(const std::string &str, const char *start_str); - const char *parse_house_number_schema(const char *schema); - std::string lbs_to_metric_ton(double lbs); std::string inch_to_feet(unsigned int inches); @@ -379,17 +348,6 @@ class StreetConverter : public Converter { static constexpr std::string_view ST_NAME = "ST_NAME"; static constexpr std::string_view COND_TYPE = "COND_TYPE"; - static constexpr std::string_view ADDR_TYPE = "ADDR_TYPE"; - static constexpr std::string_view L_REFADDR = "L_REFADDR"; - const char *L_NREFADDR = "L_NREFADDR"; - const char *L_ADDRSCH = "L_ADDRSCH"; - // const char *L_ADDRFORM = "L_ADDRFORM"; - const char *R_REFADDR = "R_REFADDR"; - const char *R_NREFADDR = "R_NREFADDR"; - const char *R_ADDRSCH = "R_ADDRSCH"; - - const double HOUSENUMBER_CURVE_OFFSET = 0.00005; - const std::filesystem::path STREETS_SHP = "Streets.shp"; const std::filesystem::path ALT_STREETS_DBF = "AltStreets.dbf"; diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index 5112b06..c21961b 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -21,6 +21,7 @@ #include "converter/BuildingConverter.hpp" #include "converter/CityConverter.hpp" #include "converter/HamletConverter.hpp" +#include "converter/HouseNumberConverter.hpp" #include "converter/LanduseConverter.hpp" #include "converter/RailwayConverter.hpp" #include "converter/RestAreaConverter.hpp" @@ -48,6 +49,7 @@ navteq_plugin::navteq_plugin(const std::filesystem::path &executable_path) converter.emplace_back(new RestAreaConverter(executable_path)); converter.emplace_back(new RailwayConverter(executable_path)); converter.emplace_back(new WaterConverter(executable_path)); + converter.emplace_back(new HouseNumberConverter(executable_path)); } navteq_plugin::~navteq_plugin() {} From b9fad6b6470e4741e333b6df5b342f210adc7e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 09:55:31 +0000 Subject: [PATCH 41/57] extract more global states --- .../converter/AdminBoundariesConverter.cpp | 12 +- plugins/navteq/converter/StreetConverter.cpp | 179 +++++++++++------- plugins/navteq/converter/StreetConverter.hpp | 90 ++++++--- .../converter/StreetConverterOSMTagger.cpp | 20 +- 4 files changed, 196 insertions(+), 105 deletions(-) diff --git a/plugins/navteq/converter/AdminBoundariesConverter.cpp b/plugins/navteq/converter/AdminBoundariesConverter.cpp index d6cab23..2d8518c 100644 --- a/plugins/navteq/converter/AdminBoundariesConverter.cpp +++ b/plugins/navteq/converter/AdminBoundariesConverter.cpp @@ -40,19 +40,19 @@ void AdminBoundariesConverter::convert(const std::filesystem::path &dir, const std::filesystem::path ADMINBNDY_5_SHP = "Adminbndy5.shp"; std::map - g_way_end_points_map; + way_end_points_map; auto mtd_area_map = process_meta_areas(dir); - addLevel1Boundaries(dir, g_way_end_points_map, mtd_area_map, writer); + addLevel1Boundaries(dir, way_end_points_map, mtd_area_map, writer); - addLevelNBoundaries(dir / ADMINBNDY_2_SHP, g_way_end_points_map, mtd_area_map, + addLevelNBoundaries(dir / ADMINBNDY_2_SHP, way_end_points_map, mtd_area_map, writer, 2); - addLevelNBoundaries(dir / ADMINBNDY_3_SHP, g_way_end_points_map, mtd_area_map, + addLevelNBoundaries(dir / ADMINBNDY_3_SHP, way_end_points_map, mtd_area_map, writer, 3); - addLevelNBoundaries(dir / ADMINBNDY_4_SHP, g_way_end_points_map, mtd_area_map, + addLevelNBoundaries(dir / ADMINBNDY_4_SHP, way_end_points_map, mtd_area_map, writer, 4); - addLevelNBoundaries(dir / ADMINBNDY_5_SHP, g_way_end_points_map, mtd_area_map, + addLevelNBoundaries(dir / ADMINBNDY_5_SHP, way_end_points_map, mtd_area_map, writer, 5); } diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 1ad0552..aa53a4b 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -33,9 +33,44 @@ StreetConverter::~StreetConverter() {} void StreetConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { + // should be global for connectivity between regions + std::map + g_way_end_points_map; + + BOOST_LOG_TRIVIAL(info) << " processing alt_streets route types"; auto route_type_map = process_alt_steets_route_types(dir); - add_street_shapes(dir, writer); + BOOST_LOG_TRIVIAL(info) << " processing conditional modifications "; + auto cdms_map = init_g_cdms_map(dir); + auto cnd_mod_map = init_g_cnd_mod_map(cdms_map, dir); + + BOOST_LOG_TRIVIAL(info) << " processing country reference"; + auto area_to_govt_code_map = init_g_area_to_govt_code_map(dir); + auto cntry_ref_map = init_g_cntry_ref_map(dir); + + BOOST_LOG_TRIVIAL(info) << " processing ramps"; + auto ramps_ref_map = init_ramp_names(dir); + + BOOST_LOG_TRIVIAL(info) << " processing highway names"; + auto hwys_ref_map = init_highway_names(dir); + + // fill data struct for tag processing + TagData data = {route_type_map, cnd_mod_map, cdms_map, + area_to_govt_code_map, cntry_ref_map, ramps_ref_map, + hwys_ref_map}; + + BOOST_LOG_TRIVIAL(info) << " processing z-levels"; + auto z_level_map = init_z_level_map(dir); + + std::map, osmium::unsigned_object_id_type> + z_lvl_nodes_map; + + BOOST_LOG_TRIVIAL(info) << " processing way end points"; + process_way_end_nodes(dir, data, g_way_end_points_map, z_level_map, writer); + + BOOST_LOG_TRIVIAL(info) << " processing ways"; + process_way(dir, data, g_way_end_points_map, z_lvl_nodes_map, z_level_map, + writer); } std::map StreetConverter::process_alt_steets_route_types( @@ -75,27 +110,6 @@ std::map StreetConverter::process_alt_steets_route_types( return route_type_map; } -void StreetConverter::add_street_shapes(const std::filesystem::path &dir, - osmium::io::Writer &writer) { - - BOOST_LOG_TRIVIAL(info) << " processing z-levels"; - auto z_level_map = init_z_level_map(dir); - - BOOST_LOG_TRIVIAL(info) << " processing conditional modifications "; - auto cdms_map = init_g_cdms_map(dir); - auto cnd_mod_map = init_g_cnd_mod_map(cdms_map, dir); - - BOOST_LOG_TRIVIAL(info) << " processing country reference"; - auto area_to_govt_code_map = init_g_area_to_govt_code_map(dir); - auto g_cntry_ref_map = init_g_cntry_ref_map(dir); - - BOOST_LOG_TRIVIAL(info) << " processing way end points"; - process_way_end_nodes(dir, z_level_map, writer); - - BOOST_LOG_TRIVIAL(info) << " processing ways"; - process_way(dir, z_level_map, writer); -} - std::map> StreetConverter::init_z_level_map(const std::filesystem::path &dir) { @@ -259,15 +273,13 @@ StreetConverter::init_g_cntry_ref_map(const std::filesystem::path &dir) { } void StreetConverter::process_way_end_nodes( - const std::filesystem::path &dir, - const std::map> + const std::filesystem::path &dir, const StreetConverter::TagData &data, + std::map + &way_end_points_map, + std::map> &z_level_map, osmium::io::Writer &writer) { - // parse ramp names and refs - std::map> ramps_ref_map = - init_ramp_names(dir); - auto path = dir / STREETS_SHP; auto ds = openDataSource(path); if (!ds) @@ -287,45 +299,51 @@ void StreetConverter::process_way_end_nodes( // omit way end nodes with different z-levels (they have to be handled // extra) if (z_level_map.find(link_id) == z_level_map.end()) - process_way_end_nodes(feat, node_buffer); + process_way_end_nodes(feat, data, way_end_points_map, node_buffer); } node_buffer.commit(); writer(std::move(node_buffer)); } void StreetConverter::process_way_end_nodes( - OGRFeatureUniquePtr &feat, osmium::memory::Buffer &node_buffer) { + OGRFeatureUniquePtr &feat, const StreetConverter::TagData &data, + std::map + &way_end_points_map, + osmium::memory::Buffer &node_buffer) { auto ogr_ls = static_cast(feat->GetGeometryRef()); - process_way_end_node(osmium::Location(ogr_ls->getX(0), ogr_ls->getY(0)), - node_buffer); + process_way_end_node(osmium::Location(ogr_ls->getX(0), ogr_ls->getY(0)), data, + way_end_points_map, node_buffer); process_way_end_node( osmium::Location(ogr_ls->getX(ogr_ls->getNumPoints() - 1), ogr_ls->getY(ogr_ls->getNumPoints() - 1)), - node_buffer); + data, way_end_points_map, node_buffer); } void StreetConverter::process_way_end_node( - const osmium::Location &location, osmium::memory::Buffer &node_buffer) { + const osmium::Location &location, const StreetConverter::TagData &data, + std::map + &way_end_points_map, + osmium::memory::Buffer &node_buffer) { - auto it = g_way_end_points_map.find(location); - if (it != g_way_end_points_map.end()) + auto it = way_end_points_map.find(location); + if (it != way_end_points_map.end()) return; osmium::builder::NodeBuilder builder(node_buffer); osmium::unsigned_object_id_type osm_id = build_node(location, builder); // add ramp tags - auto ramp = g_ramps_ref_map.find(location); - if (ramp != g_ramps_ref_map.end()) { + auto ramp = data.ramp_names.find(location); + if (ramp != data.ramp_names.end()) { if (ramp->second.find(0) != ramp->second.end()) { osmium::builder::TagListBuilder tglBuilder(builder); tglBuilder.add_tag(HIGHWAY.data(), "motorway_junction"); - tglBuilder.add_tag("ref", ramp->second[0]); - tglBuilder.add_tag("name", to_camel_case_with_spaces(ramp->second[1])); + tglBuilder.add_tag("ref", ramp->second.at(0)); + tglBuilder.add_tag("name", to_camel_case_with_spaces(ramp->second.at(1))); } } - g_way_end_points_map.emplace(location, osm_id); + way_end_points_map.emplace(location, osm_id); } std::map> @@ -412,13 +430,14 @@ void StreetConverter::parse_ramp_names( } void StreetConverter::process_way( - const std::filesystem::path &dir, + const std::filesystem::path &dir, const StreetConverter::TagData &data, + std::map + &way_end_points_map, + std::map, + osmium::unsigned_object_id_type> &z_lvl_nodes_map, std::map> &z_level_map, osmium::io::Writer &writer) { - // parse highway names and refs - auto hwys_ref_map = init_highway_names(dir); - auto path = dir / STREETS_SHP; auto ds = openDataSource(path); if (!ds) @@ -431,7 +450,8 @@ void StreetConverter::process_way( osmium::memory::Buffer node_buffer(BUFFER_SIZE); osmium::memory::Buffer way_buffer(BUFFER_SIZE); for (auto &feat : *layer) { - process_way(feat, z_level_map, node_buffer, way_buffer); + process_way(feat, data, way_end_points_map, z_lvl_nodes_map, z_level_map, + node_buffer, way_buffer); } node_buffer.commit(); @@ -482,7 +502,11 @@ void StreetConverter::parse_highway_names( } void StreetConverter::process_way( - OGRFeatureUniquePtr &feat, + OGRFeatureUniquePtr &feat, const StreetConverter::TagData &data, + std::map + &way_end_points_map, + std::map, + osmium::unsigned_object_id_type> &z_lvl_nodes_map, std::map> &z_level_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer) { @@ -499,7 +523,8 @@ void StreetConverter::process_way( auto it = z_level_map.find(link_id); if (it == z_level_map.end()) { - build_way(feat, ogr_ls, node_ref_map, way_buffer, false, -5); + build_way(feat, ogr_ls, node_ref_map, data, way_end_points_map, way_buffer, + false, -5); } else { auto &index_z_lvl_vector = it->second; @@ -510,7 +535,8 @@ void StreetConverter::process_way( if (first_point_with_different_z_lvl.index == first_index) first_z_lvl = first_point_with_different_z_lvl.z_level; - process_end_point(true, first_z_lvl, ogr_ls, node_ref_map, node_buffer); + process_end_point(true, first_z_lvl, ogr_ls, node_ref_map, + way_end_points_map, z_lvl_nodes_map, node_buffer); auto &last_point_with_different_z_lvl = index_z_lvl_vector.back(); auto last_index = ogr_ls->getNumPoints() - 1; @@ -518,15 +544,16 @@ void StreetConverter::process_way( if (last_point_with_different_z_lvl.index == last_index) last_z_lvl = last_point_with_different_z_lvl.z_level; - process_end_point(false, last_z_lvl, ogr_ls, node_ref_map, node_buffer); + process_end_point(false, last_z_lvl, ogr_ls, node_ref_map, + way_end_points_map, z_lvl_nodes_map, node_buffer); way_buffer.commit(); if (is_ferry(get_field_from_feature(feat, FERRY))) set_ferry_z_lvls_to_zero(feat, index_z_lvl_vector); - split_way_by_z_level(feat, ogr_ls, index_z_lvl_vector, node_ref_map, - link_id, way_buffer); + split_way_by_z_level(feat, ogr_ls, index_z_lvl_vector, node_ref_map, data, + way_end_points_map, link_id, way_buffer); } } @@ -545,6 +572,9 @@ void StreetConverter::middle_points_preparation( osmium::unsigned_object_id_type StreetConverter::build_way( OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, std::map &node_ref_map, + const StreetConverter::TagData &data, + std::map + &way_end_points_map, osmium::memory::Buffer &way_buffer, bool is_sub_linestring = false, short z_lvl = -5) { @@ -567,7 +597,7 @@ osmium::unsigned_object_id_type StreetConverter::build_way( *map_containing_node; if (!is_sub_linestring) { if (is_end_point) - map_containing_node = &g_way_end_points_map; + map_containing_node = &way_end_points_map; else map_containing_node = &node_ref_map; } else { @@ -575,9 +605,8 @@ osmium::unsigned_object_id_type StreetConverter::build_way( map_containing_node = &node_ref_map; } else { // node has to be in node_ref_map or way_end_points_map - assert(g_way_end_points_map.find(location) != - g_way_end_points_map.end()); - map_containing_node = &g_way_end_points_map; + assert(way_end_points_map.find(location) != way_end_points_map.end()); + map_containing_node = &way_end_points_map; } } @@ -586,31 +615,35 @@ osmium::unsigned_object_id_type StreetConverter::build_way( } } - build_tag_list(feat, builder, z_lvl); + build_tag_list(feat, data, builder, z_lvl); return builder.object().id(); } void StreetConverter::process_end_point( bool first, short z_lvl, OGRLineString *ogr_ls, std::map &node_ref_map, + std::map + &way_end_points_map, + std::map, + osmium::unsigned_object_id_type> &z_lvl_nodes_map, osmium::memory::Buffer &node_buffer) { ushort i = first ? 0 : ogr_ls->getNumPoints() - 1; osmium::Location location(ogr_ls->getX(i), ogr_ls->getY(i)); if (z_lvl != 0) { auto node_id = std::make_pair(location, z_lvl); - auto it = g_z_lvl_nodes_map.find(node_id); - if (it != g_z_lvl_nodes_map.end()) { + auto it = z_lvl_nodes_map.find(node_id); + if (it != z_lvl_nodes_map.end()) { node_ref_map.emplace(location, it->second); } else { osmium::unsigned_object_id_type osm_id = build_node(location, node_buffer); node_ref_map.emplace(location, osm_id); - g_z_lvl_nodes_map.emplace(node_id, osm_id); + z_lvl_nodes_map.emplace(node_id, osm_id); } } else { // adds all zero z-level end points to g_way_end_points_map - g_way_end_points_map.emplace(location, build_node(location, node_buffer)); + way_end_points_map.emplace(location, build_node(location, node_buffer)); } } @@ -618,6 +651,9 @@ void StreetConverter::split_way_by_z_level( OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, const std::vector &node_z_level_vector, std::map &node_ref_map, + const StreetConverter::TagData &data, + std::map + &way_end_points_map, uint64_t link_id, osmium::memory::Buffer &way_buffer) { ushort first_index = 0, last_index = ogr_ls->getNumPoints() - 1; @@ -632,7 +668,7 @@ void StreetConverter::split_way_by_z_level( // if (DEBUG) print_z_level_map(link_id, true); if (first_index != start_index) { build_sub_way_by_index(feat, ogr_ls, first_index, start_index, node_ref_map, - way_buffer, 0); + data, way_end_points_map, way_buffer, 0); BOOST_LOG_TRIVIAL(debug) << " 1 ## " << link_id << " ## " << first_index << "/" << last_index << " - " << start_index << "/" << last_index << ": \tz_lvl=" << 0 @@ -641,11 +677,11 @@ void StreetConverter::split_way_by_z_level( start_index = create_continuing_sub_ways( feat, ogr_ls, first_index, start_index, last_index, link_id, - node_z_level_vector, node_ref_map, way_buffer); + node_z_level_vector, node_ref_map, data, way_end_points_map, way_buffer); if (start_index < last_index) { build_sub_way_by_index(feat, ogr_ls, start_index, last_index, node_ref_map, - way_buffer, 0); + data, way_end_points_map, way_buffer, 0); BOOST_LOG_TRIVIAL(debug) << " 4 ## " << link_id << " ## " << start_index << "/" << last_index << " - " << last_index << "/" << last_index << ": \tz_lvl=" << 0 @@ -657,12 +693,16 @@ void StreetConverter::build_sub_way_by_index( OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, ushort start_index, ushort end_index, std::map &node_ref_map, + const StreetConverter::TagData &data, + std::map + &way_end_points_map, osmium::memory::Buffer &way_buffer, short z_lvl = 0) { assert(start_index < end_index || end_index == -1); assert(start_index < ogr_ls->getNumPoints()); OGRLineString subLineString; subLineString.addSubLineString(ogr_ls, start_index, end_index); - build_way(feat, &subLineString, node_ref_map, way_buffer, true, z_lvl); + build_way(feat, &subLineString, node_ref_map, data, way_end_points_map, + way_buffer, true, z_lvl); } ushort StreetConverter::create_continuing_sub_ways( @@ -670,6 +710,9 @@ ushort StreetConverter::create_continuing_sub_ways( ushort start_index, ushort last_index, uint link_id, const std::vector &node_z_level_vector, std::map &node_ref_map, + const StreetConverter::TagData &data, + std::map + &way_end_points_map, osmium::memory::Buffer &way_buffer) { for (auto it = node_z_level_vector.cbegin(); it != node_z_level_vector.cend(); @@ -724,14 +767,14 @@ ushort StreetConverter::create_continuing_sub_ways( << " - " << to << "/" << last_index << ": \tz_lvl=" << z_lvl << std::endl; if (from < to) { - build_sub_way_by_index(feat, ogr_ls, from, to, node_ref_map, way_buffer, - z_lvl); + build_sub_way_by_index(feat, ogr_ls, from, to, node_ref_map, data, + way_end_points_map, way_buffer, z_lvl); start_index = to; } if (not_last_element && to < next_index - 1) { build_sub_way_by_index(feat, ogr_ls, to, next_index - 1, node_ref_map, - way_buffer); + data, way_end_points_map, way_buffer); BOOST_LOG_TRIVIAL(debug) << " 3 ## " << link_id << " ## " << to << "/" << last_index << " - " << next_index - 1 << "/" << last_index diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index 152d844..a4719df 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -76,21 +76,24 @@ class StreetConverter : public Converter { bool operator!=(cntry_ref_type rhs) { return !(*this == rhs); } }; + struct TagData { + std::map route_type_map; + std::unordered_map> + cnd_mod_map; + std::multimap cdms_map; + std::map area_govt_map; + std::map cntry_map; + std::map> ramp_names; + std::map> highway_names; + }; + private: std::map process_alt_steets_route_types(const std::filesystem::path &dir); - void add_street_shapes(const std::filesystem::path &dir, - osmium::io::Writer &writer); - std::map> init_z_level_map(const std::filesystem::path &dir); - void set_ferry_z_lvls_to_zero(const OGRFeatureUniquePtr &feat, - std::vector &z_lvl_vec); - - void test__z_lvl_range(short z_lvl); - std::unordered_map> init_g_cnd_mod_map( const std::multimap &cdms_map, @@ -101,19 +104,12 @@ class StreetConverter : public Converter { std::map init_g_area_to_govt_code_map(const std::filesystem::path &dir); + std::map init_g_cntry_ref_map(const std::filesystem::path &dir); - // process end nodes - void process_way_end_nodes( - const std::filesystem::path &dir, - const std::map> - &z_level_map, - osmium::io::Writer &writer); - void process_way_end_nodes(OGRFeatureUniquePtr &feat, - osmium::memory::Buffer &node_buffer); - void process_way_end_node(const osmium::Location &location, - osmium::memory::Buffer &node_buffer); + std::map> + init_highway_names(const std::filesystem::path &dir); // ramp names std::map> @@ -125,12 +121,42 @@ class StreetConverter : public Converter { std::map> &ramps_ref_map, const std::map &junctionNames); + // process end nodes + void process_way_end_nodes( + const std::filesystem::path &dir, const StreetConverter::TagData &data, + std::map + &way_end_points_map, + std::map> + &z_level_map, + osmium::io::Writer &writer); + + void process_way_end_nodes( + OGRFeatureUniquePtr &feat, const StreetConverter::TagData &data, + std::map + &way_end_points_map, + osmium::memory::Buffer &node_buffer); + + void process_way_end_node( + const osmium::Location &location, const StreetConverter::TagData &data, + std::map + &way_end_points_map, + osmium::memory::Buffer &node_buffer); + void - process_way(const std::filesystem::path &dirs, + process_way(const std::filesystem::path &dir, + const StreetConverter::TagData &data, + std::map + &way_end_points_map, + std::map, + osmium::unsigned_object_id_type> &z_lvl_nodes_map, std::map> &z_level_map, osmium::io::Writer &writer); void - process_way(OGRFeatureUniquePtr &feat, + process_way(OGRFeatureUniquePtr &feat, const StreetConverter::TagData &data, + std::map + &way_end_points_map, + std::map, + osmium::unsigned_object_id_type> &z_lvl_nodes_map, std::map> &z_level_map, osmium::memory::Buffer &node_buffer, osmium::memory::Buffer &way_buffer); @@ -143,9 +169,12 @@ class StreetConverter : public Converter { osmium::unsigned_object_id_type build_way( OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, std::map &node_ref_map, + const StreetConverter::TagData &data, + std::map + &way_end_points_map, osmium::memory::Buffer &way_buffer, bool is_sub_linestring, short z_lvl); - uint64_t build_tag_list(OGRFeatureUniquePtr &feat, + uint64_t build_tag_list(OGRFeatureUniquePtr &feat, const TagData &data, osmium::builder::Builder &builder, short z_level); uint64_t parse_street_tags( @@ -161,8 +190,10 @@ class StreetConverter : public Converter { const std::map> &names_map, bool debugMode); - std::map> - init_highway_names(const std::filesystem::path &dir); + void set_ferry_z_lvls_to_zero(const OGRFeatureUniquePtr &feat, + std::vector &z_lvl_vec); + + void test__z_lvl_range(short z_lvl); void parse_highway_names( const std::filesystem::path &dbf_file, @@ -182,18 +213,28 @@ class StreetConverter : public Converter { void process_end_point( bool first, short z_lvl, OGRLineString *ogr_ls, std::map &node_ref_map, + std::map + &way_end_points_map, + std::map, + osmium::unsigned_object_id_type> &z_lvl_nodes_map, osmium::memory::Buffer &node_buffer); void split_way_by_z_level( OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, const std::vector &node_z_level_vector, std::map &node_ref_map, + const StreetConverter::TagData &data, + std::map + &way_end_points_map, uint64_t link_id, osmium::memory::Buffer &way_buffer); void build_sub_way_by_index( OGRFeatureUniquePtr &feat, OGRLineString *ogr_ls, ushort start_index, ushort end_index, std::map &node_ref_map, + const StreetConverter::TagData &data, + std::map + &way_end_points_map, osmium::memory::Buffer &way_buffer, short z_lvl); ushort create_continuing_sub_ways( @@ -201,6 +242,9 @@ class StreetConverter : public Converter { ushort start_index, ushort last_index, uint link_id, const std::vector &node_z_level_vector, std::map &node_ref_map, + const StreetConverter::TagData &data, + std::map + &way_end_points_map, osmium::memory::Buffer &way_buffer); bool is_imperial(uint64_t l_area_id, uint64_t r_area_id, diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 5439c64..ce0cbb3 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -75,14 +75,15 @@ static constexpr std::array speed_cat_metric{ "", ">130", "101-130", "91-100", "71-90", "51-70", "31-50", "11-30", "<11"}; uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, + const TagData &data, osmium::builder::Builder &builder, short z_level) { osmium::builder::TagListBuilder tl_builder(builder); - uint64_t link_id = parse_street_tags( - tl_builder, feat, &g_cdms_map, &g_cnd_mod_map, &g_area_to_govt_code_map, - &g_cntry_ref_map, &g_mtd_area_map, &g_route_type_map, &g_hwys_ref_map, - debugMode); + uint64_t link_id = + parse_street_tags(tl_builder, feat, data.cdms_map, data.cnd_mod_map, + data.area_govt_map, data.cntry_map, &g_mtd_area_map, + data.route_type_map, data.highway_names, debugMode); if (z_level != -5 && z_level != 0) tl_builder.add_tag("layer", std::to_string(z_level)); @@ -129,10 +130,13 @@ uint64_t StreetConverter::parse_street_tags( // get under construction condition auto itPair = cdms_map.equal_range(link_id); - bool underConstruction = - (std::find_if(itPair.first, itPair.second, [&](cond_type &cndt) { - return cndt.cond_type_type == CT_CONSTRUCTION_STATUS_CLOSED; - }) != itPair.second); + bool underConstruction = false; + for (auto i = itPair.first; i != itPair.second; ++i) { + if (i->second.cond_type_type == CT_CONSTRUCTION_STATUS_CLOSED) { + underConstruction = true; + break; + } + } add_highway_tags(builder, f, route_type, mtd_area_map, ref_name, underConstruction); From 82bcd5d9dbac4969f2b30489d8d4df3bc11c1c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 10:01:09 +0000 Subject: [PATCH 42/57] finished refactoring --- plugins/navteq/converter/Converter.hpp | 6 ++++-- plugins/navteq/converter/StreetConverter.cpp | 4 +++- plugins/navteq/converter/StreetConverter.hpp | 4 ++-- plugins/navteq/converter/StreetConverterOSMTagger.cpp | 10 ++++------ 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 0bf77a0..43b640b 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -49,8 +49,8 @@ class OGRLinearRing; class Converter { public: - Converter(const std::filesystem::path &_executable_path) - : executable_path(_executable_path) {} + Converter(const std::filesystem::path &_executable_path, bool _debug = false) + : debugMode(_debug), executable_path(_executable_path) {} virtual ~Converter() {} virtual void convert(const std::filesystem::path &dir, @@ -202,6 +202,8 @@ class Converter { static constexpr int NAVTEQ_ADMIN_LVL_MIN = 1; static constexpr int NAVTEQ_ADMIN_LVL_MAX = 7; + bool debugMode; + private: static std::map lang_code_map; std::filesystem::path executable_path; diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index aa53a4b..e12bf2e 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -54,10 +54,12 @@ void StreetConverter::convert(const std::filesystem::path &dir, BOOST_LOG_TRIVIAL(info) << " processing highway names"; auto hwys_ref_map = init_highway_names(dir); + auto mtd_area = process_meta_areas(dir); + // fill data struct for tag processing TagData data = {route_type_map, cnd_mod_map, cdms_map, area_to_govt_code_map, cntry_ref_map, ramps_ref_map, - hwys_ref_map}; + hwys_ref_map, mtd_area}; BOOST_LOG_TRIVIAL(info) << " processing z-levels"; auto z_level_map = init_z_level_map(dir); diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index a4719df..8db7317 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -85,6 +85,7 @@ class StreetConverter : public Converter { std::map cntry_map; std::map> ramp_names; std::map> highway_names; + std::map mtd_area; }; private: @@ -187,8 +188,7 @@ class StreetConverter : public Converter { const std::map &mtd_area_map, const std::map &route_type_map, - const std::map> &names_map, - bool debugMode); + const std::map> &names_map); void set_ferry_z_lvls_to_zero(const OGRFeatureUniquePtr &feat, std::vector &z_lvl_vec); diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index ce0cbb3..4f6408a 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -80,10 +80,9 @@ uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, short z_level) { osmium::builder::TagListBuilder tl_builder(builder); - uint64_t link_id = - parse_street_tags(tl_builder, feat, data.cdms_map, data.cnd_mod_map, - data.area_govt_map, data.cntry_map, &g_mtd_area_map, - data.route_type_map, data.highway_names, debugMode); + uint64_t link_id = parse_street_tags( + tl_builder, feat, data.cdms_map, data.cnd_mod_map, data.area_govt_map, + data.cntry_map, data.mtd_area, data.route_type_map, data.highway_names); if (z_level != -5 && z_level != 0) tl_builder.add_tag("layer", std::to_string(z_level)); @@ -103,8 +102,7 @@ uint64_t StreetConverter::parse_street_tags( const std::map &mtd_area_map, const std::map &route_type_map, - const std::map> &names_map, - bool debugMode) { + const std::map> &names_map) { const char *link_id_s = get_field_from_feature(f, LINK_ID); uint64_t link_id = std::stoul(link_id_s); From 77c4b4050ec5e607f3b9f3036353b2292af84ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 10:18:47 +0000 Subject: [PATCH 43/57] fix error --- plugins/navteq/converter/Converter.cpp | 15 +++--- plugins/navteq/converter/StreetConverter.cpp | 48 +++++++++++-------- .../converter/StreetConverterOSMTagger.cpp | 5 +- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index b0ca773..673e913 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -381,7 +381,8 @@ Converter::openDataSource(const std::filesystem::path &shape_file) { auto ds = GDALDatasetUniquePtr(GDALDataset::Open(shape_file_str.c_str())); if (!ds) { - BOOST_LOG_TRIVIAL(debug) << "No shp found in " << shape_file; + if (debugMode) + BOOST_LOG_TRIVIAL(debug) << "No shp found in " << shape_file; return nullptr; } @@ -439,14 +440,10 @@ const char *Converter::get_field_from_feature(const OGRFeatureUniquePtr &feat, */ uint64_t Converter::get_uint_from_feature(const OGRFeatureUniquePtr &feat, const std::string_view &field) { - const char *value = get_field_from_feature(feat, field.data()); - assert(value); - try { - return std::stoul(value); - } catch (const std::invalid_argument &) { - throw format_error("Could not parse field='" + std::string(field) + - "' with value='" + std::string(value) + "'"); - } + int field_index = feat->GetFieldIndex(field.data()); + if (field_index == -1) + BOOST_LOG_TRIVIAL(error) << field << std::endl; + return feat->GetFieldAsInteger64(field_index); } bool Converter::string_is_unsigned_integer(const std::string &s) { diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index e12bf2e..80500b3 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -671,10 +671,11 @@ void StreetConverter::split_way_by_z_level( if (first_index != start_index) { build_sub_way_by_index(feat, ogr_ls, first_index, start_index, node_ref_map, data, way_end_points_map, way_buffer, 0); - BOOST_LOG_TRIVIAL(debug) - << " 1 ## " << link_id << " ## " << first_index << "/" << last_index - << " - " << start_index << "/" << last_index << ": \tz_lvl=" << 0 - << std::endl; + if (debugMode) + BOOST_LOG_TRIVIAL(debug) + << " 1 ## " << link_id << " ## " << first_index << "/" << last_index + << " - " << start_index << "/" << last_index << ": \tz_lvl=" << 0 + << std::endl; } start_index = create_continuing_sub_ways( @@ -684,10 +685,11 @@ void StreetConverter::split_way_by_z_level( if (start_index < last_index) { build_sub_way_by_index(feat, ogr_ls, start_index, last_index, node_ref_map, data, way_end_points_map, way_buffer, 0); - BOOST_LOG_TRIVIAL(debug) - << " 4 ## " << link_id << " ## " << start_index << "/" << last_index - << " - " << last_index << "/" << last_index << ": \tz_lvl=" << 0 - << std::endl; + if (debugMode) + BOOST_LOG_TRIVIAL(debug) + << " 4 ## " << link_id << " ## " << start_index << "/" << last_index + << " - " << last_index << "/" << last_index << ": \tz_lvl=" << 0 + << std::endl; } } @@ -732,11 +734,13 @@ ushort StreetConverter::create_continuing_sub_ways( next_z_lvl = next_it->z_level; test__z_lvl_range(next_z_lvl); } - BOOST_LOG_TRIVIAL(debug) - << "first_index=" << first_index << " " - << "start_index=" << start_index << " " << "last_index=" << last_index - << " " << "index=" << index << " " << "z_lvl=" << z_lvl << " " - << "next_z_lvl=" << next_z_lvl << std::endl; + if (debugMode) + BOOST_LOG_TRIVIAL(debug) + << "first_index=" << first_index << " " + << "start_index=" << start_index << " " + << "last_index=" << last_index << " " << "index=" << index << " " + << "z_lvl=" << z_lvl << " " << "next_z_lvl=" << next_z_lvl + << std::endl; if (not_last_element) { if (index + 2 == next_index && z_lvl == next_z_lvl) @@ -764,10 +768,11 @@ ushort StreetConverter::create_continuing_sub_ways( to = std::min((ushort)(index + 1), last_index); else to = index; - BOOST_LOG_TRIVIAL(debug) - << " 2 ## " << link_id << " ## " << from << "/" << last_index - << " - " << to << "/" << last_index << ": \tz_lvl=" << z_lvl - << std::endl; + if (debugMode) + BOOST_LOG_TRIVIAL(debug) + << " 2 ## " << link_id << " ## " << from << "/" << last_index + << " - " << to << "/" << last_index << ": \tz_lvl=" << z_lvl + << std::endl; if (from < to) { build_sub_way_by_index(feat, ogr_ls, from, to, node_ref_map, data, way_end_points_map, way_buffer, z_lvl); @@ -777,10 +782,11 @@ ushort StreetConverter::create_continuing_sub_ways( if (not_last_element && to < next_index - 1) { build_sub_way_by_index(feat, ogr_ls, to, next_index - 1, node_ref_map, data, way_end_points_map, way_buffer); - BOOST_LOG_TRIVIAL(debug) - << " 3 ## " << link_id << " ## " << to << "/" << last_index - << " - " << next_index - 1 << "/" << last_index - << ": \tz_lvl=" << 0 << std::endl; + if (debugMode) + BOOST_LOG_TRIVIAL(debug) + << " 3 ## " << link_id << " ## " << to << "/" << last_index + << " - " << next_index - 1 << "/" << last_index + << ": \tz_lvl=" << 0 << std::endl; start_index = next_index - 1; } } diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 4f6408a..5af8b5f 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -328,8 +328,9 @@ void StreetConverter::add_one_way_tag(osmium::builder::TagListBuilder &builder, builder.add_tag("oneway", "-1"); // todo reverse way instead using "-1" else if (!strcmp(value, "B")) // B --> BOTH ways are allowed return; - throw( - format_error("value '" + std::string(value) + "' for oneway not valid")); + else + throw(format_error("value '" + std::string(value) + + "' for oneway not valid")); } void StreetConverter::add_access_tags(osmium::builder::TagListBuilder &builder, From 3f7dd967eba14f4276727f0d5803fdfa6d1e2b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 10:54:18 +0000 Subject: [PATCH 44/57] fix error with ramp names --- plugins/navteq/converter/StreetConverter.cpp | 27 ++++++++++---------- plugins/navteq/converter/StreetConverter.hpp | 7 ++--- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 80500b3..e66502d 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -338,20 +338,21 @@ void StreetConverter::process_way_end_node( // add ramp tags auto ramp = data.ramp_names.find(location); if (ramp != data.ramp_names.end()) { - if (ramp->second.find(0) != ramp->second.end()) { - osmium::builder::TagListBuilder tglBuilder(builder); - tglBuilder.add_tag(HIGHWAY.data(), "motorway_junction"); - tglBuilder.add_tag("ref", ramp->second.at(0)); - tglBuilder.add_tag("name", to_camel_case_with_spaces(ramp->second.at(1))); - } + auto &[exitName, junctionName] = ramp->second; + osmium::builder::TagListBuilder tglBuilder(builder); + tglBuilder.add_tag(HIGHWAY.data(), "motorway_junction"); + tglBuilder.add_tag("ref", exitName); + if (!junctionName.empty()) + tglBuilder.add_tag("name", junctionName); } way_end_points_map.emplace(location, osm_id); } -std::map> +std::map> StreetConverter::init_ramp_names(const std::filesystem::path &dir) { - std::map> ramps_ref_map; + std::map> + ramps_ref_map; // read junction names from alt_streets auto junctionMap = read_junction_names(dir / ALT_STREETS_DBF); @@ -386,7 +387,8 @@ StreetConverter::read_junction_names(const std::filesystem::path &dbf_file) { void StreetConverter::parse_ramp_names( const std::filesystem::path &shp_file, - std::map> &ramps_ref_map, + std::map> + &ramps_ref_map, const std::map &junctionNames) { auto ds = openDataSource(shp_file); @@ -419,13 +421,12 @@ void StreetConverter::parse_ramp_names( if (parse_bool(feat->GetFieldAsString(exitNameField))) { std::string exitName = feat->GetFieldAsString(baseNameField); - // add exit name - ramps_ref_map[location].emplace(0, exitName); - // add junction name auto it = junctionNames.find(feat->GetFieldAsInteger(linkIdField)); if (it != junctionNames.end()) { - ramps_ref_map[location].emplace(1, it->second); + ramps_ref_map.emplace(location, std::make_tuple(exitName, it->second)); + } else { + ramps_ref_map.emplace(location, std::make_tuple(exitName, "")); } } } diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index 8db7317..d6243e0 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -83,7 +83,7 @@ class StreetConverter : public Converter { std::multimap cdms_map; std::map area_govt_map; std::map cntry_map; - std::map> ramp_names; + std::map> ramp_names; std::map> highway_names; std::map mtd_area; }; @@ -113,13 +113,14 @@ class StreetConverter : public Converter { init_highway_names(const std::filesystem::path &dir); // ramp names - std::map> + std::map> init_ramp_names(const std::filesystem::path &dir); std::map read_junction_names(const std::filesystem::path &dbf_file); void parse_ramp_names( const std::filesystem::path &shp_file, - std::map> &ramps_ref_map, + std::map> + &ramps_ref_map, const std::map &junctionNames); // process end nodes From dcc1c89fb5b0f17e9179502d3751fcb0d88a7e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 11:12:46 +0000 Subject: [PATCH 45/57] use global endpoint map --- plugins/navteq/converter/StreetConverter.cpp | 4 ---- plugins/navteq/converter/StreetConverter.hpp | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index e66502d..eb3d5b8 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -33,10 +33,6 @@ StreetConverter::~StreetConverter() {} void StreetConverter::convert(const std::filesystem::path &dir, osmium::io::Writer &writer) { - // should be global for connectivity between regions - std::map - g_way_end_points_map; - BOOST_LOG_TRIVIAL(info) << " processing alt_streets route types"; auto route_type_map = process_alt_steets_route_types(dir); diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index d6243e0..5438d81 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -402,6 +402,10 @@ class StreetConverter : public Converter { const ushort CT_RESTRICTED_DRIVING_MANOEUVRE = 7; const ushort CT_TRANSPORT_ACCESS_RESTRICTION = 23; const ushort CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE = 26; + + // should be global for connectivity between regions + std::map + g_way_end_points_map; }; #endif // STREETCONVERTER_HPP From 0333ebf1fab3d3bec5d4791741f8a9b76af07090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 12:49:10 +0000 Subject: [PATCH 46/57] add country codes --- plugins/navteq/navteq_plugin.hpp | 58 ++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index b75152d..c92dac5 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -44,8 +44,62 @@ class navteq_plugin : public base_plugin { bool debug; const std::map HERE_REGION_ISO_MAPPING = { - {"M2", "SLO"}, {"M3", "ALB"}, {"M4", "MKD"}, {"M5", "SRB"}, - {"M6", "BIH"}, {"M7", "BLR"}, {"M9", "MLT"}}; + {"A1", "AUT"}, // Austria + {"A9", "GRC"}, {"GK", "GRC"}, // Greece + {"T1", "TUR"}, {"T3", "TUR"}, {"T4", "TUR"}, {"T5", "TUR"}, + {"T6", "TUR"}, {"T7", "TUR"}, // Turkey + {"AB", "AZE"}, // Azerbaijan + {"BB", "BEL"}, // Belgium + {"C1", "CZE"}, {"C4", "CZE"}, // Czechia + {"CA", "CHE"}, // Switzerland + {"E7", "IRL"}, // Ireland + {"E1", "GBR"}, {"E2", "GBR"}, {"E3", "GBR"}, {"E4", "GBR"}, + {"E5", "GBR"}, {"E6", "GBR"}, // Great britain + {"F1", "FRA"}, {"F2", "FRA"}, {"F3", "FRA"}, {"F4", "FRA"}, + {"F5", "FRA"}, {"F6", "FRA"}, // France + {"SP", "FIN"}, {"SQ", "FIN"}, {"SU", "FIN"}, {"SV", "FIN"}, // Finland + {"G1", "DEU"}, {"G2", "DEU"}, {"G3", "DEU"}, {"G4", "DEU"}, + {"G5", "DEU"}, {"G6", "DEU"}, {"G7", "DEU"}, {"G8", "DEU"}, // Germany + {"H1", "HUN"}, // Hungary + {"H2", "HRV"}, // Croatia + {"H3", "SVN"}, // Slovenia + {"H4", "EST"}, // Estonia + {"H5", "LVA"}, // Latvia + {"H6", "LTU"}, // Lithuania + {"H7", "BGR"}, // Bulgaria + {"H8", "ROU"}, // Rumania + {"H9", "MDA"}, // Moldova + {"I1", "ITA"}, {"I2", "ITA"}, {"I3", "ITA"}, {"I4", "ITA"}, + {"I5", "ITA"}, // Italy + {"K4", "PRT"}, {"K6", "PRT"}, {"K8", "PRT"}, // Portugal + {"K1", "ESP"}, {"K2", "ESP"}, {"K3", "ESP"}, {"K5", "ESP"}, + {"K7", "ESP"}, {"K9", "ESP"}, // Spain + {"KT", "SRB"}, // Kosovo + {"C5", "CYP"}, {"KQ", "CYP"}, // cyprus + {"LU", "LUX"}, // Luxembourg + {"MK", "MNE"}, // Montenegro + {"M2", "SVK"}, // Slovakia + {"M3", "ALB"}, // Albania + {"M4", "MKD"}, // Macedonia + {"M5", "SRB"}, // Serbia + {"M6", "BIH"}, // Bosnia and Herzegovina + {"M7", "BLR"}, // Belarus + {"M9", "MLT"}, // Malta + {"N1", "NOR"}, // Norway + {"N2", "ISL"}, // Iceland + {"N7", "NLD"}, {"NL", "NLD"}, // Netherland + {"P1", "POL"}, {"P2", "POL"}, {"P3", "POL"}, // Poland + {"S1", "SWE"}, {"S2", "SWE"}, {"S3", "SWE"}, // Sweden + {"S4", "DNK"}, // Denmark + {"U1", "UKR"}, {"U2", "UKR"}, {"U3", "UKR"}, {"U4", "UKR"}, + {"U6", "UKR"}, {"UR", "UKR"}, // Ukraine + {"4A", "RUS"}, {"4B", "RUS"}, {"4C", "RUS"}, {"4D", "RUS"}, + {"4E", "RUS"}, {"4F", "RUS"}, {"4G", "RUS"}, {"4H", "RUS"}, + {"4J", "RUS"}, {"R1", "RUS"}, {"R2", "RUS"}, {"R3", "RUS"}, + {"R4", "RUS"}, {"R5", "RUS"}, {"R6", "RUS"}, {"R7", "RUS"}, + {"R8", "RUS"}, {"R9", "RUS"}, {"RF", "RUS"}, {"RG", "RUS"}, + {"RH", "RUS"}, {"RK", "RUS"}, {"RZ", "RUS"} // Russia + }; public: navteq_plugin(const std::filesystem::path &executable_path); From bacc45e0a89447b4b7600136818961a4f3974d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 12:57:30 +0000 Subject: [PATCH 47/57] fix query --- .vscode/launch.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 54a3911..00b2bbc 100755 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,8 +18,8 @@ "MIMode": "gdb", "args": [ //"--bb=-25.0 32.9 31.4 71.7", - "--countries=ALB AND AUT BEL BGR BIH BLR CHE CYP CZE DEU DNK ESP EST FIN FRA FRO GBR GIB GRC GRL HRV HUN IMN IRL ISL ITA KOS LIE LTU LUX LVA MCO MDA MKD MLT MNE NCY NLD NOR POL PRT ROU SJM SMR SRB SVK SVN SWE VAT", - "/here-europe", + "--countries=ALB AUT BEL BGR BIH BLR CHE CYP CZE DEU DNK ESP EST FIN FRA GBR GRC HRV HUN IRL ISL ITA LTU LUX LVA MDA MKD MLT MNE NLD NOR POL PRT ROU SRB SVK SVN SWE ", + "${workspaceFolder}/here-data", "build/europa.osm.pbf" ] }, From b964facdd306332caab22fe0675a58f4aa645b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 13:01:04 +0000 Subject: [PATCH 48/57] add missing region --- plugins/navteq/navteq_plugin.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/navteq/navteq_plugin.hpp b/plugins/navteq/navteq_plugin.hpp index c92dac5..7a3f9c1 100644 --- a/plugins/navteq/navteq_plugin.hpp +++ b/plugins/navteq/navteq_plugin.hpp @@ -56,7 +56,7 @@ class navteq_plugin : public base_plugin { {"E1", "GBR"}, {"E2", "GBR"}, {"E3", "GBR"}, {"E4", "GBR"}, {"E5", "GBR"}, {"E6", "GBR"}, // Great britain {"F1", "FRA"}, {"F2", "FRA"}, {"F3", "FRA"}, {"F4", "FRA"}, - {"F5", "FRA"}, {"F6", "FRA"}, // France + {"F5", "FRA"}, {"F6", "FRA"}, {"F7", "FRA"}, // France {"SP", "FIN"}, {"SQ", "FIN"}, {"SU", "FIN"}, {"SV", "FIN"}, // Finland {"G1", "DEU"}, {"G2", "DEU"}, {"G3", "DEU"}, {"G4", "DEU"}, {"G5", "DEU"}, {"G6", "DEU"}, {"G7", "DEU"}, {"G8", "DEU"}, // Germany From 2b77804b118e6640ff7f7b39bd7904f6b9253b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Wed, 17 Jul 2024 15:02:02 +0000 Subject: [PATCH 49/57] chore: Store considered conditional modifications in cdms_map --- plugins/navteq/converter/StreetConverter.cpp | 5 ++++- plugins/navteq/converter/StreetConverterOSMTagger.cpp | 5 ----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index eb3d5b8..4df09b7 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -213,7 +213,10 @@ StreetConverter::init_g_cdms_map(const std::filesystem::path &dir) { uint64_t cond_id = get_uint_from_feature(feat, COND_ID); ushort cond_type = get_uint_from_feature(feat, COND_TYPE); - cdms_map.emplace(link_id, StreetConverter::cond_type{cond_id, cond_type}); + // only store considered conditional modifications + if (cond_type == CT_TRANSPORT_ACCESS_RESTRICTION) { + cdms_map.emplace(link_id, StreetConverter::cond_type{cond_id, cond_type}); + } } return cdms_map; diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 5af8b5f..4e9ff89 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -642,11 +642,6 @@ void StreetConverter::add_additional_restrictions( auto range = cdms_map.equal_range(link_id); for (auto it = range.first; it != range.second; ++it) { auto cond = it->second; - if (cond.cond_type_type == CT_RESTRICTED_DRIVING_MANOEUVRE || - cond.cond_type_type == CT_TRANSPORT_RESTRICTED_DRIVING_MANOEUVRE) - continue; // TODO RESTRICTED_DRIVING_MANOEUVRE should apply as - // conditional turn restriction but not for current link id - auto it2 = cnd_mod_map.find(cond.cond_id_type); if (it2 != cnd_mod_map.end()) { for (auto mod_group : it2->second) { From 8c63a355768b0edf5e66036544d75f71d9624431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Thu, 18 Jul 2024 19:28:56 +0000 Subject: [PATCH 50/57] ignore timerestrictions --- plugins/navteq/converter/StreetConverter.cpp | 81 +++++--- plugins/navteq/converter/StreetConverter.hpp | 44 ++-- .../converter/StreetConverterOSMTagger.cpp | 193 ++++++++++-------- plugins/navteq/navteq_plugin.cpp | 5 +- 4 files changed, 189 insertions(+), 134 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 4df09b7..2642829 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -37,8 +37,9 @@ void StreetConverter::convert(const std::filesystem::path &dir, auto route_type_map = process_alt_steets_route_types(dir); BOOST_LOG_TRIVIAL(info) << " processing conditional modifications "; - auto cdms_map = init_g_cdms_map(dir); - auto cnd_mod_map = init_g_cnd_mod_map(cdms_map, dir); + auto cdms_map = init_cdms_map(dir); + init_cnd_mod(cdms_map, dir); + init_cnd_dt_mod(cdms_map, dir); BOOST_LOG_TRIVIAL(info) << " processing country reference"; auto area_to_govt_code_map = init_g_area_to_govt_code_map(dir); @@ -53,9 +54,9 @@ void StreetConverter::convert(const std::filesystem::path &dir, auto mtd_area = process_meta_areas(dir); // fill data struct for tag processing - TagData data = {route_type_map, cnd_mod_map, cdms_map, - area_to_govt_code_map, cntry_ref_map, ramps_ref_map, - hwys_ref_map, mtd_area}; + TagData data = {route_type_map, cdms_map, area_to_govt_code_map, + cntry_ref_map, ramps_ref_map, hwys_ref_map, + mtd_area}; BOOST_LOG_TRIVIAL(info) << " processing z-levels"; auto z_level_map = init_z_level_map(dir); @@ -146,22 +147,19 @@ StreetConverter::init_z_level_map(const std::filesystem::path &dir) { return z_level_map; } -std::unordered_map> -StreetConverter::init_g_cnd_mod_map( - const std::multimap &cdms_map, +void StreetConverter::init_cnd_mod( + std::multimap &cdms_map, const std::filesystem::path &dir) { const std::filesystem::path CND_MOD_DBF = "CndMod.dbf"; - std::unordered_map> cnd_mod_map; - - std::set cond_ids; - for (const auto &[_, cond] : cdms_map) { - cond_ids.insert(cond.cond_id_type); + std::map conditions; + for (auto &entry : cdms_map) { + conditions.emplace(entry.second.cond_id_type, &entry.second); } auto ds = openDataSource(dir / CND_MOD_DBF); if (!ds) - return cnd_mod_map; + return; auto layer = ds->GetLayer(0); if (layer == nullptr) @@ -171,31 +169,51 @@ StreetConverter::init_g_cnd_mod_map( uint64_t cond_id = get_uint_from_feature(feat, COND_ID); // only process conditional modifications for the given cond_ids - if (cond_ids.find(cond_id) == cond_ids.end()) + auto it = conditions.find(cond_id); + if (it == conditions.end()) continue; std::string lang_code = get_field_from_feature(feat, LANG_CODE); uint64_t mod_type = get_uint_from_feature(feat, CM_MOD_TYPE); uint64_t mod_val = get_uint_from_feature(feat, CM_MOD_VAL); - auto it2 = cnd_mod_map.find(cond_id); - if (it2 == cnd_mod_map.end()) { - std::vector new_vector; - new_vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); - cnd_mod_map.emplace(cond_id, new_vector); - } else { - auto vector = it2->second; - cnd_mod_map.erase(it2); - vector.push_back(mod_group_type(mod_type, mod_val, lang_code)); - cnd_mod_map.emplace(cond_id, vector); - } + it->second->mod_group_map.emplace( + mod_type, mod_group_type(mod_type, mod_val, lang_code)); } +} + +void StreetConverter::init_cnd_dt_mod( + std::multimap &cdms_map, + const std::filesystem::path &dir) { + const std::filesystem::path CND_DT_MOD_DBF = "CdmsDtmod.dbf"; + + std::map conditions; + for (auto &entry : cdms_map) { + conditions.emplace(entry.second.cond_id_type, &entry.second); + } + + auto ds = openDataSource(dir / CND_DT_MOD_DBF); + if (!ds) + return; + + auto layer = ds->GetLayer(0); + if (layer == nullptr) + throw(shp_empty_error(dir / CND_DT_MOD_DBF)); - return cnd_mod_map; + for (auto &feat : *layer) { + uint64_t cond_id = get_uint_from_feature(feat, COND_ID); + + // only process conditional modifications for the given cond_ids + auto it = conditions.find(cond_id); + if (it == conditions.end()) + continue; + + it->second->dt_mod.hasDateTimeMod = true; + } } std::multimap -StreetConverter::init_g_cdms_map(const std::filesystem::path &dir) { +StreetConverter::init_cdms_map(const std::filesystem::path &dir) { std::multimap cdms_map; @@ -214,8 +232,11 @@ StreetConverter::init_g_cdms_map(const std::filesystem::path &dir) { ushort cond_type = get_uint_from_feature(feat, COND_TYPE); // only store considered conditional modifications - if (cond_type == CT_TRANSPORT_ACCESS_RESTRICTION) { - cdms_map.emplace(link_id, StreetConverter::cond_type{cond_id, cond_type}); + if (cond_type == CT_TRANSPORT_ACCESS_RESTRICTION || + cond_type == CT_CONSTRUCTION_STATUS_CLOSED || + cond_type == CT_TRANSPORT_SPECIAL_SPEED_SITUATION) { + cdms_map.emplace(link_id, + StreetConverter::cond_type{cond_id, cond_type, {}, {}}); } } diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index 5438d81..c4dc554 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -35,11 +35,6 @@ class StreetConverter : public Converter { short z_level; }; - struct cond_type { - uint64_t cond_id_type; - uint64_t cond_type_type; - }; - struct mod_group_type { std::string lang_code; uint64_t mod_type; @@ -52,6 +47,17 @@ class StreetConverter : public Converter { } }; + struct dateTimeMod { + bool hasDateTimeMod = false; + }; + + struct cond_type { + uint64_t cond_id_type; + uint64_t cond_type_type; + std::map mod_group_map; + dateTimeMod dt_mod; + }; + struct cntry_ref_type { std::string unit_measure; std::string speed_limit_unit; @@ -78,8 +84,7 @@ class StreetConverter : public Converter { struct TagData { std::map route_type_map; - std::unordered_map> - cnd_mod_map; + std::multimap cdms_map; std::map area_govt_map; std::map cntry_map; @@ -95,13 +100,16 @@ class StreetConverter : public Converter { std::map> init_z_level_map(const std::filesystem::path &dir); - std::unordered_map> - init_g_cnd_mod_map( - const std::multimap &cdms_map, - const std::filesystem::path &dir); + void + init_cnd_mod(std::multimap &cdms_map, + const std::filesystem::path &dir); + + void + init_cnd_dt_mod(std::multimap &cdms_map, + const std::filesystem::path &dir); std::multimap - init_g_cdms_map(const std::filesystem::path &dir); + init_cdms_map(const std::filesystem::path &dir); std::map init_g_area_to_govt_code_map(const std::filesystem::path &dir); @@ -117,6 +125,7 @@ class StreetConverter : public Converter { init_ramp_names(const std::filesystem::path &dir); std::map read_junction_names(const std::filesystem::path &dbf_file); + void parse_ramp_names( const std::filesystem::path &shp_file, std::map> @@ -182,8 +191,6 @@ class StreetConverter : public Converter { uint64_t parse_street_tags( osmium::builder::TagListBuilder &builder, OGRFeatureUniquePtr &f, const std::multimap &cdms_map, - const std::unordered_map> - &cnd_mod_map, const std::map &area_govt_map, const std::map &cntry_map, const std::map &cdms_map, - const std::unordered_map> - &cnd_mod_map, const std::map &area_govt_map, const std::map &cntry_map, const std::map diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 4e9ff89..1ba6bcc 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -20,6 +20,7 @@ #include // modifier types (MT) +const ushort MT_DIRECTION_CLOSURE = 38; const ushort MT_HAZARDOUS_RESTRICTION = 39; const ushort MT_HEIGHT_RESTRICTION = 41; const ushort MT_WEIGHT_RESTRICTION = 42; @@ -27,8 +28,6 @@ const ushort MT_WEIGHT_PER_AXLE_RESTRICTION = 43; const ushort MT_LENGTH_RESTRICTION = 44; const ushort MT_WIDTH_RESTRICTION = 45; -const ushort RESTRICTED_DRIVING_MANOEUVRE = 7; - const int INCH_BASE = 12; const int POUND_BASE = 2000; // short ton in metric tons (source: @@ -81,8 +80,8 @@ uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, osmium::builder::TagListBuilder tl_builder(builder); uint64_t link_id = parse_street_tags( - tl_builder, feat, data.cdms_map, data.cnd_mod_map, data.area_govt_map, - data.cntry_map, data.mtd_area, data.route_type_map, data.highway_names); + tl_builder, feat, data.cdms_map, data.area_govt_map, data.cntry_map, + data.mtd_area, data.route_type_map, data.highway_names); if (z_level != -5 && z_level != 0) tl_builder.add_tag("layer", std::to_string(z_level)); @@ -95,8 +94,6 @@ uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, uint64_t StreetConverter::parse_street_tags( osmium::builder::TagListBuilder &builder, OGRFeatureUniquePtr &f, const std::multimap &cdms_map, - const std::unordered_map> - &cnd_mod_map, const std::map &area_govt_map, const std::map &cntry_map, const std::map @@ -144,8 +141,7 @@ uint64_t StreetConverter::parse_street_tags( uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); // tags which apply to highways and ferry routes add_additional_restrictions(builder, link_id, l_area_id, r_area_id, cdms_map, - cnd_mod_map, area_govt_map, cntry_map, - mtd_area_map); + area_govt_map, cntry_map, mtd_area_map); // tag for debug purpose if (debugMode) { @@ -225,15 +221,13 @@ void StreetConverter::add_postcode_tag(osmium::builder::TagListBuilder &builder, void StreetConverter::add_maxspeed_tags( osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f) { - char *from_speed_limit_s = strdup(get_field_from_feature(f, FR_SPEED_LIMIT)); - char *to_speed_limit_s = strdup(get_field_from_feature(f, TO_SPEED_LIMIT)); uint from_speed_limit = get_uint_from_feature(f, FR_SPEED_LIMIT); uint to_speed_limit = get_uint_from_feature(f, TO_SPEED_LIMIT); if (from_speed_limit >= 1000 || to_speed_limit >= 1000) - throw(format_error("from_speed_limit='" + std::string(from_speed_limit_s) + - "' or to_speed_limit='" + std::string(to_speed_limit_s) + + throw(format_error("from_speed_limit='" + std::string(from_speed_limit) + + "' or to_speed_limit='" + std::string(to_speed_limit) + "' is not valid (>= 1000)")); // 998 is a ramp without speed limit information @@ -241,8 +235,10 @@ void StreetConverter::add_maxspeed_tags( return; // 999 means no speed limit at all - const char *from = from_speed_limit == 999 ? "none" : from_speed_limit_s; - const char *to = to_speed_limit == 999 ? "none" : to_speed_limit_s; + std::string from = + from_speed_limit == 999 ? "none" : std::to_string(from_speed_limit); + std::string to = + to_speed_limit == 999 ? "none" : std::to_string(to_speed_limit); if (from_speed_limit != 0 && to_speed_limit != 0) { if (from_speed_limit != to_speed_limit) { @@ -256,9 +252,6 @@ void StreetConverter::add_maxspeed_tags( } else if (from_speed_limit == 0 && to_speed_limit != 0) { builder.add_tag("maxspeed", to); } - - free(from_speed_limit_s); - free(to_speed_limit_s); } void StreetConverter::add_ferry_tag(osmium::builder::TagListBuilder &builder, @@ -619,91 +612,120 @@ void StreetConverter::add_additional_restrictions( osmium::builder::TagListBuilder &builder, uint64_t link_id, uint64_t l_area_id, uint64_t r_area_id, const std::multimap &cdms_map, - const std::unordered_map> - &cnd_mod_map, const std::map &area_govt_map, const std::map &cntry_map, const std::map &mtd_area_map) { - if (cdms_map.empty() || cnd_mod_map.empty()) + if (cdms_map.empty()) return; // default is metric units bool imperial_units = is_imperial(l_area_id, r_area_id, area_govt_map, cntry_map); - uint64_t max_height = 0; - uint64_t max_width = 0; - uint64_t max_length = 0; - uint64_t max_weight = 0; - uint64_t max_axleload = 0; - - std::vector mod_group_vector; auto range = cdms_map.equal_range(link_id); for (auto it = range.first; it != range.second; ++it) { - auto cond = it->second; - auto it2 = cnd_mod_map.find(cond.cond_id_type); - if (it2 != cnd_mod_map.end()) { - for (auto mod_group : it2->second) { - mod_group_vector.push_back(mod_group); + if (it->second.cond_type_type == CT_TRANSPORT_ACCESS_RESTRICTION) { + uint64_t max_height = 0; + uint64_t max_width = 0; + uint64_t max_length = 0; + uint64_t max_weight = 0; + uint64_t max_axleload = 0; + int direction = 0; // 1 = both, 2 = forward, 3 = backward + + if (it->second.dt_mod.hasDateTimeMod) { + BOOST_LOG_TRIVIAL(debug) + << "Skip Condition because of DateTimeMod for link_id " << link_id + << std::endl; + continue; } - } - } - for (auto mod_group : mod_group_vector) { - auto mod_type = mod_group.mod_type; - auto mod_val = mod_group.mod_val; - if (mod_type == MT_HEIGHT_RESTRICTION) { - if (!max_height || mod_val < max_height) - max_height = mod_val; - } else if (mod_type == MT_WIDTH_RESTRICTION) { - if (!max_width || mod_val < max_width) - max_width = mod_val; - } else if (mod_type == MT_LENGTH_RESTRICTION) { - if (!max_length || mod_val < max_length) - max_length = mod_val; - } else if (mod_type == MT_WEIGHT_RESTRICTION) { - if (!max_weight || mod_val < max_weight) - max_weight = mod_val; - } else if (mod_type == MT_WEIGHT_PER_AXLE_RESTRICTION) { - if (!max_axleload || mod_val < max_axleload) - max_axleload = mod_val; - } else if (mod_type == MT_HAZARDOUS_RESTRICTION) { - add_hazmat_tag(builder, mod_val); - } - } + for (auto mod_group : it->second.mod_group_map | std::views::values) { + auto mod_type = mod_group.mod_type; + auto mod_val = mod_group.mod_val; + if (mod_type == MT_HEIGHT_RESTRICTION) { + if (!max_height || mod_val < max_height) + max_height = mod_val; + } else if (mod_type == MT_WIDTH_RESTRICTION) { + if (!max_width || mod_val < max_width) + max_width = mod_val; + } else if (mod_type == MT_LENGTH_RESTRICTION) { + if (!max_length || mod_val < max_length) + max_length = mod_val; + } else if (mod_type == MT_WEIGHT_RESTRICTION) { + if (!max_weight || mod_val < max_weight) + max_weight = mod_val; + } else if (mod_type == MT_WEIGHT_PER_AXLE_RESTRICTION) { + if (!max_axleload || mod_val < max_axleload) + max_axleload = mod_val; + } else if (mod_type == MT_HAZARDOUS_RESTRICTION) { + add_hazmat_tag(builder, mod_val); + } else if (mod_type == MT_DIRECTION_CLOSURE) { + direction = mod_val; + } else { + if (debugMode) + BOOST_LOG_TRIVIAL(debug) + << "Unknown modifier type " << mod_type << " value " << mod_val + << " for Condition Type " << it->second.cond_type_type + << " for link_id " << link_id << std::endl; + } + } + + if (get_area_code_l(l_area_id, r_area_id, mtd_area_map) == 107) { + /** exceptional handling for Sweden as there are BK Roads + * + * HERE tags these roads with the most conservative values, + * which would make it unroutable for nearly every truck. + * Therefore we use the highest value and add a marker for BK2 / BK3 */ + if (max_weight == 16000 && max_axleload == 10000) { + builder.add_tag("maxweight:class", "BK2"); + max_weight = 51400; + } else if (max_weight == 12000 && max_axleload == 8000) { + builder.add_tag("maxweight:class", "BK3"); + max_weight = 37000; + } + } - if (get_area_code_l(l_area_id, r_area_id, mtd_area_map) == 107) { - /** exceptional handling for Sweden as there are BK Roads - * - * HERE tags these roads with the most conservative values, - * which would make it unroutable for nearly every truck. - * Therefore we use the highest value and add a marker for BK2 / BK3 */ - if (max_weight == 16000 && max_axleload == 10000) { - builder.add_tag("maxweight:class", "BK2"); - max_weight = 51400; - } else if (max_weight == 12000 && max_axleload == 8000) { - builder.add_tag("maxweight:class", "BK3"); - max_weight = 37000; + if (max_height > 0) + addRestrictionTag(builder, "maxheight", direction, imperial_units, + max_height); + if (max_width > 0) + addRestrictionTag(builder, "maxwidth", direction, imperial_units, + max_width); + if (max_length > 0) + addRestrictionTag(builder, "maxlength", direction, imperial_units, + max_length); + if (max_weight > 0) + addRestrictionTag(builder, "maxweight", direction, imperial_units, + max_weight); + if (max_axleload > 0) + addRestrictionTag(builder, "maxaxleload", direction, imperial_units, + max_weight); + + } else if (it->second.cond_type_type == + CT_TRANSPORT_SPECIAL_SPEED_SITUATION) { + + BOOST_LOG_TRIVIAL(debug) + << "Special speed situation detected for link_id " << link_id + << std::endl; } } +} - if (max_height > 0) - builder.add_tag("maxheight", imperial_units ? inch_to_feet(max_height) - : cm_to_m(max_height)); - if (max_width > 0) - builder.add_tag("maxwidth", imperial_units ? inch_to_feet(max_width) - : cm_to_m(max_width)); - if (max_length > 0) - builder.add_tag("maxlength", imperial_units ? inch_to_feet(max_length) - : cm_to_m(max_length)); - if (max_weight > 0) - builder.add_tag("maxweight", imperial_units ? lbs_to_metric_ton(max_weight) - : kg_to_t(max_weight)); - if (max_axleload > 0) - builder.add_tag("maxaxleload", imperial_units - ? lbs_to_metric_ton(max_axleload) - : kg_to_t(max_axleload)); +void StreetConverter::addRestrictionTag( + osmium::builder::TagListBuilder &builder, const std::string &restriction, + int direction, bool is_imperial_units, uint64_t max_value) { + { + std::string convertedValue = + is_imperial_units ? inch_to_feet(max_value) : cm_to_m(max_value); + + if (direction == 2) + builder.add_tag(restriction + ":forward", convertedValue); + else if (direction == 3) + builder.add_tag(restriction + ":backward", convertedValue); + else + builder.add_tag(restriction, convertedValue); + } } uint StreetConverter::get_number_after(const std::string &str, @@ -711,7 +733,8 @@ uint StreetConverter::get_number_after(const std::string &str, if (!str.starts_with(start_str)) return 0; /* doesn't start with start_str */ - /* Get number string after start_str until first non-digit appears */ + /* Get number string after start_str until first + * non-digit appears */ std::string end_str = str.substr(strlen(start_str)); std::string number_str; for (auto it = end_str.begin(); it != end_str.end(); ++it) { diff --git a/plugins/navteq/navteq_plugin.cpp b/plugins/navteq/navteq_plugin.cpp index c21961b..43e6063 100644 --- a/plugins/navteq/navteq_plugin.cpp +++ b/plugins/navteq/navteq_plugin.cpp @@ -174,9 +174,12 @@ void navteq_plugin::execute() { hdr.set("xml_josm_upload", "false"); osmium::io::Writer writer(outfile, hdr, osmium::io::overwrite::allow); + int i = 0; + // run converters for (auto &dir : dataDirs) { - BOOST_LOG_TRIVIAL(info) << "Processing " << dir; + BOOST_LOG_TRIVIAL(info) + << "Processing " << dir << " (" << ++i << "/" << dataDirs.size() << ")"; for (auto &c : converter) c->convert(dir, writer); } From a32d65159ca48df92ddfaba370a6824956db4764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 19 Jul 2024 08:14:26 +0000 Subject: [PATCH 51/57] fix country detection --- plugins/navteq/converter/Converter.cpp | 27 ----- plugins/navteq/converter/Converter.hpp | 8 -- plugins/navteq/converter/StreetConverter.cpp | 48 +++----- plugins/navteq/converter/StreetConverter.hpp | 48 ++++---- .../converter/StreetConverterOSMTagger.cpp | 106 +++++++++++------- 5 files changed, 104 insertions(+), 133 deletions(-) diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 673e913..4870011 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -342,33 +342,6 @@ Converter::process_meta_areas(std::filesystem::path dir) { return mtd_area_map; } -uint Converter::get_area_code_l( - uint64_t l_area_id, uint64_t r_area_id, - const std::map - &mtd_area_map) { - - auto l_area = mtd_area_map.find(l_area_id); - if (l_area != mtd_area_map.end()) - return l_area->second.area_code_1; - - auto r_area = mtd_area_map.find(r_area_id); - if (r_area != mtd_area_map.end()) - return r_area->second.area_code_1; - - throw(out_of_range_exception("could not find area_id " + - std::to_string(mtd_area_map.size()))); -} - -uint Converter::get_area_code_l( - const OGRFeatureUniquePtr &f, - const std::map - &mtd_area_map) { - uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); - uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); - - return get_area_code_l(l_area_id, r_area_id, mtd_area_map); -} - GDALDatasetUniquePtr Converter::openDataSource(const std::filesystem::path &shape_file) { diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index 43b640b..b146bc4 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -134,14 +134,6 @@ class Converter { std::map process_meta_areas(std::filesystem::path dir); - uint get_area_code_l(uint64_t l_area_id, uint64_t r_area_id, - const std::map &mtd_area_map); - - uint get_area_code_l(const OGRFeatureUniquePtr &f, - const std::map &mtd_area_map); - void parse_lang_code_file(); std::string parse_lang_code(std::string lang_code); diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 2642829..d29770a 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -42,8 +42,8 @@ void StreetConverter::convert(const std::filesystem::path &dir, init_cnd_dt_mod(cdms_map, dir); BOOST_LOG_TRIVIAL(info) << " processing country reference"; - auto area_to_govt_code_map = init_g_area_to_govt_code_map(dir); auto cntry_ref_map = init_g_cntry_ref_map(dir); + auto area_to_govt_code_map = init_g_area_to_govt_code_map(cntry_ref_map, dir); BOOST_LOG_TRIVIAL(info) << " processing ramps"; auto ramps_ref_map = init_ramp_names(dir); @@ -244,15 +244,16 @@ StreetConverter::init_cdms_map(const std::filesystem::path &dir) { } std::map StreetConverter::init_g_area_to_govt_code_map( + std::map &cntry_ref_map, const std::filesystem::path &dir) { - std::map area_to_govt_code_map; + std::map area_to_area_code_map; const std::filesystem::path MTD_AREA_DBF = "MtdArea.dbf"; auto ds = openDataSource(dir / MTD_AREA_DBF); if (!ds) - return area_to_govt_code_map; + return area_to_area_code_map; auto layer = ds->GetLayer(0); if (layer == nullptr) @@ -260,11 +261,20 @@ std::map StreetConverter::init_g_area_to_govt_code_map( for (auto &feat : *layer) { uint64_t area_id = get_uint_from_feature(feat, AREA_ID); + uint64_t areacode_1 = get_uint_from_feature(feat, AREA_CODE_1); uint64_t govt_code = get_uint_from_feature(feat, GOVT_CODE); - area_to_govt_code_map.emplace(area_id, govt_code); + + // found the area id of the admin 1 area + if (auto cntry_ref = cntry_ref_map.find(govt_code); + cntry_ref != cntry_ref_map.end()) { + // store the area code of the admin 1 area in cntry_ref_map + cntry_ref->second.area_code_1 = areacode_1; + } + + area_to_area_code_map.emplace(area_id, areacode_1); } - return area_to_govt_code_map; + return area_to_area_code_map; } std::map @@ -815,34 +825,6 @@ ushort StreetConverter::create_continuing_sub_ways( return start_index; } -bool StreetConverter::is_imperial( - uint64_t l_area_id, uint64_t r_area_id, - const std::map &area_govt_map, - const std::map &cntry_map) { - if (is_imperial(l_area_id, area_govt_map, cntry_map)) - return true; - if (is_imperial(r_area_id, area_govt_map, cntry_map)) - return true; - return false; -} - -bool StreetConverter::is_imperial( - uint64_t area_id, const std::map &area_govt_map, - const std::map &cntry_map) { - if (area_govt_map.find(area_id) != area_govt_map.end()) { - if (cntry_map.find(area_govt_map.at(area_id)) != cntry_map.end()) { - auto unit_measure = cntry_map.at(area_govt_map.at(area_id)).unit_measure; - if (unit_measure == "E") { - return true; - } else if (unit_measure != "M") { - format_error("unit_measure in navteq data is invalid: '" + - unit_measure + "'"); - } - } - } - return false; -} - void StreetConverter::set_ferry_z_lvls_to_zero( const OGRFeatureUniquePtr &feat, std::vector &z_lvl_vec) { diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index c4dc554..b42b1fa 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -62,6 +62,7 @@ class StreetConverter : public Converter { std::string unit_measure; std::string speed_limit_unit; std::string iso_code; + uint64_t area_code_1; cntry_ref_type() {} cntry_ref_type(const std::string &unit_measure, const std::string &speed_limit_unit, @@ -77,6 +78,8 @@ class StreetConverter : public Converter { return false; if (this->iso_code != rhs.iso_code) return false; + if (this->area_code_1 != rhs.area_code_1) + return false; return true; } bool operator!=(cntry_ref_type rhs) { return !(*this == rhs); } @@ -111,8 +114,9 @@ class StreetConverter : public Converter { std::multimap init_cdms_map(const std::filesystem::path &dir); - std::map - init_g_area_to_govt_code_map(const std::filesystem::path &dir); + std::map init_g_area_to_govt_code_map( + std::map &cntry_ref_map, + const std::filesystem::path &dir); std::map init_g_cntry_ref_map(const std::filesystem::path &dir); @@ -207,14 +211,11 @@ class StreetConverter : public Converter { const std::filesystem::path &dbf_file, std::map> &hwys_ref_map, bool isStreetLayer); + void add_additional_restrictions( osmium::builder::TagListBuilder &builder, uint64_t link_id, - uint64_t l_area_id, uint64_t r_area_id, const std::multimap &cdms_map, - const std::map &area_govt_map, - const std::map &cntry_map, - const std::map &mtd_area_map); + const cntry_ref_type &cntry_ref); void process_end_point( bool first, short z_lvl, OGRLineString *ogr_ls, @@ -253,30 +254,24 @@ class StreetConverter : public Converter { &way_end_points_map, osmium::memory::Buffer &way_buffer); - bool is_imperial(uint64_t l_area_id, uint64_t r_area_id, - const std::map &area_govt_map, - const std::map &cntry_map); + StreetConverter::cntry_ref_type + get_cntry_ref(const OGRFeatureUniquePtr &f, + const std::map &area_to_areacode1_map, + const std::map &cntry_map); - bool is_imperial(uint64_t area_id, - const std::map &area_govt_map, - const std::map &cntry_map); + bool is_imperial(const cntry_ref_type &cntry_ref); bool is_motorized_allowed(const OGRFeatureUniquePtr &f); - void - add_highway_tags(osmium::builder::TagListBuilder &builder, - const OGRFeatureUniquePtr &f, ushort route_type, - const std::map &mtd_area_map, - const std::string &ref_name, bool underConstruction); + void add_highway_tags(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f, ushort route_type, + const cntry_ref_type &cntry_ref, + const std::string &ref_name, bool underConstruction); - void - add_highway_tag(osmium::builder::TagListBuilder &builder, - const OGRFeatureUniquePtr &f, ushort route_type, - ushort func_class, - const std::map &mtd_area_map, - const std::string &ref_name, bool underConstruction); + void add_highway_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f, ushort route_type, + ushort func_class, const cntry_ref_type &cntry_ref, + const std::string &ref_name, bool underConstruction); std::string_view get_hwy_value(ushort route_type, ushort func_class, uint area_code_1, const std::string &ref_name, @@ -346,6 +341,7 @@ class StreetConverter : public Converter { static constexpr std::string_view POINT_NUM = "POINT_NUM"; static constexpr std::string_view GOVT_CODE = "GOVT_CODE"; + static constexpr std::string_view AREACODE_1 = "AREACODE_1"; // RDMS_DBF columns static constexpr std::string_view COND_ID = "COND_ID"; diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 1ba6bcc..7e85445 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -17,6 +17,7 @@ #include "StreetConverter.hpp" #include +#include #include // modifier types (MT) @@ -94,20 +95,22 @@ uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, uint64_t StreetConverter::parse_street_tags( osmium::builder::TagListBuilder &builder, OGRFeatureUniquePtr &f, const std::multimap &cdms_map, - const std::map &area_govt_map, + const std::map &area_to_areacode1_map, const std::map &cntry_map, const std::map &mtd_area_map, const std::map &route_type_map, const std::map> &names_map) { + cntry_ref_type cntry_ref = get_cntry_ref(f, area_to_areacode1_map, cntry_map); + const char *link_id_s = get_field_from_feature(f, LINK_ID); uint64_t link_id = std::stoul(link_id_s); bool ramp = parse_bool(get_field_from_feature(f, RAMP)); ushort route_type = 0; - if (!((std::string)get_field_from_feature(f, ROUTE)).empty()) + if (!(std::string(get_field_from_feature(f, ROUTE)).empty())) route_type = get_uint_from_feature(f, ROUTE); auto routeTypeIter = route_type_map.find(link_id); @@ -118,7 +121,6 @@ uint64_t StreetConverter::parse_street_tags( if (is_ferry(get_field_from_feature(f, FERRY))) { add_ferry_tag(builder, f); } else { // usual highways - // add tags for ref and int_ref to major highways std::string ref_name = add_highway_name_tags(builder, names_map, link_id, ramp); @@ -133,15 +135,12 @@ uint64_t StreetConverter::parse_street_tags( } } - add_highway_tags(builder, f, route_type, mtd_area_map, ref_name, + add_highway_tags(builder, f, route_type, cntry_ref, ref_name, underConstruction); } - uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); - uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); // tags which apply to highways and ferry routes - add_additional_restrictions(builder, link_id, l_area_id, r_area_id, cdms_map, - area_govt_map, cntry_map, mtd_area_map); + add_additional_restrictions(builder, link_id, cdms_map, cntry_ref); // tag for debug purpose if (debugMode) { @@ -160,7 +159,7 @@ uint64_t StreetConverter::parse_street_tags( if (!func_class.empty()) builder.add_tag("here:func_class", func_class.c_str()); - add_uint_tag(builder, "here:area_code", get_area_code_l(f, mtd_area_map)); + add_uint_tag(builder, "here:area_code", cntry_ref.area_code_1); } return link_id; } @@ -226,9 +225,9 @@ void StreetConverter::add_maxspeed_tags( uint to_speed_limit = get_uint_from_feature(f, TO_SPEED_LIMIT); if (from_speed_limit >= 1000 || to_speed_limit >= 1000) - throw(format_error("from_speed_limit='" + std::string(from_speed_limit) + - "' or to_speed_limit='" + std::string(to_speed_limit) + - "' is not valid (>= 1000)")); + throw(format_error(std::format( + "from_speed_limit='{}' or to_speed_limit='{}' is not valid (>= 1000)", + from_speed_limit, to_speed_limit))); // 998 is a ramp without speed limit information if (from_speed_limit == 998 || to_speed_limit == 998) @@ -274,23 +273,23 @@ void StreetConverter::add_ferry_tag(osmium::builder::TagListBuilder &builder, } else if (!strcmp(ferry, "R")) { builder.add_tag("railway", "ferry"); } else - throw(format_error("value '" + std::string(ferry) + "' for " + - std::string(FERRY) + " not valid")); + throw( + format_error(std::format("value '{}' for {} not valid", ferry, FERRY))); } -void StreetConverter::add_highway_tags( - osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, - ushort route_type, - const std::map - &mtd_area_map, - const std::string &ref_name, bool underConstruction) { +void StreetConverter::add_highway_tags(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f, + ushort route_type, + const cntry_ref_type &cntry_ref, + const std::string &ref_name, + bool underConstruction) { ushort func_class = 0; std::string func_class_s = get_field_from_feature(f, FUNC_CLASS); if (!func_class_s.empty()) func_class = get_uint_from_feature(f, FUNC_CLASS); - add_highway_tag(builder, f, route_type, func_class, mtd_area_map, ref_name, + add_highway_tag(builder, f, route_type, func_class, cntry_ref, ref_name, underConstruction); add_one_way_tag(builder, get_field_from_feature(f, DIR_TRAVEL)); @@ -478,12 +477,12 @@ void StreetConverter::add_hazmat_tag(osmium::builder::TagListBuilder &builder, } } -void StreetConverter::add_highway_tag( - osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, - ushort route_type, ushort func_class, - const std::map - &mtd_area_map, - const std::string &ref_name, bool underConstruction) { +void StreetConverter::add_highway_tag(osmium::builder::TagListBuilder &builder, + const OGRFeatureUniquePtr &f, + ushort route_type, ushort func_class, + const cntry_ref_type &cntry_ref, + const std::string &ref_name, + bool underConstruction) { bool paved = parse_bool(get_field_from_feature(f, PAVED)); bool motorized_allowed = is_motorized_allowed(f); @@ -514,7 +513,6 @@ void StreetConverter::add_highway_tag( bool controlled_access = parse_bool(get_field_from_feature(f, CONTRACC)); bool urban = parse_bool(get_field_from_feature(f, URBAN)); bool ramp = parse_bool(get_field_from_feature(f, RAMP)); - uint area_code_1 = get_area_code_l(f, mtd_area_map); if (controlled_access) { // controlled_access => motorway @@ -523,14 +521,14 @@ void StreetConverter::add_highway_tag( else builder.add_tag(highwayTagName, MOTORWAY.data()); } else if (func_class || route_type) { - std::string_view hwy_value = - get_hwy_value(route_type, func_class, area_code_1, ref_name, urban); + std::string_view hwy_value = get_hwy_value( + route_type, func_class, cntry_ref.area_code_1, ref_name, urban); if (!hwy_value.empty()) { builder.add_tag(highwayTagName, hwy_value.data()); } else { BOOST_LOG_TRIVIAL(error) << "ignoring highway_level'" << std::to_string(route_type) - << "' for " << area_code_1 << std::endl; + << "' for " << cntry_ref.area_code_1 << std::endl; } } else { BOOST_LOG_TRIVIAL(error) @@ -610,18 +608,13 @@ std::string_view StreetConverter::get_hwy_value(ushort route_type, void StreetConverter::add_additional_restrictions( osmium::builder::TagListBuilder &builder, uint64_t link_id, - uint64_t l_area_id, uint64_t r_area_id, const std::multimap &cdms_map, - const std::map &area_govt_map, - const std::map &cntry_map, - const std::map - &mtd_area_map) { + const cntry_ref_type &cntry_ref) { if (cdms_map.empty()) return; // default is metric units - bool imperial_units = - is_imperial(l_area_id, r_area_id, area_govt_map, cntry_map); + bool imperial_units = is_imperial(cntry_ref); auto range = cdms_map.equal_range(link_id); for (auto it = range.first; it != range.second; ++it) { @@ -671,7 +664,7 @@ void StreetConverter::add_additional_restrictions( } } - if (get_area_code_l(l_area_id, r_area_id, mtd_area_map) == 107) { + if (cntry_ref.area_code_1 == 107) { /** exceptional handling for Sweden as there are BK Roads * * HERE tags these roads with the most conservative values, @@ -750,4 +743,39 @@ uint StreetConverter::get_number_after(const std::string &str, } catch (const std::invalid_argument &) { return 0; } +} + +bool StreetConverter::is_imperial(const cntry_ref_type &cntry_ref) { + auto unit_measure = cntry_ref.unit_measure; + if (unit_measure == "E") { + return true; + } else if (unit_measure != "M") { + format_error("unit_measure in navteq data is invalid: '" + unit_measure + + "'"); + } + return false; +} + +StreetConverter::cntry_ref_type StreetConverter::get_cntry_ref( + const OGRFeatureUniquePtr &f, + const std::map &area_to_areacode1_map, + const std::map &cntry_map) { + uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); + if (auto l_area_iter = area_to_areacode1_map.find(l_area_id); + l_area_iter != area_to_areacode1_map.end()) { + if (auto l_cntry_ref = cntry_map.find(l_area_iter->second); + l_cntry_ref != cntry_map.end()) + return l_cntry_ref->second; + } + + uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); + if (auto r_area_iter = area_to_areacode1_map.find(r_area_id); + r_area_iter != area_to_areacode1_map.end()) { + if (auto r_cntry_ref = cntry_map.find(r_area_iter->second); + r_cntry_ref != cntry_map.end()) + return r_cntry_ref->second; + } + + throw format_error("cntry_ref not found for link_id " + + std::to_string(get_uint_from_feature(f, LINK_ID))); } \ No newline at end of file From db4ab84a354a2c74a809cbbef8a5b18d286826dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 19 Jul 2024 09:01:01 +0000 Subject: [PATCH 52/57] only consider adminlvl 1 for mapping aracoe to govcode --- plugins/navteq/converter/StreetConverter.cpp | 15 +++++++++-- plugins/navteq/converter/StreetConverter.hpp | 4 +-- .../converter/StreetConverterOSMTagger.cpp | 27 ++++++++++++------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index d29770a..9731452 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -260,15 +260,26 @@ std::map StreetConverter::init_g_area_to_govt_code_map( throw(shp_empty_error(dir / MTD_AREA_DBF)); for (auto &feat : *layer) { + std::string area_type = get_field_from_feature(feat, "AREA_TYPE"); + if (area_type != "B") + continue; + uint64_t area_id = get_uint_from_feature(feat, AREA_ID); uint64_t areacode_1 = get_uint_from_feature(feat, AREA_CODE_1); uint64_t govt_code = get_uint_from_feature(feat, GOVT_CODE); + uint64_t admin_level = get_uint_from_feature(feat, ADMIN_LVL); // found the area id of the admin 1 area if (auto cntry_ref = cntry_ref_map.find(govt_code); - cntry_ref != cntry_ref_map.end()) { + admin_level == 1 && cntry_ref != cntry_ref_map.end()) { // store the area code of the admin 1 area in cntry_ref_map - cntry_ref->second.area_code_1 = areacode_1; + if (cntry_ref->second.area_code_1 == 0) { + cntry_ref->second.area_code_1 = areacode_1; + } else if (cntry_ref->second.area_code_1 != areacode_1) { + BOOST_LOG_TRIVIAL(error) + << "Area code already set for govt code: " << govt_code << " old " + << cntry_ref->second.area_code_1 << " new " << areacode_1; + } } area_to_area_code_map.emplace(area_id, areacode_1); diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index b42b1fa..cc84a88 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -62,7 +62,7 @@ class StreetConverter : public Converter { std::string unit_measure; std::string speed_limit_unit; std::string iso_code; - uint64_t area_code_1; + uint64_t area_code_1 = 0; cntry_ref_type() {} cntry_ref_type(const std::string &unit_measure, const std::string &speed_limit_unit, @@ -197,8 +197,6 @@ class StreetConverter : public Converter { const std::multimap &cdms_map, const std::map &area_govt_map, const std::map &cntry_map, - const std::map &mtd_area_map, const std::map &route_type_map, const std::map> &names_map); diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 7e85445..8e80fe8 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -80,9 +80,9 @@ uint64_t StreetConverter::build_tag_list(OGRFeatureUniquePtr &feat, short z_level) { osmium::builder::TagListBuilder tl_builder(builder); - uint64_t link_id = parse_street_tags( - tl_builder, feat, data.cdms_map, data.area_govt_map, data.cntry_map, - data.mtd_area, data.route_type_map, data.highway_names); + uint64_t link_id = parse_street_tags(tl_builder, feat, data.cdms_map, + data.area_govt_map, data.cntry_map, + data.route_type_map, data.highway_names); if (z_level != -5 && z_level != 0) tl_builder.add_tag("layer", std::to_string(z_level)); @@ -97,8 +97,6 @@ uint64_t StreetConverter::parse_street_tags( const std::multimap &cdms_map, const std::map &area_to_areacode1_map, const std::map &cntry_map, - const std::map - &mtd_area_map, const std::map &route_type_map, const std::map> &names_map) { @@ -627,9 +625,10 @@ void StreetConverter::add_additional_restrictions( int direction = 0; // 1 = both, 2 = forward, 3 = backward if (it->second.dt_mod.hasDateTimeMod) { - BOOST_LOG_TRIVIAL(debug) - << "Skip Condition because of DateTimeMod for link_id " << link_id - << std::endl; + if (debugMode) + BOOST_LOG_TRIVIAL(debug) + << "Skip Condition because of DateTimeMod for link_id " << link_id + << std::endl; continue; } @@ -763,7 +762,11 @@ StreetConverter::cntry_ref_type StreetConverter::get_cntry_ref( uint64_t l_area_id = get_uint_from_feature(f, L_AREA_ID); if (auto l_area_iter = area_to_areacode1_map.find(l_area_id); l_area_iter != area_to_areacode1_map.end()) { - if (auto l_cntry_ref = cntry_map.find(l_area_iter->second); + if (auto l_cntry_ref = std::ranges::find_if( + cntry_map, + [l_area_iter](const auto &pair) { + return pair.second.area_code_1 == l_area_iter->second; + }); l_cntry_ref != cntry_map.end()) return l_cntry_ref->second; } @@ -771,7 +774,11 @@ StreetConverter::cntry_ref_type StreetConverter::get_cntry_ref( uint64_t r_area_id = get_uint_from_feature(f, R_AREA_ID); if (auto r_area_iter = area_to_areacode1_map.find(r_area_id); r_area_iter != area_to_areacode1_map.end()) { - if (auto r_cntry_ref = cntry_map.find(r_area_iter->second); + if (auto r_cntry_ref = std::ranges::find_if( + cntry_map, + [r_area_iter](const auto &pair) { + return pair.second.area_code_1 == r_area_iter->second; + }); r_cntry_ref != cntry_map.end()) return r_cntry_ref->second; } From 60c3db8f31ac75e95aced1a430475fd40c892c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Fri, 19 Jul 2024 11:19:51 +0000 Subject: [PATCH 53/57] cnsider MPH --- plugins/navteq/converter/StreetConverter.cpp | 5 +---- plugins/navteq/converter/StreetConverter.hpp | 4 ++-- .../converter/StreetConverterOSMTagger.cpp | 17 +++++++++++------ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index 9731452..ca6eeae 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -51,12 +51,9 @@ void StreetConverter::convert(const std::filesystem::path &dir, BOOST_LOG_TRIVIAL(info) << " processing highway names"; auto hwys_ref_map = init_highway_names(dir); - auto mtd_area = process_meta_areas(dir); - // fill data struct for tag processing TagData data = {route_type_map, cdms_map, area_to_govt_code_map, - cntry_ref_map, ramps_ref_map, hwys_ref_map, - mtd_area}; + cntry_ref_map, ramps_ref_map, hwys_ref_map}; BOOST_LOG_TRIVIAL(info) << " processing z-levels"; auto z_level_map = init_z_level_map(dir); diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index cc84a88..e87b2ec 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -93,7 +93,6 @@ class StreetConverter : public Converter { std::map cntry_map; std::map> ramp_names; std::map> highway_names; - std::map mtd_area; }; private: @@ -293,7 +292,8 @@ class StreetConverter : public Converter { const OGRFeatureUniquePtr &f); void add_maxspeed_tags(osmium::builder::TagListBuilder &builder, - const OGRFeatureUniquePtr &f); + const OGRFeatureUniquePtr &f, + const cntry_ref_type &cntry_ref); void add_lanes_tag(osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f); diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 8e80fe8..ce5d478 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -217,7 +217,8 @@ void StreetConverter::add_postcode_tag(osmium::builder::TagListBuilder &builder, } void StreetConverter::add_maxspeed_tags( - osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f) { + osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, + const cntry_ref_type &cntry_ref) { uint from_speed_limit = get_uint_from_feature(f, FR_SPEED_LIMIT); uint to_speed_limit = get_uint_from_feature(f, TO_SPEED_LIMIT); @@ -231,11 +232,15 @@ void StreetConverter::add_maxspeed_tags( if (from_speed_limit == 998 || to_speed_limit == 998) return; + bool mph = cntry_ref.speed_limit_unit == "MPH"; + // 999 means no speed limit at all - std::string from = - from_speed_limit == 999 ? "none" : std::to_string(from_speed_limit); - std::string to = - to_speed_limit == 999 ? "none" : std::to_string(to_speed_limit); + std::string from = from_speed_limit == 999 ? "none" + : mph ? std::format("{} mph", from_speed_limit) + : std::to_string(from_speed_limit); + std::string to = to_speed_limit == 999 ? "none" + : mph ? std::format("{} mph", to_speed_limit) + : std::to_string(to_speed_limit); if (from_speed_limit != 0 && to_speed_limit != 0) { if (from_speed_limit != to_speed_limit) { @@ -292,7 +297,7 @@ void StreetConverter::add_highway_tags(osmium::builder::TagListBuilder &builder, add_one_way_tag(builder, get_field_from_feature(f, DIR_TRAVEL)); add_access_tags(builder, f); - add_maxspeed_tags(builder, f); + add_maxspeed_tags(builder, f, cntry_ref); add_lanes_tag(builder, f); add_postcode_tag(builder, f); From ed9fb2ed74ca9a00c604798a691d9751c7cf638e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 22 Jul 2024 07:18:47 +0000 Subject: [PATCH 54/57] consider special speed limits --- plugins/navteq/converter/Converter.cpp | 8 + plugins/navteq/converter/Converter.hpp | 3 + plugins/navteq/converter/StreetConverter.cpp | 23 +- plugins/navteq/converter/StreetConverter.hpp | 17 +- .../converter/StreetConverterOSMTagger.cpp | 282 ++++++++++++------ 5 files changed, 232 insertions(+), 101 deletions(-) diff --git a/plugins/navteq/converter/Converter.cpp b/plugins/navteq/converter/Converter.cpp index 4870011..a2a6d13 100644 --- a/plugins/navteq/converter/Converter.cpp +++ b/plugins/navteq/converter/Converter.cpp @@ -419,6 +419,14 @@ uint64_t Converter::get_uint_from_feature(const OGRFeatureUniquePtr &feat, return feat->GetFieldAsInteger64(field_index); } +bool Converter::get_bool_from_feature(const OGRFeatureUniquePtr &feat, + const std::string_view &field) { + int field_index = feat->GetFieldIndex(field.data()); + if (field_index == -1) + BOOST_LOG_TRIVIAL(error) << field << std::endl; + return parse_bool(feat->GetFieldAsString(field_index)); +} + bool Converter::string_is_unsigned_integer(const std::string &s) { if (s.empty()) return false; diff --git a/plugins/navteq/converter/Converter.hpp b/plugins/navteq/converter/Converter.hpp index b146bc4..891a7c4 100644 --- a/plugins/navteq/converter/Converter.hpp +++ b/plugins/navteq/converter/Converter.hpp @@ -155,6 +155,9 @@ class Converter { uint64_t get_uint_from_feature(const OGRFeatureUniquePtr &feat, const std::string_view &field); + bool get_bool_from_feature(const OGRFeatureUniquePtr &feat, + const std::string_view &field); + bool string_is_unsigned_integer(const std::string &s); bool string_is_not_unsigned_integer(const std::string &s); diff --git a/plugins/navteq/converter/StreetConverter.cpp b/plugins/navteq/converter/StreetConverter.cpp index ca6eeae..8c644ce 100644 --- a/plugins/navteq/converter/StreetConverter.cpp +++ b/plugins/navteq/converter/StreetConverter.cpp @@ -224,17 +224,24 @@ StreetConverter::init_cdms_map(const std::filesystem::path &dir) { throw(shp_empty_error(dir / CDMS_DBF)); for (auto &feat : *layer) { - uint64_t link_id = get_uint_from_feature(feat, LINK_ID); - uint64_t cond_id = get_uint_from_feature(feat, COND_ID); + ushort cond_type = get_uint_from_feature(feat, COND_TYPE); // only store considered conditional modifications - if (cond_type == CT_TRANSPORT_ACCESS_RESTRICTION || - cond_type == CT_CONSTRUCTION_STATUS_CLOSED || - cond_type == CT_TRANSPORT_SPECIAL_SPEED_SITUATION) { - cdms_map.emplace(link_id, - StreetConverter::cond_type{cond_id, cond_type, {}, {}}); - } + if (cond_type != CT_TRANSPORT_ACCESS_RESTRICTION && + cond_type != CT_CONSTRUCTION_STATUS_CLOSED && + cond_type != CT_TRANSPORT_SPECIAL_SPEED_SITUATION) + continue; + + if (!need_to_consider(feat)) + continue; + + bool hgv_only = is_hgv_only(feat); + + uint64_t link_id = get_uint_from_feature(feat, LINK_ID); + uint64_t cond_id = get_uint_from_feature(feat, COND_ID); + cdms_map.emplace(link_id, StreetConverter::cond_type{ + cond_id, cond_type, hgv_only, {}, {}}); } return cdms_map; diff --git a/plugins/navteq/converter/StreetConverter.hpp b/plugins/navteq/converter/StreetConverter.hpp index e87b2ec..9ec0243 100644 --- a/plugins/navteq/converter/StreetConverter.hpp +++ b/plugins/navteq/converter/StreetConverter.hpp @@ -54,6 +54,7 @@ class StreetConverter : public Converter { struct cond_type { uint64_t cond_id_type; uint64_t cond_type_type; + bool only_hgv; std::map mod_group_map; dateTimeMod dt_mod; }; @@ -214,6 +215,16 @@ class StreetConverter : public Converter { const std::multimap &cdms_map, const cntry_ref_type &cntry_ref); + void addSpecialSpeedSituation( + std::multimap::const_iterator &it, + uint64_t link_id, const StreetConverter::cntry_ref_type &cntry_ref, + osmium::builder::TagListBuilder &builder, bool imperial_units); + + void addTransportAccessRestriction( + std::multimap::const_iterator &it, + osmium::builder::TagListBuilder &builder, uint64_t link_id, + const StreetConverter::cntry_ref_type &cntry_ref, bool imperial_units); + void process_end_point( bool first, short z_lvl, OGRLineString *ogr_ls, std::map &node_ref_map, @@ -260,6 +271,10 @@ class StreetConverter : public Converter { bool is_motorized_allowed(const OGRFeatureUniquePtr &f); + bool is_hgv_only(const OGRFeatureUniquePtr &f); + + bool need_to_consider(const OGRFeatureUniquePtr &f); + void add_highway_tags(osmium::builder::TagListBuilder &builder, const OGRFeatureUniquePtr &f, ushort route_type, const cntry_ref_type &cntry_ref, @@ -403,7 +418,7 @@ class StreetConverter : public Converter { // condition types (CT) const ushort CT_CONSTRUCTION_STATUS_CLOSED = 3; const ushort CT_TRANSPORT_ACCESS_RESTRICTION = 23; - const ushort CT_TRANSPORT_SPECIAL_SPEED_SITUATION = 24; + const ushort CT_TRANSPORT_SPECIAL_SPEED_SITUATION = 25; // should be global for connectivity between regions std::map diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index ce5d478..913ccb7 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -21,13 +21,22 @@ #include // modifier types (MT) -const ushort MT_DIRECTION_CLOSURE = 38; -const ushort MT_HAZARDOUS_RESTRICTION = 39; -const ushort MT_HEIGHT_RESTRICTION = 41; -const ushort MT_WEIGHT_RESTRICTION = 42; -const ushort MT_WEIGHT_PER_AXLE_RESTRICTION = 43; -const ushort MT_LENGTH_RESTRICTION = 44; -const ushort MT_WIDTH_RESTRICTION = 45; +const ushort MT_TA_DIRECTION_CLOSURE = 38; +const ushort MT_TA_HAZARDOUS_RESTRICTION = 39; +const ushort MT_TA_HEIGHT_RESTRICTION = 41; +const ushort MT_TA_WEIGHT_RESTRICTION = 42; +const ushort MT_TA_WEIGHT_PER_AXLE_RESTRICTION = 43; +const ushort MT_TA_LENGTH_RESTRICTION = 44; +const ushort MT_TA_WIDTH_RESTRICTION = 45; + +const ushort MT_SSS_SPEED_LIMIT = 48; +const ushort MT_SSS_SPEED_SITUATION_TYPE = 59; +const ushort MT_SSS_DIRECTION_CLOSURE = 60; +const ushort MT_SSS_WEIGHT_DEPENDENT = 61; +const ushort MT_SSS_WEATHER_TYPE = 62; +const ushort MT_SSS_SPEED_LIMIT_TYPE = 83; +const ushort MT_SSS_HAZARDOUS_DEPENDENT = 39; +const ushort MT_SSS_TRAILER_DEPENDENT = 46; const int INCH_BASE = 12; const int POUND_BASE = 2000; @@ -427,24 +436,39 @@ void StreetConverter::add_here_speed_cat_tag( } bool StreetConverter::is_motorized_allowed(const OGRFeatureUniquePtr &f) { - if (parse_bool(get_field_from_feature(f, AR_AUTO))) + if (get_bool_from_feature(f, AR_AUTO)) return true; - if (parse_bool(get_field_from_feature(f, AR_BUS))) + if (get_bool_from_feature(f, AR_TRUCKS)) return true; - if (parse_bool(get_field_from_feature(f, AR_TAXIS))) + if (get_bool_from_feature(f, AR_DELIV)) return true; - if (parse_bool(get_field_from_feature(f, AR_TRUCKS))) + if (get_bool_from_feature(f, AR_EMERVEH)) return true; - if (parse_bool(get_field_from_feature(f, AR_DELIV))) + if (get_bool_from_feature(f, AR_MOTORCYCLES)) return true; - if (parse_bool(get_field_from_feature(f, AR_EMERVEH))) + if (get_bool_from_feature(f, AR_BUS)) return true; - if (parse_bool(get_field_from_feature(f, AR_MOTORCYCLES))) + if (get_bool_from_feature(f, AR_TAXIS)) return true; return false; } +bool StreetConverter::need_to_consider(const OGRFeatureUniquePtr &f) { + return get_bool_from_feature(f, AR_AUTO) || + get_bool_from_feature(f, AR_TRUCKS) || + get_bool_from_feature(f, "AR_DELIVER") || + get_bool_from_feature(f, "AR_THRUTR"); +} + +bool StreetConverter::is_hgv_only(const OGRFeatureUniquePtr &f) { + if (get_bool_from_feature(f, AR_AUTO)) + return false; + + return get_bool_from_feature(f, AR_TRUCKS) || + get_bool_from_feature(f, "AR_DELIVER"); +} + void StreetConverter::add_hazmat_tag(osmium::builder::TagListBuilder &builder, uint64_t mod_val) { if (mod_val == 20) { // || mod_val == 21 @@ -621,92 +645,166 @@ void StreetConverter::add_additional_restrictions( auto range = cdms_map.equal_range(link_id); for (auto it = range.first; it != range.second; ++it) { - if (it->second.cond_type_type == CT_TRANSPORT_ACCESS_RESTRICTION) { - uint64_t max_height = 0; - uint64_t max_width = 0; - uint64_t max_length = 0; - uint64_t max_weight = 0; - uint64_t max_axleload = 0; - int direction = 0; // 1 = both, 2 = forward, 3 = backward - - if (it->second.dt_mod.hasDateTimeMod) { - if (debugMode) - BOOST_LOG_TRIVIAL(debug) - << "Skip Condition because of DateTimeMod for link_id " << link_id - << std::endl; - continue; - } - for (auto mod_group : it->second.mod_group_map | std::views::values) { - auto mod_type = mod_group.mod_type; - auto mod_val = mod_group.mod_val; - if (mod_type == MT_HEIGHT_RESTRICTION) { - if (!max_height || mod_val < max_height) - max_height = mod_val; - } else if (mod_type == MT_WIDTH_RESTRICTION) { - if (!max_width || mod_val < max_width) - max_width = mod_val; - } else if (mod_type == MT_LENGTH_RESTRICTION) { - if (!max_length || mod_val < max_length) - max_length = mod_val; - } else if (mod_type == MT_WEIGHT_RESTRICTION) { - if (!max_weight || mod_val < max_weight) - max_weight = mod_val; - } else if (mod_type == MT_WEIGHT_PER_AXLE_RESTRICTION) { - if (!max_axleload || mod_val < max_axleload) - max_axleload = mod_val; - } else if (mod_type == MT_HAZARDOUS_RESTRICTION) { - add_hazmat_tag(builder, mod_val); - } else if (mod_type == MT_DIRECTION_CLOSURE) { - direction = mod_val; - } else { - if (debugMode) - BOOST_LOG_TRIVIAL(debug) - << "Unknown modifier type " << mod_type << " value " << mod_val - << " for Condition Type " << it->second.cond_type_type - << " for link_id " << link_id << std::endl; - } - } - - if (cntry_ref.area_code_1 == 107) { - /** exceptional handling for Sweden as there are BK Roads - * - * HERE tags these roads with the most conservative values, - * which would make it unroutable for nearly every truck. - * Therefore we use the highest value and add a marker for BK2 / BK3 */ - if (max_weight == 16000 && max_axleload == 10000) { - builder.add_tag("maxweight:class", "BK2"); - max_weight = 51400; - } else if (max_weight == 12000 && max_axleload == 8000) { - builder.add_tag("maxweight:class", "BK3"); - max_weight = 37000; - } - } - - if (max_height > 0) - addRestrictionTag(builder, "maxheight", direction, imperial_units, - max_height); - if (max_width > 0) - addRestrictionTag(builder, "maxwidth", direction, imperial_units, - max_width); - if (max_length > 0) - addRestrictionTag(builder, "maxlength", direction, imperial_units, - max_length); - if (max_weight > 0) - addRestrictionTag(builder, "maxweight", direction, imperial_units, - max_weight); - if (max_axleload > 0) - addRestrictionTag(builder, "maxaxleload", direction, imperial_units, - max_weight); + if (it->second.dt_mod.hasDateTimeMod) { + if (debugMode) + BOOST_LOG_TRIVIAL(debug) + << "Skip Condition because of DateTimeMod for link_id " << link_id + << std::endl; + continue; + } + if (it->second.cond_type_type == CT_TRANSPORT_ACCESS_RESTRICTION) { + addTransportAccessRestriction(it, builder, link_id, cntry_ref, + imperial_units); } else if (it->second.cond_type_type == CT_TRANSPORT_SPECIAL_SPEED_SITUATION) { + addSpecialSpeedSituation(it, link_id, cntry_ref, builder, imperial_units); + } + } +} + +void StreetConverter::addSpecialSpeedSituation( + std::multimap::const_iterator &it, + uint64_t link_id, const StreetConverter::cntry_ref_type &cntry_ref, + osmium::builder::TagListBuilder &builder, bool imperial_units) { + uint64_t speed_limit = 0; + int direction = 0; // 1 = both, 2 = forward, 3 = backward + int weight_dependent = 0; + + for (auto mod_group : it->second.mod_group_map | std::views::values) { + auto mod_type = mod_group.mod_type; + auto mod_val = mod_group.mod_val; + if (mod_type == MT_SSS_SPEED_SITUATION_TYPE) { + if (mod_val != 3) // Weight dependent only + return; + } else if (mod_type == MT_SSS_SPEED_LIMIT) { + speed_limit = mod_val; + } else if (mod_type == MT_SSS_DIRECTION_CLOSURE) { + direction = mod_val; + } else if (mod_type == MT_SSS_SPEED_LIMIT_TYPE) { + if ((mod_val == 2)) // ignore advisory speed + return; + } else if (mod_type == MT_SSS_WEATHER_TYPE) { + // ignore weather type + } else if (mod_type == MT_SSS_HAZARDOUS_DEPENDENT) { + // ignore hazardous dependent + } else if (mod_type == MT_SSS_TRAILER_DEPENDENT) { + // ignore trailer dependent + } else if (mod_type == MT_SSS_WEIGHT_DEPENDENT) { + weight_dependent = mod_val; + } else { BOOST_LOG_TRIVIAL(debug) - << "Special speed situation detected for link_id " << link_id - << std::endl; + << "Unknown modifier type " << mod_type << " value " << mod_val + << " for Condition Type " << it->second.cond_type_type + << " for link_id " << link_id << std::endl; + } + } + + std::string key = "maxspeed"; + + // hgvs have a different speed limit + if (it->second.only_hgv) + key += ":hgv"; + + // handle direction + if (direction == 1) + key += ":forward"; + else if (direction == 2) + key += ":backward"; + + std::string convertedWeigthDepended; + if (weight_dependent != 0) { + // add conditional weight dependent speed limit + convertedWeigthDepended = imperial_units + ? lbs_to_metric_ton(weight_dependent) + : kg_to_t(weight_dependent); + key += ":conditional"; + } + + std::string speed_limit_str = cntry_ref.speed_limit_unit == "MPH" + ? std::to_string(speed_limit) + " mph" + : std::to_string(speed_limit); + + if (!convertedWeigthDepended.empty()) + speed_limit_str += " @ weight>" + convertedWeigthDepended; + + builder.add_tag(key, speed_limit_str); +} + +void StreetConverter::addTransportAccessRestriction( + std::multimap::const_iterator &it, + osmium::builder::TagListBuilder &builder, uint64_t link_id, + const StreetConverter::cntry_ref_type &cntry_ref, bool imperial_units) { + uint64_t max_height = 0; + uint64_t max_width = 0; + uint64_t max_length = 0; + uint64_t max_weight = 0; + uint64_t max_axleload = 0; + int direction = 0; // 1 = both, 2 = forward, 3 = backward + + for (auto mod_group : it->second.mod_group_map | std::views::values) { + auto mod_type = mod_group.mod_type; + auto mod_val = mod_group.mod_val; + if (mod_type == MT_TA_HEIGHT_RESTRICTION) { + if (!max_height || mod_val < max_height) + max_height = mod_val; + } else if (mod_type == MT_TA_WIDTH_RESTRICTION) { + if (!max_width || mod_val < max_width) + max_width = mod_val; + } else if (mod_type == MT_TA_LENGTH_RESTRICTION) { + if (!max_length || mod_val < max_length) + max_length = mod_val; + } else if (mod_type == MT_TA_WEIGHT_RESTRICTION) { + if (!max_weight || mod_val < max_weight) + max_weight = mod_val; + } else if (mod_type == MT_TA_WEIGHT_PER_AXLE_RESTRICTION) { + if (!max_axleload || mod_val < max_axleload) + max_axleload = mod_val; + } else if (mod_type == MT_TA_HAZARDOUS_RESTRICTION) { + add_hazmat_tag(builder, mod_val); + } else if (mod_type == MT_TA_DIRECTION_CLOSURE) { + direction = mod_val; + } else { + if (debugMode) + BOOST_LOG_TRIVIAL(debug) + << "Unknown modifier type " << mod_type << " value " << mod_val + << " for Condition Type " << it->second.cond_type_type + << " for link_id " << link_id << std::endl; } } + + if (cntry_ref.area_code_1 == 107) { + /** exceptional handling for Sweden as there are BK Roads + * + * HERE tags these roads with the most conservative values, + * which would make it unroutable for nearly every truck. + * Therefore we use the highest value and add a marker for BK2 / BK3 */ + if (max_weight == 16000 && max_axleload == 10000) { + builder.add_tag("maxweight:class", "BK2"); + max_weight = 51400; + } else if (max_weight == 12000 && max_axleload == 8000) { + builder.add_tag("maxweight:class", "BK3"); + max_weight = 37000; + } + } + + if (max_height > 0) + addRestrictionTag(builder, "maxheight", direction, imperial_units, + max_height); + if (max_width > 0) + addRestrictionTag(builder, "maxwidth", direction, imperial_units, + max_width); + if (max_length > 0) + addRestrictionTag(builder, "maxlength", direction, imperial_units, + max_length); + if (max_weight > 0) + addRestrictionTag(builder, "maxweight", direction, imperial_units, + max_weight); + if (max_axleload > 0) + addRestrictionTag(builder, "maxaxleload", direction, imperial_units, + max_weight); } void StreetConverter::addRestrictionTag( From 7df0a7bb7bd513521ba938b616dda842b8dc391d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 22 Jul 2024 09:21:21 +0000 Subject: [PATCH 55/57] no direction for access restriction --- plugins/navteq/converter/StreetConverterOSMTagger.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 913ccb7..579979a 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -742,7 +742,7 @@ void StreetConverter::addTransportAccessRestriction( uint64_t max_length = 0; uint64_t max_weight = 0; uint64_t max_axleload = 0; - int direction = 0; // 1 = both, 2 = forward, 3 = backward + int direction = 1; // 1 = both, 2 = forward, 3 = backward for (auto mod_group : it->second.mod_group_map | std::views::values) { auto mod_type = mod_group.mod_type; @@ -765,7 +765,8 @@ void StreetConverter::addTransportAccessRestriction( } else if (mod_type == MT_TA_HAZARDOUS_RESTRICTION) { add_hazmat_tag(builder, mod_val); } else if (mod_type == MT_TA_DIRECTION_CLOSURE) { - direction = mod_val; + // not supported + // direction = mod_val; } else { if (debugMode) BOOST_LOG_TRIVIAL(debug) From 9895b28b41a787ec425701125e753596a43fc3ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 22 Jul 2024 13:04:56 +0000 Subject: [PATCH 56/57] chore: Remove unused dependencies and update CMakeLists.txt --- .devcontainer/vcpkg.json | 2 -- CMakeLists.txt | 2 -- plugins/ogr_util.hpp | 1 - 3 files changed, 5 deletions(-) diff --git a/.devcontainer/vcpkg.json b/.devcontainer/vcpkg.json index a422703..84dcb1f 100644 --- a/.devcontainer/vcpkg.json +++ b/.devcontainer/vcpkg.json @@ -3,8 +3,6 @@ "boost-log", "boost-program-options", "icu", - "boost-timer", - "shapelib", "libosmium", { "name": "gdal", diff --git a/CMakeLists.txt b/CMakeLists.txt index fc28a39..1fc6877 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,6 @@ find_package(Boost REQUIRED COMPONENTS system log program_options) find_package(GDAL REQUIRED) find_package(geos REQUIRED) find_path(OSMIUM_INCLUDE_DIRS "osmium/version.hpp") -find_package(shapelib CONFIG REQUIRED) find_package(ICU COMPONENTS uc data io i18n tu) # Find includes in corresponding build directories @@ -50,6 +49,5 @@ target_link_libraries(${PROJECT_NAME} PRIVATE ${ICU_LIBRARY} PRIVATE GEOS::geos PRIVATE ${OSMIUM_INCLUDE_DIRS} PRIVATE GDAL::GDAL - PRIVATE shapelib::shp PRIVATE expat bz2 ) \ No newline at end of file diff --git a/plugins/ogr_util.hpp b/plugins/ogr_util.hpp index b498da1..6f1b1f5 100644 --- a/plugins/ogr_util.hpp +++ b/plugins/ogr_util.hpp @@ -12,7 +12,6 @@ #include #include -#include #include #include From 91becffd2e945f73c82692131df2cb7eafa0ffe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20J=C3=A4ger?= Date: Mon, 22 Jul 2024 13:07:23 +0000 Subject: [PATCH 57/57] remove useless BK road handling for sweden --- .../navteq/converter/StreetConverterOSMTagger.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/plugins/navteq/converter/StreetConverterOSMTagger.cpp b/plugins/navteq/converter/StreetConverterOSMTagger.cpp index 579979a..db704dd 100644 --- a/plugins/navteq/converter/StreetConverterOSMTagger.cpp +++ b/plugins/navteq/converter/StreetConverterOSMTagger.cpp @@ -776,21 +776,6 @@ void StreetConverter::addTransportAccessRestriction( } } - if (cntry_ref.area_code_1 == 107) { - /** exceptional handling for Sweden as there are BK Roads - * - * HERE tags these roads with the most conservative values, - * which would make it unroutable for nearly every truck. - * Therefore we use the highest value and add a marker for BK2 / BK3 */ - if (max_weight == 16000 && max_axleload == 10000) { - builder.add_tag("maxweight:class", "BK2"); - max_weight = 51400; - } else if (max_weight == 12000 && max_axleload == 8000) { - builder.add_tag("maxweight:class", "BK3"); - max_weight = 37000; - } - } - if (max_height > 0) addRestrictionTag(builder, "maxheight", direction, imperial_units, max_height);