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-2018 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, int noLanes,
110  double zuschlag1, double zuschlag2,
111  double /*length*/, const PositionVector& geom,
112  const NIVissimClosedLanesVector& clv)
113  : NIVissimAbstractEdge(id, geom),
114  myName(name), myType(type), myNoLanes(noLanes),
115  myZuschlag1(zuschlag1), myZuschlag2(zuschlag2),
116  myClosedLanes(clv), myAmWithinJunction(false) { //, mySpeed(-1)
117  assert(noLanes >= 0);
118  if (myMaxID < myID) {
119  myMaxID = myID;
120  }
121  for (int i = 0; i < noLanes; i++) {
122  myLaneSpeeds.push_back(-1);
123  }
124 }
125 
126 
128  for (NIVissimClosedLanesVector::iterator i = myClosedLanes.begin(); i != myClosedLanes.end(); i++) {
129  delete(*i);
130  }
131  myClosedLanes.clear();
132 }
133 
134 
135 bool
136 NIVissimEdge::dictionary(int id, const std::string& name,
137  const std::string& type, int noLanes,
138  double zuschlag1, double zuschlag2, double length,
139  const PositionVector& geom,
140  const NIVissimClosedLanesVector& clv) {
141  NIVissimEdge* o = new NIVissimEdge(id, name, type, noLanes, zuschlag1,
142  zuschlag2, length, geom, clv);
143  if (!dictionary(id, o)) {
144  delete o;
145  return false;
146  }
147  return true;
148 }
149 
150 
151 
152 bool
154  DictType::iterator i = myDict.find(id);
155  if (i == myDict.end()) {
156  myDict[id] = o;
157  return true;
158  }
159  return false;
160 }
161 
162 
163 
166  DictType::iterator i = myDict.find(id);
167  if (i == myDict.end()) {
168  return nullptr;
169  }
170  return (*i).second;
171 }
172 
173 
174 void
176  const double MAX_CLUSTER_DISTANCE = 10;
177  // build clusters for all edges made up from not previously assigne
178  // connections
179  for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
180  int edgeid = (*i).first;
181  NIVissimEdge* edge = (*i).second;
182  // get all connectors using this edge
183  std::vector<int> connectors = edge->myIncomingConnections;
184  copy(edge->myOutgoingConnections.begin(), edge->myOutgoingConnections.end(), back_inserter(connectors));
185  if (connectors.size() == 0) {
186  continue;
187  }
188  // sort the connectors by the place on the edge
189  sort(connectors.begin(), connectors.end(), connection_position_sorter(edgeid));
190  // try to cluster the connections participating within the current edge
191  std::vector<int> currentCluster;
192  std::vector<int>::iterator j = connectors.begin();
193  bool outgoing = NIVissimConnection::dictionary(*j)->getFromEdgeID() == (*i).first;
194  double position = outgoing
195  ? NIVissimConnection::dictionary(*j)->getFromPosition()
196  : NIVissimConnection::dictionary(*j)->getToPosition();
197 
198  // skip connections already in a cluster
199  // !!! (?)
200  while (j != connectors.end() && NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
201  ++j;
202  }
203  if (j == connectors.end()) {
204  continue;
205  }
206  currentCluster.push_back(*j);
207  do {
208  if (j + 1 != connectors.end() && !NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
209  bool n_outgoing = NIVissimConnection::dictionary(*(j + 1))->getFromEdgeID() == edgeid;
210  double n_position = n_outgoing
211  ? NIVissimConnection::dictionary(*(j + 1))->getFromPosition()
212  : NIVissimConnection::dictionary(*(j + 1))->getToPosition();
213  if (n_outgoing == outgoing && fabs(n_position - position) < MAX_CLUSTER_DISTANCE) {
214  // ok, in same cluster as prior
215  currentCluster.push_back(*(j + 1));
216  } else {
217  // start new cluster
218  VectorHelper<int>::removeDouble(currentCluster);
219  edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
220  currentCluster.clear();
221  currentCluster.push_back(*(j + 1));
222  }
223  outgoing = n_outgoing;
224  position = n_position;
225  }
226  j++;
227  } while (j != connectors.end());
228  // add last connection
229  if (currentCluster.size() > 0) {
230  VectorHelper<int>::removeDouble(currentCluster);
231  edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
232  }
233  }
234 }
235 
236 
237 void
239  NBEdgeCont& ec, double offset) {
240  for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
241  NIVissimEdge* edge = (*i).second;
242  edge->buildNBEdge(dc, nc, ec, offset);
243  }
244 }
245 
246 
247 void
249  DictType::iterator i;
250  for (i = myDict.begin(); i != myDict.end(); i++) {
251  NIVissimEdge* edge = (*i).second;
252  edge->setDistrictSpeed();
253  }
254  for (i = myDict.begin(); i != myDict.end(); i++) {
255  NIVissimEdge* edge = (*i).second;
256  edge->propagateSpeed(-1, std::vector<int>());
257  }
258  for (int j = 0; j < 3; j++) {
259  for (i = myDict.begin(); i != myDict.end(); i++) {
260  NIVissimEdge* edge = (*i).second;
261  edge->propagateOwn();
262  }
263  for (i = myDict.begin(); i != myDict.end(); i++) {
264  NIVissimEdge* edge = (*i).second;
266  }
267  }
268 }
269 
270 
271 void
273  for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
274  if (myLaneSpeeds[i] == -1) {
275  double speed = -1;
276  int j1 = i - 1; // !!! recheck - j1 may become negative?
277  int j2 = i;
278  while (j2 != (int) myLaneSpeeds.size() && myLaneSpeeds[j2] == -1) {
279  j2++;
280  }
281  if (j1 < 0) {
282  if (j2 < (int) myLaneSpeeds.size()) {
283  speed = myLaneSpeeds[j2];
284  }
285  } else {
286  if (j2 >= (int) myLaneSpeeds.size()) {
287  speed = myLaneSpeeds[j1];
288  } else {
289  speed = (myLaneSpeeds[j1] + myLaneSpeeds[j2]) / (double) 2.0;
290  }
291  }
292  if (speed == -1) {
293  continue;
294  }
295  myLaneSpeeds[i] = speed;
296  std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
297  for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
298  NIVissimConnection* c = *j;
300  // propagate
301  e->propagateSpeed(/*dc, */speed, c->getToLanes());
302  }
303  }
304  }
305 }
306 
307 
308 void
310  for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
311  if (myLaneSpeeds[i] == -1) {
312  continue;
313  }
314  std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
315  for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
316  NIVissimConnection* c = *j;
318  // propagate
319  e->propagateSpeed(/*dc, */myLaneSpeeds[i], c->getToLanes());
320  }
321  }
322 }
323 
324 
325 void
326 NIVissimEdge::propagateSpeed(double speed, std::vector<int> forLanes) {
327  // if no lane is given, all set be set
328  if (forLanes.size() == 0) {
329  for (int i = 0; i < myNoLanes; i++) {
330  forLanes.push_back((int) i);
331  }
332  }
333  // for the case of a first call
334  // go through the lanes
335  for (std::vector<int>::const_iterator i = forLanes.begin(); i < forLanes.end(); i++) {
336  // check whether a speed was set before
337  if (myLaneSpeeds[*i] != -1) {
338  // do not reset it from incoming
339  continue;
340  }
341  // check whether the lane has a new speed to set
342  if ((int) myPatchedSpeeds.size() > *i && myPatchedSpeeds[*i] != -1) {
343  // use it
344  speed = getRealSpeed(/*dc, */myPatchedSpeeds[*i]);
345  }
346  // check whether a speed is given
347  if (speed == -1) {
348  // do nothing if not
349  continue;
350  }
351  // set the lane's speed to the given
352  myLaneSpeeds[*i] = speed;
353  // propagate the speed further
354  // get the list of connected edges
355  std::vector<NIVissimConnection*> connected = getOutgoingConnected(*i);
356  // go throught the list
357  for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
358  NIVissimConnection* c = *j;
360  // propagate
361  e->propagateSpeed(/*dc, */speed, c->getToLanes());
362  }
363  }
364 }
365 
366 
367 
368 void
370  if (myDistrictConnections.size() > 0) {
371  double pos = *(myDistrictConnections.begin());
372  if (pos < getLength() - pos) {
375  if (d != nullptr) {
376  double speed = d->getMeanSpeed(/*dc*/);
377  if (speed == -1) {
378  return;
379  }
380  for (int i = 0; i < myNoLanes; i++) {
381  myLaneSpeeds[i] = speed;
382  // propagate the speed further
383  // get the list of connected edges
384  std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
385  // go throught the list
386  for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
387  NIVissimConnection* c = *j;
389  // propagate
390  e->propagateSpeed(/*dc, */speed, c->getToLanes());
391  }
392  }
393  }
394  }
395  }
396 }
397 
398 
399 std::vector<NIVissimConnection*>
401  std::vector<NIVissimConnection*> ret;
402  for (std::vector<int>::const_iterator i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
404  const std::vector<int>& lanes = c->getFromLanes();
405  if (find(lanes.begin(), lanes.end(), lane) != lanes.end()) {
407  if (e != nullptr) {
408  ret.push_back(c);
409  }
410  }
411  }
412  return ret;
413 }
414 
415 
416 void
418  double sameNodesOffset) {
419  // build the edge
420  std::pair<NIVissimConnectionCluster*, NBNode*> fromInf, toInf;
421  NBNode* fromNode, *toNode;
422  fromNode = toNode = nullptr;
424  sort(myDistrictConnections.begin(), myDistrictConnections.end());
426  if (tmpClusters.size() != 0) {
427  sort(tmpClusters.begin(), tmpClusters.end(), connection_cluster_position_sorter(myID));
428  // get or build the from-node
429  // A node may have to be build when the edge starts or ends at
430  // a parking place or something like this
431  fromInf = getFromNode(nc, tmpClusters);
432  fromNode = fromInf.second;
433  // get or build the to-node
434  //if(tmpClusters.size()>0) {
435  toInf = getToNode(nc, tmpClusters);
436  toNode = toInf.second;
437  if (fromInf.first != 0 && toNode != nullptr && fromInf.first->around(toNode->getPosition())) {
438  WRITE_WARNING("Will not build edge '" + toString(myID) + "'.");
439  myAmWithinJunction = true;
440  return;
441  }
442  //}
443  // if both nodes are the same, resolve the problem otherwise
444  if (fromNode == toNode) {
445  std::pair<NBNode*, NBNode*> tmp = resolveSameNode(nc, sameNodesOffset, fromNode, toNode);
446  if (fromNode != tmp.first) {
447  fromInf.first = 0;
448  }
449  if (toNode != tmp.second) {
450  toInf.first = 0;
451  }
452  fromNode = tmp.first;
453  toNode = tmp.second;
454  }
455  }
456 
457  //
458  if (fromNode == nullptr) {
459  fromInf.first = 0;
460  Position pos = myGeom[0];
461  fromNode = new NBNode(toString<int>(myID) + "-SourceNode", pos, NODETYPE_NOJUNCTION);
462  if (!nc.insert(fromNode)) {
463  throw ProcessError("Could not insert node '" + fromNode->getID() + "' to nodes container.");
464  }
465  }
466  if (toNode == nullptr) {
467  toInf.first = 0;
468  Position pos = myGeom[-1];
469  toNode = new NBNode(toString<int>(myID) + "-DestinationNode", pos, NODETYPE_NOJUNCTION);
470  if (!nc.insert(toNode)) {
471  throw ProcessError("Could not insert node '" + toNode->getID() + "' to nodes container.");
472  }
473  }
474 
475  // build the edge
476  double avgSpeed = 0;
477  for (int i = 0; i < myNoLanes; i++) {
478  if ((int)myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
479  myLanesWithMissingSpeeds.push_back(toString(myID) + "_" + toString(i));
480  avgSpeed += OptionsCont::getOptions().getFloat("vissim.default-speed");
481  } else {
482  avgSpeed += myLaneSpeeds[i];
483  }
484  }
485  avgSpeed /= (double) myLaneSpeeds.size();
486  avgSpeed *= OptionsCont::getOptions().getFloat("vissim.speed-norm");
487 
488  if (fromNode == toNode) {
489  WRITE_WARNING("Could not build edge '" + toString(myID) + "'; would connect same node.");
490  return;
491  }
492 
493  NBEdge* buildEdge = new NBEdge(toString<int>(myID), fromNode, toNode, myType,
494  avgSpeed / (double) 3.6, myNoLanes, -1,
496  myGeom, myName, "", LANESPREAD_CENTER, true);
497  for (int i = 0; i < myNoLanes; i++) {
498  if ((int) myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
499  buildEdge->setSpeed(i, OptionsCont::getOptions().getFloat("vissim.default-speed") / (double) 3.6);
500  } else {
501  buildEdge->setSpeed(i, myLaneSpeeds[i] / (double) 3.6);
502  }
503  }
504  ec.insert(buildEdge);
505  // check whether the edge contains any other clusters
506  if (tmpClusters.size() > 0) {
507  bool cont = true;
508  for (ConnectionClusters::iterator j = tmpClusters.begin(); cont && j != tmpClusters.end(); ++j) {
509  // split the edge at the previously build node
510  std::string nextID = buildEdge->getID() + "[1]";
511  cont = ec.splitAt(dc, buildEdge, (*j)->getNBNode());
512  // !!! what to do if the edge could not be split?
513  buildEdge = ec.retrieve(nextID);
514  }
515  }
516 }
517 
518 
519 double
521  std::string id = toString<int>(distNo);
522  Distribution* dist = DistributionCont::dictionary("speed", id);
523  if (dist == nullptr) {
524  WRITE_WARNING("The referenced speed distribution '" + id + "' is not known.");
525  return -1;
526  }
527  assert(dist != 0);
528  double speed = dist->getMax();
529  if (speed < 0 || speed > 1000) {
530  WRITE_WARNING("What about distribution '" + toString<int>(distNo) + "' ");
531  }
532  return speed;
533 }
534 
535 /*
536 bool
537 NIVissimEdge::recheckSpeedPatches()
538 {
539 // int speed_idx = -1;
540  // check set speeds
541  if(myPatchedSpeeds.size()!=0) {
542  std::vector<double>::iterator i =
543  find(myPatchedSpeeds.begin(), myPatchedSpeeds.end(), -1);
544  if(myPatchedSpeeds.size()!=myNoLanes||i!=myPatchedSpeeds.end()) {
545  cot << "Warning! Not all lanes are patched! (edge:" << myID << ")." << endl;
546  }
547  //
548  if(std::vector<double>Helper::maxValue(myPatchedSpeeds)!=std::vector<double>Helper::minValue(myPatchedSpeeds)) {
549  cot << "Warning! Not all lanes have the same speed!! (edge:" << myID << ")." << endl;
550  }
551  //
552 / // !!! ist natuerlich Quatsch - erst recht, wenn Edges zusammengefasst werden
553  speed = std::vector<double>Helper::sum(myPatchedSpeeds);
554  speed /= (double) myPatchedSpeeds.size();*/
555 /* return true;
556  }
557  if(myDistrictConnections.size()>0) {
558  double pos = *(myDistrictConnections.begin());
559 // if(pos<10) {
560  NIVissimDistrictConnection *d =
561  NIVissimDistrictConnection::dict_findForEdge(myID);
562  if(d!=0) {
563  return true;
564 // speed = d->getMeanSpeed();
565  }
566 // }
567 // return true;
568  }
569  return false;
570 }
571 */
572 
573 std::pair<NIVissimConnectionCluster*, NBNode*>
575  // changed MAX_DISTANCE from 10 to 3.5, because 3.5 is the default lane width in VISSIM
576  const double MAX_DISTANCE = 3.5;
577  assert(clusters.size() >= 1);
578  const Position& beg = myGeom.front();
579  NIVissimConnectionCluster* c = *(clusters.begin());
580  // check whether the edge starts within a already build node
581  if (c->around(beg, MAX_DISTANCE)) {
582  clusters.erase(clusters.begin());
583  return std::pair<NIVissimConnectionCluster*, NBNode*>
584  (c, c->getNBNode());
585  }
586  // check for a parking place at the begin
587  if (myDistrictConnections.size() > 0) {
588  double pos = *(myDistrictConnections.begin());
589  if (pos < 10) {
590  NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, NODETYPE_NOJUNCTION);
591  if (!nc.insert(node)) {
592  throw 1;
593  }
594  while (myDistrictConnections.size() > 0 && *(myDistrictConnections.begin()) < 10) {
596  }
597  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
598  }
599  }
600  // build a new node for the edge's begin otherwise
601  NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, NODETYPE_NOJUNCTION);
602  if (!nc.insert(node)) {
603  throw 1;
604  }
605  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
606 }
607 
608 
609 std::pair<NIVissimConnectionCluster*, NBNode*>
611  const Position& end = myGeom.back();
612  if (clusters.size() > 0) {
613  const double MAX_DISTANCE = 10.;
614  assert(clusters.size() >= 1);
615  NIVissimConnectionCluster* c = *(clusters.end() - 1);
616  // check whether the edge ends within a already build node
617  if (c->around(end, MAX_DISTANCE)) {
618  clusters.erase(clusters.end() - 1);
619  return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
620  }
621  }
622  // check for a parking place at the end
623  if (myDistrictConnections.size() > 0) {
624  double pos = *(myDistrictConnections.end() - 1);
625  if (pos > myGeom.length() - 10) {
626  NBNode* node = new NBNode(toString<int>(myID) + "-end", end, NODETYPE_NOJUNCTION);
627  if (!nc.insert(node)) {
628  throw 1;
629  }
630  while (myDistrictConnections.size() > 0 && *(myDistrictConnections.end() - 1) < myGeom.length() - 10) {
632  }
633  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
634  }
635  }
636 
637  // build a new node for the edge's end otherwise
638  NBNode* node = new NBNode(toString<int>(myID) + "-end", end, NODETYPE_NOJUNCTION);
639  if (!nc.insert(node)) {
640  throw 1;
641  }
642  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
643  /*
644  if (clusters.size()>0) {
645  NIVissimConnectionCluster *c = *(clusters.end()-1);
646  clusters.erase(clusters.end()-1);
647  return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
648  } else {
649  // !!! self-loop edge?!
650  return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), (*(myConnectionClusters.begin()))->getNBNode());
651  }
652  */
653 }
654 
655 
656 std::pair<NBNode*, NBNode*>
659  NBNode* fromNode, NBNode* toNode) {
660  std::string nid = "ParkingPlace" + toString<int>(d->getID());
661  if (d->geomPosition().distanceTo(fromNode->getPosition())
662  <
663  d->geomPosition().distanceTo(toNode->getPosition())) {
664 
665  NBNode* newNode = new NBNode(nid,
666  fromNode->getPosition(),
668  nc.erase(fromNode);
669  nc.insert(newNode);
670  return std::pair<NBNode*, NBNode*>(newNode, toNode);
671  } else {
672  NBNode* newNode = new NBNode(nid,
673  toNode->getPosition(),
675  nc.erase(toNode);
676  nc.insert(newNode);
677  return std::pair<NBNode*, NBNode*>(fromNode, newNode);
678  }
679 }
680 
681 
682 
683 std::pair<NBNode*, NBNode*>
685  NBNode* prevFrom, NBNode* prevTo) {
686  // check whether the edge is connected to a district
687  // use it if so
690  if (d != nullptr) {
691  Position pos = d->geomPosition();
692  double position = d->getPosition();
693  // the district is at the begin of the edge
694  if (myGeom.length() - position > position) {
695  std::string nid = "ParkingPlace" + toString<int>(d->getID());
696  NBNode* node = nc.retrieve(nid);
697  if (node == nullptr) {
698  node = new NBNode(nid,
699  pos, NODETYPE_NOJUNCTION);
700  if (!nc.insert(node)) {
701  throw 1;
702  }
703  }
704  return std::pair<NBNode*, NBNode*>(node, prevTo);
705  }
706  // the district is at the end of the edge
707  else {
708  std::string nid = "ParkingPlace" + toString<int>(d->getID());
709  NBNode* node = nc.retrieve(nid);
710  if (node == nullptr) {
711  node = new NBNode(nid, pos, NODETYPE_NOJUNCTION);
712  if (!nc.insert(node)) {
713  throw 1;
714  }
715  }
716  assert(node != 0);
717  return std::pair<NBNode*, NBNode*>(prevFrom, node);
718  }
719  }
720  // otherwise, check whether the edge is some kind of
721  // a dead end...
722  // check which end is nearer to the node centre
723  if (myConnectionClusters.size() == 1) {
724  NBNode* node = prevFrom; // it is the same as getToNode()
725 
727  // no end node given
728  if (c->around(myGeom.front(), offset) && !c->around(myGeom.back(), offset)) {
729  NBNode* end = new NBNode(
730  toString<int>(myID) + "-End",
731  myGeom.back(),
733  if (!nc.insert(end)) {
734  throw 1;
735  }
736  return std::pair<NBNode*, NBNode*>(node, end);
737  }
738 
739  // no begin node given
740  if (!c->around(myGeom.front(), offset) && c->around(myGeom.back(), offset)) {
741  NBNode* beg = new NBNode(
742  toString<int>(myID) + "-Begin",
743  myGeom.front(),
745  if (!nc.insert(beg)) {
746  std::cout << "nope, NIVissimDisturbance" << std::endl;
747  throw 1;
748  }
749  return std::pair<NBNode*, NBNode*>(beg, node);
750  }
751 
752  // self-loop edge - both points lie within the same cluster
753  if (c->around(myGeom.front()) && c->around(myGeom.back())) {
754  return std::pair<NBNode*, NBNode*>(node, node);
755  }
756  }
757  // what to do in other cases?
758  // It simply is a self-looping edge....
759  return std::pair<NBNode*, NBNode*>(prevFrom, prevTo);
760 }
761 
762 
763 
764 
765 void
767  myNode = nodeid;
768 }
769 
770 
771 void
773 
774 
775 void
777  myIncomingConnections.push_back(id);
778 }
779 
780 
781 void
783  myOutgoingConnections.push_back(id);
784 }
785 
786 
787 
788 void
791  ConnectionClusters::iterator i =
792  find(myConnectionClusters.begin(), myConnectionClusters.end(), old);
793  if (i != myConnectionClusters.end()) {
794  myConnectionClusters.erase(i);
795  }
796  i = find(myConnectionClusters.begin(), myConnectionClusters.end(), act);
797  if (i == myConnectionClusters.end()) {
798  myConnectionClusters.push_back(act);
799  }
800 }
801 
802 
803 
804 void
806  ConnectionClusters::iterator i =
807  find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
808  assert(i != myConnectionClusters.end());
809  myConnectionClusters.erase(i);
810 }
811 
812 
813 void
815  ConnectionClusters::iterator i =
816  find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
817  if (i == myConnectionClusters.end()) {
818  myConnectionClusters.push_back(c);
819  }
820 }
821 
822 
823 Position // !!! reference?
825  return myGeom[0];
826 }
827 
828 
829 Position // !!! reference?
831  return myGeom[-1];
832 }
833 
834 
835 double
837  return myGeom.length();
838 }
839 
840 
841 void
843  if (find(myDistrictConnections.begin(), myDistrictConnections.end(), pos) == myDistrictConnections.end()) {
844  myDistrictConnections.push_back(pos);
845  /* int id = NIVissimConnection::getMaxID() + 1;
846  std::vector<int> currentCluster;
847  currentCluster.push_back(id);
848  myConnectionClusters.push_back(
849  new NIVissimConnectionCluster(currentCluster, -1, myID));*/
850  }
851 }
852 
853 
854 void
855 NIVissimEdge::setSpeed(int lane, int speedDist) {
856  while ((int)myPatchedSpeeds.size() <= lane) {
857  myPatchedSpeeds.push_back(-1);
858  }
859  myPatchedSpeeds[lane] = speedDist;
860 }
861 
862 
863 void
865  // go through the edges
866  for (DictType::iterator i1 = myDict.begin(); i1 != myDict.end(); i1++) {
867  // retrieve needed values from the first edge
868  NIVissimEdge* e1 = (*i1).second;
869  const PositionVector& g1 = e1->getGeometry();
870  // check all other edges
871  DictType::iterator i2 = i1;
872  i2++;
873  for (; i2 != myDict.end(); i2++) {
874  // retrieve needed values from the second edge
875  NIVissimEdge* e2 = (*i2).second;
876  const PositionVector& g2 = e2->getGeometry();
877  // get the connection description
878  NIVissimConnection* c = e1->getConnectionTo(e2);
879  if (c == nullptr) {
880  c = e2->getConnectionTo(e1);
881  }
882  // the edge must not be a direct contiuation of the other
883  if (c != nullptr) {
884  if ((c->getFromEdgeID() == e1->getID() && fabs(c->getFromPosition() - e1->getGeometry().length()) < 5)
885  ||
886  (c->getFromEdgeID() == e2->getID() && fabs(c->getFromPosition() - e2->getGeometry().length()) < 5)) {
887 
888  continue;
889  }
890  }
891  // only parallel edges which do end at the same node
892  // should be joined
893  // check for parallelity
894  // !!! the usage of an explicit value is not very fine
895  if (fabs(GeomHelper::angleDiff(g1.beginEndAngle(), g2.beginEndAngle())) > DEG2RAD(2.0)) {
896  // continue if the lines are not parallel
897  continue;
898  }
899 
900  // check whether the same node is approached
901  // (the distance between the ends should not be too large)
902  // !!! the usage of an explicit value is not very fine
903  if (g1.back().distanceTo(g2.back()) > 10) {
904  // continue if the lines do not end at the same length
905  continue;
906  }
907  // ok, seem to be different lanes for the same edge
908  // mark as possibly joined later
909  e1->addToTreatAsSame(e2);
910  e2->addToTreatAsSame(e1);
911  }
912  }
913 }
914 
915 
916 bool
918  if (e == this) {
919  return false;
920  }
921  // check whether this edge already knows about the other
922  if (find(myToTreatAsSame.begin(), myToTreatAsSame.end(), e) == myToTreatAsSame.end()) {
923  myToTreatAsSame.push_back(e);
924  return true;
925  } else {
926  return false; // !!! check this
927  }
928  /*
929  //
930  std::vector<NIVissimEdge*>::iterator i;
931  // add to all other that shall be treated as same
932  bool changed = true;
933  while (changed) {
934  changed = false;
935  for (i = myToTreatAsSame.begin(); !changed && i != myToTreatAsSame.end(); i++) {
936  changed |= (*i)->addToTreatAsSame(e);
937  }
938  for (i = myToTreatAsSame.begin(); !changed && i != myToTreatAsSame.end(); i++) {
939  changed |= e->addToTreatAsSame(*i);
940  }
941  }
942  */
943 }
944 
947  std::vector<int>::iterator i;
948  for (i = myIncomingConnections.begin(); i != myIncomingConnections.end(); i++) {
950  if (c->getFromEdgeID() == e->getID()) {
951  return c;
952  }
953  }
954  for (i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
956  if (c->getToEdgeID() == e->getID()) {
957  return c;
958  }
959  }
960  return nullptr;
961 }
962 
963 
964 const std::vector<NIVissimEdge*>&
966  return myToTreatAsSame;
967 }
968 
969 
970 void
972  if (myLanesWithMissingSpeeds.size() == 0) {
973  return;
974  }
975  std::ostringstream str;
976  str << "The following lanes have no explicit speed information:\n ";
977  for (std::vector<std::string>::iterator i = myLanesWithMissingSpeeds.begin(); i != myLanesWithMissingSpeeds.end(); ++i) {
978  if (i != myLanesWithMissingSpeeds.begin()) {
979  str << ", ";
980  }
981  str << *i;
982  }
983  WRITE_WARNING(str.str());
984 }
985 
986 
989  // @todo seems as this would have been a hard hack!
990  /*
991  for (std::vector<int>::const_iterator i = myIncomingConnections.begin(); i != myIncomingConnections.end(); ++i) {
992  NIVissimConnection* c = NIVissimConnection::dictionary(*i);
993  return NIVissimEdge::dictionary(c->getFromEdgeID());
994  }
995  return 0;
996  */
997  if (myIncomingConnections.size() != 0) {
999  }
1000  return nullptr;
1001 }
1002 
1003 
1004 NIVissimEdge*
1006  // @todo seems as this would have been a hard hack!
1007  /*
1008  for (std::vector<int>::const_iterator i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); ++i) {
1009  NIVissimConnection* c = NIVissimConnection::dictionary(*i);
1010  return NIVissimEdge::dictionary(c->getToEdgeID());
1011  }
1012  return 0;
1013  */
1014  if (myOutgoingConnections.size() != 0) {
1016  }
1017  return nullptr;
1018 }
1019 
1020 
1021 
1022 /****************************************************************************/
1023 
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:294
NIVissimEdge(int id, const std::string &name, const std::string &type, int noLanes, double zuschlag1, double zuschlag2, double length, const PositionVector &geom, const NIVissimClosedLanesVector &clv)
Constructor.
std::vector< double > myDistrictConnections
Definition: NIVissimEdge.h:275
~NIVissimEdge()
Destructor.
std::string myName
The name of the edge.
Definition: NIVissimEdge.h:252
const std::vector< int > & getFromLanes() const
static void dict_checkEdges2Join()
std::map< int, NIVissimEdge * > DictType
Definition of the dictionary type.
Definition: NIVissimEdge.h:288
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3272
std::vector< int > myPatchedSpeeds
Definition: NIVissimEdge.h:277
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:65
ConnectionClusters myConnectionClusters
List of connection clusters along this edge.
Definition: NIVissimEdge.h:267
std::vector< double > myLaneSpeeds
Definition: NIVissimEdge.h:279
double myZuschlag2
Definition: NIVissimEdge.h:261
A container for districts.
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:261
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:78
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:258
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
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
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:258
double myZuschlag1
Additional load values for this edge.
Definition: NIVissimEdge.h:261
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:49
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:284
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:270
double getLength() const
Returns the length of the node.
void checkDistrictConnectionExistanceAt(double pos)
static void removeDouble(std::vector< T > &v)
Definition: VectorHelper.h:70
std::string myType
The type of the edge.
Definition: NIVissimEdge.h:255
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.
double getToPosition() const
static void buildConnectionClusters()
Clusters connections of each edge.
std::vector< NIVissimEdge * > myToTreatAsSame
Definition: NIVissimEdge.h:281
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:296
NIVissimClosedLanesVector myClosedLanes
List of lanes closed on this edge.
Definition: NIVissimEdge.h:264
std::vector< NIVissimConnectionCluster * > ConnectionClusters
The definition for a container for connection clusters.
Definition: NIVissimEdge.h:162
const Position & getPosition() const
Definition: NBNode.h:242
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:291
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:167
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:273
std::pair< NIVissimConnectionCluster *, NBNode * > getFromNode(NBNodeCont &nc, ConnectionClusters &clusters)
Returns the origin node.
void removeFromConnectionCluster(NIVissimConnectionCluster *c)
double getFromPosition() const