SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00009 // ------------------- 00010 /****************************************************************************/ 00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00012 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00013 /****************************************************************************/ 00014 // 00015 // This file is part of SUMO. 00016 // SUMO is free software: you can redistribute it and/or modify 00017 // it under the terms of the GNU General Public License as published by 00018 // the Free Software Foundation, either version 3 of the License, or 00019 // (at your option) any later version. 00020 // 00021 /****************************************************************************/ 00022 00023 00024 // =========================================================================== 00025 // included modules 00026 // =========================================================================== 00027 #ifdef _MSC_VER 00028 #include <windows_config.h> 00029 #else 00030 #include <config.h> 00031 #endif 00032 00033 #include <algorithm> 00034 #include <iostream> 00035 #include <cassert> 00036 #include <iterator> 00037 #include <utils/geom/Boundary.h> 00038 #include <utils/geom/GeomHelper.h> 00039 #include <utils/common/VectorHelper.h> 00040 #include <utils/common/MsgHandler.h> 00041 #include <utils/common/ToString.h> 00042 #include "NIVissimConnection.h" 00043 #include "NIVissimDisturbance.h" 00044 #include "NIVissimNodeCluster.h" 00045 #include "NIVissimNodeDef.h" 00046 #include "NIVissimEdge.h" 00047 #include "NIVissimTL.h" 00048 #include "NIVissimConnectionCluster.h" 00049 00050 #ifdef CHECK_MEMORY_LEAKS 00051 #include <foreign/nvwa/debug_new.h> 00052 #endif // CHECK_MEMORY_LEAKS 00053 00054 00055 // =========================================================================== 00056 // static members 00057 // =========================================================================== 00058 NIVissimConnectionCluster::ContType NIVissimConnectionCluster::myClusters; 00059 int NIVissimConnectionCluster::myFirstFreeID = 100000; 00060 int NIVissimConnectionCluster::myStaticBlaID = 0; 00061 00062 00063 00064 // =========================================================================== 00065 // method definitions 00066 // =========================================================================== 00067 // --------------------------------------------------------------------------- 00068 // NIVissimConnectionCluster::NodeSubCluster - methods 00069 // --------------------------------------------------------------------------- 00070 NIVissimConnectionCluster::NodeSubCluster::NodeSubCluster(NIVissimConnection* c) { 00071 add(c); 00072 } 00073 00074 00075 NIVissimConnectionCluster::NodeSubCluster::~NodeSubCluster() {} 00076 00077 00078 void 00079 NIVissimConnectionCluster::NodeSubCluster::add(NIVissimConnection* c) { 00080 myBoundary.add(c->getBoundingBox()); 00081 myConnections.push_back(c); 00082 } 00083 00084 00085 void 00086 NIVissimConnectionCluster::NodeSubCluster::add(const NIVissimConnectionCluster::NodeSubCluster& c) { 00087 for (ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) { 00088 add(*i); 00089 } 00090 } 00091 00092 00093 size_t 00094 NIVissimConnectionCluster::NodeSubCluster::size() const { 00095 return myConnections.size(); 00096 } 00097 00098 00099 std::vector<int> 00100 NIVissimConnectionCluster::NodeSubCluster::getConnectionIDs() const { 00101 std::vector<int> ret; 00102 int id = NIVissimConnectionCluster::getNextFreeNodeID(); 00103 for (ConnectionCont::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00104 ret.push_back((*i)->getID()); 00105 (*i)->setNodeCluster(id); 00106 } 00107 return ret; 00108 } 00109 00110 00111 bool 00112 NIVissimConnectionCluster::NodeSubCluster::overlapsWith( 00113 const NIVissimConnectionCluster::NodeSubCluster& c, 00114 SUMOReal offset) { 00115 assert(myBoundary.xmax() >= myBoundary.xmin()); 00116 assert(c.myBoundary.xmax() >= c.myBoundary.xmin()); 00117 return myBoundary.overlapsWith(c.myBoundary, offset); 00118 } 00119 00120 00121 00122 // --------------------------------------------------------------------------- 00123 // NIVissimConnectionCluster - methods 00124 // --------------------------------------------------------------------------- 00125 NIVissimConnectionCluster::NIVissimConnectionCluster( 00126 const std::vector<int>& connections, int nodeCluster, int edgeid) 00127 : myConnections(connections), myNodeCluster(nodeCluster), 00128 myBlaID(myStaticBlaID++) { 00129 recomputeBoundary(); 00130 myClusters.push_back(this); 00131 assert(edgeid > 0); 00132 if (edgeid >= 0) { 00133 myEdges.push_back(edgeid); 00134 } 00135 // add information about incoming and outgoing edges 00136 for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) { 00137 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00138 assert(c != 0); 00139 myOutgoingEdges.push_back(c->getToEdgeID()); 00140 myIncomingEdges.push_back(c->getFromEdgeID()); 00141 assert(c->getFromEdgeID() == edgeid || c->getToEdgeID() == edgeid); 00142 } 00143 VectorHelper<int>::removeDouble(myIncomingEdges); 00144 VectorHelper<int>::removeDouble(myOutgoingEdges); 00145 } 00146 00147 00148 NIVissimConnectionCluster::NIVissimConnectionCluster( 00149 const std::vector<int>& connections, const Boundary& boundary, 00150 int nodeCluster, const std::vector<int>& edges) 00151 : myConnections(connections), myBoundary(boundary), 00152 myNodeCluster(nodeCluster), myEdges(edges) { 00153 myClusters.push_back(this); 00154 recomputeBoundary(); 00155 assert(myBoundary.xmax() >= myBoundary.xmin()); 00156 // add information about incoming and outgoing edges 00157 for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) { 00158 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00159 assert(c != 0); 00160 myOutgoingEdges.push_back(c->getToEdgeID()); 00161 myIncomingEdges.push_back(c->getFromEdgeID()); 00162 assert(find(edges.begin(), edges.end(), c->getFromEdgeID()) != edges.end() 00163 || 00164 find(edges.begin(), edges.end(), c->getToEdgeID()) != edges.end()); 00165 } 00166 VectorHelper<int>::removeDouble(myIncomingEdges); 00167 VectorHelper<int>::removeDouble(myOutgoingEdges); 00168 } 00169 00170 00171 NIVissimConnectionCluster::~NIVissimConnectionCluster() {} 00172 00173 00174 00175 int 00176 NIVissimConnectionCluster::getNextFreeNodeID() { 00177 return myFirstFreeID++; 00178 } 00179 00180 00181 bool 00182 NIVissimConnectionCluster::overlapsWith(NIVissimConnectionCluster* c, 00183 SUMOReal offset) const { 00184 assert(myBoundary.xmax() >= myBoundary.xmin()); 00185 assert(c->myBoundary.xmax() >= c->myBoundary.xmin()); 00186 return c->myBoundary.overlapsWith(myBoundary, offset); 00187 } 00188 00189 00190 void 00191 NIVissimConnectionCluster::add(NIVissimConnectionCluster* c) { 00192 assert(myBoundary.xmax() >= myBoundary.xmin()); 00193 assert(c->myBoundary.xmax() >= c->myBoundary.xmin()); 00194 myBoundary.add(c->myBoundary); 00195 for (std::vector<int>::iterator i = c->myConnections.begin(); i != c->myConnections.end(); i++) { 00196 myConnections.push_back(*i); 00197 } 00198 VectorHelper<int>::removeDouble(myConnections); 00199 assert(myNodeCluster == -1 || c->myNodeCluster == -1); 00200 if (myNodeCluster == -1) { 00201 myNodeCluster = c->myNodeCluster; 00202 } 00203 // inform edges about merging 00204 // !!! merge should be done within one method 00205 for (std::vector<int>::iterator j = c->myEdges.begin(); j != c->myEdges.end(); j++) { 00206 NIVissimEdge::dictionary(*j)->mergedInto(c, this); 00207 } 00208 copy(c->myEdges.begin(), c->myEdges.end(), back_inserter(myEdges)); 00209 copy(c->myIncomingEdges.begin(), c->myIncomingEdges.end(), 00210 back_inserter(myIncomingEdges)); 00211 copy(c->myOutgoingEdges.begin(), c->myOutgoingEdges.end(), 00212 back_inserter(myOutgoingEdges)); 00213 VectorHelper<int>::removeDouble(myEdges); 00214 VectorHelper<int>::removeDouble(myIncomingEdges); 00215 VectorHelper<int>::removeDouble(myOutgoingEdges); 00216 } 00217 00218 00219 00220 void 00221 NIVissimConnectionCluster::joinBySameEdges(SUMOReal offset) { 00222 // !!! ... 00223 // Further, we try to omit joining of overlaping nodes. This is done by holding 00224 // the lists of incoming and outgoing edges and incrementally building the nodes 00225 // regarding this information 00226 std::vector<NIVissimConnectionCluster*> joinAble; 00227 size_t pos = 0; 00228 ContType::iterator i = myClusters.begin(); 00229 // step1 - faster but no complete 00230 while (i != myClusters.end()) { 00231 joinAble.clear(); 00232 ContType::iterator j = i + 1; 00233 00234 // check whether every combination has been processed 00235 while (j != myClusters.end()) { 00236 // check whether the current clusters overlap 00237 if ((*i)->joinable(*j, offset)) { 00238 joinAble.push_back(*j); 00239 } 00240 j++; 00241 } 00242 for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin(); 00243 k != joinAble.end(); k++) { 00244 // add the overlaping cluster 00245 (*i)->add(*k); 00246 // erase the overlaping cluster 00247 delete *k; 00248 myClusters.erase(find(myClusters.begin(), myClusters.end(), *k)); 00249 } 00250 // 00251 if (joinAble.size() > 0) { 00252 i = myClusters.begin() + pos; 00253 // clear temporary storages 00254 joinAble.clear(); 00255 } else { 00256 i++; 00257 pos++; 00258 } 00259 } 00260 // 00261 pos = 0; 00262 i = myClusters.begin(); 00263 while (i != myClusters.end()) { 00264 ContType::iterator j = i + 1; 00265 // check whether every combination has been processed 00266 while (j != myClusters.end()) { 00267 // check whether the current clusters overlap 00268 if ((*i)->joinable(*j, offset)) { 00269 joinAble.push_back(*j); 00270 } 00271 j++; 00272 } 00273 for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin(); 00274 k != joinAble.end(); k++) { 00275 // add the overlaping cluster 00276 (*i)->add(*k); 00277 // erase the overlaping cluster 00278 delete *k; 00279 myClusters.erase(find(myClusters.begin(), myClusters.end(), *k)); 00280 } 00281 // 00282 if (joinAble.size() > 0) { 00283 i = myClusters.begin(); 00284 // clear temporary storages 00285 joinAble.clear(); 00286 pos = 0; 00287 } else { 00288 i++; 00289 pos++; 00290 } 00291 } 00292 // check for weak district connections 00293 // (junctions made up by district connections, where prohibitions are not 00294 // modelled properly) 00295 pos = 0; 00296 i = myClusters.begin(); 00297 while (i != myClusters.end()) { 00298 ContType::iterator j = i + 1; 00299 // check whether every combination has been processed 00300 while (j != myClusters.end()) { 00301 // check whether the current clusters overlap 00302 if ((*i)->isWeakDistrictConnRealisation(*j)) { 00303 joinAble.push_back(*j); 00304 } 00305 j++; 00306 } 00307 for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin(); 00308 k != joinAble.end(); k++) { 00309 // add the overlaping cluster 00310 (*i)->add(*k); 00311 // erase the overlaping cluster 00312 delete *k; 00313 myClusters.erase(find(myClusters.begin(), myClusters.end(), *k)); 00314 } 00315 // 00316 if (joinAble.size() > 0) { 00317 i = myClusters.begin(); 00318 // clear temporary storages 00319 joinAble.clear(); 00320 pos = 0; 00321 } else { 00322 i++; 00323 pos++; 00324 } 00325 } 00326 } 00327 00328 00329 bool 00330 NIVissimConnectionCluster::joinable(NIVissimConnectionCluster* c2, SUMOReal offset) { 00331 // join clusters which have at least one connection in common 00332 if (VectorHelper<int>::subSetExists(myConnections, c2->myConnections)) { 00333 return true; 00334 } 00335 00336 // connections shall overlap otherwise 00337 if (!overlapsWith(c2, offset)) { 00338 return false; 00339 } 00340 00341 // at least one of the clusters shall not be assigned to a node in previous (!!!??) 00342 if (hasNodeCluster() && c2->hasNodeCluster()) { 00343 return false; 00344 } 00345 00346 // join clusters which where connections do disturb each other 00347 if (VectorHelper<int>::subSetExists(c2->getDisturbanceParticipators(), myConnections) 00348 || 00349 VectorHelper<int>::subSetExists(getDisturbanceParticipators(), c2->myConnections)) { 00350 00351 return true; 00352 } 00353 00354 00355 // join clusters which do share the same incoming or outgoing edges (not mutually) 00356 std::vector<int> extendedOutgoing1; 00357 std::vector<int> extendedIncoming1; 00358 std::vector<int> extendedOutgoing2; 00359 std::vector<int> extendedIncoming2; 00360 if (myIncomingEdges.size() > 1 || c2->myIncomingEdges.size() > 1) { 00361 extendedOutgoing1 = 00362 extendByToTreatAsSame(myOutgoingEdges, myIncomingEdges); 00363 extendedIncoming1 = 00364 extendByToTreatAsSame(myIncomingEdges, myOutgoingEdges); 00365 extendedOutgoing2 = 00366 extendByToTreatAsSame(c2->myOutgoingEdges, c2->myIncomingEdges); 00367 extendedIncoming2 = 00368 extendByToTreatAsSame(c2->myIncomingEdges, c2->myOutgoingEdges); 00369 } else { 00370 extendedOutgoing1 = myIncomingEdges; 00371 extendedIncoming1 = myOutgoingEdges; 00372 extendedOutgoing2 = c2->myIncomingEdges; 00373 extendedIncoming2 = c2->myOutgoingEdges; 00374 } 00375 00376 if (VectorHelper<int>::subSetExists(extendedOutgoing1, extendedOutgoing2) 00377 || 00378 VectorHelper<int>::subSetExists(extendedIncoming1, extendedIncoming2) 00379 ) { 00380 return true; 00381 } 00382 return false; 00383 } 00384 00385 00386 bool 00387 NIVissimConnectionCluster::isWeakDistrictConnRealisation(NIVissimConnectionCluster* c2) { 00388 if ((myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1)) { 00389 return false; 00390 } 00391 if ((c2->myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1)) { 00392 return false; 00393 } 00394 00395 // ok, may be the other way round 00396 if (myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1) { 00397 return c2->isWeakDistrictConnRealisation(this); 00398 } 00399 // connections must cross 00400 bool crosses = false; 00401 for (std::vector<int>::const_iterator j1 = myConnections.begin(); j1 != myConnections.end() && !crosses; j1++) { 00402 NIVissimConnection* c1 = NIVissimConnection::dictionary(*j1); 00403 const PositionVector& g1 = c1->getGeometry(); 00404 for (std::vector<int>::const_iterator j2 = c2->myConnections.begin(); j2 != c2->myConnections.end() && !crosses; j2++) { 00405 NIVissimConnection* c2 = NIVissimConnection::dictionary(*j2); 00406 const PositionVector& g2 = c2->getGeometry(); 00407 if (g1.intersects(g2)) { 00408 crosses = true; 00409 } 00410 } 00411 } 00412 if (!crosses) { 00413 return false; 00414 } 00415 // ok, check for connection 00416 if (myOutgoingEdges.size() != 1 || c2->myIncomingEdges.size() != 1) { 00417 return false; 00418 } 00419 // check whether the connection is bidirectional 00420 NIVissimEdge* oe = NIVissimEdge::dictionary(myOutgoingEdges[0]); 00421 NIVissimEdge* ie = NIVissimEdge::dictionary(c2->myIncomingEdges[0]); 00422 if (oe == 0 || ie == 0) { 00423 return false; 00424 } 00425 Line l1(oe->getGeometry().getBegin(), oe->getGeometry().getEnd()); 00426 Line l2(ie->getGeometry().getEnd(), ie->getGeometry().getBegin()); 00427 SUMOReal a1 = l1.atan2DegreeAngle(); 00428 SUMOReal a2 = l2.atan2DegreeAngle(); 00429 return fabs(a1 - a2) < 5; 00430 } 00431 00432 00433 bool 00434 NIVissimConnectionCluster::liesOnSameEdgesEnd(NIVissimConnectionCluster* cc2) { 00435 // 00436 for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00437 NIVissimConnection* c1 = NIVissimConnection::dictionary(*i); 00438 for (std::vector<int>::iterator j = cc2->myConnections.begin(); j != cc2->myConnections.end(); j++) { 00439 NIVissimConnection* c2 = NIVissimConnection::dictionary(*j); 00440 if (c1->getFromEdgeID() == c2->getFromEdgeID()) { 00441 NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID()); 00442 const PositionVector& g = e->getGeometry(); 00443 SUMOReal pos1 = GeomHelper::nearest_position_on_line_to_point2D( 00444 g.getBegin(), g.getEnd(), c1->getBoundary().getCenter()); 00445 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point2D( 00446 g.getBegin(), g.getEnd(), c2->getBoundary().getCenter()); 00447 if (pos1 <= 5.0 && pos2 <= 5.0) { 00448 return true; 00449 } 00450 } 00451 if (c1->getToEdgeID() == c2->getToEdgeID()) { 00452 NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID()); 00453 const PositionVector& g = e->getGeometry(); 00454 SUMOReal pos1 = GeomHelper::nearest_position_on_line_to_point2D( 00455 g.getBegin(), g.getEnd(), c1->getBoundary().getCenter()); 00456 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point2D( 00457 g.getBegin(), g.getEnd(), c2->getBoundary().getCenter()); 00458 if (pos1 >= g.length() - 5.0 && pos2 >= g.length() - 5.0) { 00459 return true; 00460 } 00461 } 00462 } 00463 } 00464 return false; 00465 } 00466 00467 00468 std::vector<int> 00469 NIVissimConnectionCluster::extendByToTreatAsSame(const std::vector<int>& iv1, 00470 const std::vector<int>& iv2) const { 00471 std::vector<int> ret(iv1); 00472 for (std::vector<int>::const_iterator i = iv1.begin(); i != iv1.end(); i++) { 00473 NIVissimEdge* e = NIVissimEdge::dictionary(*i); 00474 const std::vector<NIVissimEdge*> treatAsSame = e->getToTreatAsSame(); 00475 for (std::vector<NIVissimEdge*>::const_iterator j = treatAsSame.begin(); j != treatAsSame.end(); j++) { 00476 if (find(iv2.begin(), iv2.end(), (*j)->getID()) == iv2.end()) { 00477 ret.push_back((*j)->getID()); 00478 } 00479 } 00480 } 00481 return ret; 00482 } 00483 00484 std::vector<int> 00485 NIVissimConnectionCluster::getDisturbanceParticipators() { 00486 std::vector<int> ret; 00487 for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00488 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00489 const std::vector<int>& disturbances = c->getDisturbances(); 00490 for (std::vector<int>::const_iterator j = disturbances.begin(); j != disturbances.end(); j++) { 00491 NIVissimDisturbance* d = NIVissimDisturbance::dictionary(*j); 00492 ret.push_back(d->getEdgeID()); 00493 ret.push_back(d->getDisturbanceID()); 00494 } 00495 } 00496 return ret; 00497 } 00498 00499 00500 void 00501 NIVissimConnectionCluster::buildNodeClusters() { 00502 for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) { 00503 std::vector<int> disturbances; 00504 std::vector<int> tls; 00505 std::vector<int> nodes; 00506 int tlsid = -1; 00507 int nodeid = -1; 00508 if ((*i)->myConnections.size() > 0) { 00509 (*i)->recomputeBoundary(); 00510 disturbances = NIVissimDisturbance::getWithin((*i)->myBoundary); 00511 } 00512 nodes = (*i)->myNodes;//NIVissimTL::getWithin((*i)->myBoundary, 5.0); 00513 if (nodes.size() > 1) { 00514 WRITE_WARNING("NIVissimConnectionCluster:More than a single node"); 00515 // throw 1; // !!! eigentlich sollte hier nur eine Ampelanlage sein 00516 } 00517 if (nodes.size() > 0) { 00518 nodeid = nodes[0]; 00519 } 00520 // 00521 // 00522 int id = NIVissimNodeCluster::dictionary( 00523 nodeid, tlsid, (*i)->myConnections, 00524 disturbances, (*i)->myIncomingEdges.size() < 2); 00525 assert((*i)->myNodeCluster == id || (*i)->myNodeCluster < 0); 00526 (*i)->myNodeCluster = id; 00527 } 00528 } 00529 00530 00531 void 00532 NIVissimConnectionCluster::searchForConnection(int id) { 00533 int pos = 0; 00534 for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) { 00535 std::vector<int> connections = (*i)->myConnections; 00536 if (find(connections.begin(), connections.end(), id) != connections.end()) { 00537 for (std::vector<int>::iterator j = connections.begin(); j != connections.end(); j++) { 00538 int checkdummy = *j; 00539 } 00540 } 00541 pos++; 00542 } 00543 } 00544 00545 00546 void 00547 NIVissimConnectionCluster::_debugOut(std::ostream& into) { 00548 for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) { 00549 std::vector<int> connections = (*i)->myConnections; 00550 for (std::vector<int>::iterator j = connections.begin(); j != connections.end(); j++) { 00551 if (j != connections.begin()) { 00552 into << ", "; 00553 } 00554 into << *j; 00555 } 00556 into << "(" << (*i)->myBoundary << ")" << std::endl; 00557 } 00558 into << "---------------------------" << std::endl; 00559 } 00560 00561 00562 00563 bool 00564 NIVissimConnectionCluster::hasNodeCluster() const { 00565 return myNodeCluster != -1; 00566 } 00567 00568 00569 size_t 00570 NIVissimConnectionCluster::dictSize() { 00571 return myClusters.size(); 00572 } 00573 00574 00575 void 00576 NIVissimConnectionCluster::removeConnections(const NodeSubCluster& c) { 00577 for (NodeSubCluster::ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) { 00578 NIVissimConnection* conn = *i; 00579 int connid = conn->getID(); 00580 std::vector<int>::iterator j = find(myConnections.begin(), myConnections.end(), connid); 00581 if (j != myConnections.end()) { 00582 myConnections.erase(j); 00583 } 00584 } 00585 recomputeBoundary(); 00586 } 00587 00588 00589 void 00590 NIVissimConnectionCluster::recomputeBoundary() { 00591 myBoundary = Boundary(); 00592 for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00593 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00594 if (c != 0) { 00595 myBoundary.add(c->getFromGeomPosition()); 00596 myBoundary.add(c->getToGeomPosition()); 00597 if (c->getGeometry().size() != 0) { 00598 myBoundary.add(c->getGeometry().getBoxBoundary()); 00599 } 00600 } 00601 } 00602 assert(myBoundary.xmax() >= myBoundary.xmin()); 00603 } 00604 00605 00606 NBNode* 00607 NIVissimConnectionCluster::getNBNode() const { 00608 return NIVissimNodeCluster::dictionary(myNodeCluster)->getNBNode(); 00609 } 00610 00611 00612 bool 00613 NIVissimConnectionCluster::around(const Position& p, SUMOReal offset) const { 00614 assert(myBoundary.xmax() >= myBoundary.xmin()); 00615 return myBoundary.around(p, offset); 00616 } 00617 00618 00619 00620 void 00621 NIVissimConnectionCluster::recheckEdges() { 00622 assert(myConnections.size() != 0); 00623 // remove the cluster from all edges at first 00624 std::vector<int>::iterator i; 00625 for (i = myEdges.begin(); i != myEdges.end(); i++) { 00626 NIVissimEdge* edge = NIVissimEdge::dictionary(*i); 00627 edge->removeFromConnectionCluster(this); 00628 } 00629 // clear edge information 00630 myEdges.clear(); 00631 // recheck which edges do still participate and add edges 00632 for (i = myConnections.begin(); i != myConnections.end(); i++) { 00633 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00634 assert(myBoundary.xmax() >= myBoundary.xmin()); 00635 if (myBoundary.around(c->getFromGeomPosition(), 5)) { 00636 myEdges.push_back(c->getFromEdgeID()); 00637 } 00638 assert(myBoundary.xmax() >= myBoundary.xmin()); 00639 if (myBoundary.around(c->getToGeomPosition(), 5)) { 00640 myEdges.push_back(c->getToEdgeID()); 00641 } 00642 } 00643 // connect edges 00644 for (i = myEdges.begin(); i != myEdges.end(); i++) { 00645 NIVissimEdge* edge = NIVissimEdge::dictionary(*i); 00646 edge->addToConnectionCluster(this); 00647 } 00648 } 00649 00650 00651 SUMOReal 00652 NIVissimConnectionCluster::getPositionForEdge(int edgeid) const { 00653 // return the middle of the connections when there are any 00654 if (myConnections.size() != 0) { 00655 SUMOReal sum = 0; 00656 size_t part = 0; 00657 std::vector<int>::const_iterator i; 00658 for (i = myConnections.begin(); i != myConnections.end(); i++) { 00659 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00660 if (c->getFromEdgeID() == edgeid) { 00661 part++; 00662 sum += c->getFromPosition(); 00663 } 00664 if (c->getToEdgeID() == edgeid) { 00665 part++; 00666 sum += c->getToPosition(); 00667 } 00668 } 00669 if (part > 0) { 00670 return sum / (SUMOReal) part; 00671 } 00672 } 00673 // use the position of the node if possible 00674 if (myNodeCluster >= 0) { 00675 // try to find the nearest point on the edge 00676 // !!! only the main geometry is regarded 00677 NIVissimNodeDef* node = 00678 NIVissimNodeDef::dictionary(myNodeCluster); 00679 if (node != 0) { 00680 SUMOReal pos = node->getEdgePosition(edgeid); 00681 if (pos >= 0) { 00682 return pos; 00683 } 00684 } 00685 /* 00686 SUMOReal try1 = GeomHelper::nearest_position_on_line_to_point( 00687 edge->getBegin2D(), edge->getEnd2D(), node->getPos()); 00688 if(try1>=0) { 00689 return try1; 00690 } 00691 // try to use simple distance 00692 SUMOReal dist1 = 00693 GeomHelper::distance(node->getPos(), edge->getBegin2D()); 00694 SUMOReal dist2 = 00695 GeomHelper::distance(node->getPos(), edge->getEnd2D()); 00696 return dist1<dist2 00697 ? 0 : edge->getLength(); 00698 */ 00699 } 00700 // what else? 00701 WRITE_WARNING("NIVissimConnectionCluster: how to get an edge's position?"); 00702 // !!! 00703 assert(myBoundary.xmin() <= myBoundary.xmax()); 00704 NIVissimEdge* edge = NIVissimEdge::dictionary(edgeid); 00705 std::vector<int>::const_iterator i = find(myEdges.begin(), myEdges.end(), edgeid); 00706 if (i == myEdges.end()) { 00707 // edge does not exist!? 00708 throw 1; 00709 } 00710 const PositionVector& edgeGeom = edge->getGeometry(); 00711 Position p = GeomHelper::crossPoint(myBoundary, edgeGeom); 00712 return GeomHelper::nearest_position_on_line_to_point2D( 00713 edgeGeom.getBegin(), edgeGeom.getEnd(), p); 00714 } 00715 00716 00717 00718 void 00719 NIVissimConnectionCluster::clearDict() { 00720 for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) { 00721 delete(*i); 00722 } 00723 myClusters.clear(); 00724 myFirstFreeID = 100000; 00725 } 00726 00727 00728 PositionVector 00729 NIVissimConnectionCluster::getIncomingContinuationGeometry(NIVissimEdge* e) const { 00730 // collect connection where this edge is the incoming one 00731 std::vector<NIVissimConnection*> edgeIsIncoming; 00732 for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00733 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00734 if (c->getFromEdgeID() == e->getID()) { 00735 edgeIsIncoming.push_back(c); 00736 } 00737 } 00738 // 00739 if (edgeIsIncoming.size() == 0) { 00740 return PositionVector(); 00741 } 00742 // sort connected edges in same direction 00743 sort(edgeIsIncoming.begin(), edgeIsIncoming.end(), 00744 same_direction_sorter(e->getGeometry().beginEndAngle())); 00745 NIVissimConnection* c = *(edgeIsIncoming.begin()); 00746 return c->getGeometry(); 00747 } 00748 00749 00750 00751 NIVissimConnection* 00752 NIVissimConnectionCluster::getIncomingContinuation(NIVissimEdge* e) const { 00753 // collect connection where this edge is the incoming one 00754 std::vector<NIVissimConnection*> edgeIsIncoming; 00755 for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00756 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00757 if (c->getFromEdgeID() == e->getID()) { 00758 edgeIsIncoming.push_back(c); 00759 } 00760 } 00761 // 00762 if (edgeIsIncoming.size() == 0) { 00763 return 0; 00764 } 00765 // sort connected edges in same direction 00766 sort(edgeIsIncoming.begin(), edgeIsIncoming.end(), 00767 same_direction_sorter(e->getGeometry().beginEndAngle())); 00768 return *(edgeIsIncoming.begin()); 00769 } 00770 00771 00772 00773 PositionVector 00774 NIVissimConnectionCluster::getOutgoingContinuationGeometry(NIVissimEdge* e) const { 00775 // collect connection where this edge is the outgoing one 00776 std::vector<NIVissimConnection*> edgeIsOutgoing; 00777 for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00778 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00779 if (c->getToEdgeID() == e->getID()) { 00780 edgeIsOutgoing.push_back(c); 00781 } 00782 } 00783 // 00784 if (edgeIsOutgoing.size() == 0) { 00785 return PositionVector(); 00786 } 00787 // sort connected edges in same direction 00788 sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(), 00789 same_direction_sorter(e->getGeometry().beginEndAngle())); 00790 NIVissimConnection* c = *(edgeIsOutgoing.begin()); 00791 return c->getGeometry(); 00792 } 00793 00794 00795 NIVissimConnection* 00796 NIVissimConnectionCluster::getOutgoingContinuation(NIVissimEdge* e) const { 00797 // collect connection where this edge is the outgoing one 00798 std::vector<NIVissimConnection*> edgeIsOutgoing; 00799 for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00800 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00801 if (c->getToEdgeID() == e->getID()) { 00802 edgeIsOutgoing.push_back(c); 00803 } 00804 } 00805 // 00806 if (edgeIsOutgoing.size() == 0) { 00807 return 0; 00808 } 00809 // sort connected edges in same direction 00810 sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(), 00811 same_direction_sorter(e->getGeometry().beginEndAngle())); 00812 return *(edgeIsOutgoing.begin()); 00813 } 00814 00815 00816 00817 /****************************************************************************/ 00818