Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
PCLoaderOSM.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2008-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
22// A reader of pois and polygons stored in OSM-format
23/****************************************************************************/
24#include <config.h>
25
26#include <string>
27#include <map>
28#include <fstream>
37#include <utils/geom/Position.h>
39#include <utils/xml/XMLSubSys.h>
45#include "PCLoaderOSM.h"
46
47// static members
48// ---------------------------------------------------------------------------
50bool PCLoaderOSM::myFullType(false);
51
52// ===========================================================================
53// method definitions
54// ===========================================================================
55// ---------------------------------------------------------------------------
56// static interface
57// ---------------------------------------------------------------------------
58std::set<std::string> PCLoaderOSM::initMyKeysToInclude() {
59 std::set<std::string> result;
60 result.insert("highway");
61 result.insert("railway");
62 result.insert("railway:position");
63 result.insert("railway:position:exact");
64 result.insert("waterway");
65 result.insert("aeroway");
66 result.insert("aerialway");
67 result.insert("power");
68 result.insert("man_made");
69 result.insert("building");
70 result.insert("leisure");
71 result.insert("amenity");
72 result.insert("shop");
73 result.insert("tourism");
74 result.insert("historic");
75 result.insert("landuse");
76 result.insert("natural");
77 result.insert("military");
78 result.insert("boundary");
79 result.insert("admin_level");
80 result.insert("sport");
81 result.insert("polygon");
82 result.insert("place");
83 result.insert("population");
84 result.insert("barrier");
85 result.insert("openGeoDB:population");
86 result.insert("openGeoDB:name");
87 return result;
88}
89
90void
92 if (!oc.isSet("osm-files")) {
93 return;
94 }
95 // parse file(s)
96 std::vector<std::string> files = oc.getStringVector("osm-files");
97 // load nodes, first
98 std::map<long long int, PCOSMNode*> nodes;
99 bool withAttributes = oc.getBool("all-attributes");
100 myFullType = oc.getBool("osm.keep-full-type");
102 NodesHandler nodesHandler(nodes, withAttributes, *m);
103 for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
104 // nodes
105 if (!FileHelpers::isReadable(*file)) {
106 WRITE_ERRORF(TL("Could not open osm-file '%'."), *file);
107 return;
108 }
109 const long before = PROGRESS_BEGIN_TIME_MESSAGE("Parsing nodes from osm-file '" + *file + "'");
110 if (!XMLSubSys::runParser(nodesHandler, *file)) {
111 for (std::map<long long int, PCOSMNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
112 delete (*i).second;
113 }
114 throw ProcessError();
115 }
116 PROGRESS_TIME_MESSAGE(before);
117 }
118 // load relations to see which additional ways may be relevant
119 Relations relations;
120 RelationsMap additionalWays;
121 std::set<long long int> innerEdges;
122 RelationsHandler relationsHandler(additionalWays, relations, innerEdges, withAttributes, *m);
123 for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
124 // edges
125 const long before = PROGRESS_BEGIN_TIME_MESSAGE("Parsing relations from osm-file '" + *file + "'");
126 XMLSubSys::runParser(relationsHandler, *file);
127 PROGRESS_TIME_MESSAGE(before);
128 }
129
130 // load ways
131 EdgeMap edges;
132 EdgesHandler edgesHandler(nodes, edges, additionalWays, withAttributes, *m);
133 for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
134 // edges
135 const long before = PROGRESS_BEGIN_TIME_MESSAGE("Parsing edges from osm-file '" + *file + "'");
136 XMLSubSys::runParser(edgesHandler, *file);
137 PROGRESS_TIME_MESSAGE(before);
138 }
139
140 // build all
141 const bool useName = oc.getBool("osm.use-name");
142 const double mergeRelationsThreshold = OptionsCont::getOptions().getFloat("osm.merge-relations");
143 // create polygons from relations
144 if (mergeRelationsThreshold >= 0) {
145 for (PCOSMRelation* rel : relations) {
146 if (!rel->keep || rel->myWays.empty()) {
147 continue;
148 }
149 // filter unknown and empty ways
150 int numNodes = 0;
151 for (auto it = rel->myWays.begin(); it != rel->myWays.end();) {
152 if (edges.count(*it) == 0 || edges[*it]->myCurrentNodes.empty()) {
153 it = rel->myWays.erase(it);
154 } else if (innerEdges.count(*it) > 0) {
155 // @note: it would be a good idea to merge inner shapes but
156 // it's difficult since there may be more than one
157 // independent inner shape
158 edges[*it]->standalone = true;
159 it = rel->myWays.erase(it);
160 } else {
161 numNodes += (int)edges[*it]->myCurrentNodes.size();
162 it++;
163 }
164 }
165 if (numNodes == 0) {
166 WRITE_WARNINGF(TL("Could not import polygon from relation '%' (missing ways)"), rel->id);
167 continue;
168 }
169 PCOSMEdge* e = new PCOSMEdge();
170 e->id = rel->id;
171 e->name = rel->name;
172 e->myAttributes = rel->myAttributes;
173 e->myIsClosed = false;
174 e->standalone = true;
175
176 std::vector<std::vector<long long int> > snippets;
177 for (const long long int wayID : rel->myWays) {
178 PCOSMEdge* edge = edges[wayID];
179 snippets.push_back(edge->myCurrentNodes);
180 }
181 double maxDist = 0.;
182 bool ok = true;
183 while (snippets.size() > 1) {
184 maxDist = MAX2(maxDist, mergeClosest(nodes, snippets));
185 if (maxDist > mergeRelationsThreshold) {
186 ok = false;
187 break;
188 }
189 }
190 if (ok) {
191 e->myCurrentNodes = snippets.front();
192 edges[e->id] = e;
193 double frontBackDist = 0;
194 if (e->myCurrentNodes.front() != e->myCurrentNodes.back()) {
195 // should be filled
196 const Position posFront = convertNodePosition(nodes[e->myCurrentNodes.front()]);
197 const Position posBack = convertNodePosition(nodes[e->myCurrentNodes.back()]);
198 frontBackDist = posFront.distanceTo2D(posBack);
199 if (frontBackDist < mergeRelationsThreshold) {
200 e->myCurrentNodes.push_back(e->myCurrentNodes.front());
201 frontBackDist = 0;
202 }
203 }
204 std::string frontBackMsg = "";
205 if (frontBackDist > 0) {
206 frontBackMsg = TLF(", (front-to-back dist: %)", frontBackDist);
207 }
208 WRITE_MESSAGEF(TL("Assembled polygon from relation '%' (name:%)%"), toString(rel->id), e->name, frontBackMsg);
209 } else {
210 WRITE_WARNINGF(TL("Could not import polygon from relation '%' (name:% reason: found gap of %m)."), rel->id, rel->name, maxDist)
211 delete e;
212 // export ways by themselves
213 for (long long int wayID : rel->myWays) {
214 PCOSMEdge* part = edges[wayID];
215 part->standalone = true;
216 }
217 }
218 }
219 }
220
221 // instantiate polygons
222 for (EdgeMap::iterator i = edges.begin(); i != edges.end(); ++i) {
223 PCOSMEdge* e = (*i).second;
224 if (e->myAttributes.size() == 0) {
225 // cannot be relevant as a polygon
226 continue;
227 }
228 if (!e->standalone && mergeRelationsThreshold >= 0) {
229 // part of a relation
230 continue;
231 }
232 if (e->myCurrentNodes.size() == 0) {
233 WRITE_WARNINGF(TL("Polygon '%' has no shape."), toString(e->id));
234 continue;
235 }
236 // compute shape
237 PositionVector vec;
238 for (std::vector<long long int>::iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
239 PCOSMNode* n = nodes.find(*j)->second;
240 Position pos(n->lon, n->lat);
241 if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
242 WRITE_WARNINGF(TL("Unable to project coordinates for polygon '%'."), e->id);
243 }
244 vec.push_back_noDoublePos(pos);
245 }
246 const bool ignorePruning = OptionsCont::getOptions().isInStringVector("prune.keep-list", toString(e->id));
247 // add as many polygons as keys match defined types
248 int index = 0;
249 std::string unknownPolyType = "";
250 bool isInner = mergeRelationsThreshold >= 0 && innerEdges.count(e->id) != 0 && tm.has("inner");
251 for (std::map<std::string, std::string>::iterator it = e->myAttributes.begin(); it != e->myAttributes.end(); ++it) {
252 const std::string& key = it->first;
253 const std::string& value = it->second;
254 const std::string fullType = key + "." + value;
255 if (tm.has(key + "." + value)) {
256 auto def = tm.get(isInner ? "inner" : fullType);
257 index = addPolygon(e, vec, def, fullType, index, useName, toFill, ignorePruning, withAttributes);
258 } else if (tm.has(key)) {
259 auto def = tm.get(isInner ? "inner" : key);
260 index = addPolygon(e, vec, def, fullType, index, useName, toFill, ignorePruning, withAttributes);
261 } else if (MyKeysToInclude.count(key) > 0) {
262 unknownPolyType = fullType;
263 }
264 }
265 const PCTypeMap::TypeDef& def = tm.getDefault();
266 if (index == 0 && !def.discard && unknownPolyType != "") {
267 addPolygon(e, vec, def, unknownPolyType, index, useName, toFill, ignorePruning, withAttributes);
268 }
269 }
270
271
272 // instantiate pois
273 for (std::map<long long int, PCOSMNode*>::iterator i = nodes.begin(); i != nodes.end(); ++i) {
274 PCOSMNode* n = (*i).second;
275 if (n->myAttributes.size() == 0) {
276 // cannot be relevant as a poi
277 continue;
278 }
279 Position pos(n->lon, n->lat);
280 if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
281 WRITE_WARNINGF(TL("Unable to project coordinates for POI '%'."), n->id);
282 }
283 const bool ignorePruning = OptionsCont::getOptions().isInStringVector("prune.keep-list", toString(n->id));
284 // add as many POIs as keys match defined types
285 int index = 0;
286 std::string unKnownPOIType = "";
287 for (std::map<std::string, std::string>::iterator it = n->myAttributes.begin(); it != n->myAttributes.end(); ++it) {
288 const std::string& key = it->first;
289 const std::string& value = it->second;
290 const std::string fullType = key + "." + value;
291 if (tm.has(key + "." + value)) {
292 index = addPOI(n, pos, tm.get(fullType), fullType, index, useName, toFill, ignorePruning, withAttributes);
293 } else if (tm.has(key)) {
294 index = addPOI(n, pos, tm.get(key), fullType, index, useName, toFill, ignorePruning, withAttributes);
295 } else if (MyKeysToInclude.count(key) > 0) {
296 unKnownPOIType = fullType;
297 }
298 }
299 const PCTypeMap::TypeDef& def = tm.getDefault();
300 if (index == 0 && !def.discard && unKnownPOIType != "") {
301 addPOI(n, pos, def, unKnownPOIType, index, useName, toFill, ignorePruning, withAttributes);
302 }
303 }
304 // delete nodes
305 for (std::map<long long int, PCOSMNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
306 delete (*i).second;
307 }
308 // delete edges
309 for (EdgeMap::iterator i = edges.begin(); i != edges.end(); ++i) {
310 delete (*i).second;
311 }
312 // delete relations
313 for (Relations::iterator i = relations.begin(); i != relations.end(); ++i) {
314 delete (*i);
315 }
316}
317
318
325
326
327double
328PCLoaderOSM::parseHeight(const std::map<std::string, std::string>& attrs, long long int id) {
329 auto itH = attrs.find("height");
330 if (itH != attrs.end()) {
331 try {
332 return StringUtils::parseDist(itH->second);
333 } catch (...) {
334 WRITE_WARNINGF(TL("Value of key '%' is not numeric ('%') in way '%'."), "height", itH->second, id);
335 }
336 }
338}
339
340
341int
342PCLoaderOSM::addPolygon(const PCOSMEdge* edge, const PositionVector& vec, const PCTypeMap::TypeDef& def, const std::string& fullType, int index, bool useName, PCPolyContainer& toFill, bool ignorePruning, bool withAttributes) {
343 if (def.discard) {
344 return index;
345 } else {
346 const bool closedShape = vec.front() == vec.back();
347 const std::string idSuffix = (index == 0 ? "" : "#" + toString(index));
348 const std::string id = def.prefix + (useName && edge->name != "" ? edge->name : toString(edge->id)) + idSuffix;
349 bool fill = def.allowFill == PCTypeMap::Filltype::FORCE || (def.allowFill == PCTypeMap::Filltype::FILL && closedShape);
350 SUMOPolygon* poly = new SUMOPolygon(
352 StringUtils::escapeXML(myFullType ? fullType : def.id),
353 def.color, vec, false, fill, 1, def.layer,
357 parseHeight(edge->myAttributes, edge->id));
358 if (withAttributes) {
359 poly->updateParameters(edge->myAttributes);
360 }
361 if (!toFill.add(poly, ignorePruning)) {
362 return index;
363 } else {
364 return index + 1;
365 }
366 }
367}
368
369
370int
371PCLoaderOSM::addPOI(const PCOSMNode* node, const Position& pos, const PCTypeMap::TypeDef& def, const std::string& fullType,
372 int index, bool useName, PCPolyContainer& toFill, bool ignorePruning, bool withAttributes) {
373 if (def.discard) {
374 return index;
375 } else {
376 const std::string idSuffix = (index == 0 ? "" : "#" + toString(index));
377 const std::string id = def.prefix + (useName && node->name != "" ? node->name : toString(node->id)) + idSuffix;
380 StringUtils::escapeXML(myFullType ? fullType : def.id),
381 def.color, pos, false, "", 0, false, 0, def.icon, def.layer);
382 if (withAttributes) {
383 poi->updateParameters(node->myAttributes);
384 }
385 if (!toFill.add(poi, ignorePruning)) {
386 return index;
387 } else {
388 return index + 1;
389 }
390 }
391}
392
393
394// ---------------------------------------------------------------------------
395// definitions of PCLoaderOSM::NodesHandler-methods
396// ---------------------------------------------------------------------------
397PCLoaderOSM::NodesHandler::NodesHandler(std::map<long long int, PCOSMNode*>& toFill,
398 bool withAttributes, MsgHandler& errorHandler) :
399 SUMOSAXHandler("osm - file"),
400 myWithAttributes(withAttributes),
401 myErrorHandler(errorHandler),
402 myToFill(toFill), myLastNodeID(-1) {}
403
404
406
407
408void
410 myParentElements.push_back(element);
411 if (element == SUMO_TAG_NODE) {
412 bool ok = true;
413 long long int id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
414 if (!ok) {
415 return;
416 }
417 myLastNodeID = -1;
418 if (myToFill.find(id) == myToFill.end()) {
419 myLastNodeID = id;
420 // assume we are loading multiple files...
421 // ... so we won't report duplicate nodes
422 PCOSMNode* toAdd = new PCOSMNode();
423 toAdd->id = id;
424 toAdd->lon = attrs.get<double>(SUMO_ATTR_LON, toString(id).c_str(), ok);
425 toAdd->lat = attrs.get<double>(SUMO_ATTR_LAT, toString(id).c_str(), ok);
426 if (!ok) {
427 delete toAdd;
428 return;
429 }
430 myToFill[toAdd->id] = toAdd;
431 }
432 }
433 if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_NODE
434 && myLastNodeID != -1) {
435 bool ok = true;
436 std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myLastNodeID).c_str(), ok, "", false);
437 std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myLastNodeID).c_str(), ok, "", false);
438 if (key == "name") {
439 myToFill[myLastNodeID]->name = value;
440 } else if (key == "") {
441 myErrorHandler.inform("Empty key in a a tag while parsing node '" + toString(myLastNodeID) + "' occurred.");
442 ok = false;
443 }
444 if (!ok) {
445 return;
446 }
447 myToFill[myLastNodeID]->myAttributes[key] = value;
448 }
449}
450
451
452void
454 if (element == SUMO_TAG_NODE) {
455 myLastNodeID = -1;
456 }
457 myParentElements.pop_back();
458}
459
460
461// ---------------------------------------------------------------------------
462// definitions of PCLoaderOSM::RelationsHandler-methods
463// ---------------------------------------------------------------------------
465 Relations& relations,
466 std::set<long long int>& innerEdges,
467 bool withAttributes,
468 MsgHandler& errorHandler) :
469 SUMOSAXHandler("osm - file"),
470 myAdditionalWays(additionalWays),
471 myRelations(relations),
472 myInnerEdges(innerEdges),
473 myWithAttributes(withAttributes),
474 myErrorHandler(errorHandler),
475 myCurrentRelation(nullptr) {
476}
477
478
481
482
483void
485 myParentElements.push_back(element);
486 // parse "relation" elements
487 if (element == SUMO_TAG_RELATION) {
488 myCurrentWays.clear();
489 bool ok = true;
490 const std::string& action = attrs.getOpt<std::string>(SUMO_ATTR_ACTION, nullptr, ok);
491 if (action == "delete" || !ok) {
492 myCurrentRelation = nullptr;
493 } else {
494 myCurrentRelation = new PCOSMRelation();
495 myCurrentRelation->keep = false;
496 myCurrentRelation->id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
497 myRelations.push_back(myCurrentRelation);
498 }
499 return;
500 } else if (myCurrentRelation == nullptr) {
501 return;
502 }
503 // parse member elements
504 if (element == SUMO_TAG_MEMBER) {
505 bool ok = true;
506 std::string role = attrs.hasAttribute("role") ? attrs.getStringSecure("role", "") : "";
507 long long int ref = attrs.get<long long int>(SUMO_ATTR_REF, nullptr, ok);
508 if (role == "outer" || role == "inner") {
509 std::string memberType = attrs.get<std::string>(SUMO_ATTR_TYPE, nullptr, ok);
510 if (memberType == "way") {
511 myCurrentWays.push_back(ref);
512 if (role == "inner") {
513 myInnerEdges.insert(ref);
514 }
515 }
516 }
517 return;
518 }
519 // parse values
520 if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_RELATION
521 && myCurrentRelation != nullptr) {
522 bool ok = true;
523 std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myCurrentRelation).c_str(), ok, "", false);
524 std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, "", false);
525 if (key == "") {
526 myErrorHandler.inform("Empty key in a a tag while parsing way '" + toString(myCurrentRelation) + "' occurred.");
527 ok = false;
528 }
529 if (!ok) {
530 return;
531 }
532 if (key == "name") {
533 myCurrentRelation->name = value;
534 } else if (MyKeysToInclude.count(key) > 0) {
535 myCurrentRelation->keep = true;
536 for (std::vector<long long int>::iterator it = myCurrentWays.begin(); it != myCurrentWays.end(); ++it) {
537 myAdditionalWays[*it] = myCurrentRelation;
538 }
539 }
540 myCurrentRelation->myAttributes[key] = value;
541 }
542}
543
544
545void
547 myParentElements.pop_back();
548 if (element == SUMO_TAG_RELATION) {
549 myCurrentRelation->myWays = myCurrentWays;
550 myCurrentRelation = nullptr;
551 myCurrentWays.clear();
552 }
553}
554
555
556// ---------------------------------------------------------------------------
557// definitions of PCLoaderOSM::EdgesHandler-methods
558// ---------------------------------------------------------------------------
559PCLoaderOSM::EdgesHandler::EdgesHandler(const std::map<long long int, PCOSMNode*>& osmNodes,
560 EdgeMap& toFill,
561 const RelationsMap& additionalWays,
562 bool withAttributes, MsgHandler& errorHandler) :
563 SUMOSAXHandler("osm - file"),
564 myWithAttributes(withAttributes),
565 myErrorHandler(errorHandler),
566 myOSMNodes(osmNodes),
567 myEdgeMap(toFill),
568 myAdditionalWays(additionalWays) {
569}
570
571
574
575
576void
578 myParentElements.push_back(element);
579 // parse "way" elements
580 if (element == SUMO_TAG_WAY) {
581 bool ok = true;
582 const long long int id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
583 const std::string& action = attrs.getOpt<std::string>(SUMO_ATTR_ACTION, nullptr, ok);
584 if (action == "delete" || !ok) {
585 myCurrentEdge = nullptr;
586 return;
587 }
588 myCurrentEdge = new PCOSMEdge();
589 myCurrentEdge->id = id;
590 myCurrentEdge->myIsClosed = false;
591 myCurrentEdge->standalone = false;
592 myKeep = (myAdditionalWays.find(id) != myAdditionalWays.end());
593 }
594 // parse "nd" (node) elements
595 if (element == SUMO_TAG_ND && myCurrentEdge != nullptr) {
596 bool ok = true;
597 const long long int ref = attrs.get<long long int>(SUMO_ATTR_REF, nullptr, ok);
598 if (ok) {
599 if (myOSMNodes.find(ref) == myOSMNodes.end()) {
600 WRITE_WARNINGF(TL("The referenced geometry information (ref='%') is not known"), ref);
601 return;
602 }
603 myCurrentEdge->myCurrentNodes.push_back(ref);
604 }
605 }
606 // parse values
607 if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_WAY
608 && myCurrentEdge != nullptr) {
609 bool ok = true;
610 std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myCurrentEdge->id).c_str(), ok, "", false);
611 std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myCurrentEdge->id).c_str(), ok, "", false);
612 if (key == "") {
613 myErrorHandler.inform("Empty key in a a tag while parsing way '" + toString(myCurrentEdge->id) + "' occurred.");
614 ok = false;
615 }
616 if (!ok) {
617 return;
618 }
619 if (key == "name") {
620 myCurrentEdge->name = value;
621 } else if (MyKeysToInclude.count(key) > 0) {
622 myKeep = true;
623 myCurrentEdge->standalone = true;
624 }
625 myCurrentEdge->myAttributes[key] = value;
626 }
627}
628
629
630void
632 myParentElements.pop_back();
633 if (element == SUMO_TAG_WAY && myCurrentEdge != nullptr) {
634 if (myKeep) {
635 RelationsMap::const_iterator it = myAdditionalWays.find(myCurrentEdge->id);
636 if (it != myAdditionalWays.end()) {
637 myCurrentEdge->myAttributes.insert((*it).second->myAttributes.begin(), (*it).second->myAttributes.end());
638 }
639 myEdgeMap[myCurrentEdge->id] = myCurrentEdge;
640 } else {
641 delete myCurrentEdge;
642 }
643 myCurrentEdge = nullptr;
644 }
645}
646
647
648double
649PCLoaderOSM::mergeClosest(const std::map<long long int, PCOSMNode*>& nodes, std::vector<std::vector<long long int> >& snippets) {
650 double best = std::numeric_limits<double>::max();
651 int best_i = 0;
652 int best_j = 1;
653 bool iFW = true;
654 bool jFW = true;
655
656 for (int i = 0; i < (int)snippets.size(); i++) {
657 for (int j = i + 1; j < (int)snippets.size(); j++) {
658 Position front1(convertNodePosition(nodes.find(snippets[i].front())->second));
659 Position back1(convertNodePosition(nodes.find(snippets[i].back())->second));
660 Position front2(convertNodePosition(nodes.find(snippets[j].front())->second));
661 Position back2(convertNodePosition(nodes.find(snippets[j].back())->second));
662 double dist1 = front1.distanceTo2D(front2);
663 double dist2 = front1.distanceTo2D(back2);
664 double dist3 = back1.distanceTo2D(front2);
665 double dist4 = back1.distanceTo2D(back2);
666 if (dist1 < best) {
667 best = dist1;
668 best_i = i;
669 best_j = j;
670 iFW = false;
671 jFW = true;
672 }
673 if (dist2 < best) {
674 best = dist2;
675 best_i = i;
676 best_j = j;
677 iFW = false;
678 jFW = false;
679 }
680 if (dist3 < best) {
681 best = dist3;
682 best_i = i;
683 best_j = j;
684 iFW = true;
685 jFW = true;
686 }
687 if (dist4 < best) {
688 best = dist4;
689 best_i = i;
690 best_j = j;
691 iFW = true;
692 jFW = false;
693 }
694 }
695 }
696 std::vector<long long int> merged;
697 if (iFW) {
698 merged.insert(merged.end(), snippets[best_i].begin(), snippets[best_i].end());
699 } else {
700 merged.insert(merged.end(), snippets[best_i].rbegin(), snippets[best_i].rend());
701 }
702 if (jFW) {
703 merged.insert(merged.end(), snippets[best_j].begin(), snippets[best_j].end());
704 } else {
705 merged.insert(merged.end(), snippets[best_j].rbegin(), snippets[best_j].rend());
706 }
707 snippets.erase(snippets.begin() + best_j);
708 snippets.erase(snippets.begin() + best_i);
709 snippets.push_back(merged);
710 return best;
711}
712
713/****************************************************************************/
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_MESSAGEF(...)
Definition MsgHandler.h:289
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define PROGRESS_BEGIN_TIME_MESSAGE(msg)
Definition MsgHandler.h:292
#define TL(string)
Definition MsgHandler.h:304
#define PROGRESS_TIME_MESSAGE(before)
Definition MsgHandler.h:293
#define TLF(string,...)
Definition MsgHandler.h:306
@ SUMO_TAG_MEMBER
@ SUMO_TAG_ND
@ SUMO_TAG_WAY
@ SUMO_TAG_NODE
alternative definition for junction
@ SUMO_TAG_RELATION
@ SUMO_TAG_TAG
@ SUMO_ATTR_LON
@ SUMO_ATTR_V
@ SUMO_ATTR_REF
@ SUMO_ATTR_LAT
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_ACTION
@ SUMO_ATTR_K
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:57
static bool isReadable(std::string path)
Checks whether the given file is readable.
bool x2cartesian(Position &from, bool includeInBoundary=true)
Converts the given coordinate into a cartesian and optionally update myConvBoundary.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
bool isInStringVector(const std::string &optionName, const std::string &itemName) const
Returns the named option is a list of string values containing the specified item.
A class which extracts OSM-edges from a parsed OSM-file.
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
void myEndElement(int element)
Called when a closing tag occurs.
EdgesHandler(const std::map< long long int, PCOSMNode * > &osmNodes, EdgeMap &toFill, const RelationsMap &additionalWays, bool withAttributes, MsgHandler &errorHandler)
Constructor.
A class which extracts OSM-nodes from a parsed OSM-file.
NodesHandler(std::map< long long int, PCOSMNode * > &toFill, bool withAttributes, MsgHandler &errorHandler)
Contructor.
void myEndElement(int element)
Called when a closing tag occurs.
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
A class which extracts relevant way-ids from relations in a parsed OSM-file.
void myEndElement(int element)
Called when a closing tag occurs.
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
RelationsHandler(RelationsMap &additionalWays, Relations &relations, std::set< long long int > &innerEdges, bool withAttributes, MsgHandler &errorHandler)
Constructor.
static int addPolygon(const PCOSMEdge *edge, const PositionVector &vec, const PCTypeMap::TypeDef &def, const std::string &fullType, int index, bool useName, PCPolyContainer &toFill, bool ignorePruning, bool withAttributes)
try add the polygon and return the next index on success
std::map< long long int, PCOSMEdge * > EdgeMap
static Position convertNodePosition(PCOSMNode *n)
retrieve cartesian coordinate for given node
static int addPOI(const PCOSMNode *node, const Position &pos, const PCTypeMap::TypeDef &def, const std::string &fullType, int index, bool useName, PCPolyContainer &toFill, bool ignorePruning, bool withAttributes)
try add the POI and return the next index on success
static double mergeClosest(const std::map< long long int, PCOSMNode * > &nodes, std::vector< std::vector< long long int > > &snippets)
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored as OSM-XML.
std::vector< PCOSMRelation * > Relations
static const std::set< std::string > MyKeysToInclude
static bool myFullType
Whether the type id or full type should be used.
std::map< long long int, PCOSMRelation * > RelationsMap
static double parseHeight(const std::map< std::string, std::string > &attrs, long long int id)
static std::set< std::string > initMyKeysToInclude()
A storage for loaded polygons and pois.
bool add(SUMOPolygon *poly, bool ignorePruning=false)
Adds a polygon to the storage.
A storage for type mappings.
Definition PCTypeMap.h:42
const TypeDef & getDefault()
get the default type according to the given options
Definition PCTypeMap.h:116
const TypeDef & get(const std::string &id)
Returns a type definition.
Definition PCTypeMap.cpp:70
bool has(const std::string &id)
Returns the information whether the named type is known.
Definition PCTypeMap.cpp:76
void updateParameters(const Parameterised::Map &mapArg)
Adds or updates all given parameters from the map.
A point-of-interest.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition Position.h:273
A list of positions.
void push_back_noDoublePos(const Position &p)
insert in back a non double position
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
virtual std::string getStringSecure(int id, const std::string &def) const =0
Returns the string-value of the named (by its enum-value) attribute.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
SAX-handler base for SUMO-files.
static const double DEFAULT_HEIGHT
Definition Shape.h:50
static const std::string DEFAULT_IMG_FILE
Definition Shape.h:47
static const double DEFAULT_ANGLE
Definition Shape.h:46
static const std::string DEFAULT_NAME
Definition Shape.h:51
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
static double parseDist(const std::string &sData)
parse a distance, length or width value with a unit
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
unsigned node
An internal definition of a loaded edge.
bool myIsClosed
Information whether this area is closed.
long long int id
The edge's id.
std::map< std::string, std::string > myAttributes
Additional attributes.
std::vector< long long int > myCurrentNodes
The list of nodes this edge is made of.
std::string name
The edge's name (if any)
An internal representation of an OSM-node.
Definition PCLoaderOSM.h:68
double lat
The latitude the node is located at.
Definition PCLoaderOSM.h:74
double lon
The longitude the node is located at.
Definition PCLoaderOSM.h:72
long long int id
The node's id.
Definition PCLoaderOSM.h:70
std::map< std::string, std::string > myAttributes
Additional attributes.
Definition PCLoaderOSM.h:78
An internal definition of a loaded relation.
Definition PCLoaderOSM.h:84
A single definition of values that shall be used for a given type.
Definition PCTypeMap.h:61
std::string icon
the icon to use
Definition PCTypeMap.h:69
bool discard
Information whether polygons of this type shall be discarded.
Definition PCTypeMap.h:77
std::string prefix
The prefix to use.
Definition PCTypeMap.h:67
double layer
The layer to use.
Definition PCTypeMap.h:71
std::string id
The new type id to use.
Definition PCTypeMap.h:63
RGBColor color
The color to use.
Definition PCTypeMap.h:65
Filltype allowFill
Information whether polygons of this type can be filled.
Definition PCTypeMap.h:79