Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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>
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// ===========================================================================
54std::vector<std::string> NIVissimEdge::myLanesWithMissingSpeeds;
55
56
57// ===========================================================================
58// method definitions
59// ===========================================================================
62
63
64int
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
87
88
89int
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
106NIVissimEdge::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),
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
136bool
137NIVissimEdge::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
153bool
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
175void
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
238void
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
248void
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
272void
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
309void
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
326void
327NIVissimEdge::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
369void
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
400std::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
417void
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
521double
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/*
538bool
539NIVissimEdge::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
575std::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
611std::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
658std::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
685std::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
767void
769 myNode = nodeid;
770}
771
772
773void
775
776
777void
781
782
783void
787
788
789
790void
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
806void
808 ConnectionClusters::iterator i =
809 std::find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
810 assert(i != myConnectionClusters.end());
811 myConnectionClusters.erase(i);
812}
813
814
815void
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
825Position // !!! reference?
827 return myGeom[0];
828}
829
830
831Position // !!! reference?
833 return myGeom[-1];
834}
835
836
837double
839 return myGeom.length();
840}
841
842
843void
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
856void
857NIVissimEdge::setSpeed(int lane, int speedDist) {
858 while ((int)myPatchedSpeeds.size() <= lane) {
859 myPatchedSpeeds.push_back(-1);
860 }
861 myPatchedSpeeds[lane] = speedDist;
862}
863
864
865void
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
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
918bool
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
966const std::vector<NIVissimEdge*>&
970
971
972void
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
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.
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.
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
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:4294
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition NBEdge.h:355
const std::string & getID() const
Definition NBEdge.h:1528
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition NBEdge.cpp:4165
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition NBEdge.h:346
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition NBEdge.h:349
Container for nodes during the netbuilding process.
Definition NBNodeCont.h:57
bool erase(NBNode *node)
Removes the given node, deleting it.
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
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)
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
int operator()(int c1id, int c2id) const
comparing operation
connection_position_sorter(int edgeid)
constructor
A temporary storage for edges imported from Vissim.
void checkDistrictConnectionExistanceAt(double pos)
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.
NIVissimClosedLanesVector myClosedLanes
List of lanes closed on this edge.
static std::vector< std::string > myLanesWithMissingSpeeds
std::string myName
The name of the edge.
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.
static DictType myDict
The dictionary.
static void reportUnsetSpeeds()
Writes edges with unset speeds to the warnings message log instance.
std::map< int, NIVissimEdge * > DictType
Definition of the dictionary type.
double getRealSpeed(int distNo)
std::vector< double > myDistrictConnections
NIVissimEdge * getBestIncoming() const
~NIVissimEdge()
Destructor.
void addOutgoingConnection(int id)
Adds a connection where this edge is the source.
std::vector< double > myLaneSpeeds
std::vector< NIVissimConnectionCluster * > ConnectionClusters
The definition for a container for connection clusters.
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
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.
static void dict_propagateSpeeds()
std::pair< NIVissimConnectionCluster *, NBNode * > getToNode(NBNodeCont &nc, ConnectionClusters &clusters)
Returns the destination node.
std::vector< double > myLaneWidths
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.
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.
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.
void setNodeCluster(int nodeid)
NIVissimConnection * getConnectionTo(NIVissimEdge *e)
std::vector< int > myPatchedSpeeds
std::pair< NBNode *, NBNode * > remapOneOfNodes(NBNodeCont &nc, NIVissimDistrictConnection *d, NBNode *fromNode, NBNode *toNode)
ConnectionClusters myConnectionClusters
List of connection clusters along this edge.
double myZuschlag2
std::vector< int > myIncomingConnections
List of connections incoming to this edge.
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.
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:266
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)