SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NIVissimConnectionCluster.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // -------------------
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
12 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <algorithm>
34 #include <iostream>
35 #include <cassert>
36 #include <iterator>
37 #include <utils/geom/Boundary.h>
38 #include <utils/geom/GeomHelper.h>
41 #include <utils/common/ToString.h>
42 #include "NIVissimConnection.h"
43 #include "NIVissimDisturbance.h"
44 #include "NIVissimNodeCluster.h"
45 #include "NIVissimNodeDef.h"
46 #include "NIVissimEdge.h"
47 #include "NIVissimTL.h"
49 
50 #ifdef CHECK_MEMORY_LEAKS
51 #include <foreign/nvwa/debug_new.h>
52 #endif // CHECK_MEMORY_LEAKS
53 
54 
55 // ===========================================================================
56 // static members
57 // ===========================================================================
61 
62 
63 
64 // ===========================================================================
65 // method definitions
66 // ===========================================================================
67 // ---------------------------------------------------------------------------
68 // NIVissimConnectionCluster::NodeSubCluster - methods
69 // ---------------------------------------------------------------------------
71  add(c);
72 }
73 
74 
76 
77 
78 void
81  myConnections.push_back(c);
82 }
83 
84 
85 void
87  for (ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) {
88  add(*i);
89  }
90 }
91 
92 
93 size_t
95  return myConnections.size();
96 }
97 
98 
99 std::vector<int>
101  std::vector<int> ret;
103  for (ConnectionCont::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
104  ret.push_back((*i)->getID());
105  (*i)->setNodeCluster(id);
106  }
107  return ret;
108 }
109 
110 
111 bool
114  SUMOReal offset) {
115  assert(myBoundary.xmax() >= myBoundary.xmin());
116  assert(c.myBoundary.xmax() >= c.myBoundary.xmin());
117  return myBoundary.overlapsWith(c.myBoundary, offset);
118 }
119 
120 
121 
122 // ---------------------------------------------------------------------------
123 // NIVissimConnectionCluster - methods
124 // ---------------------------------------------------------------------------
126  const std::vector<int>& connections, int nodeCluster, int edgeid)
127  : myConnections(connections), myNodeCluster(nodeCluster),
130  myClusters.push_back(this);
131  assert(edgeid > 0);
132  if (edgeid >= 0) {
133  myEdges.push_back(edgeid);
134  }
135  // add information about incoming and outgoing edges
136  for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) {
138  assert(c != 0);
139  myOutgoingEdges.push_back(c->getToEdgeID());
140  myIncomingEdges.push_back(c->getFromEdgeID());
141  assert(c->getFromEdgeID() == edgeid || c->getToEdgeID() == edgeid);
142  }
145 }
146 
147 
149  const std::vector<int>& connections, const Boundary& boundary,
150  int nodeCluster, const std::vector<int>& edges)
151  : myConnections(connections), myBoundary(boundary),
152  myNodeCluster(nodeCluster), myEdges(edges) {
153  myClusters.push_back(this);
155  assert(myBoundary.xmax() >= myBoundary.xmin());
156  // add information about incoming and outgoing edges
157  for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) {
159  assert(c != 0);
160  myOutgoingEdges.push_back(c->getToEdgeID());
161  myIncomingEdges.push_back(c->getFromEdgeID());
162  assert(find(edges.begin(), edges.end(), c->getFromEdgeID()) != edges.end()
163  ||
164  find(edges.begin(), edges.end(), c->getToEdgeID()) != edges.end());
165  }
168 }
169 
170 
172 
173 
174 
175 int
177  return myFirstFreeID++;
178 }
179 
180 
181 bool
183  SUMOReal offset) const {
184  assert(myBoundary.xmax() >= myBoundary.xmin());
185  assert(c->myBoundary.xmax() >= c->myBoundary.xmin());
186  return c->myBoundary.overlapsWith(myBoundary, offset);
187 }
188 
189 
190 void
192  assert(myBoundary.xmax() >= myBoundary.xmin());
193  assert(c->myBoundary.xmax() >= c->myBoundary.xmin());
195  for (std::vector<int>::iterator i = c->myConnections.begin(); i != c->myConnections.end(); i++) {
196  myConnections.push_back(*i);
197  }
199  assert(myNodeCluster == -1 || c->myNodeCluster == -1);
200  if (myNodeCluster == -1) {
202  }
203  // inform edges about merging
204  // !!! merge should be done within one method
205  for (std::vector<int>::iterator j = c->myEdges.begin(); j != c->myEdges.end(); j++) {
206  NIVissimEdge::dictionary(*j)->mergedInto(c, this);
207  }
208  copy(c->myEdges.begin(), c->myEdges.end(), back_inserter(myEdges));
209  copy(c->myIncomingEdges.begin(), c->myIncomingEdges.end(),
210  back_inserter(myIncomingEdges));
211  copy(c->myOutgoingEdges.begin(), c->myOutgoingEdges.end(),
212  back_inserter(myOutgoingEdges));
214  VectorHelper<int>::removeDouble(myIncomingEdges);
215  VectorHelper<int>::removeDouble(myOutgoingEdges);
216 }
217 
218 
219 
220 void
222  // !!! ...
223  // Further, we try to omit joining of overlaping nodes. This is done by holding
224  // the lists of incoming and outgoing edges and incrementally building the nodes
225  // regarding this information
226  std::vector<NIVissimConnectionCluster*> joinAble;
227  size_t pos = 0;
228  ContType::iterator i = myClusters.begin();
229  // step1 - faster but no complete
230  while (i != myClusters.end()) {
231  joinAble.clear();
232  ContType::iterator j = i + 1;
233 
234  // check whether every combination has been processed
235  while (j != myClusters.end()) {
236  // check whether the current clusters overlap
237  if ((*i)->joinable(*j, offset)) {
238  joinAble.push_back(*j);
239  }
240  j++;
241  }
242  for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
243  k != joinAble.end(); k++) {
244  // add the overlaping cluster
245  (*i)->add(*k);
246  // erase the overlaping cluster
247  delete *k;
248  myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
249  }
250  //
251  if (joinAble.size() > 0) {
252  i = myClusters.begin() + pos;
253  // clear temporary storages
254  joinAble.clear();
255  } else {
256  i++;
257  pos++;
258  }
259  }
260  //
261  pos = 0;
262  i = myClusters.begin();
263  while (i != myClusters.end()) {
264  ContType::iterator j = i + 1;
265  // check whether every combination has been processed
266  while (j != myClusters.end()) {
267  // check whether the current clusters overlap
268  if ((*i)->joinable(*j, offset)) {
269  joinAble.push_back(*j);
270  }
271  j++;
272  }
273  for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
274  k != joinAble.end(); k++) {
275  // add the overlaping cluster
276  (*i)->add(*k);
277  // erase the overlaping cluster
278  delete *k;
279  myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
280  }
281  //
282  if (joinAble.size() > 0) {
283  i = myClusters.begin();
284  // clear temporary storages
285  joinAble.clear();
286  pos = 0;
287  } else {
288  i++;
289  pos++;
290  }
291  }
292  // check for weak district connections
293  // (junctions made up by district connections, where prohibitions are not
294  // modelled properly)
295  pos = 0;
296  i = myClusters.begin();
297  while (i != myClusters.end()) {
298  ContType::iterator j = i + 1;
299  // check whether every combination has been processed
300  while (j != myClusters.end()) {
301  // check whether the current clusters overlap
302  if ((*i)->isWeakDistrictConnRealisation(*j)) {
303  joinAble.push_back(*j);
304  }
305  j++;
306  }
307  for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
308  k != joinAble.end(); k++) {
309  // add the overlaping cluster
310  (*i)->add(*k);
311  // erase the overlaping cluster
312  delete *k;
313  myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
314  }
315  //
316  if (joinAble.size() > 0) {
317  i = myClusters.begin();
318  // clear temporary storages
319  joinAble.clear();
320  pos = 0;
321  } else {
322  i++;
323  pos++;
324  }
325  }
326 }
327 
328 
329 bool
331  // join clusters which have at least one connection in common
333  return true;
334  }
335 
336  // connections shall overlap otherwise
337  if (!overlapsWith(c2, offset)) {
338  return false;
339  }
340 
341  // at least one of the clusters shall not be assigned to a node in previous (!!!??)
342  if (hasNodeCluster() && c2->hasNodeCluster()) {
343  return false;
344  }
345 
346  // join clusters which where connections do disturb each other
348  ||
350 
351  return true;
352  }
353 
354 
355  // join clusters which do share the same incoming or outgoing edges (not mutually)
356  std::vector<int> extendedOutgoing1;
357  std::vector<int> extendedIncoming1;
358  std::vector<int> extendedOutgoing2;
359  std::vector<int> extendedIncoming2;
360  if (myIncomingEdges.size() > 1 || c2->myIncomingEdges.size() > 1) {
361  extendedOutgoing1 =
363  extendedIncoming1 =
365  extendedOutgoing2 =
367  extendedIncoming2 =
369  } else {
370  extendedOutgoing1 = myIncomingEdges;
371  extendedIncoming1 = myOutgoingEdges;
372  extendedOutgoing2 = c2->myIncomingEdges;
373  extendedIncoming2 = c2->myOutgoingEdges;
374  }
375 
376  if (VectorHelper<int>::subSetExists(extendedOutgoing1, extendedOutgoing2)
377  ||
378  VectorHelper<int>::subSetExists(extendedIncoming1, extendedIncoming2)
379  ) {
380  return true;
381  }
382  return false;
383 }
384 
385 
386 bool
388  if ((myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1)) {
389  return false;
390  }
391  if ((c2->myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1)) {
392  return false;
393  }
394 
395  // ok, may be the other way round
396  if (myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1) {
397  return c2->isWeakDistrictConnRealisation(this);
398  }
399  // connections must cross
400  bool crosses = false;
401  for (std::vector<int>::const_iterator j1 = myConnections.begin(); j1 != myConnections.end() && !crosses; j1++) {
403  const PositionVector& g1 = c1->getGeometry();
404  for (std::vector<int>::const_iterator j2 = c2->myConnections.begin(); j2 != c2->myConnections.end() && !crosses; j2++) {
406  const PositionVector& g2 = c2->getGeometry();
407  if (g1.intersects(g2)) {
408  crosses = true;
409  }
410  }
411  }
412  if (!crosses) {
413  return false;
414  }
415  // ok, check for connection
416  if (myOutgoingEdges.size() != 1 || c2->myIncomingEdges.size() != 1) {
417  return false;
418  }
419  // check whether the connection is bidirectional
422  if (oe == 0 || ie == 0) {
423  return false;
424  }
425  Line l1(oe->getGeometry().getBegin(), oe->getGeometry().getEnd());
426  Line l2(ie->getGeometry().getEnd(), ie->getGeometry().getBegin());
427  SUMOReal a1 = l1.atan2DegreeAngle();
428  SUMOReal a2 = l2.atan2DegreeAngle();
429  return fabs(a1 - a2) < 5;
430 }
431 
432 
433 bool
435  //
436  for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
438  for (std::vector<int>::iterator j = cc2->myConnections.begin(); j != cc2->myConnections.end(); j++) {
440  if (c1->getFromEdgeID() == c2->getFromEdgeID()) {
442  const PositionVector& g = e->getGeometry();
444  g.getBegin(), g.getEnd(), c1->getBoundary().getCenter());
446  g.getBegin(), g.getEnd(), c2->getBoundary().getCenter());
447  if (pos1 <= 5.0 && pos2 <= 5.0) {
448  return true;
449  }
450  }
451  if (c1->getToEdgeID() == c2->getToEdgeID()) {
453  const PositionVector& g = e->getGeometry();
455  g.getBegin(), g.getEnd(), c1->getBoundary().getCenter());
457  g.getBegin(), g.getEnd(), c2->getBoundary().getCenter());
458  if (pos1 >= g.length() - 5.0 && pos2 >= g.length() - 5.0) {
459  return true;
460  }
461  }
462  }
463  }
464  return false;
465 }
466 
467 
468 std::vector<int>
470  const std::vector<int>& iv2) const {
471  std::vector<int> ret(iv1);
472  for (std::vector<int>::const_iterator i = iv1.begin(); i != iv1.end(); i++) {
474  const std::vector<NIVissimEdge*> treatAsSame = e->getToTreatAsSame();
475  for (std::vector<NIVissimEdge*>::const_iterator j = treatAsSame.begin(); j != treatAsSame.end(); j++) {
476  if (find(iv2.begin(), iv2.end(), (*j)->getID()) == iv2.end()) {
477  ret.push_back((*j)->getID());
478  }
479  }
480  }
481  return ret;
482 }
483 
484 std::vector<int>
486  std::vector<int> ret;
487  for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
489  const std::vector<int>& disturbances = c->getDisturbances();
490  for (std::vector<int>::const_iterator j = disturbances.begin(); j != disturbances.end(); j++) {
492  ret.push_back(d->getEdgeID());
493  ret.push_back(d->getDisturbanceID());
494  }
495  }
496  return ret;
497 }
498 
499 
500 void
502  for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
503  std::vector<int> disturbances;
504  std::vector<int> tls;
505  std::vector<int> nodes;
506  int tlsid = -1;
507  int nodeid = -1;
508  if ((*i)->myConnections.size() > 0) {
509  (*i)->recomputeBoundary();
510  disturbances = NIVissimDisturbance::getWithin((*i)->myBoundary);
511  }
512  nodes = (*i)->myNodes;//NIVissimTL::getWithin((*i)->myBoundary, 5.0);
513  if (nodes.size() > 1) {
514  WRITE_WARNING("NIVissimConnectionCluster:More than a single node");
515  // throw 1; // !!! eigentlich sollte hier nur eine Ampelanlage sein
516  }
517  if (nodes.size() > 0) {
518  nodeid = nodes[0];
519  }
520  //
521  //
523  nodeid, tlsid, (*i)->myConnections,
524  disturbances, (*i)->myIncomingEdges.size() < 2);
525  assert((*i)->myNodeCluster == id || (*i)->myNodeCluster < 0);
526  (*i)->myNodeCluster = id;
527  }
528 }
529 
530 
531 void
533  int pos = 0;
534  for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
535  std::vector<int> connections = (*i)->myConnections;
536  if (find(connections.begin(), connections.end(), id) != connections.end()) {
537  for (std::vector<int>::iterator j = connections.begin(); j != connections.end(); j++) {
538  int checkdummy = *j;
539  }
540  }
541  pos++;
542  }
543 }
544 
545 
546 void
548  for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
549  std::vector<int> connections = (*i)->myConnections;
550  for (std::vector<int>::iterator j = connections.begin(); j != connections.end(); j++) {
551  if (j != connections.begin()) {
552  into << ", ";
553  }
554  into << *j;
555  }
556  into << "(" << (*i)->myBoundary << ")" << std::endl;
557  }
558  into << "---------------------------" << std::endl;
559 }
560 
561 
562 
563 bool
565  return myNodeCluster != -1;
566 }
567 
568 
569 size_t
571  return myClusters.size();
572 }
573 
574 
575 void
577  for (NodeSubCluster::ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) {
578  NIVissimConnection* conn = *i;
579  int connid = conn->getID();
580  std::vector<int>::iterator j = find(myConnections.begin(), myConnections.end(), connid);
581  if (j != myConnections.end()) {
582  myConnections.erase(j);
583  }
584  }
586 }
587 
588 
589 void
591  myBoundary = Boundary();
592  for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
594  if (c != 0) {
597  if (c->getGeometry().size() != 0) {
599  }
600  }
601  }
602  assert(myBoundary.xmax() >= myBoundary.xmin());
603 }
604 
605 
606 NBNode*
608  return NIVissimNodeCluster::dictionary(myNodeCluster)->getNBNode();
609 }
610 
611 
612 bool
614  assert(myBoundary.xmax() >= myBoundary.xmin());
615  return myBoundary.around(p, offset);
616 }
617 
618 
619 
620 void
622  assert(myConnections.size() != 0);
623  // remove the cluster from all edges at first
624  std::vector<int>::iterator i;
625  for (i = myEdges.begin(); i != myEdges.end(); i++) {
627  edge->removeFromConnectionCluster(this);
628  }
629  // clear edge information
630  myEdges.clear();
631  // recheck which edges do still participate and add edges
632  for (i = myConnections.begin(); i != myConnections.end(); i++) {
634  assert(myBoundary.xmax() >= myBoundary.xmin());
635  if (myBoundary.around(c->getFromGeomPosition(), 5)) {
636  myEdges.push_back(c->getFromEdgeID());
637  }
638  assert(myBoundary.xmax() >= myBoundary.xmin());
639  if (myBoundary.around(c->getToGeomPosition(), 5)) {
640  myEdges.push_back(c->getToEdgeID());
641  }
642  }
643  // connect edges
644  for (i = myEdges.begin(); i != myEdges.end(); i++) {
646  edge->addToConnectionCluster(this);
647  }
648 }
649 
650 
651 SUMOReal
653  // return the middle of the connections when there are any
654  if (myConnections.size() != 0) {
655  SUMOReal sum = 0;
656  size_t part = 0;
657  std::vector<int>::const_iterator i;
658  for (i = myConnections.begin(); i != myConnections.end(); i++) {
660  if (c->getFromEdgeID() == edgeid) {
661  part++;
662  sum += c->getFromPosition();
663  }
664  if (c->getToEdgeID() == edgeid) {
665  part++;
666  sum += c->getToPosition();
667  }
668  }
669  if (part > 0) {
670  return sum / (SUMOReal) part;
671  }
672  }
673  // use the position of the node if possible
674  if (myNodeCluster >= 0) {
675  // try to find the nearest point on the edge
676  // !!! only the main geometry is regarded
677  NIVissimNodeDef* node =
679  if (node != 0) {
680  SUMOReal pos = node->getEdgePosition(edgeid);
681  if (pos >= 0) {
682  return pos;
683  }
684  }
685  /*
686  SUMOReal try1 = GeomHelper::nearest_position_on_line_to_point(
687  edge->getBegin2D(), edge->getEnd2D(), node->getPos());
688  if(try1>=0) {
689  return try1;
690  }
691  // try to use simple distance
692  SUMOReal dist1 =
693  GeomHelper::distance(node->getPos(), edge->getBegin2D());
694  SUMOReal dist2 =
695  GeomHelper::distance(node->getPos(), edge->getEnd2D());
696  return dist1<dist2
697  ? 0 : edge->getLength();
698  */
699  }
700  // what else?
701  WRITE_WARNING("NIVissimConnectionCluster: how to get an edge's position?");
702  // !!!
703  assert(myBoundary.xmin() <= myBoundary.xmax());
704  NIVissimEdge* edge = NIVissimEdge::dictionary(edgeid);
705  std::vector<int>::const_iterator i = find(myEdges.begin(), myEdges.end(), edgeid);
706  if (i == myEdges.end()) {
707  // edge does not exist!?
708  throw 1;
709  }
710  const PositionVector& edgeGeom = edge->getGeometry();
713  edgeGeom.getBegin(), edgeGeom.getEnd(), p);
714 }
715 
716 
717 
718 void
720  for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
721  delete(*i);
722  }
723  myClusters.clear();
724  myFirstFreeID = 100000;
725 }
726 
727 
730  // collect connection where this edge is the incoming one
731  std::vector<NIVissimConnection*> edgeIsIncoming;
732  for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
734  if (c->getFromEdgeID() == e->getID()) {
735  edgeIsIncoming.push_back(c);
736  }
737  }
738  //
739  if (edgeIsIncoming.size() == 0) {
740  return PositionVector();
741  }
742  // sort connected edges in same direction
743  sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),
745  NIVissimConnection* c = *(edgeIsIncoming.begin());
746  return c->getGeometry();
747 }
748 
749 
750 
753  // collect connection where this edge is the incoming one
754  std::vector<NIVissimConnection*> edgeIsIncoming;
755  for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
757  if (c->getFromEdgeID() == e->getID()) {
758  edgeIsIncoming.push_back(c);
759  }
760  }
761  //
762  if (edgeIsIncoming.size() == 0) {
763  return 0;
764  }
765  // sort connected edges in same direction
766  sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),
768  return *(edgeIsIncoming.begin());
769 }
770 
771 
772 
775  // collect connection where this edge is the outgoing one
776  std::vector<NIVissimConnection*> edgeIsOutgoing;
777  for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
779  if (c->getToEdgeID() == e->getID()) {
780  edgeIsOutgoing.push_back(c);
781  }
782  }
783  //
784  if (edgeIsOutgoing.size() == 0) {
785  return PositionVector();
786  }
787  // sort connected edges in same direction
788  sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),
790  NIVissimConnection* c = *(edgeIsOutgoing.begin());
791  return c->getGeometry();
792 }
793 
794 
797  // collect connection where this edge is the outgoing one
798  std::vector<NIVissimConnection*> edgeIsOutgoing;
799  for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
801  if (c->getToEdgeID() == e->getID()) {
802  edgeIsOutgoing.push_back(c);
803  }
804  }
805  //
806  if (edgeIsOutgoing.size() == 0) {
807  return 0;
808  }
809  // sort connected edges in same direction
810  sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),
812  return *(edgeIsOutgoing.begin());
813 }
814 
815 
816 
817 /****************************************************************************/
818