|
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 IntVector 00100 NIVissimConnectionCluster::NodeSubCluster::getConnectionIDs() const { 00101 IntVector 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 IntVector& 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 (IntVector::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 IntVector& connections, const Boundary& boundary, 00150 int nodeCluster, const IntVector& 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 (IntVector::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 (IntVector::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 (IntVector::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 MsgHandler::getMessageInstance()->progressMsg("Checked(1): " + toString(pos) + "/" + toString(myClusters.size()) + " "); 00258 pos++; 00259 } 00260 } 00261 // 00262 pos = 0; 00263 i = myClusters.begin(); 00264 while (i != myClusters.end()) { 00265 ContType::iterator j = i + 1; 00266 // check whether every combination has been processed 00267 while (j != myClusters.end()) { 00268 // check whether the current clusters overlap 00269 if ((*i)->joinable(*j, offset)) { 00270 joinAble.push_back(*j); 00271 } 00272 j++; 00273 } 00274 for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin(); 00275 k != joinAble.end(); k++) { 00276 // add the overlaping cluster 00277 (*i)->add(*k); 00278 // erase the overlaping cluster 00279 delete *k; 00280 myClusters.erase(find(myClusters.begin(), myClusters.end(), *k)); 00281 } 00282 // 00283 if (joinAble.size() > 0) { 00284 i = myClusters.begin(); 00285 // clear temporary storages 00286 joinAble.clear(); 00287 pos = 0; 00288 } else { 00289 i++; 00290 pos++; 00291 MsgHandler::getMessageInstance()->progressMsg("Checked(2): " + toString(pos) + "/" + toString(myClusters.size()) + " "); 00292 } 00293 } 00294 // check for weak district connections 00295 // (junctions made up by district connections, where prohibitions are not 00296 // modelled properly) 00297 pos = 0; 00298 i = myClusters.begin(); 00299 while (i != myClusters.end()) { 00300 ContType::iterator j = i + 1; 00301 // check whether every combination has been processed 00302 while (j != myClusters.end()) { 00303 // check whether the current clusters overlap 00304 if ((*i)->isWeakDistrictConnRealisation(*j)) { 00305 joinAble.push_back(*j); 00306 } 00307 j++; 00308 } 00309 for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin(); 00310 k != joinAble.end(); k++) { 00311 // add the overlaping cluster 00312 (*i)->add(*k); 00313 // erase the overlaping cluster 00314 delete *k; 00315 myClusters.erase(find(myClusters.begin(), myClusters.end(), *k)); 00316 } 00317 // 00318 if (joinAble.size() > 0) { 00319 i = myClusters.begin(); 00320 // clear temporary storages 00321 joinAble.clear(); 00322 pos = 0; 00323 } else { 00324 i++; 00325 pos++; 00326 MsgHandler::getMessageInstance()->progressMsg("Checked(3): " + toString(pos) + "/" + toString(myClusters.size()) + " "); 00327 } 00328 } 00329 } 00330 00331 00332 bool 00333 NIVissimConnectionCluster::joinable(NIVissimConnectionCluster* c2, SUMOReal offset) { 00334 // join clusters which have at least one connection in common 00335 if (VectorHelper<int>::subSetExists(myConnections, c2->myConnections)) { 00336 return true; 00337 } 00338 00339 // connections shall overlap otherwise 00340 if (!overlapsWith(c2, offset)) { 00341 return false; 00342 } 00343 00344 // at least one of the clusters shall not be assigned to a node in previous (!!!??) 00345 if (hasNodeCluster() && c2->hasNodeCluster()) { 00346 return false; 00347 } 00348 00349 // join clusters which where connections do disturb each other 00350 if (VectorHelper<int>::subSetExists(c2->getDisturbanceParticipators(), myConnections) 00351 || 00352 VectorHelper<int>::subSetExists(getDisturbanceParticipators(), c2->myConnections)) { 00353 00354 return true; 00355 } 00356 00357 00358 // join clusters which do share the same incoming or outgoing edges (not mutually) 00359 IntVector extendedOutgoing1; 00360 IntVector extendedIncoming1; 00361 IntVector extendedOutgoing2; 00362 IntVector extendedIncoming2; 00363 if (myIncomingEdges.size() > 1 || c2->myIncomingEdges.size() > 1) { 00364 extendedOutgoing1 = 00365 extendByToTreatAsSame(myOutgoingEdges, myIncomingEdges); 00366 extendedIncoming1 = 00367 extendByToTreatAsSame(myIncomingEdges, myOutgoingEdges); 00368 extendedOutgoing2 = 00369 extendByToTreatAsSame(c2->myOutgoingEdges, c2->myIncomingEdges); 00370 extendedIncoming2 = 00371 extendByToTreatAsSame(c2->myIncomingEdges, c2->myOutgoingEdges); 00372 } else { 00373 extendedOutgoing1 = myIncomingEdges; 00374 extendedIncoming1 = myOutgoingEdges; 00375 extendedOutgoing2 = c2->myIncomingEdges; 00376 extendedIncoming2 = c2->myOutgoingEdges; 00377 } 00378 00379 if (VectorHelper<int>::subSetExists(extendedOutgoing1, extendedOutgoing2) 00380 || 00381 VectorHelper<int>::subSetExists(extendedIncoming1, extendedIncoming2) 00382 ) { 00383 return true; 00384 } 00385 return false; 00386 } 00387 00388 00389 bool 00390 NIVissimConnectionCluster::isWeakDistrictConnRealisation(NIVissimConnectionCluster* c2) { 00391 if ((myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1)) { 00392 return false; 00393 } 00394 if ((c2->myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1)) { 00395 return false; 00396 } 00397 00398 // ok, may be the other way round 00399 if (myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1) { 00400 return c2->isWeakDistrictConnRealisation(this); 00401 } 00402 // connections must cross 00403 bool crosses = false; 00404 for (IntVector::const_iterator j1 = myConnections.begin(); j1 != myConnections.end() && !crosses; j1++) { 00405 NIVissimConnection* c1 = NIVissimConnection::dictionary(*j1); 00406 const PositionVector& g1 = c1->getGeometry(); 00407 for (IntVector::const_iterator j2 = c2->myConnections.begin(); j2 != c2->myConnections.end() && !crosses; j2++) { 00408 NIVissimConnection* c2 = NIVissimConnection::dictionary(*j2); 00409 const PositionVector& g2 = c2->getGeometry(); 00410 if (g1.intersects(g2)) { 00411 crosses = true; 00412 } 00413 } 00414 } 00415 if (!crosses) { 00416 return false; 00417 } 00418 // ok, check for connection 00419 if (myOutgoingEdges.size() != 1 || c2->myIncomingEdges.size() != 1) { 00420 return false; 00421 } 00422 // check whether the connection is bidirectional 00423 NIVissimEdge* oe = NIVissimEdge::dictionary(myOutgoingEdges[0]); 00424 NIVissimEdge* ie = NIVissimEdge::dictionary(c2->myIncomingEdges[0]); 00425 if (oe == 0 || ie == 0) { 00426 return false; 00427 } 00428 Line l1(oe->getGeometry().getBegin(), oe->getGeometry().getEnd()); 00429 Line l2(ie->getGeometry().getEnd(), ie->getGeometry().getBegin()); 00430 SUMOReal a1 = l1.atan2DegreeAngle(); 00431 SUMOReal a2 = l2.atan2DegreeAngle(); 00432 return fabs(a1 - a2) < 5; 00433 } 00434 00435 00436 bool 00437 NIVissimConnectionCluster::liesOnSameEdgesEnd(NIVissimConnectionCluster* cc2) { 00438 // 00439 for (IntVector::iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00440 NIVissimConnection* c1 = NIVissimConnection::dictionary(*i); 00441 for (IntVector::iterator j = cc2->myConnections.begin(); j != cc2->myConnections.end(); j++) { 00442 NIVissimConnection* c2 = NIVissimConnection::dictionary(*j); 00443 if (c1->getFromEdgeID() == c2->getFromEdgeID()) { 00444 NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID()); 00445 const PositionVector& g = e->getGeometry(); 00446 SUMOReal pos1 = GeomHelper::nearest_position_on_line_to_point2D( 00447 g.getBegin(), g.getEnd(), c1->getBoundary().getCenter()); 00448 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point2D( 00449 g.getBegin(), g.getEnd(), c2->getBoundary().getCenter()); 00450 if (pos1 <= 5.0 && pos2 <= 5.0) { 00451 return true; 00452 } 00453 } 00454 if (c1->getToEdgeID() == c2->getToEdgeID()) { 00455 NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID()); 00456 const PositionVector& g = e->getGeometry(); 00457 SUMOReal pos1 = GeomHelper::nearest_position_on_line_to_point2D( 00458 g.getBegin(), g.getEnd(), c1->getBoundary().getCenter()); 00459 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point2D( 00460 g.getBegin(), g.getEnd(), c2->getBoundary().getCenter()); 00461 if (pos1 >= g.length() - 5.0 && pos2 >= g.length() - 5.0) { 00462 return true; 00463 } 00464 } 00465 } 00466 } 00467 return false; 00468 } 00469 00470 00471 IntVector 00472 NIVissimConnectionCluster::extendByToTreatAsSame(const IntVector& iv1, 00473 const IntVector& iv2) const { 00474 IntVector ret(iv1); 00475 for (IntVector::const_iterator i = iv1.begin(); i != iv1.end(); i++) { 00476 NIVissimEdge* e = NIVissimEdge::dictionary(*i); 00477 const std::vector<NIVissimEdge*> treatAsSame = e->getToTreatAsSame(); 00478 for (std::vector<NIVissimEdge*>::const_iterator j = treatAsSame.begin(); j != treatAsSame.end(); j++) { 00479 if (find(iv2.begin(), iv2.end(), (*j)->getID()) == iv2.end()) { 00480 ret.push_back((*j)->getID()); 00481 } 00482 } 00483 } 00484 return ret; 00485 } 00486 00487 IntVector 00488 NIVissimConnectionCluster::getDisturbanceParticipators() { 00489 IntVector ret; 00490 for (IntVector::iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00491 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00492 const IntVector& disturbances = c->getDisturbances(); 00493 for (IntVector::const_iterator j = disturbances.begin(); j != disturbances.end(); j++) { 00494 NIVissimDisturbance* d = NIVissimDisturbance::dictionary(*j); 00495 ret.push_back(d->getEdgeID()); 00496 ret.push_back(d->getDisturbanceID()); 00497 } 00498 } 00499 return ret; 00500 } 00501 00502 00503 void 00504 NIVissimConnectionCluster::buildNodeClusters() { 00505 for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) { 00506 IntVector disturbances; 00507 IntVector tls; 00508 IntVector nodes; 00509 int tlsid = -1; 00510 int nodeid = -1; 00511 if ((*i)->myConnections.size() > 0) { 00512 (*i)->recomputeBoundary(); 00513 disturbances = NIVissimDisturbance::getWithin((*i)->myBoundary); 00514 } 00515 nodes = (*i)->myNodes;//NIVissimTL::getWithin((*i)->myBoundary, 5.0); 00516 if (nodes.size() > 1) { 00517 WRITE_WARNING("NIVissimConnectionCluster:More than a single node"); 00518 // throw 1; // !!! eigentlich sollte hier nur eine Ampelanlage sein 00519 } 00520 if (nodes.size() > 0) { 00521 nodeid = nodes[0]; 00522 } 00523 // 00524 // 00525 int id = NIVissimNodeCluster::dictionary( 00526 nodeid, tlsid, (*i)->myConnections, 00527 disturbances, (*i)->myIncomingEdges.size() < 2); 00528 assert((*i)->myNodeCluster == id || (*i)->myNodeCluster < 0); 00529 (*i)->myNodeCluster = id; 00530 } 00531 } 00532 00533 00534 void 00535 NIVissimConnectionCluster::searchForConnection(int id) { 00536 int pos = 0; 00537 for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) { 00538 IntVector connections = (*i)->myConnections; 00539 if (find(connections.begin(), connections.end(), id) != connections.end()) { 00540 for (IntVector::iterator j = connections.begin(); j != connections.end(); j++) { 00541 int checkdummy = *j; 00542 } 00543 } 00544 pos++; 00545 } 00546 } 00547 00548 00549 void 00550 NIVissimConnectionCluster::_debugOut(std::ostream& into) { 00551 for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) { 00552 IntVector connections = (*i)->myConnections; 00553 for (IntVector::iterator j = connections.begin(); j != connections.end(); j++) { 00554 if (j != connections.begin()) { 00555 into << ", "; 00556 } 00557 into << *j; 00558 } 00559 into << "(" << (*i)->myBoundary << ")" << std::endl; 00560 } 00561 into << "---------------------------" << std::endl; 00562 } 00563 00564 00565 00566 bool 00567 NIVissimConnectionCluster::hasNodeCluster() const { 00568 return myNodeCluster != -1; 00569 } 00570 00571 00572 size_t 00573 NIVissimConnectionCluster::dictSize() { 00574 return myClusters.size(); 00575 } 00576 00577 00578 void 00579 NIVissimConnectionCluster::removeConnections(const NodeSubCluster& c) { 00580 for (NodeSubCluster::ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) { 00581 NIVissimConnection* conn = *i; 00582 int connid = conn->getID(); 00583 IntVector::iterator j = find(myConnections.begin(), myConnections.end(), connid); 00584 if (j != myConnections.end()) { 00585 myConnections.erase(j); 00586 } 00587 } 00588 recomputeBoundary(); 00589 } 00590 00591 00592 void 00593 NIVissimConnectionCluster::recomputeBoundary() { 00594 myBoundary = Boundary(); 00595 for (IntVector::iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00596 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00597 if (c != 0) { 00598 myBoundary.add(c->getFromGeomPosition()); 00599 myBoundary.add(c->getToGeomPosition()); 00600 if (c->getGeometry().size() != 0) { 00601 myBoundary.add(c->getGeometry().getBoxBoundary()); 00602 } 00603 } 00604 } 00605 assert(myBoundary.xmax() >= myBoundary.xmin()); 00606 } 00607 00608 00609 NBNode* 00610 NIVissimConnectionCluster::getNBNode() const { 00611 return NIVissimNodeCluster::dictionary(myNodeCluster)->getNBNode(); 00612 } 00613 00614 00615 bool 00616 NIVissimConnectionCluster::around(const Position& p, SUMOReal offset) const { 00617 assert(myBoundary.xmax() >= myBoundary.xmin()); 00618 return myBoundary.around(p, offset); 00619 } 00620 00621 00622 00623 void 00624 NIVissimConnectionCluster::recheckEdges() { 00625 assert(myConnections.size() != 0); 00626 // remove the cluster from all edges at first 00627 IntVector::iterator i; 00628 for (i = myEdges.begin(); i != myEdges.end(); i++) { 00629 NIVissimEdge* edge = NIVissimEdge::dictionary(*i); 00630 edge->removeFromConnectionCluster(this); 00631 } 00632 // clear edge information 00633 myEdges.clear(); 00634 // recheck which edges do still participate and add edges 00635 for (i = myConnections.begin(); i != myConnections.end(); i++) { 00636 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00637 assert(myBoundary.xmax() >= myBoundary.xmin()); 00638 if (myBoundary.around(c->getFromGeomPosition(), 5)) { 00639 myEdges.push_back(c->getFromEdgeID()); 00640 } 00641 assert(myBoundary.xmax() >= myBoundary.xmin()); 00642 if (myBoundary.around(c->getToGeomPosition(), 5)) { 00643 myEdges.push_back(c->getToEdgeID()); 00644 } 00645 } 00646 // connect edges 00647 for (i = myEdges.begin(); i != myEdges.end(); i++) { 00648 NIVissimEdge* edge = NIVissimEdge::dictionary(*i); 00649 edge->addToConnectionCluster(this); 00650 } 00651 } 00652 00653 00654 SUMOReal 00655 NIVissimConnectionCluster::getPositionForEdge(int edgeid) const { 00656 // return the middle of the connections when there are any 00657 if (myConnections.size() != 0) { 00658 SUMOReal sum = 0; 00659 size_t part = 0; 00660 IntVector::const_iterator i; 00661 for (i = myConnections.begin(); i != myConnections.end(); i++) { 00662 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00663 if (c->getFromEdgeID() == edgeid) { 00664 part++; 00665 sum += c->getFromPosition(); 00666 } 00667 if (c->getToEdgeID() == edgeid) { 00668 part++; 00669 sum += c->getToPosition(); 00670 } 00671 } 00672 if (part > 0) { 00673 return sum / (SUMOReal) part; 00674 } 00675 } 00676 // use the position of the node if possible 00677 if (myNodeCluster >= 0) { 00678 // try to find the nearest point on the edge 00679 // !!! only the main geometry is regarded 00680 NIVissimNodeDef* node = 00681 NIVissimNodeDef::dictionary(myNodeCluster); 00682 if (node != 0) { 00683 SUMOReal pos = node->getEdgePosition(edgeid); 00684 if (pos >= 0) { 00685 return pos; 00686 } 00687 } 00688 /* 00689 SUMOReal try1 = GeomHelper::nearest_position_on_line_to_point( 00690 edge->getBegin2D(), edge->getEnd2D(), node->getPos()); 00691 if(try1>=0) { 00692 return try1; 00693 } 00694 // try to use simple distance 00695 SUMOReal dist1 = 00696 GeomHelper::distance(node->getPos(), edge->getBegin2D()); 00697 SUMOReal dist2 = 00698 GeomHelper::distance(node->getPos(), edge->getEnd2D()); 00699 return dist1<dist2 00700 ? 0 : edge->getLength(); 00701 */ 00702 } 00703 // what else? 00704 WRITE_WARNING("NIVissimConnectionCluster: how to get an edge's position?"); 00705 // !!! 00706 assert(myBoundary.xmin() <= myBoundary.xmax()); 00707 NIVissimEdge* edge = NIVissimEdge::dictionary(edgeid); 00708 IntVector::const_iterator i = find(myEdges.begin(), myEdges.end(), edgeid); 00709 if (i == myEdges.end()) { 00710 // edge does not exist!? 00711 throw 1; 00712 } 00713 const PositionVector& edgeGeom = edge->getGeometry(); 00714 Position p = GeomHelper::crossPoint(myBoundary, edgeGeom); 00715 return GeomHelper::nearest_position_on_line_to_point2D( 00716 edgeGeom.getBegin(), edgeGeom.getEnd(), p); 00717 } 00718 00719 00720 00721 void 00722 NIVissimConnectionCluster::clearDict() { 00723 for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) { 00724 delete(*i); 00725 } 00726 myClusters.clear(); 00727 myFirstFreeID = 100000; 00728 } 00729 00730 00731 PositionVector 00732 NIVissimConnectionCluster::getIncomingContinuationGeometry(NIVissimEdge* e) const { 00733 // collect connection where this edge is the incoming one 00734 std::vector<NIVissimConnection*> edgeIsIncoming; 00735 for (IntVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00736 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00737 if (c->getFromEdgeID() == e->getID()) { 00738 edgeIsIncoming.push_back(c); 00739 } 00740 } 00741 // 00742 if (edgeIsIncoming.size() == 0) { 00743 return PositionVector(); 00744 } 00745 // sort connected edges in same direction 00746 sort(edgeIsIncoming.begin(), edgeIsIncoming.end(), 00747 same_direction_sorter(e->getGeometry().beginEndAngle())); 00748 NIVissimConnection* c = *(edgeIsIncoming.begin()); 00749 return c->getGeometry(); 00750 } 00751 00752 00753 00754 NIVissimConnection* 00755 NIVissimConnectionCluster::getIncomingContinuation(NIVissimEdge* e) const { 00756 // collect connection where this edge is the incoming one 00757 std::vector<NIVissimConnection*> edgeIsIncoming; 00758 for (IntVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00759 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00760 if (c->getFromEdgeID() == e->getID()) { 00761 edgeIsIncoming.push_back(c); 00762 } 00763 } 00764 // 00765 if (edgeIsIncoming.size() == 0) { 00766 return 0; 00767 } 00768 // sort connected edges in same direction 00769 sort(edgeIsIncoming.begin(), edgeIsIncoming.end(), 00770 same_direction_sorter(e->getGeometry().beginEndAngle())); 00771 return *(edgeIsIncoming.begin()); 00772 } 00773 00774 00775 00776 PositionVector 00777 NIVissimConnectionCluster::getOutgoingContinuationGeometry(NIVissimEdge* e) const { 00778 // collect connection where this edge is the outgoing one 00779 std::vector<NIVissimConnection*> edgeIsOutgoing; 00780 for (IntVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00781 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00782 if (c->getToEdgeID() == e->getID()) { 00783 edgeIsOutgoing.push_back(c); 00784 } 00785 } 00786 // 00787 if (edgeIsOutgoing.size() == 0) { 00788 return PositionVector(); 00789 } 00790 // sort connected edges in same direction 00791 sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(), 00792 same_direction_sorter(e->getGeometry().beginEndAngle())); 00793 NIVissimConnection* c = *(edgeIsOutgoing.begin()); 00794 return c->getGeometry(); 00795 } 00796 00797 00798 NIVissimConnection* 00799 NIVissimConnectionCluster::getOutgoingContinuation(NIVissimEdge* e) const { 00800 // collect connection where this edge is the outgoing one 00801 std::vector<NIVissimConnection*> edgeIsOutgoing; 00802 for (IntVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) { 00803 NIVissimConnection* c = NIVissimConnection::dictionary(*i); 00804 if (c->getToEdgeID() == e->getID()) { 00805 edgeIsOutgoing.push_back(c); 00806 } 00807 } 00808 // 00809 if (edgeIsOutgoing.size() == 0) { 00810 return 0; 00811 } 00812 // sort connected edges in same direction 00813 sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(), 00814 same_direction_sorter(e->getGeometry().beginEndAngle())); 00815 return *(edgeIsOutgoing.begin()); 00816 } 00817 00818 00819 00820 /****************************************************************************/ 00821