Eclipse SUMO - Simulation of Urban MObility
NIVissimEdge.cpp
Go to the documentation of this file.
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 /****************************************************************************/
20 // A temporary storage for edges imported from Vissim
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <string>
25 #include <algorithm>
26 #include <map>
27 #include <cassert>
28 #include <iomanip>
29 #include <cmath>
30 #include <iostream>
31 #include <sstream>
32 #include <iterator>
33 #include <utils/common/ToString.h>
35 #include <utils/geom/GeomHelper.h>
37 #include <netbuild/NBNode.h>
38 #include <netbuild/NBNodeCont.h>
40 #include "NIVissimNodeCluster.h"
43 #include "NIVissimConnection.h"
44 #include "NIVissimDisturbance.h"
45 #include "NIVissimEdge.h"
47 
48 
49 // ===========================================================================
50 // static members
51 // ===========================================================================
53 int NIVissimEdge::myMaxID = 0;
54 std::vector<std::string> NIVissimEdge::myLanesWithMissingSpeeds;
55 
56 
57 // ===========================================================================
58 // method definitions
59 // ===========================================================================
61  : myEdgeID(edgeid) {}
62 
63 
64 int
66  int c2id) const {
69  double pos1 =
70  c1->getFromEdgeID() == myEdgeID
71  ? c1->getFromPosition() : c1->getToPosition();
72  double pos2 =
73  c2->getFromEdgeID() == myEdgeID
74  ? c2->getFromPosition() : c2->getToPosition();
75  return pos1 < pos2;
76 }
77 
78 
79 
80 
81 
82 
83 
84 
86  : myEdgeID(edgeid) {}
87 
88 
89 int
92  NIVissimConnectionCluster* cc2) const {
93  double pos1 = cc1->getPositionForEdge(myEdgeID);
94  double pos2 = cc2->getPositionForEdge(myEdgeID);
95  if (pos2 < 0 || pos1 < 0) {
96  cc1->getPositionForEdge(myEdgeID);
97  cc2->getPositionForEdge(myEdgeID);
98  }
99  assert(pos1 >= 0 && pos2 >= 0);
100  return pos1 < pos2;
101 }
102 
103 
104 
105 
106 NIVissimEdge::NIVissimEdge(int id, const std::string& name,
107  const std::string& type,
108  std::vector<double> laneWidths,
109  double zuschlag1, double zuschlag2,
110  double /*length*/, const PositionVector& geom,
111  const NIVissimClosedLanesVector& clv) :
112  NIVissimAbstractEdge(id, geom),
113  myName(name), myType(type), myNoLanes((int)laneWidths.size()),
114  myLaneWidths(laneWidths),
115  myZuschlag1(zuschlag1), myZuschlag2(zuschlag2),
116  myClosedLanes(clv),
117  myLaneSpeeds(myNoLanes, -1),
118  myAmWithinJunction(false)
119  //, mySpeed(-1)
120 {
121  assert(myNoLanes >= 0);
122  if (myMaxID < myID) {
123  myMaxID = myID;
124  }
125 }
126 
127 
129  for (NIVissimClosedLanesVector::iterator i = myClosedLanes.begin(); i != myClosedLanes.end(); i++) {
130  delete (*i);
131  }
132  myClosedLanes.clear();
133 }
134 
135 
136 bool
137 NIVissimEdge::dictionary(int id, const std::string& name,
138  const std::string& type, int noLanes,
139  double zuschlag1, double zuschlag2, double length,
140  const PositionVector& geom,
141  const NIVissimClosedLanesVector& clv) {
142  NIVissimEdge* o = new NIVissimEdge(id, name, type, std::vector<double>(noLanes, NBEdge::UNSPECIFIED_WIDTH),
143  zuschlag1, zuschlag2, length, geom, clv);
144  if (!dictionary(id, o)) {
145  delete o;
146  return false;
147  }
148  return true;
149 }
150 
151 
152 
153 bool
155  DictType::iterator i = myDict.find(id);
156  if (i == myDict.end()) {
157  myDict[id] = o;
158  return true;
159  }
160  return false;
161 }
162 
163 
164 
167  DictType::iterator i = myDict.find(id);
168  if (i == myDict.end()) {
169  return nullptr;
170  }
171  return (*i).second;
172 }
173 
174 
175 void
177  const double MAX_CLUSTER_DISTANCE = 10;
178  // build clusters for all edges made up from not previously assigne
179  // connections
180  for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
181  int edgeid = (*i).first;
182  NIVissimEdge* edge = (*i).second;
183  // get all connectors using this edge
184  std::vector<int> connectors = edge->myIncomingConnections;
185  copy(edge->myOutgoingConnections.begin(), edge->myOutgoingConnections.end(), back_inserter(connectors));
186  if (connectors.size() == 0) {
187  continue;
188  }
189  // sort the connectors by the place on the edge
190  sort(connectors.begin(), connectors.end(), connection_position_sorter(edgeid));
191  // try to cluster the connections participating within the current edge
192  std::vector<int> currentCluster;
193  std::vector<int>::iterator j = connectors.begin();
194  bool outgoing = NIVissimConnection::dictionary(*j)->getFromEdgeID() == (*i).first;
195  double position = outgoing
196  ? NIVissimConnection::dictionary(*j)->getFromPosition()
197  : NIVissimConnection::dictionary(*j)->getToPosition();
198 
199  // skip connections already in a cluster
200  // !!! (?)
201  while (j != connectors.end() && NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
202  ++j;
203  }
204  if (j == connectors.end()) {
205  continue;
206  }
207  currentCluster.push_back(*j);
208  do {
209  if (j + 1 != connectors.end() && !NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
210  bool n_outgoing = NIVissimConnection::dictionary(*(j + 1))->getFromEdgeID() == edgeid;
211  double n_position = n_outgoing
212  ? NIVissimConnection::dictionary(*(j + 1))->getFromPosition()
213  : NIVissimConnection::dictionary(*(j + 1))->getToPosition();
214  if (n_outgoing == outgoing && fabs(n_position - position) < MAX_CLUSTER_DISTANCE) {
215  // ok, in same cluster as prior
216  currentCluster.push_back(*(j + 1));
217  } else {
218  // start new cluster
219  VectorHelper<int>::removeDouble(currentCluster);
220  edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
221  currentCluster.clear();
222  currentCluster.push_back(*(j + 1));
223  }
224  outgoing = n_outgoing;
225  position = n_position;
226  }
227  j++;
228  } while (j != connectors.end());
229  // add last connection
230  if (currentCluster.size() > 0) {
231  VectorHelper<int>::removeDouble(currentCluster);
232  edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
233  }
234  }
235 }
236 
237 
238 void
240  NBEdgeCont& ec, double offset) {
241  for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
242  NIVissimEdge* edge = (*i).second;
243  edge->buildNBEdge(dc, nc, ec, offset);
244  }
245 }
246 
247 
248 void
250  DictType::iterator i;
251  for (i = myDict.begin(); i != myDict.end(); i++) {
252  NIVissimEdge* edge = (*i).second;
253  edge->setDistrictSpeed();
254  }
255  for (i = myDict.begin(); i != myDict.end(); i++) {
256  NIVissimEdge* edge = (*i).second;
257  edge->propagateSpeed(-1, std::vector<int>());
258  }
259  for (int j = 0; j < 3; j++) {
260  for (i = myDict.begin(); i != myDict.end(); i++) {
261  NIVissimEdge* edge = (*i).second;
262  edge->propagateOwn();
263  }
264  for (i = myDict.begin(); i != myDict.end(); i++) {
265  NIVissimEdge* edge = (*i).second;
267  }
268  }
269 }
270 
271 
272 void
274  for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
275  if (myLaneSpeeds[i] == -1) {
276  double speed = -1;
277  int j1 = i - 1; // !!! recheck - j1 may become negative?
278  int j2 = i;
279  while (j2 != (int) myLaneSpeeds.size() && myLaneSpeeds[j2] == -1) {
280  j2++;
281  }
282  if (j1 < 0) {
283  if (j2 < (int) myLaneSpeeds.size()) {
284  speed = myLaneSpeeds[j2];
285  }
286  } else {
287  if (j2 >= (int) myLaneSpeeds.size()) {
288  speed = myLaneSpeeds[j1];
289  } else {
290  speed = (myLaneSpeeds[j1] + myLaneSpeeds[j2]) / (double) 2.0;
291  }
292  }
293  if (speed == -1) {
294  continue;
295  }
296  myLaneSpeeds[i] = speed;
297  std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
298  for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
299  NIVissimConnection* c = *j;
301  // propagate
302  e->propagateSpeed(/*dc, */speed, c->getToLanes());
303  }
304  }
305  }
306 }
307 
308 
309 void
311  for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
312  if (myLaneSpeeds[i] == -1) {
313  continue;
314  }
315  std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
316  for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
317  NIVissimConnection* c = *j;
319  // propagate
320  e->propagateSpeed(/*dc, */myLaneSpeeds[i], c->getToLanes());
321  }
322  }
323 }
324 
325 
326 void
327 NIVissimEdge::propagateSpeed(double speed, std::vector<int> forLanes) {
328  // if no lane is given, all set be set
329  if (forLanes.size() == 0) {
330  for (int i = 0; i < myNoLanes; i++) {
331  forLanes.push_back((int) i);
332  }
333  }
334  // for the case of a first call
335  // go through the lanes
336  for (std::vector<int>::const_iterator i = forLanes.begin(); i < forLanes.end(); i++) {
337  // check whether a speed was set before
338  if (myLaneSpeeds[*i] != -1) {
339  // do not reset it from incoming
340  continue;
341  }
342  // check whether the lane has a new speed to set
343  if ((int) myPatchedSpeeds.size() > *i && myPatchedSpeeds[*i] != -1) {
344  // use it
345  speed = getRealSpeed(/*dc, */myPatchedSpeeds[*i]);
346  }
347  // check whether a speed is given
348  if (speed == -1) {
349  // do nothing if not
350  continue;
351  }
352  // set the lane's speed to the given
353  myLaneSpeeds[*i] = speed;
354  // propagate the speed further
355  // get the list of connected edges
356  std::vector<NIVissimConnection*> connected = getOutgoingConnected(*i);
357  // go through the list
358  for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
359  NIVissimConnection* c = *j;
361  // propagate
362  e->propagateSpeed(/*dc, */speed, c->getToLanes());
363  }
364  }
365 }
366 
367 
368 
369 void
371  if (myDistrictConnections.size() > 0) {
372  double pos = *(myDistrictConnections.begin());
373  if (pos < getLength() - pos) {
376  if (d != nullptr) {
377  double speed = d->getMeanSpeed(/*dc*/);
378  if (speed == -1) {
379  return;
380  }
381  for (int i = 0; i < myNoLanes; i++) {
382  myLaneSpeeds[i] = speed;
383  // propagate the speed further
384  // get the list of connected edges
385  std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
386  // go through the list
387  for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
388  NIVissimConnection* c = *j;
390  // propagate
391  e->propagateSpeed(/*dc, */speed, c->getToLanes());
392  }
393  }
394  }
395  }
396  }
397 }
398 
399 
400 std::vector<NIVissimConnection*>
402  std::vector<NIVissimConnection*> ret;
403  for (std::vector<int>::const_iterator i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
405  const std::vector<int>& lanes = c->getFromLanes();
406  if (find(lanes.begin(), lanes.end(), lane) != lanes.end()) {
408  if (e != nullptr) {
409  ret.push_back(c);
410  }
411  }
412  }
413  return ret;
414 }
415 
416 
417 void
419  double sameNodesOffset) {
420  // build the edge
421  std::pair<NIVissimConnectionCluster*, NBNode*> fromInf, toInf;
422  NBNode* fromNode, *toNode;
423  fromNode = toNode = nullptr;
425  sort(myDistrictConnections.begin(), myDistrictConnections.end());
427  if (tmpClusters.size() != 0) {
428  sort(tmpClusters.begin(), tmpClusters.end(), connection_cluster_position_sorter(myID));
429  // get or build the from-node
430  // A node may have to be build when the edge starts or ends at
431  // a parking place or something like this
432  fromInf = getFromNode(nc, tmpClusters);
433  fromNode = fromInf.second;
434  // get or build the to-node
435  //if(tmpClusters.size()>0) {
436  toInf = getToNode(nc, tmpClusters);
437  toNode = toInf.second;
438  if (fromInf.first != 0 && toNode != nullptr && fromInf.first->around(toNode->getPosition())) {
439  WRITE_WARNINGF(TL("Will not build edge '%'."), toString(myID));
440  myAmWithinJunction = true;
441  return;
442  }
443  //}
444  // if both nodes are the same, resolve the problem otherwise
445  if (fromNode == toNode) {
446  std::pair<NBNode*, NBNode*> tmp = resolveSameNode(nc, sameNodesOffset, fromNode, toNode);
447  if (fromNode != tmp.first) {
448  fromInf.first = 0;
449  }
450  if (toNode != tmp.second) {
451  toInf.first = 0;
452  }
453  fromNode = tmp.first;
454  toNode = tmp.second;
455  }
456  }
457 
458  //
459  if (fromNode == nullptr) {
460  fromInf.first = 0;
461  Position pos = myGeom[0];
462  fromNode = new NBNode(toString<int>(myID) + "-SourceNode", pos, SumoXMLNodeType::NOJUNCTION);
463  if (!nc.insert(fromNode)) {
464  throw ProcessError(TLF("Could not insert node '%' to nodes container.", fromNode->getID()));
465  }
466  }
467  if (toNode == nullptr) {
468  toInf.first = 0;
469  Position pos = myGeom[-1];
470  toNode = new NBNode(toString<int>(myID) + "-DestinationNode", pos, SumoXMLNodeType::NOJUNCTION);
471  if (!nc.insert(toNode)) {
472  throw ProcessError(TLF("Could not insert node '%' to nodes container.", toNode->getID()));
473  }
474  }
475 
476  // build the edge
477  double avgSpeed = 0;
478  for (int i = 0; i < myNoLanes; i++) {
479  if ((int)myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
480  myLanesWithMissingSpeeds.push_back(toString(myID) + "_" + toString(i));
481  avgSpeed += OptionsCont::getOptions().getFloat("vissim.default-speed");
482  } else {
483  avgSpeed += myLaneSpeeds[i];
484  }
485  }
486  avgSpeed /= (double) myLaneSpeeds.size();
487  avgSpeed *= OptionsCont::getOptions().getFloat("vissim.speed-norm");
488 
489  if (fromNode == toNode) {
490  WRITE_WARNINGF(TL("Could not build edge '%'; would connect same node."), toString(myID));
491  return;
492  }
493 
494  NBEdge* buildEdge = new NBEdge(toString<int>(myID), fromNode, toNode, myType,
495  avgSpeed / 3.6, NBEdge::UNSPECIFIED_FRICTION, myNoLanes, -1,
498  for (int i = 0; i < myNoLanes; i++) {
499  buildEdge->setLaneWidth(i, myLaneWidths[i]);
500  if ((int) myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
501  buildEdge->setSpeed(i, OptionsCont::getOptions().getFloat("vissim.default-speed") / (double) 3.6);
502  } else {
503  buildEdge->setSpeed(i, myLaneSpeeds[i] / (double) 3.6);
504  }
505  }
506  ec.insert(buildEdge);
507  // check whether the edge contains any other clusters
508  if (tmpClusters.size() > 0) {
509  bool cont = true;
510  for (ConnectionClusters::iterator j = tmpClusters.begin(); cont && j != tmpClusters.end(); ++j) {
511  // split the edge at the previously build node
512  std::string nextID = buildEdge->getID() + "[1]";
513  cont = ec.splitAt(dc, buildEdge, (*j)->getNBNode());
514  // !!! what to do if the edge could not be split?
515  buildEdge = ec.retrieve(nextID);
516  }
517  }
518 }
519 
520 
521 double
523  std::string id = toString<int>(distNo);
524  Distribution* dist = DistributionCont::dictionary("speed", id);
525  if (dist == nullptr) {
526  WRITE_WARNINGF(TL("The referenced speed distribution '%' is not known."), id);
527  return -1;
528  }
529  assert(dist != 0);
530  double speed = dist->getMax();
531  if (speed < 0 || speed > 1000) {
532  WRITE_WARNINGF(TL("What about distribution '%' "), toString<int>(distNo));
533  }
534  return speed;
535 }
536 
537 /*
538 bool
539 NIVissimEdge::recheckSpeedPatches()
540 {
541 // int speed_idx = -1;
542  // check set speeds
543  if(myPatchedSpeeds.size()!=0) {
544  std::vector<double>::iterator i =
545  std::find(myPatchedSpeeds.begin(), myPatchedSpeeds.end(), -1);
546  if(myPatchedSpeeds.size()!=myNoLanes||i!=myPatchedSpeeds.end()) {
547  cot << "Warning! Not all lanes are patched! (edge:" << myID << ")." << endl;
548  }
549  //
550  if(std::vector<double>Helper::maxValue(myPatchedSpeeds)!=std::vector<double>Helper::minValue(myPatchedSpeeds)) {
551  cot << "Warning! Not all lanes have the same speed!! (edge:" << myID << ")." << endl;
552  }
553  //
554 / // !!! ist natuerlich Quatsch - erst recht, wenn Edges zusammengefasst werden
555  speed = std::vector<double>Helper::sum(myPatchedSpeeds);
556  speed /= (double) myPatchedSpeeds.size();*/
557 /* return true;
558  }
559  if(myDistrictConnections.size()>0) {
560  double pos = *(myDistrictConnections.begin());
561 // if(pos<10) {
562  NIVissimDistrictConnection *d =
563  NIVissimDistrictConnection::dict_findForEdge(myID);
564  if(d!=0) {
565  return true;
566 // speed = d->getMeanSpeed();
567  }
568 // }
569 // return true;
570  }
571  return false;
572 }
573 */
574 
575 std::pair<NIVissimConnectionCluster*, NBNode*>
577  // changed MAX_DISTANCE from 10 to 3.5, because 3.5 is the default lane width in VISSIM
578  const double MAX_DISTANCE = 3.5;
579  assert(clusters.size() >= 1);
580  const Position& beg = myGeom.front();
581  NIVissimConnectionCluster* c = *(clusters.begin());
582  // check whether the edge starts within a already build node
583  if (c->around(beg, MAX_DISTANCE)) {
584  clusters.erase(clusters.begin());
585  return std::pair<NIVissimConnectionCluster*, NBNode*>
586  (c, c->getNBNode());
587  }
588  // check for a parking place at the begin
589  if (myDistrictConnections.size() > 0) {
590  double pos = *(myDistrictConnections.begin());
591  if (pos < 10) {
592  NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, SumoXMLNodeType::NOJUNCTION);
593  if (!nc.insert(node)) {
594  throw 1;
595  }
596  while (myDistrictConnections.size() > 0 && *(myDistrictConnections.begin()) < 10) {
598  }
599  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
600  }
601  }
602  // build a new node for the edge's begin otherwise
603  NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, SumoXMLNodeType::NOJUNCTION);
604  if (!nc.insert(node)) {
605  throw 1;
606  }
607  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
608 }
609 
610 
611 std::pair<NIVissimConnectionCluster*, NBNode*>
613  const Position& end = myGeom.back();
614  if (clusters.size() > 0) {
615  const double MAX_DISTANCE = 10.;
616  assert(clusters.size() >= 1);
617  NIVissimConnectionCluster* c = *(clusters.end() - 1);
618  // check whether the edge ends within a already build node
619  if (c->around(end, MAX_DISTANCE)) {
620  clusters.erase(clusters.end() - 1);
621  return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
622  }
623  }
624  // check for a parking place at the end
625  if (myDistrictConnections.size() > 0) {
626  double pos = *(myDistrictConnections.end() - 1);
627  if (pos > myGeom.length() - 10) {
628  NBNode* node = new NBNode(toString<int>(myID) + "-end", end, SumoXMLNodeType::NOJUNCTION);
629  if (!nc.insert(node)) {
630  throw 1;
631  }
632  while (myDistrictConnections.size() > 0 && *(myDistrictConnections.end() - 1) < myGeom.length() - 10) {
634  }
635  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
636  }
637  }
638 
639  // build a new node for the edge's end otherwise
640  NBNode* node = new NBNode(toString<int>(myID) + "-end", end, SumoXMLNodeType::NOJUNCTION);
641  if (!nc.insert(node)) {
642  throw 1;
643  }
644  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
645  /*
646  if (clusters.size()>0) {
647  NIVissimConnectionCluster *c = *(clusters.end()-1);
648  clusters.erase(clusters.end()-1);
649  return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
650  } else {
651  // !!! self-loop edge?!
652  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), (*(myConnectionClusters.begin()))->getNBNode());
653  }
654  */
655 }
656 
657 
658 std::pair<NBNode*, NBNode*>
661  NBNode* fromNode, NBNode* toNode) {
662  std::string nid = "ParkingPlace" + toString<int>(d->getID());
663  if (d->geomPosition().distanceTo(fromNode->getPosition())
664  <
665  d->geomPosition().distanceTo(toNode->getPosition())) {
666 
667  NBNode* newNode = new NBNode(nid,
668  fromNode->getPosition(),
670  nc.erase(fromNode);
671  nc.insert(newNode);
672  return std::pair<NBNode*, NBNode*>(newNode, toNode);
673  } else {
674  NBNode* newNode = new NBNode(nid,
675  toNode->getPosition(),
677  nc.erase(toNode);
678  nc.insert(newNode);
679  return std::pair<NBNode*, NBNode*>(fromNode, newNode);
680  }
681 }
682 
683 
684 
685 std::pair<NBNode*, NBNode*>
687  NBNode* prevFrom, NBNode* prevTo) {
688  // check whether the edge is connected to a district
689  // use it if so
692  if (d != nullptr) {
693  Position pos = d->geomPosition();
694  double position = d->getPosition();
695  // the district is at the begin of the edge
696  if (myGeom.length() - position > position) {
697  std::string nid = "ParkingPlace" + toString<int>(d->getID());
698  NBNode* node = nc.retrieve(nid);
699  if (node == nullptr) {
700  node = new NBNode(nid,
702  if (!nc.insert(node)) {
703  throw 1;
704  }
705  }
706  return std::pair<NBNode*, NBNode*>(node, prevTo);
707  }
708  // the district is at the end of the edge
709  else {
710  std::string nid = "ParkingPlace" + toString<int>(d->getID());
711  NBNode* node = nc.retrieve(nid);
712  if (node == nullptr) {
713  node = new NBNode(nid, pos, SumoXMLNodeType::NOJUNCTION);
714  if (!nc.insert(node)) {
715  throw 1;
716  }
717  }
718  assert(node != 0);
719  return std::pair<NBNode*, NBNode*>(prevFrom, node);
720  }
721  }
722  // otherwise, check whether the edge is some kind of
723  // a dead end...
724  // check which end is nearer to the node centre
725  if (myConnectionClusters.size() == 1) {
726  NBNode* node = prevFrom; // it is the same as getToNode()
727 
729  // no end node given
730  if (c->around(myGeom.front(), offset) && !c->around(myGeom.back(), offset)) {
731  NBNode* end = new NBNode(
732  toString<int>(myID) + "-End",
733  myGeom.back(),
735  if (!nc.insert(end)) {
736  throw 1;
737  }
738  return std::pair<NBNode*, NBNode*>(node, end);
739  }
740 
741  // no begin node given
742  if (!c->around(myGeom.front(), offset) && c->around(myGeom.back(), offset)) {
743  NBNode* beg = new NBNode(
744  toString<int>(myID) + "-Begin",
745  myGeom.front(),
747  if (!nc.insert(beg)) {
748  std::cout << "nope, NIVissimDisturbance" << std::endl;
749  throw 1;
750  }
751  return std::pair<NBNode*, NBNode*>(beg, node);
752  }
753 
754  // self-loop edge - both points lie within the same cluster
755  if (c->around(myGeom.front()) && c->around(myGeom.back())) {
756  return std::pair<NBNode*, NBNode*>(node, node);
757  }
758  }
759  // what to do in other cases?
760  // It simply is a self-looping edge....
761  return std::pair<NBNode*, NBNode*>(prevFrom, prevTo);
762 }
763 
764 
765 
766 
767 void
769  myNode = nodeid;
770 }
771 
772 
773 void
775 
776 
777 void
779  myIncomingConnections.push_back(id);
780 }
781 
782 
783 void
785  myOutgoingConnections.push_back(id);
786 }
787 
788 
789 
790 void
793  ConnectionClusters::iterator i =
794  std::find(myConnectionClusters.begin(), myConnectionClusters.end(), old);
795  if (i != myConnectionClusters.end()) {
796  myConnectionClusters.erase(i);
797  }
798  i = std::find(myConnectionClusters.begin(), myConnectionClusters.end(), act);
799  if (i == myConnectionClusters.end()) {
800  myConnectionClusters.push_back(act);
801  }
802 }
803 
804 
805 
806 void
808  ConnectionClusters::iterator i =
809  std::find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
810  assert(i != myConnectionClusters.end());
811  myConnectionClusters.erase(i);
812 }
813 
814 
815 void
817  ConnectionClusters::iterator i =
818  std::find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
819  if (i == myConnectionClusters.end()) {
820  myConnectionClusters.push_back(c);
821  }
822 }
823 
824 
825 Position // !!! reference?
827  return myGeom[0];
828 }
829 
830 
831 Position // !!! reference?
833  return myGeom[-1];
834 }
835 
836 
837 double
839  return myGeom.length();
840 }
841 
842 
843 void
845  if (find(myDistrictConnections.begin(), myDistrictConnections.end(), pos) == myDistrictConnections.end()) {
846  myDistrictConnections.push_back(pos);
847  /* int id = NIVissimConnection::getMaxID() + 1;
848  std::vector<int> currentCluster;
849  currentCluster.push_back(id);
850  myConnectionClusters.push_back(
851  new NIVissimConnectionCluster(currentCluster, -1, myID));*/
852  }
853 }
854 
855 
856 void
857 NIVissimEdge::setSpeed(int lane, int speedDist) {
858  while ((int)myPatchedSpeeds.size() <= lane) {
859  myPatchedSpeeds.push_back(-1);
860  }
861  myPatchedSpeeds[lane] = speedDist;
862 }
863 
864 
865 void
867  // go through the edges
868  for (DictType::iterator i1 = myDict.begin(); i1 != myDict.end(); i1++) {
869  // retrieve needed values from the first edge
870  NIVissimEdge* e1 = (*i1).second;
871  const PositionVector& g1 = e1->getGeometry();
872  // check all other edges
873  DictType::iterator i2 = i1;
874  i2++;
875  for (; i2 != myDict.end(); i2++) {
876  // retrieve needed values from the second edge
877  NIVissimEdge* e2 = (*i2).second;
878  const PositionVector& g2 = e2->getGeometry();
879  // get the connection description
880  NIVissimConnection* c = e1->getConnectionTo(e2);
881  if (c == nullptr) {
882  c = e2->getConnectionTo(e1);
883  }
884  // the edge must not be a direct contiuation of the other
885  if (c != nullptr) {
886  if ((c->getFromEdgeID() == e1->getID() && fabs(c->getFromPosition() - e1->getGeometry().length()) < 5)
887  ||
888  (c->getFromEdgeID() == e2->getID() && fabs(c->getFromPosition() - e2->getGeometry().length()) < 5)) {
889 
890  continue;
891  }
892  }
893  // only parallel edges which do end at the same node
894  // should be joined
895  // check for parallelity
896  // !!! the usage of an explicit value is not very fine
897  if (fabs(GeomHelper::angleDiff(g1.beginEndAngle(), g2.beginEndAngle())) > DEG2RAD(2.0)) {
898  // continue if the lines are not parallel
899  continue;
900  }
901 
902  // check whether the same node is approached
903  // (the distance between the ends should not be too large)
904  // !!! the usage of an explicit value is not very fine
905  if (g1.back().distanceTo(g2.back()) > 10) {
906  // continue if the lines do not end at the same length
907  continue;
908  }
909  // ok, seem to be different lanes for the same edge
910  // mark as possibly joined later
911  e1->addToTreatAsSame(e2);
912  e2->addToTreatAsSame(e1);
913  }
914  }
915 }
916 
917 
918 bool
920  if (e == this) {
921  return false;
922  }
923  // check whether this edge already knows about the other
924  if (find(myToTreatAsSame.begin(), myToTreatAsSame.end(), e) == myToTreatAsSame.end()) {
925  myToTreatAsSame.push_back(e);
926  return true;
927  } else {
928  return false; // !!! check this
929  }
930  /*
931  //
932  std::vector<NIVissimEdge*>::iterator i;
933  // add to all other that shall be treated as same
934  bool changed = true;
935  while (changed) {
936  changed = false;
937  for (i = myToTreatAsSame.begin(); !changed && i != myToTreatAsSame.end(); i++) {
938  changed |= (*i)->addToTreatAsSame(e);
939  }
940  for (i = myToTreatAsSame.begin(); !changed && i != myToTreatAsSame.end(); i++) {
941  changed |= e->addToTreatAsSame(*i);
942  }
943  }
944  */
945 }
946 
949  std::vector<int>::iterator i;
950  for (i = myIncomingConnections.begin(); i != myIncomingConnections.end(); i++) {
952  if (c->getFromEdgeID() == e->getID()) {
953  return c;
954  }
955  }
956  for (i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
958  if (c->getToEdgeID() == e->getID()) {
959  return c;
960  }
961  }
962  return nullptr;
963 }
964 
965 
966 const std::vector<NIVissimEdge*>&
968  return myToTreatAsSame;
969 }
970 
971 
972 void
974  if (myLanesWithMissingSpeeds.size() == 0) {
975  return;
976  }
977  std::ostringstream str;
978  str << "The following lanes have no explicit speed information:\n ";
979  for (std::vector<std::string>::iterator i = myLanesWithMissingSpeeds.begin(); i != myLanesWithMissingSpeeds.end(); ++i) {
980  if (i != myLanesWithMissingSpeeds.begin()) {
981  str << ", ";
982  }
983  str << *i;
984  }
985  WRITE_WARNING(str.str());
986 }
987 
988 
991  // @todo seems as this would have been a hard hack!
992  /*
993  for (std::vector<int>::const_iterator i = myIncomingConnections.begin(); i != myIncomingConnections.end(); ++i) {
994  NIVissimConnection* c = NIVissimConnection::dictionary(*i);
995  return NIVissimEdge::dictionary(c->getFromEdgeID());
996  }
997  return 0;
998  */
999  if (myIncomingConnections.size() != 0) {
1001  }
1002  return nullptr;
1003 }
1004 
1005 
1006 NIVissimEdge*
1008  // @todo seems as this would have been a hard hack!
1009  /*
1010  for (std::vector<int>::const_iterator i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); ++i) {
1011  NIVissimConnection* c = NIVissimConnection::dictionary(*i);
1012  return NIVissimEdge::dictionary(c->getToEdgeID());
1013  }
1014  return 0;
1015  */
1016  if (myOutgoingConnections.size() != 0) {
1018  }
1019  return nullptr;
1020 }
1021 
1022 
1023 /****************************************************************************/
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
std::vector< NIVissimClosedLaneDef * > NIVissimClosedLanesVector
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static bool dictionary(const std::string &type, const std::string &id, Distribution *d)
Adds a distribution of the given type and name to the container.
virtual double getMax() const =0
Returns the maximum value of this distribution.
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
Definition: GeomHelper.cpp:178
A container for districts.
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:59
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:281
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:182
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:604
The representation of a single edge during network building.
Definition: NBEdge.h:92
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4223
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition: NBEdge.h:351
const std::string & getID() const
Definition: NBEdge.h:1522
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4094
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:342
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:345
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:57
bool erase(NBNode *node)
Removes the given node, deleting it.
Definition: NBNodeCont.cpp:146
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:87
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:116
Represents a single node (junction) during network building.
Definition: NBNode.h:66
const Position & getPosition() const
Definition: NBNode.h:260
const PositionVector & getGeometry() const
bool around(const Position &p, double offset=0) const
double getPositionForEdge(int edgeid) const
const std::vector< int > & getFromLanes() const
double getFromPosition() const
const std::vector< int > & getToLanes() const
static bool dictionary(int id, NIVissimConnection *o)
double getToPosition() const
static NIVissimDistrictConnection * dict_findForEdge(int edgeid)
Returns the connection to a district placed at the given node Yep, there onyl should be one,...
Position geomPosition() const
Returns the position The position yields from the edge geometry and the place the connection is plaed...
double getPosition() const
Returns the position of the connection at the edge.
int getID() const
Returns the id of the connection.
int operator()(NIVissimConnectionCluster *cc1, NIVissimConnectionCluster *cc2) const
comparing operation
connection_cluster_position_sorter(int edgeid)
constructor
int operator()(int c1id, int c2id) const
comparing operation
connection_position_sorter(int edgeid)
constructor
A temporary storage for edges imported from Vissim.
Definition: NIVissimEdge.h:51
void checkDistrictConnectionExistanceAt(double pos)
void propagateOwn()
std::pair< NBNode *, NBNode * > resolveSameNode(NBNodeCont &nc, double offset, NBNode *prevFrom, NBNode *prevTo)
Tries to resolve the problem that the same node has been returned as origin and destination node.
void mergedInto(NIVissimConnectionCluster *old, NIVissimConnectionCluster *act)
void propagateSpeed(double speed, std::vector< int > forLanes)
const std::vector< NIVissimEdge * > & getToTreatAsSame() const
static int myMaxID
The current maximum id; needed for further id assignment.
Definition: NIVissimEdge.h:290
NIVissimClosedLanesVector myClosedLanes
List of lanes closed on this edge.
Definition: NIVissimEdge.h:260
static std::vector< std::string > myLanesWithMissingSpeeds
Definition: NIVissimEdge.h:292
std::string myName
The name of the edge.
Definition: NIVissimEdge.h:247
NIVissimEdge * getBestOutgoing() const
void addIncomingConnection(int id)
Adds a connection where this edge is the destination.
bool myAmWithinJunction
Information whether this edge was not build due to being within a junction.
Definition: NIVissimEdge.h:280
static DictType myDict
The dictionary.
Definition: NIVissimEdge.h:287
static void reportUnsetSpeeds()
Writes edges with unset speeds to the warnings message log instance.
std::map< int, NIVissimEdge * > DictType
Definition of the dictionary type.
Definition: NIVissimEdge.h:284
double getRealSpeed(int distNo)
std::vector< double > myDistrictConnections
Definition: NIVissimEdge.h:271
NIVissimEdge * getBestIncoming() const
~NIVissimEdge()
Destructor.
void addOutgoingConnection(int id)
Adds a connection where this edge is the source.
std::vector< double > myLaneSpeeds
Definition: NIVissimEdge.h:275
std::vector< NIVissimConnectionCluster * > ConnectionClusters
The definition for a container for connection clusters.
Definition: NIVissimEdge.h:157
double getLength() const
Returns the length of the node.
void addToConnectionCluster(NIVissimConnectionCluster *c)
void setSpeed(int lane, int speedDist)
std::pair< NIVissimConnectionCluster *, NBNode * > getFromNode(NBNodeCont &nc, ConnectionClusters &clusters)
Returns the origin node.
std::vector< NIVissimEdge * > myToTreatAsSame
Definition: NIVissimEdge.h:277
void removeFromConnectionCluster(NIVissimConnectionCluster *c)
static void dict_checkEdges2Join()
static void buildConnectionClusters()
Clusters connections of each edge.
Position getBegin2D() const
std::vector< NIVissimConnection * > getOutgoingConnected(int lane) const
static void dict_buildNBEdges(NBDistrictCont &dc, NBNodeCont &nc, NBEdgeCont &ec, double offset)
Builds NBEdges from the VissimEdges within the dictionary.
NIVissimEdge(int id, const std::string &name, const std::string &type, std::vector< double > laneWidths, double zuschlag1, double zuschlag2, double length, const PositionVector &geom, const NIVissimClosedLanesVector &clv)
Constructor.
void checkUnconnectedLaneSpeeds()
double myZuschlag1
Additional load values for this edge.
Definition: NIVissimEdge.h:257
static void dict_propagateSpeeds()
std::pair< NIVissimConnectionCluster *, NBNode * > getToNode(NBNodeCont &nc, ConnectionClusters &clusters)
Returns the destination node.
std::vector< double > myLaneWidths
Definition: NIVissimEdge.h:254
static bool dictionary(int id, const std::string &name, const std::string &type, int noLanes, double zuschlag1, double zuschlag2, double length, const PositionVector &geom, const NIVissimClosedLanesVector &clv)
Adds the described item to the dictionary Builds the edge first.
std::string myType
The type of the edge.
Definition: NIVissimEdge.h:250
void buildNBEdge(NBDistrictCont &dc, NBNodeCont &nc, NBEdgeCont &ec, double sameNodesOffset)
Builds the NBEdge from this VissimEdge.
std::vector< int > myOutgoingConnections
List of connections outgoing from this edge.
Definition: NIVissimEdge.h:269
Position getEnd2D() const
Returns the end position of the edge.
void setDistrictSpeed()
bool addToTreatAsSame(NIVissimEdge *e)
int myNoLanes
The number of lanes the edge has.
Definition: NIVissimEdge.h:253
void setNodeCluster(int nodeid)
NIVissimConnection * getConnectionTo(NIVissimEdge *e)
std::vector< int > myPatchedSpeeds
Definition: NIVissimEdge.h:273
std::pair< NBNode *, NBNode * > remapOneOfNodes(NBNodeCont &nc, NIVissimDistrictConnection *d, NBNode *fromNode, NBNode *toNode)
ConnectionClusters myConnectionClusters
List of connection clusters along this edge.
Definition: NIVissimEdge.h:263
double myZuschlag2
Definition: NIVissimEdge.h:257
std::vector< int > myIncomingConnections
List of connections incoming to this edge.
Definition: NIVissimEdge.h:266
const std::string & getID() const
Returns the id.
Definition: Named.h:74
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimensions
Definition: Position.h:261
A list of positions.
double beginEndAngle() const
returns the angle in radians of the line connecting the first and the last position
double length() const
Returns the length.
static void removeDouble(std::vector< T > &v)
Definition: VectorHelper.h:66