1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    NIVissimConnection.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Sascha Krieg
14 /// @author  Michael Behrisch
15 /// @author  Laura Bieker
16 /// @date    Sept 2002
17 /// @version $Id$
18 ///
19 // -------------------
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27 
28 #include <string>
29 #include <map>
30 #include <iostream>
31 #include <cassert>
32 #include <utils/common/VectorHelper.h>
33 #include <utils/common/MsgHandler.h>
34 #include <utils/common/ToString.h>
35 #include "NIVissimExtendedEdgePoint.h"
36 #include <utils/geom/PositionVector.h>
37 #include <utils/geom/Boundary.h>
38 #include <utils/geom/GeomHelper.h>
39 #include <netbuild/NBEdge.h>
40 #include <netbuild/NBNode.h>
41 #include <netbuild/NBEdgeCont.h>
42 #include "NIVissimEdge.h"
43 #include "NIVissimClosedLanesVector.h"
44 #include "NIVissimNodeDef.h"
45 #include "NIVissimConnection.h"
46 #include <utils/common/UtilExceptions.h>
47 
48 
49 // ===========================================================================
50 // static members
51 // ===========================================================================
52 NIVissimConnection::DictType NIVissimConnection::myDict;
53 int NIVissimConnection::myMaxID;
54 
55 
56 // ===========================================================================
57 // method definitions
58 // ===========================================================================
NIVissimConnection(int id,const std::string & name,const NIVissimExtendedEdgePoint & from_def,const NIVissimExtendedEdgePoint & to_def,const PositionVector & geom,const std::vector<int> & assignedVehicles,const NIVissimClosedLanesVector & clv)59 NIVissimConnection::NIVissimConnection(int id,
60                                        const std::string& name, const NIVissimExtendedEdgePoint& from_def,
61                                        const NIVissimExtendedEdgePoint& to_def,
62                                        const PositionVector& geom,
63                                        const std::vector<int>& assignedVehicles, const NIVissimClosedLanesVector& clv)
64     : NIVissimAbstractEdge(id, geom),
65       myName(name), myFromDef(from_def), myToDef(to_def),
66       myAssignedVehicles(assignedVehicles), myClosedLanes(clv) {}
67 
68 
~NIVissimConnection()69 NIVissimConnection::~NIVissimConnection() {
70     for (NIVissimClosedLanesVector::iterator i = myClosedLanes.begin(); i != myClosedLanes.end(); i++) {
71         delete (*i);
72     }
73     myClosedLanes.clear();
74 }
75 
76 
77 bool
dictionary(int id,NIVissimConnection * o)78 NIVissimConnection::dictionary(int id, NIVissimConnection* o) {
79     DictType::iterator i = myDict.find(id);
80     if (i == myDict.end()) {
81         myDict[id] = o;
82         return true;
83     }
84     return false;
85 }
86 
87 
88 
89 NIVissimConnection*
dictionary(int id)90 NIVissimConnection::dictionary(int id) {
91     DictType::iterator i = myDict.find(id);
92     if (i == myDict.end()) {
93         return nullptr;
94     }
95     return (*i).second;
96 }
97 
98 
99 void
buildNodeClusters()100 NIVissimConnection::buildNodeClusters() {
101     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
102         NIVissimConnection* e = (*i).second;
103         if (!e->clustered()) {
104             assert(e->myBoundary != 0 && e->myBoundary->xmax() > e->myBoundary->xmin());
105             std::vector<int> connections =
106                 NIVissimConnection::getWithin(*(e->myBoundary));
107             NIVissimNodeCluster::dictionary(-1, -1, connections,
108                                             std::vector<int>(), true); // 19.5.!!! should be on a single edge
109         }
110     }
111 }
112 
113 
114 
115 
116 
117 std::vector<int>
getWithin(const AbstractPoly & poly)118 NIVissimConnection::getWithin(const AbstractPoly& poly) {
119     std::vector<int> ret;
120     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
121         if ((*i).second->crosses(poly)) {
122             ret.push_back((*i).second->myID);
123         }
124     }
125     return ret;
126 }
127 
128 
129 void
computeBounding()130 NIVissimConnection::computeBounding() {
131     Boundary* bound = new Boundary();
132     bound->add(myFromDef.getGeomPosition());
133     bound->add(myToDef.getGeomPosition());
134     assert(myBoundary == 0);
135     myBoundary = bound;
136 }
137 
138 
139 std::vector<int>
getForEdge(int edgeid,bool)140 NIVissimConnection::getForEdge(int edgeid, bool /*omitNodeAssigned*/) {
141     std::vector<int> ret;
142     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
143         int connID = (*i).first;
144         if ((*i).second->myFromDef.getEdgeID() == edgeid
145                 ||
146                 (*i).second->myToDef.getEdgeID() == edgeid) {
147             if (!(*i).second->hasNodeCluster()) {
148                 ret.push_back(connID);
149             }
150         }
151     }
152     return ret;
153 }
154 
155 
156 int
getFromEdgeID() const157 NIVissimConnection::getFromEdgeID() const {
158     return myFromDef.getEdgeID();
159 }
160 
161 
162 int
getToEdgeID() const163 NIVissimConnection::getToEdgeID() const {
164     return myToDef.getEdgeID();
165 }
166 
167 
168 double
getFromPosition() const169 NIVissimConnection::getFromPosition() const {
170     return myFromDef.getPosition();
171 }
172 
173 
174 double
getToPosition() const175 NIVissimConnection::getToPosition() const {
176     return myToDef.getPosition();
177 }
178 
179 
180 Position
getFromGeomPosition() const181 NIVissimConnection::getFromGeomPosition() const {
182     return myFromDef.getGeomPosition();
183 }
184 
185 
186 
187 Position
getToGeomPosition() const188 NIVissimConnection::getToGeomPosition() const {
189     return myToDef.getGeomPosition();
190 }
191 
192 
193 void
setNodeCluster(int nodeid)194 NIVissimConnection::setNodeCluster(int nodeid) {
195     assert(myNode == -1);
196     myNode = nodeid;
197 }
198 
199 
200 void
buildGeom()201 NIVissimConnection::buildGeom() {
202     if (myGeom.size() > 0) {
203         return;
204     }
205     myGeom.push_back(myFromDef.getGeomPosition());
206     myGeom.push_back(myToDef.getGeomPosition());
207 }
208 
209 
210 int
buildEdgeConnections(NBEdgeCont & ec)211 NIVissimConnection::buildEdgeConnections(NBEdgeCont& ec) {
212     int unsetConnections = 0;
213     // try to determine the connected edges
214     NBEdge* fromEdge = nullptr;
215     NBEdge* toEdge = nullptr;
216     NIVissimEdge* vissimFrom = NIVissimEdge::dictionary(getFromEdgeID());
217     if (vissimFrom->wasWithinAJunction()) {
218         // this edge was not built, try to get one that approaches it
219         vissimFrom = vissimFrom->getBestIncoming();
220         if (vissimFrom != nullptr) {
221             fromEdge = ec.retrievePossiblySplit(toString(vissimFrom->getID()), toString(getFromEdgeID()), true);
222         }
223     } else {
224         // this edge was built, try to get the proper part
225         fromEdge = ec.retrievePossiblySplit(toString(getFromEdgeID()), toString(getToEdgeID()), true);
226     }
227     NIVissimEdge* vissimTo = NIVissimEdge::dictionary(getToEdgeID());
228     if (vissimTo->wasWithinAJunction()) {
229         vissimTo = vissimTo->getBestOutgoing();
230         if (vissimTo != nullptr) {
231             toEdge = ec.retrievePossiblySplit(toString(vissimTo->getID()), toString(getToEdgeID()), true);
232         }
233     } else {
234         toEdge = ec.retrievePossiblySplit(toString(getToEdgeID()), toString(getFromEdgeID()), false);
235     }
236 
237     // try to get the edges the current connection connects
238     /*
239     NBEdge *fromEdge = ec.retrievePossiblySplit(toString(getFromEdgeID()), toString(getToEdgeID()), true);
240     NBEdge *toEdge = ec.retrievePossiblySplit(toString(getToEdgeID()), toString(getFromEdgeID()), false);
241     */
242     if (fromEdge == nullptr || toEdge == nullptr) {
243         WRITE_WARNING("Could not build connection between '" + toString(getFromEdgeID()) + "' and '" + toString(getToEdgeID()) + "'.");
244         return 1; // !!! actually not 1
245     }
246     recheckLanes(fromEdge, toEdge);
247     const std::vector<int>& fromLanes = getFromLanes();
248     const std::vector<int>& toLanes = getToLanes();
249     if (fromLanes.size() != toLanes.size()) {
250         WRITE_WARNING("Lane sizes differ for connection '" + toString(getID()) + "'.");
251     } else {
252         for (int index = 0; index < (int)fromLanes.size(); ++index) {
253             if (fromEdge->getNumLanes() <= fromLanes[index]) {
254                 WRITE_WARNING("Could not set connection between '" + fromEdge->getID() + "_" + toString(fromLanes[index]) + "' and '" + toEdge->getID() + "_" + toString(toLanes[index]) + "'.");
255                 ++unsetConnections;
256             } else if (!fromEdge->addLane2LaneConnection(fromLanes[index], toEdge, toLanes[index], NBEdge::L2L_VALIDATED)) {
257                 WRITE_WARNING("Could not set connection between '" + fromEdge->getID() + "_" + toString(fromLanes[index]) + "' and '" + toEdge->getID() + "_" + toString(toLanes[index]) + "'.");
258                 ++unsetConnections;
259             }
260         }
261     }
262     return unsetConnections;
263 }
264 
265 
266 void
dict_buildNBEdgeConnections(NBEdgeCont & ec)267 NIVissimConnection::dict_buildNBEdgeConnections(NBEdgeCont& ec) {
268     int unsetConnections = 0;
269     // go through connections
270     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
271         unsetConnections += (*i).second->buildEdgeConnections(ec);
272     }
273     if (unsetConnections != 0) {
274         WRITE_WARNING(toString<int>(unsetConnections) + " of " + toString<int>((int)myDict.size()) + " connections could not be assigned.");
275     }
276 }
277 
278 
279 const std::vector<int>&
getFromLanes() const280 NIVissimConnection::getFromLanes() const {
281     return myFromDef.getLanes();
282 }
283 
284 
285 const std::vector<int>&
getToLanes() const286 NIVissimConnection::getToLanes() const {
287     return myToDef.getLanes();
288 }
289 
290 
291 void
recheckLanes(const NBEdge * const fromEdge,const NBEdge * const toEdge)292 NIVissimConnection::recheckLanes(const NBEdge* const fromEdge, const NBEdge* const toEdge) {
293     myFromDef.recheckLanes(fromEdge);
294     myToDef.recheckLanes(toEdge);
295 }
296 
297 
298 const Boundary&
getBoundingBox() const299 NIVissimConnection::getBoundingBox() const {
300     assert(myBoundary != 0 && myBoundary->xmax() >= myBoundary->xmin());
301     return *myBoundary;
302 }
303 
304 
305 void
dict_assignToEdges()306 NIVissimConnection::dict_assignToEdges() {
307     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
308         NIVissimConnection* c = (*i).second;
309         NIVissimEdge::dictionary(c->getFromEdgeID())->addOutgoingConnection((*i).first);
310         NIVissimEdge::dictionary(c->getToEdgeID())->addIncomingConnection((*i).first);
311     }
312 }
313 
314 
315 int
getMaxID()316 NIVissimConnection::getMaxID() {
317     return myMaxID;
318 }
319 
320 
321 /****************************************************************************/
322 
323 
324