54 #define KM_PER_MILE 1.609344
105 importer.
load(oc, nb);
117 delete myEdge.second;
121 delete myPlatformShape.second;
128 if (!oc.
isSet(
"osm-files")) {
136 for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
139 WRITE_ERROR(
"Could not open osm-file '" + *file +
"'.");
154 for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
163 if (!oc.
getBool(
"osm.skip-duplicates-check")) {
167 std::set<const Edge*, CompareEdges> dupsFinder;
169 if (dupsFinder.count(it->second) > 0) {
174 dupsFinder.insert(it->second);
179 if (numRemoved > 0) {
188 std::map<long long int, int> nodeUsage;
190 for (std::map<long long int, Edge*>::const_iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
191 Edge* e = (*i).second;
193 for (std::vector<long long int>::const_iterator j = e->
myCurrentNodes.begin();
196 if (nodeUsage.find(*j) == nodeUsage.end()) {
199 nodeUsage[*j] = nodeUsage[*j] + 1;
203 for (std::map<long long int, NIOSMNode*>::const_iterator nodesIt =
myOSMNodes.begin();
206 if (nodesIt->second->tlsControlled || nodesIt->second->railwaySignal ) {
209 nodeUsage[nodesIt->first] += 1;
219 Edge* e = myEdge.second;
232 std::vector<long long int> passed;
234 passed.push_back(*j);
237 running =
insertEdge(e, running, currentFrom, currentTo, passed, nb);
238 currentFrom = currentTo;
240 passed.push_back(*j);
246 insertEdge(e, running, currentFrom, last, passed, nb);
249 const double layerElevation = oc.
getFloat(
"osm.layer-elevation");
250 if (layerElevation > 0) {
263 for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
275 if (node ==
nullptr) {
300 if (!tlsc.
insert(tlDef)) {
315 const std::vector<long long int>& passed,
NBNetBuilder& nb) {
324 if (from ==
nullptr || to ==
nullptr) {
325 WRITE_ERROR(
"Discarding edge '" +
id +
"' because the nodes could not be built.");
334 assert(passed.size() >= 2);
335 if (passed.size() == 2) {
336 WRITE_WARNINGF(
"Discarding edge '%' which connects two identical nodes without geometry.",
id);
340 int intermediateIndex = (int) passed.size() / 2;
342 std::vector<long long int> part1(passed.begin(), passed.begin() + intermediateIndex + 1);
343 std::vector<long long int> part2(passed.begin() + intermediateIndex, passed.end());
344 index =
insertEdge(e, index, from, intermediate, part1, nb);
345 return insertEdge(e, index, intermediate, to, part2, nb);
347 const int newIndex = index + 1;
351 double distanceStart =
myOSMNodes[passed.front()]->positionMeters;
352 double distanceEnd =
myOSMNodes[passed.back()]->positionMeters;
353 const bool useDistance = distanceStart != std::numeric_limits<double>::max() && distanceEnd != std::numeric_limits<double>::max();
356 if (distanceStart < distanceEnd) {
365 for (
long long i : passed) {
369 if (existingPtStop !=
nullptr) {
383 shape.push_back(pos);
386 WRITE_ERROR(
"Unable to project coordinates for edge '" +
id +
"'.");
406 if (streetName == e->
ref) {
414 bool addForward =
true;
415 bool addBackward =
true;
432 if (addForward && !addBackward) {
434 }
else if (!addForward && addBackward) {
442 numLanesForward = (int) std::ceil(e->
myNoLanes / 2.0);
444 numLanesBackward = e->
myNoLanes - numLanesForward;
447 numLanesForward =
MAX2(1, numLanesForward);
448 numLanesBackward =
MAX2(1, numLanesBackward);
451 WRITE_WARNINGF(
"Skipping edge '%' because it has zero lanes.",
id);
458 double speedBackward = speed;
462 if (speed <= 0 || speedBackward <= 0) {
463 WRITE_WARNINGF(
"Skipping edge '%' because it has speed %.",
id, speed);
469 if (!addForward && (cyclewayType &
WAY_FORWARD) != 0) {
477 if (!addBackward && (cyclewayType &
WAY_BACKWARD) != 0) {
481 numLanesBackward = 1;
489 if (!addForward && (sidewalkType &
WAY_FORWARD) != 0) {
497 if (!addBackward && (sidewalkType &
WAY_BACKWARD) != 0) {
501 numLanesBackward = 1;
515 numLanesBackward = 1;
525 const std::string reverseID =
"-" + id;
528 assert(numLanesForward > 0);
553 assert(numLanesBackward > 0);
574 throw ProcessError(
"Could not add edge '-" +
id +
"'.");
609 std::set<NIOSMNode*, CompareNodes>& uniqueNodes,
616 myIsInValidNodeTag(false),
618 myUniqueNodes(uniqueNodes),
619 myImportElevation(oc.getBool(
"osm.elevation")),
631 if (myHierarchyLevel != 2) {
636 +
"', level='" +
toString(myHierarchyLevel) +
"').");
639 const long long int id = attrs.
get<
long long int>(
SUMO_ATTR_ID,
nullptr, ok);
641 if (action ==
"delete" || !ok) {
645 if (myToFill.find(
id) == myToFill.end()) {
669 auto* toAdd =
new NIOSMNode(
id, tlon, tlat);
670 myIsInValidNodeTag =
true;
677 toAdd = *similarNode;
680 myToFill[id] = toAdd;
684 if (myHierarchyLevel != 3) {
685 WRITE_ERROR(
"Tag element on wrong XML hierarchy level.");
691 if (key ==
"highway" || key ==
"ele" || key ==
"crossing" || key ==
"railway" || key ==
"public_transport"
692 || key ==
"name" || key ==
"train" || key ==
"bus" || key ==
"tram" || key ==
"light_rail" || key ==
"subway" || key ==
"station" || key ==
"noexit"
697 if (key ==
"highway" && value.find(
"traffic_signal") != std::string::npos) {
698 myToFill[myLastNodeID]->tlsControlled =
true;
699 }
else if (key ==
"crossing" && value.find(
"traffic_signals") != std::string::npos) {
700 myToFill[myLastNodeID]->tlsControlled =
true;
701 }
else if ((key ==
"noexit" && value ==
"yes")
702 || (key ==
"railway" && value ==
"buffer_stop")) {
703 myToFill[myLastNodeID]->railwayBufferStop =
true;
704 }
else if (key ==
"railway" && value.find(
"crossing") != std::string::npos) {
705 myToFill[myLastNodeID]->railwayCrossing =
true;
707 value ==
"block" || value ==
"entry" || value ==
"exit" || value ==
"intermediate")) {
708 myToFill[myLastNodeID]->railwaySignal =
true;
709 }
else if (
StringUtils::startsWith(key,
"railway:position") && value.size() > myToFill[myLastNodeID]->position.size()) {
711 myToFill[myLastNodeID]->position = value;
712 }
else if ((key ==
"public_transport" && value ==
"stop_position") ||
713 (key ==
"highway" && value ==
"bus_stop")) {
714 myToFill[myLastNodeID]->ptStopPosition =
true;
715 if (myToFill[myLastNodeID]->ptStopLength == 0) {
717 myToFill[myLastNodeID]->ptStopLength = myOptionsCont.getFloat(
"osm.stop-output.length");
719 }
else if (key ==
"name") {
720 myToFill[myLastNodeID]->name = value;
721 }
else if (myImportElevation && key ==
"ele") {
724 if (
ISNAN(elevation)) {
727 myToFill[myLastNodeID]->ele = elevation;
732 }
else if (key ==
"station") {
746 myIsInValidNodeTag =
false;
755 const std::map<long long int, NIOSMNode*>& osmNodes,
756 std::map<long long int, Edge*>& toFill, std::map<long long int, Edge*>& platformShapes):
760 myPlatformShapesMap(platformShapes) {
851 myParentElements.push_back(element);
855 const long long int id = attrs.
get<
long long int>(
SUMO_ATTR_ID,
nullptr, ok);
857 if (action ==
"delete" || !ok) {
858 myCurrentEdge =
nullptr;
861 myCurrentEdge =
new Edge(
id);
864 if (element ==
SUMO_TAG_ND && myCurrentEdge !=
nullptr) {
874 ref = node->second->id;
875 if (myCurrentEdge->myCurrentNodes.empty() ||
876 myCurrentEdge->myCurrentNodes.back() != ref) {
877 myCurrentEdge->myCurrentNodes.push_back(ref);
883 if (element ==
SUMO_TAG_TAG && myParentElements.size() > 2
884 && myParentElements[myParentElements.size() - 2] ==
SUMO_TAG_WAY) {
885 if (myCurrentEdge ==
nullptr) {
892 const std::string cyclewaySpec = key.substr(9);
894 if (cyclewaySpec ==
"right") {
895 myCurrentEdge->myCyclewayType = (
WayType)(myCurrentEdge->myCyclewayType |
WAY_FORWARD);
896 }
else if (cyclewaySpec ==
"left") {
898 }
else if (cyclewaySpec ==
"both") {
899 myCurrentEdge->myCyclewayType = (
WayType)(myCurrentEdge->myCyclewayType |
WAY_BOTH);
903 if ((myCurrentEdge->myCyclewayType &
WAY_BOTH) != 0) {
905 myCurrentEdge->myCyclewayType = (
WayType)(myCurrentEdge->myCyclewayType & ~
WAY_UNKNOWN);
909 const std::string buswaySpec = key.substr(7);
911 if (buswaySpec ==
"right") {
913 }
else if (buswaySpec ==
"left") {
915 }
else if (buswaySpec ==
"both") {
916 myCurrentEdge->myBuswayType = (
WayType)(myCurrentEdge->myBuswayType |
WAY_BOTH);
921 if (myAllAttributes && (key ==
"bridge" || key ==
"tunnel")) {
922 myCurrentEdge->setParameter(key,
"true");
926 && key !=
"maxspeed" && key !=
"maxspeed:type"
927 && key !=
"maxspeed:forward" && key !=
"maxspeed:backward"
928 && key !=
"junction" && key !=
"name" && key !=
"tracks" && key !=
"layer"
932 && key !=
"highspeed"
934 && key !=
"postal_code"
935 && key !=
"railway:preferred_direction"
936 && key !=
"railway:bidirectional"
937 && key !=
"railway:track_ref"
939 && key !=
"electrified"
940 && key !=
"public_transport") {
945 if ((key ==
"highway" && value !=
"platform") || key ==
"railway" || key ==
"waterway" || key ==
"cycleway"
946 || key ==
"busway" || key ==
"route" || key ==
"sidewalk" || key ==
"highspeed"
949 std::string singleTypeID = key +
"." + value;
950 myCurrentEdge->myCurrentIsRoad =
true;
952 if (key ==
"cycleway") {
956 if (value ==
"opposite_track") {
958 }
else if (value ==
"opposite_lane") {
963 if (key ==
"sidewalk") {
964 if (value ==
"no" || value ==
"none") {
965 myCurrentEdge->mySidewalkType =
WAY_NONE;
966 }
else if (value ==
"both") {
967 myCurrentEdge->mySidewalkType =
WAY_BOTH;
968 }
else if (value ==
"right") {
970 }
else if (value ==
"left") {
977 if (key ==
"busway") {
981 if (value ==
"opposite_track") {
983 }
else if (value ==
"opposite_lane") {
989 if (key ==
"highspeed") {
993 singleTypeID =
"railway.highspeed";
996 if (!myCurrentEdge->myHighWayType.empty() && singleTypeID !=
"railway.highspeed") {
997 if (myCurrentEdge->myHighWayType ==
"railway.highspeed") {
1002 std::vector<std::string> types =
StringTokenizer(myCurrentEdge->myHighWayType,
1004 types.push_back(singleTypeID);
1007 myCurrentEdge->myHighWayType = singleTypeID;
1009 }
else if (key ==
"lanes") {
1015 std::vector<std::string> list = st.
getVector();
1016 if (list.size() >= 2) {
1017 int minLanes = std::numeric_limits<int>::max();
1019 for (
auto& i : list) {
1021 minLanes =
MIN2(minLanes, numLanes);
1023 myCurrentEdge->myNoLanes = minLanes;
1024 WRITE_WARNINGF(
"Using minimum lane number from list (%) for edge '%'.", value,
toString(myCurrentEdge->id));
1026 WRITE_WARNING(
"Value of key '" + key +
"' is not numeric ('" + value +
"') in edge '" +
1027 toString(myCurrentEdge->id) +
"'.");
1031 WRITE_WARNING(
"Value of key '" + key +
"' is not numeric ('" + value +
"') in edge '" +
1032 toString(myCurrentEdge->id) +
"'.");
1034 }
else if (key ==
"lanes:forward") {
1038 WRITE_WARNING(
"Value of key '" + key +
"' is not numeric ('" + value +
"') in edge '" +
1039 toString(myCurrentEdge->id) +
"'.");
1041 }
else if (key ==
"lanes:backward") {
1046 WRITE_WARNING(
"Value of key '" + key +
"' is not numeric ('" + value +
"') in edge '" +
1047 toString(myCurrentEdge->id) +
"'.");
1050 (key ==
"maxspeed" || key ==
"maxspeed:type" || key ==
"maxspeed:forward")) {
1052 myCurrentEdge->myMaxSpeed = interpretSpeed(key, value);
1053 }
else if (key ==
"maxspeed:backward" && myCurrentEdge->myMaxSpeedBackward ==
MAXSPEED_UNGIVEN) {
1054 myCurrentEdge->myMaxSpeedBackward = interpretSpeed(key, value);
1055 }
else if (key ==
"junction") {
1056 if ((value ==
"roundabout") && (myCurrentEdge->myIsOneWay.empty())) {
1057 myCurrentEdge->myIsOneWay =
"yes";
1059 }
else if (key ==
"oneway") {
1060 myCurrentEdge->myIsOneWay = value;
1061 }
else if (key ==
"name") {
1062 myCurrentEdge->streetName = value;
1063 }
else if (key ==
"ref") {
1064 myCurrentEdge->ref = value;
1065 myCurrentEdge->setParameter(
"ref", value);
1066 }
else if (key ==
"layer") {
1067 if (myAllAttributes) {
1068 myCurrentEdge->setParameter(key, value);
1073 WRITE_WARNING(
"Value of key '" + key +
"' is not numeric ('" + value +
"') in edge '" +
1074 toString(myCurrentEdge->id) +
"'.");
1076 }
else if (key ==
"tracks") {
1079 myCurrentEdge->myIsOneWay =
"true";
1081 WRITE_WARNING(
"Ignoring track count " + value +
" for edge '" +
toString(myCurrentEdge->id) +
"'.");
1084 WRITE_WARNING(
"Value of key '" + key +
"' is not numeric ('" + value +
"') in edge '" +
1085 toString(myCurrentEdge->id) +
"'.");
1087 }
else if (myAllAttributes && key ==
"postal_code") {
1088 myCurrentEdge->setParameter(key, value);
1089 }
else if (key ==
"railway:preferred_direction") {
1090 if (value ==
"both") {
1091 myCurrentEdge->myRailDirection =
WAY_BOTH;
1092 }
else if (value ==
"backward") {
1095 }
else if (key ==
"railway:bidirectional") {
1096 if (value ==
"regular") {
1097 myCurrentEdge->myRailDirection =
WAY_BOTH;
1099 }
else if (key ==
"electrified") {
1100 if (value !=
"no") {
1101 myCurrentEdge->myCurrentIsElectrified =
true;
1103 }
else if (key ==
"railway:track_ref") {
1104 myCurrentEdge->setParameter(key, value);
1105 }
else if (key ==
"public_transport" && value ==
"platform") {
1106 myCurrentEdge->myCurrentIsPlatform =
true;
1120 if (mySpeedMap.find(value) != mySpeedMap.end()) {
1121 return mySpeedMap[value];
1123 double conversion = 1;
1133 WRITE_WARNING(
"Value of key '" + key +
"' is not numeric ('" + value +
"') in edge '" +
1134 toString(myCurrentEdge->id) +
"'.");
1143 myParentElements.pop_back();
1144 if (element ==
SUMO_TAG_WAY && myCurrentEdge !=
nullptr) {
1145 if (myCurrentEdge->myCurrentIsRoad) {
1146 myEdgeMap[myCurrentEdge->id] = myCurrentEdge;
1147 }
else if (myCurrentEdge->myCurrentIsPlatform) {
1148 myPlatformShapesMap[myCurrentEdge->id] = myCurrentEdge;
1150 delete myCurrentEdge;
1152 myCurrentEdge =
nullptr;
1160 const std::map<long long int, NIOSMNode*>& osmNodes,
1161 const std::map<long long int, Edge*>& osmEdges,
NBPTStopCont* nbptStopCont,
1162 const std::map<long long int, Edge*>& platformShapes,
1167 myOSMEdges(osmEdges),
1169 myNBPTStopCont(nbptStopCont),
1170 myNBPTLineCont(nbptLineCont),
1180 myIsRestriction =
false;
1185 myRestrictionType = RESTRICTION_UNKNOWN;
1186 myPlatforms.clear();
1189 myIsStopArea =
false;
1197 myParentElements.push_back(element);
1201 myCurrentRelation = attrs.
get<
long long int>(
SUMO_ATTR_ID,
nullptr, ok);
1203 if (action ==
"delete" || !ok) {
1209 myNightService =
"";
1219 auto ref = attrs.
get<
long
1222 if (role ==
"via") {
1225 if (memberType ==
"way" && checkEdgeRef(ref)) {
1227 }
else if (memberType ==
"node") {
1234 }
else if (role ==
"from" && checkEdgeRef(ref)) {
1236 }
else if (role ==
"to" && checkEdgeRef(ref)) {
1238 }
else if (role ==
"stop") {
1239 myStops.push_back(ref);
1240 }
else if (role ==
"platform") {
1242 if (memberType ==
"way") {
1243 const std::map<
long long int,
1248 platform.
isWay =
true;
1250 myPlatforms.push_back(platform);
1252 }
else if (memberType ==
"node") {
1253 if (!myIsStopArea) {
1255 myStops.push_back(ref);
1258 platform.
isWay =
false;
1260 myPlatforms.push_back(platform);
1263 }
else if (role.empty()) {
1265 if (memberType ==
"way") {
1266 myWays.push_back(ref);
1267 }
else if (memberType ==
"node") {
1268 myStops.push_back(ref);
1278 if (key ==
"type" || key ==
"restriction") {
1280 if (key ==
"type" && value ==
"restriction") {
1281 myIsRestriction =
true;
1284 if (key ==
"type" && value ==
"route") {
1288 if (key ==
"restriction") {
1291 if (value.substr(0, 5) ==
"only_") {
1292 myRestrictionType = RESTRICTION_ONLY;
1293 }
else if (value.substr(0, 3) ==
"no_") {
1294 myRestrictionType = RESTRICTION_NO;
1296 WRITE_WARNINGF(
"Found unknown restriction type '%' in relation '%'", value,
toString(myCurrentRelation));
1300 }
else if (key ==
"public_transport") {
1302 if (value ==
"stop_area") {
1303 myIsStopArea =
true;
1305 }
else if (key ==
"route") {
1307 if (value ==
"train" || value ==
"subway" || value ==
"light_rail" || value ==
"monorail" || value ==
"tram" || value ==
"bus"
1308 || value ==
"trolleybus" || value ==
"arialway" || value ==
"ferry") {
1309 myPTRouteType = value;
1312 }
else if (key ==
"name") {
1314 }
else if (key ==
"ref") {
1316 }
else if (key ==
"interval" || key ==
"headway") {
1318 }
else if (key ==
"by_night") {
1326 if (myOSMEdges.find(ref) != myOSMEdges.end()) {
1337 myParentElements.pop_back();
1339 if (myIsRestriction) {
1342 if (myRestrictionType == RESTRICTION_UNKNOWN) {
1358 if (ok && !applyRestriction()) {
1362 for (
long long ref : myStops) {
1372 if (ptStop ==
nullptr) {
1379 if (myPlatform.isWay) {
1383 WRITE_WARNINGF(
"Platform '%' in relation: '%' is given as polygon, which currently is not supported.", myPlatform.ref, myCurrentRelation);
1401 p.push_back(pNodePos);
1403 if (p.size() == 0) {
1404 WRITE_WARNINGF(
"Referenced platform: '%' in relation: '%' is corrupt. Probably OSM file is incomplete.",
1422 NBPTPlatform platform(platformPos, myOptionsCont.getFloat(
1423 "osm.stop-output.length"));
1433 for (
long long ref : myStops) {
1441 WRITE_WARNINGF(
"Done reading first coherent chunk of pt stops. Further stops in relation % are ignored", myCurrentRelation);
1449 if (ptStop ==
nullptr) {
1456 myNBPTStopCont->insert(ptStop);
1460 for (
long long& myWay : myWays) {
1461 auto entr = myOSMEdges.find(myWay);
1462 if (entr != myOSMEdges.end()) {
1463 Edge* edge = entr->second;
1470 WRITE_WARNINGF(
"PT line in relation % with no stops ignored. Probably OSM file is incomplete.", myCurrentRelation);
1474 if (myNBPTLineCont->getLines().count(ptLine->
getLineID()) == 0) {
1475 myNBPTLineCont->insert(ptLine);
1491 if (viaNode ==
nullptr) {
1497 if (from ==
nullptr) {
1501 if (to ==
nullptr) {
1505 if (myRestrictionType == RESTRICTION_ONLY) {
1519 WRITE_WARNINGF(
"direction of restriction relation could not be determined%",
"");
1527 const std::vector<NBEdge*>& candidates)
const {
1528 const std::string prefix =
toString(wayRef);
1529 const std::string backPrefix =
"-" + prefix;
1530 NBEdge* result =
nullptr;
1532 for (
auto candidate : candidates) {
1533 if ((candidate->getID().substr(0, prefix.size()) == prefix) ||
1534 (candidate->getID().substr(0, backPrefix.size()) == backPrefix)) {
1540 WRITE_WARNINGF(
"Ambiguous way reference '%' in restriction relation", prefix);
1554 std::map<NBNode*, std::vector<std::pair<double, double> > > layerForces;
1557 std::set<NBNode*> knownElevation;
1558 for (
auto& myEdge :
myEdges) {
1559 Edge* e = myEdge.second;
1563 if (node !=
nullptr) {
1564 knownElevation.insert(node);
1565 layerForces[node].emplace_back(e->
myLayer * layerElevation, POSITION_EPS);
1570 #ifdef DEBUG_LAYER_ELEVATION
1571 std::cout <<
"known elevations:\n";
1572 for (std::set<NBNode*>::iterator it = knownElevation.begin(); it != knownElevation.end(); ++it) {
1573 const std::vector<std::pair<double, double> >& primaryLayers = layerForces[*it];
1574 std::cout <<
" node=" << (*it)->
getID() <<
" ele=";
1575 for (std::vector<std::pair<double, double> >::const_iterator it_ele = primaryLayers.begin(); it_ele != primaryLayers.end(); ++it_ele) {
1576 std::cout << it_ele->first <<
" ";
1584 std::map<NBNode*, double> knownEleMax;
1585 for (
auto it : knownElevation) {
1586 double eleMax = -std::numeric_limits<double>::max();
1587 const std::vector<std::pair<double, double> >& primaryLayers = layerForces[it];
1588 for (
const auto& primaryLayer : primaryLayers) {
1589 eleMax =
MAX2(eleMax, primaryLayer.first);
1591 knownEleMax[it] = eleMax;
1594 bool changed =
true;
1597 for (
auto it = knownElevation.begin(); it != knownElevation.end(); ++it) {
1600 / gradeThreshold * 3,
1602 for (
auto& neighbor : neighbors) {
1603 if (knownElevation.count(neighbor.first) != 0) {
1604 const double grade = fabs(knownEleMax[*it] - knownEleMax[neighbor.first])
1605 /
MAX2(POSITION_EPS, neighbor.second.first);
1606 #ifdef DEBUG_LAYER_ELEVATION
1607 std::cout <<
" grade at node=" << (*it)->getID() <<
" ele=" << knownEleMax[*it] <<
" neigh=" << it_neigh->first->getID() <<
" neighEle=" << knownEleMax[it_neigh->first] <<
" grade=" << grade <<
" dist=" << it_neigh->second.first <<
" speed=" << it_neigh->second.second <<
"\n";
1609 if (grade > gradeThreshold * 50 / 3.6 / neighbor.second.second) {
1611 const double eleMax =
MAX2(knownEleMax[*it], knownEleMax[neighbor.first]);
1612 if (knownEleMax[*it] < eleMax) {
1613 knownEleMax[*it] = eleMax;
1615 knownEleMax[neighbor.first] = eleMax;
1625 std::set<NBNode*> unknownElevation;
1626 for (
auto it = knownElevation.begin(); it != knownElevation.end(); ++it) {
1627 const double eleMax = knownEleMax[*it];
1628 const double maxDist = fabs(eleMax) * 100 / layerElevation;
1629 std::map<NBNode*, std::pair<double, double> > neighbors =
getNeighboringNodes(*it, maxDist, knownElevation);
1630 for (
auto& neighbor : neighbors) {
1631 if (knownElevation.count(neighbor.first) == 0) {
1632 unknownElevation.insert(neighbor.first);
1633 layerForces[neighbor.first].emplace_back(eleMax, neighbor.second.first);
1639 for (
auto it = unknownElevation.begin(); it != unknownElevation.end(); ++it) {
1640 double eleMax = -std::numeric_limits<double>::max();
1641 const std::vector<std::pair<double, double> >& primaryLayers = layerForces[*it];
1642 for (
const auto& primaryLayer : primaryLayers) {
1643 eleMax =
MAX2(eleMax, primaryLayer.first);
1645 const double maxDist = fabs(eleMax) * 100 / layerElevation;
1646 std::map<NBNode*, std::pair<double, double> > neighbors =
getNeighboringNodes(*it, maxDist, knownElevation);
1647 for (
auto& neighbor : neighbors) {
1648 if (knownElevation.count(neighbor.first) == 0 && unknownElevation.count(neighbor.first) == 0) {
1649 layerForces[*it].emplace_back(0, neighbor.second.first);
1654 #ifdef DEBUG_LAYER_ELEVATION
1655 std::cout <<
"summation of forces\n";
1657 std::map<NBNode*, double> nodeElevation;
1658 for (
auto& layerForce : layerForces) {
1659 const std::vector<std::pair<double, double> >& forces = layerForce.second;
1660 if (knownElevation.count(layerForce.first) != 0) {
1668 #ifdef DEBUG_LAYER_ELEVATION
1669 std::cout <<
" node=" << it->first->getID() <<
" knownElevation=" << knownEleMax[it->first] <<
"\n";
1671 nodeElevation[layerForce.first] = knownEleMax[layerForce.first];
1672 }
else if (forces.size() == 1) {
1673 nodeElevation[layerForce.first] = forces.front().first;
1677 for (
const auto& force : forces) {
1678 distSum += force.second;
1680 double weightSum = 0;
1681 double elevation = 0;
1682 #ifdef DEBUG_LAYER_ELEVATION
1683 std::cout <<
" node=" << it->first->getID() <<
" distSum=" << distSum <<
"\n";
1685 for (
const auto& force : forces) {
1686 const double weight = (distSum - force.second) / distSum;
1687 weightSum += weight;
1688 elevation += force.first * weight;
1690 #ifdef DEBUG_LAYER_ELEVATION
1691 std::cout <<
" force=" << it_force->first <<
" dist=" << it_force->second <<
" weight=" << weight <<
" ele=" << elevation <<
"\n";
1694 nodeElevation[layerForce.first] = elevation / weightSum;
1697 #ifdef DEBUG_LAYER_ELEVATION
1698 std::cout <<
"final elevations:\n";
1699 for (std::map<NBNode*, double>::iterator it = nodeElevation.begin(); it != nodeElevation.end(); ++it) {
1700 std::cout <<
" node=" << (it->first)->getID() <<
" ele=" << it->second <<
"\n";
1704 for (
auto& it : nodeElevation) {
1711 for (
const auto& it : ec) {
1712 NBEdge* edge = it.second;
1714 const double length = geom.
length2D();
1715 const double zFrom = nodeElevation[edge->
getFromNode()];
1716 const double zTo = nodeElevation[edge->
getToNode()];
1721 for (
auto it_pos = geom.begin(); it_pos != geom.end(); ++it_pos) {
1722 if (it_pos != geom.begin()) {
1723 dist += (*it_pos).distanceTo2D(*(it_pos - 1));
1725 newGeom.push_back((*it_pos) +
Position(0, 0, zFrom + (zTo - zFrom) * dist / length));
1731 std::map<NBNode*, std::pair<double, double> >
1733 std::map<NBNode*, std::pair<double, double> > result;
1734 std::set<NBNode*> visited;
1735 std::vector<NBNode*> open;
1736 open.push_back(node);
1737 result[node] = std::make_pair(0, 0);
1738 while (!open.empty()) {
1741 if (visited.count(n) != 0) {
1746 for (
auto e : edges) {
1749 s = e->getFromNode();
1753 const double dist = result[n].first + e->getGeometry().length2D();
1754 const double speed =
MAX2(e->getSpeed(), result[n].second);
1755 if (result.count(s) == 0) {
1756 result[s] = std::make_pair(dist, speed);
1758 result[s] = std::make_pair(
MIN2(dist, result[s].first),
MAX2(speed, result[s].second));
1760 if (dist < maxDist && knownElevation.count(s) == 0) {
1772 if (tc.
knows(type)) {
1783 std::vector<std::string> types;
1785 std::string t = tok.
next();
1787 if (std::find(types.begin(), types.end(), t) == types.end()) {
1790 }
else if (tok.
size() > 1) {
1791 WRITE_WARNINGF(
"Discarding unknown compound '%' in type '%' (first occurence for edge '%').", t, type,
id);
1794 if (types.empty()) {
1795 WRITE_WARNINGF(
"Discarding unusable type '%' (first occurence for edge '%').", type,
id);
1800 if (tc.
knows(newType)) {
1808 double maxSpeed = 0;
1813 bool defaultIsOneWay =
true;
1815 bool discard =
true;
1816 for (
auto& type2 : types) {
1842 WRITE_WARNINGF(
"Discarding compound type '%' (first occurence for edge '%').", newType,
id);
1847 WRITE_MESSAGE(
"Adding new type '" + type +
"' (first occurence for edge '" +
id +
"').");
1848 tc.
insertEdgeType(newType, numLanes, maxSpeed, prio, permissions, width, defaultIsOneWay,
1849 sidewalkWidth, bikelaneWidth, 0, 0, 0);
1850 for (
auto& type3 : types) {
1865 std::vector<NIOSMNode*> nodes;
1866 std::vector<double> usablePositions;
1867 std::vector<int> usableIndex;
1871 if (node->
positionMeters != std::numeric_limits<double>::max()) {
1873 usableIndex.push_back((
int)nodes.size());
1875 nodes.push_back(node);
1877 if (usablePositions.size() == 0) {
1880 bool forward =
true;
1881 if (usablePositions.size() == 1) {
1882 WRITE_WARNINGF(
"Ambiguous railway kilometrage direction for way '%' (assuming forward)",
id);
1884 forward = usablePositions.front() < usablePositions.back();
1887 for (
int i = 1; i < (int)usablePositions.size(); i++) {
1888 if ((usablePositions[i - 1] < usablePositions[i]) != forward) {
1889 WRITE_WARNINGF(
"Inconsistent railway kilometrage direction for way '%': %s (skipping)",
id,
toString(usablePositions));
1893 if (nodes.size() > usablePositions.size()) {
1897 shape.push_back(
Position(node->lon, node->lat, 0));
1902 double sign = forward ? 1 : -1;
1904 for (
int i = usableIndex.front() - 1; i >= 0; i--) {
1905 nodes[i]->positionMeters = nodes[i + 1]->positionMeters - sign * shape[i].distanceTo2D(shape[i + 1]);
1908 for (
int i = usableIndex.front() + 1; i < (
int)nodes.size(); i++) {
1909 if (nodes[i]->positionMeters == std::numeric_limits<double>::max()) {
1910 nodes[i]->positionMeters = nodes[i - 1]->positionMeters + sign * shape[i].distanceTo2D(shape[i - 1]);
1937 return std::numeric_limits<double>::max();
1943 if (type ==
"train") {
1945 }
else if (type ==
"subway" || type ==
"light_rail") {
1950 std::string stop =
"";
1953 }
else if (result ==
SVC_BUS) {
#define WRITE_WARNINGF(...)
#define WRITE_MESSAGE(msg)
#define WRITE_WARNING(msg)
#define PROGRESS_DONE_MESSAGE()
#define PROGRESS_BEGIN_MESSAGE(msg)
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
StringBijection< SUMOVehicleClass > SumoVehicleClassStrings(sumoVehicleClassStringInitializer, SVC_CUSTOM2, false)
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_RAIL
vehicle is a not electrified rail
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_RAIL_FAST
vehicle that is allowed to drive on high-speed rail tracks
@ SVC_RAIL_ELECTRIC
rail vehicle that requires electrified tracks
@ SVC_RAIL_URBAN
vehicle is a city rail
@ SVC_TRAM
vehicle is a light rail
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SUMO_TAG_NODE
alternative definition for junction
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge's lateral offset shal...
const double SUMO_const_laneWidth
std::string joinToStringSorting(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static bool isReadable(std::string path)
Checks whether the given file is readable.
void setFileName(const std::string &name)
Sets the current file name.
Storage for edges, including some functionality operating on multiple edges.
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
The representation of a single edge during network building.
bool addEdge2EdgeConnection(NBEdge *dest, bool overrideRemoval=false)
Adds a connection to another edge.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
void addBikeLane(double width)
add a bicycle lane of the given width and shift existing connctions
void setDistance(double distance)
set lane specific speed (negative lane implies set for all lanes)
NBNode * getToNode() const
Returns the destination node of the edge.
void addSidewalk(double width)
add a pedestrian sidewalk of the given width and shift existing connctions
const PositionVector & getGeometry() const
Returns the geometry of the edge.
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false, const bool keepPossibleTurns=false)
Removes the specified connection(s)
bool isConnectedTo(const NBEdge *e, const bool ignoreTurnaround=false) const
Returns the information whethe a connection to the given edge has been added (or computed)
static const double UNSPECIFIED_WIDTH
unspecified lane width
static const double UNSPECIFIED_OFFSET
unspecified lane offset
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
NBNode * getFromNode() const
Returns the origin node of the edge.
Instance responsible for building networks.
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
NBTypeCont & getTypeCont()
Returns a reference to the type container.
NBParkingCont & getParkingCont()
NBPTLineCont & getPTLineCont()
Returns a reference to the pt line container.
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
NBEdgeCont & getEdgeCont()
NBPTStopCont & getPTStopCont()
Returns a reference to the pt stop container.
NBNodeCont & getNodeCont()
Returns a reference to the node container.
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Container for nodes during the netbuilding process.
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Represents a single node (junction) during network building.
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
SumoXMLNodeType getType() const
Returns the type of this node.
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
const Position & getPosition() const
A traffic light logics which must be computed (only nodes/edges are given)
void addPTStop(NBPTStop *pStop)
const std::string & getLineID() const
void addWayNode(long long int way, long long int node)
void setMyNumOfStops(int numStops)
std::vector< NBPTStop * > getStops()
bool insert(NBPTStop *ptStop)
Inserts a node into the map.
int cleanupDeleted(NBEdgeCont &cont)
remove stops on non existing (removed) edges
NBPTStop * get(std::string id)
Retrieve a previously inserted pt stop.
The representation of a single pt stop.
void registerAdditionalEdge(std::string wayId, std::string edgeId)
void addPlatformCand(NBPTPlatform platform)
void setIsMultipleStopPositions(bool multipleStopPositions)
The representation of a single pt stop.
A container for traffic light definitions and built programs.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
A storage for available edgeTypes of edges.
bool getEdgeTypeShallBeDiscarded(const std::string &edgeType) const
Returns the information whether edges of this edgeType shall be discarded.
bool copyEdgeTypeRestrictionsAndAttrs(const std::string &fromId, const std::string &toId)
Copy restrictions to a edgeType.
double getEdgeTypeSpeed(const std::string &edgeType) const
Returns the maximal velocity for the given edgeType [m/s].
int getEdgeTypePriority(const std::string &edgeType) const
Returns the priority for the given edgeType.
int getEdgeTypeNumLanes(const std::string &edgeType) const
Returns the number of lanes for the given edgeType.
double getEdgeTypeWidth(const std::string &edgeType) const
Returns the lane width for the given edgeType [m].
SVCPermissions getEdgeTypePermissions(const std::string &edgeType) const
Returns allowed vehicle classes for the given edgeType.
void insertEdgeType(const std::string &id, int numLanes, double maxSpeed, int prio, SVCPermissions permissions, double width, bool oneWayIsDefault, double sidewalkWidth, double bikeLaneWidth, double widthResolution, double maxWidth, double minWidth)
Adds a edgeType into the list.
bool knows(const std::string &edgeType) const
Returns whether the named edgeType is in the container.
double getEdgeTypeSidewalkWidth(const std::string &edgeType) const
Returns the lane width for a sidewalk to be added [m].
double getEdgeTypeBikeLaneWidth(const std::string &edgeType) const
Returns the lane width for a bike lane to be added [m].
bool getEdgeTypeIsOneWay(const std::string &edgeType) const
Returns whether edges are one-way per default for the given edgeType.
Functor which compares two Edges.
bool operator()(const Edge *e1, const Edge *e2) const
An internal definition of a loaded edge.
WayType mySidewalkType
Information about the kind of sidwalk along this road.
bool myCurrentIsRoad
Information whether this is a road.
WayType myCyclewayType
Information about the kind of cycleway along this road.
int myNoLanesForward
number of lanes in forward direction or 0 if unknown, negative if backwards lanes are meant
double myMaxSpeed
maximum speed in km/h, or MAXSPEED_UNGIVEN
bool myCurrentIsElectrified
Information whether this is railway is electrified.
std::string ref
The edge's track name.
std::string myHighWayType
The type, stored in "highway" key.
const long long int id
The edge's id.
int myLayer
Information about the relative z-ordering of ways.
int myNoLanes
number of lanes, or -1 if unknown
std::vector< long long int > myCurrentNodes
The list of nodes this edge is made of.
int myParkingType
Information about road-side parking.
double myMaxSpeedBackward
maximum speed in km/h, or MAXSPEED_UNGIVEN
WayType myBuswayType
Information about the kind of busway along this road.
std::string streetName
The edge's street name.
WayType myRailDirection
Information about the direction(s) of railway usage.
std::string myIsOneWay
Information whether this is an one-way road.
A class which extracts OSM-edges from a parsed OSM-file.
EdgesHandler(const std::map< long long int, NIOSMNode * > &osmNodes, std::map< long long int, Edge * > &toFill, std::map< long long int, Edge * > &platformShapes)
Constructor.
~EdgesHandler() override
Destructor.
bool myAllAttributes
whether additional way attributes shall be added to the edge
void myEndElement(int element) override
Called when a closing tag occurs.
double interpretSpeed(const std::string &key, std::string value)
std::map< std::string, double > mySpeedMap
A map of non-numeric speed descriptions to their numeric values.
void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
A class which extracts OSM-nodes from a parsed OSM-file.
~NodesHandler() override
Destructor.
int getDuplicateNodes() const
void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
NodesHandler(std::map< long long int, NIOSMNode * > &toFill, std::set< NIOSMNode *, CompareNodes > &uniqueNodes, const OptionsCont &cont)
Contructor.
void myEndElement(int element) override
Called when a closing tag occurs.
A class which extracts relevant relation information from a parsed OSM-file.
void myEndElement(int element) override
Called when a closing tag occurs.
void resetValues()
reset members to their defaults for parsing a new relation
void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
~RelationHandler() override
Destructor.
RelationHandler(const std::map< long long int, NIOSMNode * > &osmNodes, const std::map< long long int, Edge * > &osmEdges, NBPTStopCont *nbptStopCont, const std::map< long long int, Edge * > &platfromShapes, NBPTLineCont *nbptLineCont, const OptionsCont &oc)
Constructor.
bool checkEdgeRef(long long int ref) const
check whether a referenced way has a corresponding edge
bool applyRestriction() const
try to apply the parsed restriction and return whether successful
NBEdge * findEdgeRef(long long int wayRef, const std::vector< NBEdge * > &candidates) const
try to find the way segment among candidates
Importer for networks stored in OpenStreetMap format.
int insertEdge(Edge *e, int index, NBNode *from, NBNode *to, const std::vector< long long int > &passed, NBNetBuilder &nb)
Builds an NBEdge.
std::map< long long int, Edge * > myEdges
the map from OSM way ids to edge objects
std::map< long long int, NIOSMNode * > myOSMNodes
the map from OSM node ids to actual nodes
NIImporter_OpenStreetMap()
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads content of the optionally given OSM file.
static const long long int INVALID_ID
static const double MAXSPEED_UNGIVEN
~NIImporter_OpenStreetMap()
std::map< long long int, Edge * > myPlatformShapes
the map from OSM way ids to platform shapes
void load(const OptionsCont &oc, NBNetBuilder &nb)
std::set< NIOSMNode *, CompareNodes > myUniqueNodes
the set of unique nodes used in NodesHandler, used when freeing memory
void reconstructLayerElevation(double layerElevation, NBNetBuilder &nb)
reconstruct elevation from layer info
static SUMOVehicleClass interpretTransportType(const std::string &type, NIOSMNode *toSet=nullptr)
translate osm transport designations into sumo vehicle class
std::map< std::string, std::string > myKnownCompoundTypes
The compound types that have already been mapped to other known types.
static const std::string compoundTypeSeparator
The separator within newly created compound type names.
std::set< std::string > myUnusableTypes
The compounds types that do not contain known types.
std::map< NBNode *, std::pair< double, double > > getNeighboringNodes(NBNode *node, double maxDist, const std::set< NBNode * > &knownElevation)
collect neighboring nodes with their road distance and maximum between-speed. Search does not continu...
static double interpretDistance(NIOSMNode *node)
read distance value from node and return value in m
NBNode * insertNodeChecking(long long int id, NBNodeCont &nc, NBTrafficLightLogicCont &tlsc)
Builds an NBNode.
void extendRailwayDistances(Edge *e, NBTypeCont &tc)
extend kilometrage data for all nodes along railway
std::string usableType(const std::string &type, const std::string &id, NBTypeCont &tc)
check whether the type is known or consists of known type compounds. return empty string otherwise
const std::string & getID() const
Returns the id.
A storage for options typed value containers)
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.
void unsetParameter(const std::string &key)
Removes a parameter.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
void updateParameters(const std::map< std::string, std::string > &mapArg)
Adds or updates all given parameters from the map.
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value map.
A point in 2D or 3D with translation and scaling methods.
double length2D() const
Returns the length.
double length() const
Returns the length.
PositionVector reverse() const
reverse position vector
Encapsulated SAX-Attributes.
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 StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
T get(const std::string &str) const
int size() const
returns the number of existing substrings
std::vector< std::string > getVector()
return vector of strings
bool hasNext()
returns the information whether further substrings exist
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
static std::string to_lower_case(std::string str)
Transfers the content to lower case.
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false)
Runs the given handler on the given file; returns if everything's ok.
An internal representation of an OSM-node.
SVCPermissions permissions
type of pt stop
NBNode * node
the NBNode that was instantiated
double positionMeters
position converted to m (using highest precision available)
std::string position
kilometrage/mileage
const long long int id
The node's id.
bool tlsControlled
Whether this is a tls controlled junction.
double ptStopLength
The length of the pt stop.
bool ptStopPosition
Whether this is a public transport stop position.
std::string name
The name of the node.
bool railwayCrossing
Whether this is a railway crossing.
double ele
The elevation of this node.
bool railwayBufferStop
Whether this is a railway buffer stop.
const double lon
The longitude the node is located at.
const double lat
The latitude the node is located at.
bool railwaySignal
Whether this is a railway (main) signal.