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