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