Line data Source code
1 : /****************************************************************************/ 2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 3 : // Copyright (C) 2001-2024 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 : /****************************************************************************/ 14 : /// @file NLNetShapeHandler.cpp 15 : /// @author Daniel Krajzewicz 16 : /// @author Jakob Erdmann 17 : /// @author Clemens Honomichl 18 : /// @author Sascha Krieg 19 : /// @author Michael Behrisch 20 : /// @author Felix Brack 21 : /// @date Mon, 9 Jul 2001 22 : /// 23 : // The XML-Handler for network loading 24 : /****************************************************************************/ 25 : #include <config.h> 26 : 27 : #include <string> 28 : #include <microsim/MSEdge.h> 29 : #include <microsim/MSLane.h> 30 : #include <microsim/MSLink.h> 31 : #include <microsim/MSJunction.h> 32 : #include <microsim/MSJunctionControl.h> 33 : #include "NLNetShapeHandler.h" 34 : 35 : 36 : // =========================================================================== 37 : // method definitions 38 : // =========================================================================== 39 0 : NLNetShapeHandler::NLNetShapeHandler(const std::string& file, MSNet& net) : 40 : SUMOSAXHandler(file, "net"), 41 0 : myNet(net), 42 0 : myPrimaryEdges(MSEdge::getAllEdges().begin(), MSEdge::getAllEdges().end()) { 43 0 : } 44 : 45 : 46 0 : NLNetShapeHandler::~NLNetShapeHandler() {} 47 : 48 : 49 : void 50 0 : NLNetShapeHandler::myStartElement(int element, 51 : const SUMOSAXAttributes& attrs) { 52 0 : switch (element) { 53 0 : case SUMO_TAG_LANE: 54 0 : addLane(attrs); 55 0 : break; 56 0 : case SUMO_TAG_JUNCTION: 57 0 : addJunction(attrs); 58 0 : break; 59 0 : case SUMO_TAG_CONNECTION: 60 0 : if (myNet.hasInternalLinks()) { 61 : // see sortInternalShapes 62 0 : addConnection(attrs); 63 : } 64 : break; 65 : default: 66 : break; 67 : } 68 0 : } 69 : 70 : 71 : void 72 0 : NLNetShapeHandler::addLane(const SUMOSAXAttributes& attrs) { 73 0 : bool ok = true; 74 : // get the id, report an error if not given or empty... 75 0 : std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok); 76 0 : if (!myNet.hasInternalLinks() && id[0] == ':') { 77 : return; 78 : } 79 0 : MSLane* lane = MSLane::dictionary(id); 80 0 : if (lane == nullptr) { 81 0 : WRITE_WARNINGF("The lane '%' does not exist in the primary network.", id); 82 0 : return; 83 : } 84 0 : const PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok); 85 0 : lane->addSecondaryShape(shape); 86 0 : myPrimaryEdges.erase(&lane->getEdge()); 87 0 : } 88 : 89 : 90 : void 91 0 : NLNetShapeHandler::addJunction(const SUMOSAXAttributes& attrs) { 92 0 : bool ok = true; 93 : // get the id, report an error if not given or empty... 94 0 : std::string id = attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok); 95 0 : if (!myNet.hasInternalLinks() && id[0] == ':') { 96 : return; 97 : } 98 : MSJunction* junction = myNet.getJunctionControl().get(id); 99 0 : if (junction == nullptr) { 100 0 : WRITE_WARNINGF("The junction '%' does not exist in the primary network.", id); 101 0 : return; 102 : } 103 0 : double x = attrs.get<double>(SUMO_ATTR_X, id.c_str(), ok); 104 0 : double y = attrs.get<double>(SUMO_ATTR_Y, id.c_str(), ok); 105 0 : double z = attrs.getOpt<double>(SUMO_ATTR_Z, id.c_str(), ok, 0); 106 : junction->addSecondaryPosition(Position(x, y, z)); 107 : } 108 : 109 : 110 : void 111 0 : NLNetShapeHandler::addConnection(const SUMOSAXAttributes& attrs) { 112 0 : if (!attrs.hasAttribute(SUMO_ATTR_VIA)) { 113 0 : return; 114 : } 115 0 : bool ok = true; 116 0 : const std::string fromID = attrs.get<std::string>(SUMO_ATTR_FROM, nullptr, ok); 117 0 : const std::string toID = attrs.get<std::string>(SUMO_ATTR_TO, nullptr, ok); 118 0 : const int fromLaneIdx = attrs.get<int>(SUMO_ATTR_FROM_LANE, nullptr, ok); 119 0 : const int toLaneIdx = attrs.get<int>(SUMO_ATTR_TO_LANE, nullptr, ok); 120 0 : std::string viaID = attrs.get<std::string>(SUMO_ATTR_VIA, nullptr, ok); 121 0 : MSLane* lane = MSLane::dictionary(viaID); 122 0 : if (lane == nullptr) { 123 : // warning already given in addLane 124 : return; 125 : } 126 0 : std::string fromLaneID = fromID + "_" + toString(fromLaneIdx); 127 0 : std::string toLaneID = toID + "_" + toString(toLaneIdx); 128 : 129 0 : if (lane->getLinkCont()[0]->getLane()->getID() != toLaneID 130 0 : || lane->getIncomingLanes()[0].lane->getID() != fromLaneID) { 131 : // mismatch: find the correct lane that connects fromLaneID and toLaneID 132 0 : const MSJunction* junction = lane->getEdge().getToJunction(); 133 0 : for (MSLane* lane2 : junction->getInternalLanes()) { 134 0 : if (lane2->getLinkCont()[0]->getLane()->getID() == toLaneID 135 0 : && lane2->getIncomingLanes()[0].lane->getID() == fromLaneID) { 136 0 : myShuffledJunctions[junction][lane2] = lane; 137 0 : break; 138 : } 139 : } 140 : } 141 : } 142 : 143 : 144 : void 145 0 : NLNetShapeHandler::sortInternalShapes() { 146 : // even when the alternative network has the same topology as 147 : // the primary network, the ids of internal lanes may differ 148 : // since they are based on a clockwise sorting of the edges. 149 : // hence we must verify connections and shuffle the shapes as needed 150 0 : for (auto item : myShuffledJunctions) { 151 0 : const MSJunction* junction = item.first; 152 : std::map<MSLane*, PositionVector> shapes2; 153 0 : for (MSLane* lane : junction->getInternalLanes()) { 154 0 : shapes2[lane] = lane->getShape(true); 155 : } 156 : 157 0 : for (auto laneMap : item.second) { 158 0 : laneMap.first->addSecondaryShape(shapes2[laneMap.second]); 159 : } 160 : } 161 : // final warning 162 0 : if (myPrimaryEdges.size() > 0) { 163 0 : WRITE_WARNING(TLF("% edges of the primary network did not occur in the alternative-net-file", myPrimaryEdges.size())); 164 : } 165 0 : } 166 : /****************************************************************************/