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 0 : }
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 0 : }
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 : /****************************************************************************/
|