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 /****************************************************************************/
10 /// @file    NIVissimEdge.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Michael Behrisch
14 /// @date    Sept 2002
15 /// @version $Id$
16 ///
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>
36 #include <utils/geom/PositionVector.h>
37 #include <utils/geom/GeomHelper.h>
38 #include <utils/distribution/DistributionCont.h>
39 #include <netbuild/NBNode.h>
40 #include <netbuild/NBNodeCont.h>
41 #include <utils/options/OptionsCont.h>
42 #include "NIVissimNodeCluster.h"
43 #include "NIVissimDistrictConnection.h"
44 #include "NIVissimClosedLanesVector.h"
45 #include "NIVissimConnection.h"
46 #include "NIVissimDisturbance.h"
47 #include "NIVissimEdge.h"
48 #include <utils/common/MsgHandler.h>
49 
50 
51 // ===========================================================================
52 // static members
53 // ===========================================================================
54 NIVissimEdge::DictType NIVissimEdge::myDict;
55 int NIVissimEdge::myMaxID = 0;
56 std::vector<std::string> NIVissimEdge::myLanesWithMissingSpeeds;
57 
58 
59 // ===========================================================================
60 // method definitions
61 // ===========================================================================
connection_position_sorter(int edgeid)62 NIVissimEdge::connection_position_sorter::connection_position_sorter(int edgeid)
63     : myEdgeID(edgeid) {}
64 
65 
66 int
operator ()(int c1id,int c2id) const67 NIVissimEdge::connection_position_sorter::operator()(int c1id,
68         int c2id) const {
69     NIVissimConnection* c1 = NIVissimConnection::dictionary(c1id);
70     NIVissimConnection* c2 = NIVissimConnection::dictionary(c2id);
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 
connection_cluster_position_sorter(int edgeid)87 NIVissimEdge::connection_cluster_position_sorter::connection_cluster_position_sorter(int edgeid)
88     : myEdgeID(edgeid) {}
89 
90 
91 int
operator ()(NIVissimConnectionCluster * cc1,NIVissimConnectionCluster * cc2) const92 NIVissimEdge::connection_cluster_position_sorter::operator()(
93     NIVissimConnectionCluster* cc1,
94     NIVissimConnectionCluster* cc2) const {
95     double pos1 = cc1->getPositionForEdge(myEdgeID);
96     double pos2 = cc2->getPositionForEdge(myEdgeID);
97     if (pos2 < 0 || pos1 < 0) {
98         cc1->getPositionForEdge(myEdgeID);
99         cc2->getPositionForEdge(myEdgeID);
100     }
101     assert(pos1 >= 0 && pos2 >= 0);
102     return pos1 < pos2;
103 }
104 
105 
106 
107 
NIVissimEdge(int id,const std::string & name,const std::string & type,std::vector<double> laneWidths,double zuschlag1,double zuschlag2,double,const PositionVector & geom,const NIVissimClosedLanesVector & clv)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 
~NIVissimEdge()130 NIVissimEdge::~NIVissimEdge() {
131     for (NIVissimClosedLanesVector::iterator i = myClosedLanes.begin(); i != myClosedLanes.end(); i++) {
132         delete (*i);
133     }
134     myClosedLanes.clear();
135 }
136 
137 
138 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)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
dictionary(int id,NIVissimEdge * o)156 NIVissimEdge::dictionary(int id, NIVissimEdge* o) {
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 
167 NIVissimEdge*
dictionary(int id)168 NIVissimEdge::dictionary(int id) {
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
buildConnectionClusters()178 NIVissimEdge::buildConnectionClusters() {
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
dict_buildNBEdges(NBDistrictCont & dc,NBNodeCont & nc,NBEdgeCont & ec,double offset)241 NIVissimEdge::dict_buildNBEdges(NBDistrictCont& dc, NBNodeCont& nc,
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
dict_propagateSpeeds()251 NIVissimEdge::dict_propagateSpeeds() {
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;
268             edge->checkUnconnectedLaneSpeeds();
269         }
270     }
271 }
272 
273 
274 void
checkUnconnectedLaneSpeeds()275 NIVissimEdge::checkUnconnectedLaneSpeeds() {
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;
302                 NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
303                 // propagate
304                 e->propagateSpeed(/*dc, */speed, c->getToLanes());
305             }
306         }
307     }
308 }
309 
310 
311 void
propagateOwn()312 NIVissimEdge::propagateOwn() {
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;
320             NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
321             // propagate
322             e->propagateSpeed(/*dc, */myLaneSpeeds[i], c->getToLanes());
323         }
324     }
325 }
326 
327 
328 void
propagateSpeed(double speed,std::vector<int> forLanes)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;
362             NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
363             // propagate
364             e->propagateSpeed(/*dc, */speed, c->getToLanes());
365         }
366     }
367 }
368 
369 
370 
371 void
setDistrictSpeed()372 NIVissimEdge::setDistrictSpeed() {
373     if (myDistrictConnections.size() > 0) {
374         double pos = *(myDistrictConnections.begin());
375         if (pos < getLength() - pos) {
376             NIVissimDistrictConnection* d =
377                 NIVissimDistrictConnection::dict_findForEdge(myID);
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;
391                         NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
392                         // propagate
393                         e->propagateSpeed(/*dc, */speed, c->getToLanes());
394                     }
395                 }
396             }
397         }
398     }
399 }
400 
401 
402 std::vector<NIVissimConnection*>
getOutgoingConnected(int lane) const403 NIVissimEdge::getOutgoingConnected(int lane) const {
404     std::vector<NIVissimConnection*> ret;
405     for (std::vector<int>::const_iterator i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
406         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
407         const std::vector<int>& lanes = c->getFromLanes();
408         if (find(lanes.begin(), lanes.end(), lane) != lanes.end()) {
409             NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
410             if (e != nullptr) {
411                 ret.push_back(c);
412             }
413         }
414     }
415     return ret;
416 }
417 
418 
419 void
buildNBEdge(NBDistrictCont & dc,NBNodeCont & nc,NBEdgeCont & ec,double sameNodesOffset)420 NIVissimEdge::buildNBEdge(NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec,
421                           double sameNodesOffset) {
422     // build the edge
423     std::pair<NIVissimConnectionCluster*, NBNode*> fromInf, toInf;
424     NBNode* fromNode, *toNode;
425     fromNode = toNode = nullptr;
426     sort(myConnectionClusters.begin(), myConnectionClusters.end(), connection_cluster_position_sorter(myID));
427     sort(myDistrictConnections.begin(), myDistrictConnections.end());
428     ConnectionClusters tmpClusters = myConnectionClusters;
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,
498                                    NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
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
getRealSpeed(int distNo)524 NIVissimEdge::getRealSpeed(int distNo) {
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*>
getFromNode(NBNodeCont & nc,ConnectionClusters & clusters)578 NIVissimEdge::getFromNode(NBNodeCont& nc, ConnectionClusters& clusters) {
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) {
599                 myDistrictConnections.erase(myDistrictConnections.begin());
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*>
getToNode(NBNodeCont & nc,ConnectionClusters & clusters)614 NIVissimEdge::getToNode(NBNodeCont& nc, ConnectionClusters& clusters) {
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) {
635                 myDistrictConnections.erase(myDistrictConnections.end() - 1);
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*>
remapOneOfNodes(NBNodeCont & nc,NIVissimDistrictConnection * d,NBNode * fromNode,NBNode * toNode)661 NIVissimEdge::remapOneOfNodes(NBNodeCont& nc,
662                               NIVissimDistrictConnection* d,
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(),
671                                      NODETYPE_NOJUNCTION);
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(),
678                                      NODETYPE_NOJUNCTION);
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*>
resolveSameNode(NBNodeCont & nc,double offset,NBNode * prevFrom,NBNode * prevTo)688 NIVissimEdge::resolveSameNode(NBNodeCont& nc, double offset,
689                               NBNode* prevFrom, NBNode* prevTo) {
690     // check whether the edge is connected to a district
691     //  use it if so
692     NIVissimDistrictConnection* d =
693         NIVissimDistrictConnection::dict_findForEdge(myID);
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 
730         NIVissimConnectionCluster* c = *(myConnectionClusters.begin());
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(),
736                 NODETYPE_NOJUNCTION);
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(),
748                 NODETYPE_NOJUNCTION);
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
setNodeCluster(int nodeid)770 NIVissimEdge::setNodeCluster(int nodeid) {
771     myNode = nodeid;
772 }
773 
774 
775 void
buildGeom()776 NIVissimEdge::buildGeom() {}
777 
778 
779 void
addIncomingConnection(int id)780 NIVissimEdge::addIncomingConnection(int id) {
781     myIncomingConnections.push_back(id);
782 }
783 
784 
785 void
addOutgoingConnection(int id)786 NIVissimEdge::addOutgoingConnection(int id) {
787     myOutgoingConnections.push_back(id);
788 }
789 
790 
791 
792 void
mergedInto(NIVissimConnectionCluster * old,NIVissimConnectionCluster * act)793 NIVissimEdge::mergedInto(NIVissimConnectionCluster* old,
794                          NIVissimConnectionCluster* act) {
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
removeFromConnectionCluster(NIVissimConnectionCluster * c)809 NIVissimEdge::removeFromConnectionCluster(NIVissimConnectionCluster* c) {
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
addToConnectionCluster(NIVissimConnectionCluster * c)818 NIVissimEdge::addToConnectionCluster(NIVissimConnectionCluster* c) {
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?
getBegin2D() const828 NIVissimEdge::getBegin2D() const {
829     return myGeom[0];
830 }
831 
832 
833 Position // !!! reference?
getEnd2D() const834 NIVissimEdge::getEnd2D() const {
835     return myGeom[-1];
836 }
837 
838 
839 double
getLength() const840 NIVissimEdge::getLength() const {
841     return myGeom.length();
842 }
843 
844 
845 void
checkDistrictConnectionExistanceAt(double pos)846 NIVissimEdge::checkDistrictConnectionExistanceAt(double pos) {
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
setSpeed(int lane,int speedDist)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
dict_checkEdges2Join()868 NIVissimEdge::dict_checkEdges2Join() {
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
addToTreatAsSame(NIVissimEdge * e)921 NIVissimEdge::addToTreatAsSame(NIVissimEdge* e) {
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 
949 NIVissimConnection*
getConnectionTo(NIVissimEdge * e)950 NIVissimEdge::getConnectionTo(NIVissimEdge* e) {
951     std::vector<int>::iterator i;
952     for (i = myIncomingConnections.begin(); i != myIncomingConnections.end(); i++) {
953         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
954         if (c->getFromEdgeID() == e->getID()) {
955             return c;
956         }
957     }
958     for (i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
959         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
960         if (c->getToEdgeID() == e->getID()) {
961             return c;
962         }
963     }
964     return nullptr;
965 }
966 
967 
968 const std::vector<NIVissimEdge*>&
getToTreatAsSame() const969 NIVissimEdge::getToTreatAsSame() const {
970     return myToTreatAsSame;
971 }
972 
973 
974 void
reportUnsetSpeeds()975 NIVissimEdge::reportUnsetSpeeds() {
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 
991 NIVissimEdge*
getBestIncoming() const992 NIVissimEdge::getBestIncoming() const {
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) {
1002         return NIVissimEdge::dictionary(NIVissimConnection::dictionary(myIncomingConnections.front())->getFromEdgeID());
1003     }
1004     return nullptr;
1005 }
1006 
1007 
1008 NIVissimEdge*
getBestOutgoing() const1009 NIVissimEdge::getBestOutgoing() const {
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) {
1019         return NIVissimEdge::dictionary(NIVissimConnection::dictionary(myOutgoingConnections.front())->getToEdgeID());
1020     }
1021     return nullptr;
1022 }
1023 
1024 
1025 
1026 /****************************************************************************/
1027 
1028