CARLA
Loading...
Searching...
No Matches
OsmIngest.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#include "OsmIngest.h"
8
9#include <limits>
10#include <stdexcept>
11
13
14namespace twinmodel {
15
16 namespace {
17
18 Tags ReadTags(const pugi::xml_node &node) {
19 Tags tags;
20 for (pugi::xml_node tag = node.child("tag"); tag; tag = tag.next_sibling("tag")) {
21 const char *key = tag.attribute("k").value();
22 const char *value = tag.attribute("v").value();
23 if (key != nullptr && key[0] != '\0') {
24 tags.emplace(key, value != nullptr ? value : "");
25 }
26 }
27 return tags;
28 }
29
30 } // namespace
31
33 BoundingBox extent;
34 extent.south = std::numeric_limits<double>::max();
35 extent.west = std::numeric_limits<double>::max();
36 extent.north = std::numeric_limits<double>::lowest();
37 extent.east = std::numeric_limits<double>::lowest();
38 for (const auto &entry : nodes) {
39 extent.south = std::min(extent.south, entry.second.lat);
40 extent.north = std::max(extent.north, entry.second.lat);
41 extent.west = std::min(extent.west, entry.second.lon);
42 extent.east = std::max(extent.east, entry.second.lon);
43 }
44 return extent;
45 }
46
47 OsmData ParseOsmXml(const std::string &xml) {
48 pugi::xml_document document;
49 const pugi::xml_parse_result result = document.load_buffer(xml.data(), xml.size());
50 if (!result) {
51 throw std::runtime_error(std::string("osm: could not parse the document: ") +
52 result.description());
53 }
54 const pugi::xml_node root = document.child("osm");
55 if (!root) {
56 throw std::runtime_error("osm: the document has no <osm> element");
57 }
58
59 OsmData data;
60 for (pugi::xml_node node = root.child("node"); node; node = node.next_sibling("node")) {
61 OsmNode parsed;
62 parsed.id = node.attribute("id").as_llong();
63 parsed.lat = node.attribute("lat").as_double();
64 parsed.lon = node.attribute("lon").as_double();
65 parsed.tags = ReadTags(node);
66 data.nodes.emplace(parsed.id, std::move(parsed));
67 }
68 if (data.nodes.empty()) {
69 throw std::runtime_error("osm: the document carries no nodes");
70 }
71
72 for (pugi::xml_node way = root.child("way"); way; way = way.next_sibling("way")) {
73 OsmWay parsed;
74 parsed.id = way.attribute("id").as_llong();
75 for (pugi::xml_node ref = way.child("nd"); ref; ref = ref.next_sibling("nd")) {
76 const long long id = ref.attribute("ref").as_llong();
77 if (data.nodes.count(id) != 0u) {
78 parsed.nodes.push_back(id);
79 }
80 }
81 parsed.tags = ReadTags(way);
82 if (parsed.nodes.size() >= 2u) {
83 data.ways.push_back(std::move(parsed));
84 }
85 }
86
87 for (pugi::xml_node rel = root.child("relation"); rel; rel = rel.next_sibling("relation")) {
88 OsmRelation parsed;
89 parsed.id = rel.attribute("id").as_llong();
90 for (pugi::xml_node member = rel.child("member"); member;
91 member = member.next_sibling("member")) {
92 OsmMember entry;
93 entry.type = member.attribute("type").value();
94 entry.ref = member.attribute("ref").as_llong();
95 entry.role = member.attribute("role").value();
96 parsed.members.push_back(std::move(entry));
97 }
98 parsed.tags = ReadTags(rel);
99 data.relations.push_back(std::move(parsed));
100 }
101
102 const pugi::xml_node bounds = root.child("bounds");
103 if (bounds) {
104 BoundingBox box;
105 box.south = bounds.attribute("minlat").as_double();
106 box.west = bounds.attribute("minlon").as_double();
107 box.north = bounds.attribute("maxlat").as_double();
108 box.east = bounds.attribute("maxlon").as_double();
109 data.bbox = box;
110 }
111 return data;
112 }
113
114} // namespace twinmodel
long long node
Definition LaneGraph.cpp:43
Tags tags
Definition LaneGraph.cpp:25
double as_double(double def=0) const
Definition pugixml.cpp:5178
xml_parse_result load_buffer(const void *contents, size_t size, unsigned int options=parse_default, xml_encoding encoding=encoding_auto)
Definition pugixml.cpp:7128
xml_node child(const char_t *name) const
Definition pugixml.cpp:5490
xml_node next_sibling() const
Definition pugixml.cpp:5521
xml_attribute attribute(const char_t *name) const
Definition pugixml.cpp:5500
OsmData ParseOsmXml(const std::string &xml)
Parse an OpenStreetMap XML document.
Definition OsmIngest.cpp:47
std::map< std::string, std::string > Tags
Definition Model.h:18
const char * description() const
Definition pugixml.cpp:6812
std::vector< OsmRelation > relations
Definition OsmIngest.h:53
std::vector< OsmWay > ways
Definition OsmIngest.h:52
BoundingBox NodeExtent() const
Extent of the nodes themselves, used when the file carries no <bounds> or the bounds are smaller than...
Definition OsmIngest.cpp:32
std::map< long long, OsmNode > nodes
Definition OsmIngest.h:51
std::optional< BoundingBox > bbox
Definition OsmIngest.h:54
std::string type
Definition OsmIngest.h:32
std::string role
Definition OsmIngest.h:34
std::vector< OsmMember > members
Definition OsmIngest.h:39
std::vector< long long > nodes
Definition OsmIngest.h:27