Line data Source code
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 : /****************************************************************************/
14 : /// @file NIVissimEdge.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // A temporary storage for edges imported from Vissim
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <string>
25 : #include <algorithm>
26 : #include <map>
27 : #include <cassert>
28 : #include <iomanip>
29 : #include <cmath>
30 : #include <iostream>
31 : #include <sstream>
32 : #include <iterator>
33 : #include <utils/common/ToString.h>
34 : #include <utils/geom/PositionVector.h>
35 : #include <utils/geom/GeomHelper.h>
36 : #include <utils/distribution/DistributionCont.h>
37 : #include <netbuild/NBNode.h>
38 : #include <netbuild/NBNodeCont.h>
39 : #include <utils/options/OptionsCont.h>
40 : #include "NIVissimNodeCluster.h"
41 : #include "NIVissimDistrictConnection.h"
42 : #include "NIVissimClosedLanesVector.h"
43 : #include "NIVissimConnection.h"
44 : #include "NIVissimDisturbance.h"
45 : #include "NIVissimEdge.h"
46 : #include <utils/common/MsgHandler.h>
47 :
48 :
49 : // ===========================================================================
50 : // static members
51 : // ===========================================================================
52 : NIVissimEdge::DictType NIVissimEdge::myDict;
53 : int NIVissimEdge::myMaxID = 0;
54 : std::vector<std::string> NIVissimEdge::myLanesWithMissingSpeeds;
55 :
56 :
57 : // ===========================================================================
58 : // method definitions
59 : // ===========================================================================
60 494 : NIVissimEdge::connection_position_sorter::connection_position_sorter(int edgeid)
61 494 : : myEdgeID(edgeid) {}
62 :
63 :
64 : int
65 3364 : NIVissimEdge::connection_position_sorter::operator()(int c1id,
66 : int c2id) const {
67 3364 : NIVissimConnection* c1 = NIVissimConnection::dictionary(c1id);
68 3364 : NIVissimConnection* c2 = NIVissimConnection::dictionary(c2id);
69 : double pos1 =
70 3364 : c1->getFromEdgeID() == myEdgeID
71 3364 : ? c1->getFromPosition() : c1->getToPosition();
72 : double pos2 =
73 3364 : c2->getFromEdgeID() == myEdgeID
74 3364 : ? c2->getFromPosition() : c2->getToPosition();
75 3364 : return pos1 < pos2;
76 : }
77 :
78 :
79 :
80 :
81 :
82 :
83 :
84 :
85 1177 : NIVissimEdge::connection_cluster_position_sorter::connection_cluster_position_sorter(int edgeid)
86 1177 : : myEdgeID(edgeid) {}
87 :
88 :
89 : int
90 2141 : NIVissimEdge::connection_cluster_position_sorter::operator()(
91 : NIVissimConnectionCluster* cc1,
92 : NIVissimConnectionCluster* cc2) const {
93 2141 : double pos1 = cc1->getPositionForEdge(myEdgeID);
94 2141 : double pos2 = cc2->getPositionForEdge(myEdgeID);
95 2141 : if (pos2 < 0 || pos1 < 0) {
96 0 : cc1->getPositionForEdge(myEdgeID);
97 0 : cc2->getPositionForEdge(myEdgeID);
98 : }
99 : assert(pos1 >= 0 && pos2 >= 0);
100 2141 : return pos1 < pos2;
101 : }
102 :
103 :
104 :
105 :
106 683 : NIVissimEdge::NIVissimEdge(int id, const std::string& name,
107 : const std::string& type,
108 : std::vector<double> laneWidths,
109 : double zuschlag1, double zuschlag2,
110 : double /*length*/, const PositionVector& geom,
111 683 : const NIVissimClosedLanesVector& clv) :
112 : NIVissimAbstractEdge(id, geom),
113 683 : myName(name), myType(type), myNoLanes((int)laneWidths.size()),
114 683 : myLaneWidths(laneWidths),
115 683 : myZuschlag1(zuschlag1), myZuschlag2(zuschlag2),
116 683 : myClosedLanes(clv),
117 683 : myLaneSpeeds(myNoLanes, -1),
118 683 : myAmWithinJunction(false)
119 : //, mySpeed(-1)
120 : {
121 : assert(myNoLanes >= 0);
122 683 : if (myMaxID < myID) {
123 683 : myMaxID = myID;
124 : }
125 683 : }
126 :
127 :
128 1366 : NIVissimEdge::~NIVissimEdge() {
129 733 : for (NIVissimClosedLanesVector::iterator i = myClosedLanes.begin(); i != myClosedLanes.end(); i++) {
130 50 : delete (*i);
131 : }
132 : myClosedLanes.clear();
133 1366 : }
134 :
135 :
136 : bool
137 0 : NIVissimEdge::dictionary(int id, const std::string& name,
138 : const std::string& type, int noLanes,
139 : double zuschlag1, double zuschlag2, double length,
140 : const PositionVector& geom,
141 : const NIVissimClosedLanesVector& clv) {
142 0 : NIVissimEdge* o = new NIVissimEdge(id, name, type, std::vector<double>(noLanes, NBEdge::UNSPECIFIED_WIDTH),
143 0 : zuschlag1, zuschlag2, length, geom, clv);
144 0 : if (!dictionary(id, o)) {
145 0 : delete o;
146 0 : return false;
147 : }
148 : return true;
149 : }
150 :
151 :
152 :
153 : bool
154 683 : NIVissimEdge::dictionary(int id, NIVissimEdge* o) {
155 : DictType::iterator i = myDict.find(id);
156 683 : if (i == myDict.end()) {
157 683 : myDict[id] = o;
158 683 : return true;
159 : }
160 : return false;
161 : }
162 :
163 :
164 :
165 : NIVissimEdge*
166 9102 : NIVissimEdge::dictionary(int id) {
167 : DictType::iterator i = myDict.find(id);
168 9102 : if (i == myDict.end()) {
169 : return nullptr;
170 : }
171 8830 : return (*i).second;
172 : }
173 :
174 :
175 : void
176 9 : NIVissimEdge::buildConnectionClusters() {
177 : const double MAX_CLUSTER_DISTANCE = 10;
178 : // build clusters for all edges made up from not previously assigne
179 : // connections
180 692 : for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
181 683 : int edgeid = (*i).first;
182 683 : NIVissimEdge* edge = (*i).second;
183 : // get all connectors using this edge
184 683 : std::vector<int> connectors = edge->myIncomingConnections;
185 : copy(edge->myOutgoingConnections.begin(), edge->myOutgoingConnections.end(), back_inserter(connectors));
186 683 : if (connectors.size() == 0) {
187 189 : continue;
188 : }
189 : // sort the connectors by the place on the edge
190 988 : 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 494 : bool outgoing = NIVissimConnection::dictionary(*j)->getFromEdgeID() == (*i).first;
195 : double position = outgoing
196 494 : ? NIVissimConnection::dictionary(*j)->getFromPosition()
197 435 : : NIVissimConnection::dictionary(*j)->getToPosition();
198 :
199 : // skip connections already in a cluster
200 : // !!! (?)
201 494 : while (j != connectors.end() && NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
202 : ++j;
203 : }
204 494 : if (j == connectors.end()) {
205 : continue;
206 : }
207 494 : currentCluster.push_back(*j);
208 : do {
209 1854 : if (j + 1 != connectors.end() && !NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
210 1360 : bool n_outgoing = NIVissimConnection::dictionary(*(j + 1))->getFromEdgeID() == edgeid;
211 : double n_position = n_outgoing
212 1360 : ? NIVissimConnection::dictionary(*(j + 1))->getFromPosition()
213 492 : : NIVissimConnection::dictionary(*(j + 1))->getToPosition();
214 1360 : if (n_outgoing == outgoing && fabs(n_position - position) < MAX_CLUSTER_DISTANCE) {
215 : // ok, in same cluster as prior
216 715 : currentCluster.push_back(*(j + 1));
217 : } else {
218 : // start new cluster
219 645 : VectorHelper<int>::removeDouble(currentCluster);
220 645 : edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
221 : currentCluster.clear();
222 645 : currentCluster.push_back(*(j + 1));
223 : }
224 : outgoing = n_outgoing;
225 : position = n_position;
226 : }
227 : j++;
228 1854 : } while (j != connectors.end());
229 : // add last connection
230 494 : if (currentCluster.size() > 0) {
231 494 : VectorHelper<int>::removeDouble(currentCluster);
232 494 : edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
233 : }
234 683 : }
235 9 : }
236 :
237 :
238 : void
239 9 : NIVissimEdge::dict_buildNBEdges(NBDistrictCont& dc, NBNodeCont& nc,
240 : NBEdgeCont& ec, double offset) {
241 692 : for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
242 683 : NIVissimEdge* edge = (*i).second;
243 683 : edge->buildNBEdge(dc, nc, ec, offset);
244 : }
245 9 : }
246 :
247 :
248 : void
249 9 : NIVissimEdge::dict_propagateSpeeds() {
250 : DictType::iterator i;
251 692 : for (i = myDict.begin(); i != myDict.end(); i++) {
252 683 : NIVissimEdge* edge = (*i).second;
253 683 : edge->setDistrictSpeed();
254 : }
255 692 : for (i = myDict.begin(); i != myDict.end(); i++) {
256 683 : NIVissimEdge* edge = (*i).second;
257 683 : edge->propagateSpeed(-1, std::vector<int>());
258 : }
259 36 : for (int j = 0; j < 3; j++) {
260 2076 : for (i = myDict.begin(); i != myDict.end(); i++) {
261 2049 : NIVissimEdge* edge = (*i).second;
262 2049 : edge->propagateOwn();
263 : }
264 2076 : for (i = myDict.begin(); i != myDict.end(); i++) {
265 2049 : NIVissimEdge* edge = (*i).second;
266 2049 : edge->checkUnconnectedLaneSpeeds();
267 : }
268 : }
269 9 : }
270 :
271 :
272 : void
273 2049 : NIVissimEdge::checkUnconnectedLaneSpeeds() {
274 4839 : for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
275 2790 : if (myLaneSpeeds[i] == -1) {
276 : double speed = -1;
277 2781 : int j1 = i - 1; // !!! recheck - j1 may become negative?
278 : int j2 = i;
279 6393 : while (j2 != (int) myLaneSpeeds.size() && myLaneSpeeds[j2] == -1) {
280 3612 : j2++;
281 : }
282 2781 : if (j1 < 0) {
283 2040 : if (j2 < (int) myLaneSpeeds.size()) {
284 0 : speed = myLaneSpeeds[j2];
285 : }
286 : } else {
287 741 : if (j2 >= (int) myLaneSpeeds.size()) {
288 741 : speed = myLaneSpeeds[j1];
289 : } else {
290 0 : speed = (myLaneSpeeds[j1] + myLaneSpeeds[j2]) / (double) 2.0;
291 : }
292 : }
293 741 : if (speed == -1) {
294 2781 : continue;
295 : }
296 0 : myLaneSpeeds[i] = speed;
297 0 : std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
298 0 : for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
299 0 : NIVissimConnection* c = *j;
300 0 : NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
301 : // propagate
302 0 : e->propagateSpeed(/*dc, */speed, c->getToLanes());
303 : }
304 0 : }
305 : }
306 2049 : }
307 :
308 :
309 : void
310 2049 : NIVissimEdge::propagateOwn() {
311 4839 : for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
312 2790 : if (myLaneSpeeds[i] == -1) {
313 2781 : continue;
314 : }
315 9 : std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
316 9 : for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
317 0 : NIVissimConnection* c = *j;
318 0 : NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
319 : // propagate
320 0 : e->propagateSpeed(/*dc, */myLaneSpeeds[i], c->getToLanes());
321 : }
322 9 : }
323 2049 : }
324 :
325 :
326 : void
327 683 : NIVissimEdge::propagateSpeed(double speed, std::vector<int> forLanes) {
328 : // if no lane is given, all set be set
329 683 : if (forLanes.size() == 0) {
330 1613 : for (int i = 0; i < myNoLanes; i++) {
331 930 : forLanes.push_back((int) i);
332 : }
333 : }
334 : // for the case of a first call
335 : // go through the lanes
336 1613 : for (std::vector<int>::const_iterator i = forLanes.begin(); i < forLanes.end(); i++) {
337 : // check whether a speed was set before
338 930 : if (myLaneSpeeds[*i] != -1) {
339 : // do not reset it from incoming
340 927 : continue;
341 : }
342 : // check whether the lane has a new speed to set
343 930 : if ((int) myPatchedSpeeds.size() > *i && myPatchedSpeeds[*i] != -1) {
344 : // use it
345 3 : speed = getRealSpeed(/*dc, */myPatchedSpeeds[*i]);
346 : }
347 : // check whether a speed is given
348 930 : if (speed == -1) {
349 : // do nothing if not
350 927 : continue;
351 : }
352 : // set the lane's speed to the given
353 3 : myLaneSpeeds[*i] = speed;
354 : // propagate the speed further
355 : // get the list of connected edges
356 3 : std::vector<NIVissimConnection*> connected = getOutgoingConnected(*i);
357 : // go through the list
358 3 : for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
359 0 : NIVissimConnection* c = *j;
360 0 : NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
361 : // propagate
362 0 : e->propagateSpeed(/*dc, */speed, c->getToLanes());
363 : }
364 3 : }
365 683 : }
366 :
367 :
368 :
369 : void
370 683 : NIVissimEdge::setDistrictSpeed() {
371 683 : if (myDistrictConnections.size() > 0) {
372 0 : double pos = *(myDistrictConnections.begin());
373 0 : if (pos < getLength() - pos) {
374 : NIVissimDistrictConnection* d =
375 0 : NIVissimDistrictConnection::dict_findForEdge(myID);
376 0 : if (d != nullptr) {
377 0 : double speed = d->getMeanSpeed(/*dc*/);
378 0 : if (speed == -1) {
379 : return;
380 : }
381 0 : for (int i = 0; i < myNoLanes; i++) {
382 0 : myLaneSpeeds[i] = speed;
383 : // propagate the speed further
384 : // get the list of connected edges
385 0 : std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
386 : // go through the list
387 0 : for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
388 0 : NIVissimConnection* c = *j;
389 0 : NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
390 : // propagate
391 0 : e->propagateSpeed(/*dc, */speed, c->getToLanes());
392 : }
393 0 : }
394 : }
395 : }
396 : }
397 : }
398 :
399 :
400 : std::vector<NIVissimConnection*>
401 12 : NIVissimEdge::getOutgoingConnected(int lane) const {
402 : std::vector<NIVissimConnection*> ret;
403 12 : for (std::vector<int>::const_iterator i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
404 0 : NIVissimConnection* c = NIVissimConnection::dictionary(*i);
405 0 : const std::vector<int>& lanes = c->getFromLanes();
406 0 : if (find(lanes.begin(), lanes.end(), lane) != lanes.end()) {
407 0 : NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
408 0 : if (e != nullptr) {
409 0 : ret.push_back(c);
410 : }
411 : }
412 : }
413 12 : return ret;
414 0 : }
415 :
416 :
417 : void
418 683 : NIVissimEdge::buildNBEdge(NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec,
419 : double sameNodesOffset) {
420 : // build the edge
421 : std::pair<NIVissimConnectionCluster*, NBNode*> fromInf, toInf;
422 : NBNode* fromNode, *toNode;
423 : fromNode = toNode = nullptr;
424 1366 : sort(myConnectionClusters.begin(), myConnectionClusters.end(), connection_cluster_position_sorter(myID));
425 683 : sort(myDistrictConnections.begin(), myDistrictConnections.end());
426 683 : ConnectionClusters tmpClusters = myConnectionClusters;
427 683 : if (tmpClusters.size() != 0) {
428 494 : 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 494 : fromInf = getFromNode(nc, tmpClusters);
433 : fromNode = fromInf.second;
434 : // get or build the to-node
435 : //if(tmpClusters.size()>0) {
436 494 : toInf = getToNode(nc, tmpClusters);
437 : toNode = toInf.second;
438 494 : if (fromInf.first != 0 && toNode != nullptr && fromInf.first->around(toNode->getPosition())) {
439 4 : WRITE_WARNINGF(TL("Will not build edge '%'."), toString(myID));
440 2 : myAmWithinJunction = true;
441 2 : return;
442 : }
443 : //}
444 : // if both nodes are the same, resolve the problem otherwise
445 492 : if (fromNode == toNode) {
446 0 : 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 492 : if (fromNode == nullptr) {
460 : fromInf.first = 0;
461 189 : Position pos = myGeom[0];
462 378 : fromNode = new NBNode(toString<int>(myID) + "-SourceNode", pos, SumoXMLNodeType::NOJUNCTION);
463 189 : if (!nc.insert(fromNode)) {
464 0 : throw ProcessError(TLF("Could not insert node '%' to nodes container.", fromNode->getID()));
465 : }
466 : }
467 681 : if (toNode == nullptr) {
468 : toInf.first = 0;
469 189 : Position pos = myGeom[-1];
470 378 : toNode = new NBNode(toString<int>(myID) + "-DestinationNode", pos, SumoXMLNodeType::NOJUNCTION);
471 189 : if (!nc.insert(toNode)) {
472 0 : throw ProcessError(TLF("Could not insert node '%' to nodes container.", toNode->getID()));
473 : }
474 : }
475 :
476 : // build the edge
477 : double avgSpeed = 0;
478 1608 : for (int i = 0; i < myNoLanes; i++) {
479 927 : if ((int)myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
480 2772 : myLanesWithMissingSpeeds.push_back(toString(myID) + "_" + toString(i));
481 924 : avgSpeed += OptionsCont::getOptions().getFloat("vissim.default-speed");
482 : } else {
483 3 : avgSpeed += myLaneSpeeds[i];
484 : }
485 : }
486 681 : avgSpeed /= (double) myLaneSpeeds.size();
487 681 : avgSpeed *= OptionsCont::getOptions().getFloat("vissim.speed-norm");
488 :
489 681 : if (fromNode == toNode) {
490 0 : WRITE_WARNINGF(TL("Could not build edge '%'; would connect same node."), toString(myID));
491 0 : return;
492 : }
493 :
494 1362 : NBEdge* buildEdge = new NBEdge(toString<int>(myID), fromNode, toNode, myType,
495 : avgSpeed / 3.6, NBEdge::UNSPECIFIED_FRICTION, myNoLanes, -1,
496 : NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
497 2043 : myGeom, LaneSpreadFunction::CENTER, myName, "", true);
498 1608 : for (int i = 0; i < myNoLanes; i++) {
499 927 : buildEdge->setLaneWidth(i, myLaneWidths[i]);
500 927 : if ((int) myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
501 1848 : buildEdge->setSpeed(i, OptionsCont::getOptions().getFloat("vissim.default-speed") / (double) 3.6);
502 : } else {
503 3 : buildEdge->setSpeed(i, myLaneSpeeds[i] / (double) 3.6);
504 : }
505 : }
506 681 : ec.insert(buildEdge);
507 : // check whether the edge contains any other clusters
508 681 : if (tmpClusters.size() > 0) {
509 : bool cont = true;
510 247 : for (ConnectionClusters::iterator j = tmpClusters.begin(); cont && j != tmpClusters.end(); ++j) {
511 : // split the edge at the previously build node
512 188 : std::string nextID = buildEdge->getID() + "[1]";
513 188 : cont = ec.splitAt(dc, buildEdge, (*j)->getNBNode());
514 : // !!! what to do if the edge could not be split?
515 188 : buildEdge = ec.retrieve(nextID);
516 : }
517 : }
518 683 : }
519 :
520 :
521 : double
522 3 : NIVissimEdge::getRealSpeed(int distNo) {
523 3 : std::string id = toString<int>(distNo);
524 3 : Distribution* dist = DistributionCont::dictionary("speed", id);
525 3 : if (dist == nullptr) {
526 0 : WRITE_WARNINGF(TL("The referenced speed distribution '%' is not known."), id);
527 0 : return -1;
528 : }
529 : assert(dist != 0);
530 3 : double speed = dist->getMax();
531 3 : if (speed < 0 || speed > 1000) {
532 0 : WRITE_WARNINGF(TL("What about distribution '%'"), toString<int>(distNo));
533 : }
534 : return speed;
535 : }
536 :
537 : /*
538 : bool
539 : NIVissimEdge::recheckSpeedPatches()
540 : {
541 : // int speed_idx = -1;
542 : // check set speeds
543 : if(myPatchedSpeeds.size()!=0) {
544 : std::vector<double>::iterator i =
545 : std::find(myPatchedSpeeds.begin(), myPatchedSpeeds.end(), -1);
546 : if(myPatchedSpeeds.size()!=myNoLanes||i!=myPatchedSpeeds.end()) {
547 : cot << "Warning! Not all lanes are patched! (edge:" << myID << ")." << endl;
548 : }
549 : //
550 : if(std::vector<double>Helper::maxValue(myPatchedSpeeds)!=std::vector<double>Helper::minValue(myPatchedSpeeds)) {
551 : cot << "Warning! Not all lanes have the same speed!! (edge:" << myID << ")." << endl;
552 : }
553 : //
554 : / // !!! ist natuerlich Quatsch - erst recht, wenn Edges zusammengefasst werden
555 : speed = std::vector<double>Helper::sum(myPatchedSpeeds);
556 : speed /= (double) myPatchedSpeeds.size();*/
557 : /* return true;
558 : }
559 : if(myDistrictConnections.size()>0) {
560 : double pos = *(myDistrictConnections.begin());
561 : // if(pos<10) {
562 : NIVissimDistrictConnection *d =
563 : NIVissimDistrictConnection::dict_findForEdge(myID);
564 : if(d!=0) {
565 : return true;
566 : // speed = d->getMeanSpeed();
567 : }
568 : // }
569 : // return true;
570 : }
571 : return false;
572 : }
573 : */
574 :
575 : std::pair<NIVissimConnectionCluster*, NBNode*>
576 494 : NIVissimEdge::getFromNode(NBNodeCont& nc, ConnectionClusters& clusters) {
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 494 : NIVissimConnectionCluster* c = *(clusters.begin());
582 : // check whether the edge starts within a already build node
583 494 : if (c->around(beg, MAX_DISTANCE)) {
584 : clusters.erase(clusters.begin());
585 : return std::pair<NIVissimConnectionCluster*, NBNode*>
586 429 : (c, c->getNBNode());
587 : }
588 : // check for a parking place at the begin
589 65 : if (myDistrictConnections.size() > 0) {
590 0 : double pos = *(myDistrictConnections.begin());
591 0 : if (pos < 10) {
592 0 : NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, SumoXMLNodeType::NOJUNCTION);
593 0 : if (!nc.insert(node)) {
594 0 : throw 1;
595 : }
596 0 : while (myDistrictConnections.size() > 0 && *(myDistrictConnections.begin()) < 10) {
597 0 : myDistrictConnections.erase(myDistrictConnections.begin());
598 : }
599 0 : return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
600 : }
601 : }
602 : // build a new node for the edge's begin otherwise
603 130 : NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, SumoXMLNodeType::NOJUNCTION);
604 65 : if (!nc.insert(node)) {
605 0 : throw 1;
606 : }
607 65 : return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
608 : }
609 :
610 :
611 : std::pair<NIVissimConnectionCluster*, NBNode*>
612 494 : NIVissimEdge::getToNode(NBNodeCont& nc, ConnectionClusters& clusters) {
613 : const Position& end = myGeom.back();
614 494 : if (clusters.size() > 0) {
615 : const double MAX_DISTANCE = 10.;
616 : assert(clusters.size() >= 1);
617 474 : NIVissimConnectionCluster* c = *(clusters.end() - 1);
618 : // check whether the edge ends within a already build node
619 474 : if (c->around(end, MAX_DISTANCE)) {
620 : clusters.erase(clusters.end() - 1);
621 444 : return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
622 : }
623 : }
624 : // check for a parking place at the end
625 50 : if (myDistrictConnections.size() > 0) {
626 0 : double pos = *(myDistrictConnections.end() - 1);
627 0 : if (pos > myGeom.length() - 10) {
628 0 : NBNode* node = new NBNode(toString<int>(myID) + "-end", end, SumoXMLNodeType::NOJUNCTION);
629 0 : if (!nc.insert(node)) {
630 0 : throw 1;
631 : }
632 0 : while (myDistrictConnections.size() > 0 && *(myDistrictConnections.end() - 1) < myGeom.length() - 10) {
633 0 : myDistrictConnections.erase(myDistrictConnections.end() - 1);
634 : }
635 0 : 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 100 : NBNode* node = new NBNode(toString<int>(myID) + "-end", end, SumoXMLNodeType::NOJUNCTION);
641 50 : if (!nc.insert(node)) {
642 0 : throw 1;
643 : }
644 50 : return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
645 : /*
646 : if (clusters.size()>0) {
647 : NIVissimConnectionCluster *c = *(clusters.end()-1);
648 : clusters.erase(clusters.end()-1);
649 : return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
650 : } else {
651 : // !!! self-loop edge?!
652 : return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), (*(myConnectionClusters.begin()))->getNBNode());
653 : }
654 : */
655 : }
656 :
657 :
658 : std::pair<NBNode*, NBNode*>
659 0 : NIVissimEdge::remapOneOfNodes(NBNodeCont& nc,
660 : NIVissimDistrictConnection* d,
661 : NBNode* fromNode, NBNode* toNode) {
662 0 : std::string nid = "ParkingPlace" + toString<int>(d->getID());
663 0 : if (d->geomPosition().distanceTo(fromNode->getPosition())
664 : <
665 0 : d->geomPosition().distanceTo(toNode->getPosition())) {
666 :
667 : NBNode* newNode = new NBNode(nid,
668 : fromNode->getPosition(),
669 0 : SumoXMLNodeType::NOJUNCTION);
670 0 : nc.erase(fromNode);
671 0 : nc.insert(newNode);
672 0 : return std::pair<NBNode*, NBNode*>(newNode, toNode);
673 : } else {
674 : NBNode* newNode = new NBNode(nid,
675 : toNode->getPosition(),
676 0 : SumoXMLNodeType::NOJUNCTION);
677 0 : nc.erase(toNode);
678 0 : nc.insert(newNode);
679 0 : return std::pair<NBNode*, NBNode*>(fromNode, newNode);
680 : }
681 : }
682 :
683 :
684 :
685 : std::pair<NBNode*, NBNode*>
686 0 : NIVissimEdge::resolveSameNode(NBNodeCont& nc, double offset,
687 : NBNode* prevFrom, NBNode* prevTo) {
688 : // check whether the edge is connected to a district
689 : // use it if so
690 : NIVissimDistrictConnection* d =
691 0 : NIVissimDistrictConnection::dict_findForEdge(myID);
692 0 : if (d != nullptr) {
693 0 : Position pos = d->geomPosition();
694 : double position = d->getPosition();
695 : // the district is at the begin of the edge
696 0 : if (myGeom.length() - position > position) {
697 0 : std::string nid = "ParkingPlace" + toString<int>(d->getID());
698 0 : NBNode* node = nc.retrieve(nid);
699 0 : if (node == nullptr) {
700 : node = new NBNode(nid,
701 0 : pos, SumoXMLNodeType::NOJUNCTION);
702 0 : if (!nc.insert(node)) {
703 0 : throw 1;
704 : }
705 : }
706 0 : return std::pair<NBNode*, NBNode*>(node, prevTo);
707 : }
708 : // the district is at the end of the edge
709 : else {
710 0 : std::string nid = "ParkingPlace" + toString<int>(d->getID());
711 0 : NBNode* node = nc.retrieve(nid);
712 0 : if (node == nullptr) {
713 0 : node = new NBNode(nid, pos, SumoXMLNodeType::NOJUNCTION);
714 0 : if (!nc.insert(node)) {
715 0 : throw 1;
716 : }
717 : }
718 : assert(node != 0);
719 0 : 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 0 : if (myConnectionClusters.size() == 1) {
726 : NBNode* node = prevFrom; // it is the same as getToNode()
727 :
728 0 : NIVissimConnectionCluster* c = *(myConnectionClusters.begin());
729 : // no end node given
730 0 : if (c->around(myGeom.front(), offset) && !c->around(myGeom.back(), offset)) {
731 : NBNode* end = new NBNode(
732 0 : toString<int>(myID) + "-End",
733 : myGeom.back(),
734 0 : SumoXMLNodeType::NOJUNCTION);
735 0 : if (!nc.insert(end)) {
736 0 : throw 1;
737 : }
738 0 : return std::pair<NBNode*, NBNode*>(node, end);
739 : }
740 :
741 : // no begin node given
742 0 : if (!c->around(myGeom.front(), offset) && c->around(myGeom.back(), offset)) {
743 : NBNode* beg = new NBNode(
744 0 : toString<int>(myID) + "-Begin",
745 : myGeom.front(),
746 0 : SumoXMLNodeType::NOJUNCTION);
747 0 : if (!nc.insert(beg)) {
748 : std::cout << "nope, NIVissimDisturbance" << std::endl;
749 0 : throw 1;
750 : }
751 0 : return std::pair<NBNode*, NBNode*>(beg, node);
752 : }
753 :
754 : // self-loop edge - both points lie within the same cluster
755 0 : if (c->around(myGeom.front()) && c->around(myGeom.back())) {
756 0 : 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 0 : return std::pair<NBNode*, NBNode*>(prevFrom, prevTo);
762 : }
763 :
764 :
765 :
766 :
767 : void
768 0 : NIVissimEdge::setNodeCluster(int nodeid) {
769 0 : myNode = nodeid;
770 0 : }
771 :
772 :
773 : void
774 0 : NIVissimEdge::buildGeom() {}
775 :
776 :
777 : void
778 927 : NIVissimEdge::addIncomingConnection(int id) {
779 927 : myIncomingConnections.push_back(id);
780 927 : }
781 :
782 :
783 : void
784 927 : NIVissimEdge::addOutgoingConnection(int id) {
785 927 : myOutgoingConnections.push_back(id);
786 927 : }
787 :
788 :
789 :
790 : void
791 803 : NIVissimEdge::mergedInto(NIVissimConnectionCluster* old,
792 : NIVissimConnectionCluster* act) {
793 : ConnectionClusters::iterator i =
794 803 : std::find(myConnectionClusters.begin(), myConnectionClusters.end(), old);
795 803 : if (i != myConnectionClusters.end()) {
796 803 : myConnectionClusters.erase(i);
797 : }
798 803 : i = std::find(myConnectionClusters.begin(), myConnectionClusters.end(), act);
799 803 : if (i == myConnectionClusters.end()) {
800 734 : myConnectionClusters.push_back(act);
801 : }
802 803 : }
803 :
804 :
805 :
806 : void
807 0 : NIVissimEdge::removeFromConnectionCluster(NIVissimConnectionCluster* c) {
808 : ConnectionClusters::iterator i =
809 0 : std::find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
810 : assert(i != myConnectionClusters.end());
811 0 : myConnectionClusters.erase(i);
812 0 : }
813 :
814 :
815 : void
816 0 : NIVissimEdge::addToConnectionCluster(NIVissimConnectionCluster* c) {
817 : ConnectionClusters::iterator i =
818 0 : std::find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
819 0 : if (i == myConnectionClusters.end()) {
820 0 : myConnectionClusters.push_back(c);
821 : }
822 0 : }
823 :
824 :
825 : Position // !!! reference?
826 0 : NIVissimEdge::getBegin2D() const {
827 0 : return myGeom[0];
828 : }
829 :
830 :
831 : Position // !!! reference?
832 0 : NIVissimEdge::getEnd2D() const {
833 0 : return myGeom[-1];
834 : }
835 :
836 :
837 : double
838 0 : NIVissimEdge::getLength() const {
839 0 : return myGeom.length();
840 : }
841 :
842 :
843 : void
844 0 : NIVissimEdge::checkDistrictConnectionExistanceAt(double pos) {
845 0 : if (find(myDistrictConnections.begin(), myDistrictConnections.end(), pos) == myDistrictConnections.end()) {
846 0 : 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 0 : }
854 :
855 :
856 : void
857 6 : NIVissimEdge::setSpeed(int lane, int speedDist) {
858 9 : while ((int)myPatchedSpeeds.size() <= lane) {
859 3 : myPatchedSpeeds.push_back(-1);
860 : }
861 6 : myPatchedSpeeds[lane] = speedDist;
862 6 : }
863 :
864 :
865 : void
866 9 : NIVissimEdge::dict_checkEdges2Join() {
867 : // go through the edges
868 692 : for (DictType::iterator i1 = myDict.begin(); i1 != myDict.end(); i1++) {
869 : // retrieve needed values from the first edge
870 683 : NIVissimEdge* e1 = (*i1).second;
871 683 : const PositionVector& g1 = e1->getGeometry();
872 : // check all other edges
873 : DictType::iterator i2 = i1;
874 : i2++;
875 38738 : for (; i2 != myDict.end(); i2++) {
876 : // retrieve needed values from the second edge
877 38055 : NIVissimEdge* e2 = (*i2).second;
878 38055 : const PositionVector& g2 = e2->getGeometry();
879 : // get the connection description
880 38055 : NIVissimConnection* c = e1->getConnectionTo(e2);
881 38055 : if (c == nullptr) {
882 37312 : c = e2->getConnectionTo(e1);
883 : }
884 : // the edge must not be a direct contiuation of the other
885 37312 : if (c != nullptr) {
886 1055 : if ((c->getFromEdgeID() == e1->getID() && fabs(c->getFromPosition() - e1->getGeometry().length()) < 5)
887 1263 : ||
888 951 : (c->getFromEdgeID() == e2->getID() && fabs(c->getFromPosition() - e2->getGeometry().length()) < 5)) {
889 :
890 614 : 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 37441 : if (fabs(GeomHelper::angleDiff(g1.beginEndAngle(), g2.beginEndAngle())) > DEG2RAD(2.0)) {
898 : // continue if the lines are not parallel
899 36474 : 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 967 : if (g1.back().distanceTo(g2.back()) > 10) {
906 : // continue if the lines do not end at the same length
907 933 : continue;
908 : }
909 : // ok, seem to be different lanes for the same edge
910 : // mark as possibly joined later
911 34 : e1->addToTreatAsSame(e2);
912 34 : e2->addToTreatAsSame(e1);
913 : }
914 : }
915 9 : }
916 :
917 :
918 : bool
919 68 : NIVissimEdge::addToTreatAsSame(NIVissimEdge* e) {
920 68 : if (e == this) {
921 : return false;
922 : }
923 : // check whether this edge already knows about the other
924 68 : if (find(myToTreatAsSame.begin(), myToTreatAsSame.end(), e) == myToTreatAsSame.end()) {
925 68 : myToTreatAsSame.push_back(e);
926 68 : 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 :
947 : NIVissimConnection*
948 75367 : NIVissimEdge::getConnectionTo(NIVissimEdge* e) {
949 : std::vector<int>::iterator i;
950 172404 : for (i = myIncomingConnections.begin(); i != myIncomingConnections.end(); i++) {
951 97468 : NIVissimConnection* c = NIVissimConnection::dictionary(*i);
952 97468 : if (c->getFromEdgeID() == e->getID()) {
953 431 : return c;
954 : }
955 : }
956 171088 : for (i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
957 96464 : NIVissimConnection* c = NIVissimConnection::dictionary(*i);
958 96464 : if (c->getToEdgeID() == e->getID()) {
959 312 : return c;
960 : }
961 : }
962 : return nullptr;
963 : }
964 :
965 :
966 : const std::vector<NIVissimEdge*>&
967 4011 : NIVissimEdge::getToTreatAsSame() const {
968 4011 : return myToTreatAsSame;
969 : }
970 :
971 :
972 : void
973 1 : NIVissimEdge::reportUnsetSpeeds() {
974 1 : if (myLanesWithMissingSpeeds.size() == 0) {
975 0 : return;
976 : }
977 1 : std::ostringstream str;
978 1 : str << "The following lanes have no explicit speed information:\n ";
979 115 : for (std::vector<std::string>::iterator i = myLanesWithMissingSpeeds.begin(); i != myLanesWithMissingSpeeds.end(); ++i) {
980 114 : if (i != myLanesWithMissingSpeeds.begin()) {
981 113 : str << ", ";
982 : }
983 : str << *i;
984 : }
985 1 : WRITE_WARNING(str.str());
986 1 : }
987 :
988 :
989 : NIVissimEdge*
990 2 : NIVissimEdge::getBestIncoming() const {
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 2 : if (myIncomingConnections.size() != 0) {
1000 2 : return NIVissimEdge::dictionary(NIVissimConnection::dictionary(myIncomingConnections.front())->getFromEdgeID());
1001 : }
1002 : return nullptr;
1003 : }
1004 :
1005 :
1006 : NIVissimEdge*
1007 6 : NIVissimEdge::getBestOutgoing() const {
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 6 : if (myOutgoingConnections.size() != 0) {
1017 6 : return NIVissimEdge::dictionary(NIVissimConnection::dictionary(myOutgoingConnections.front())->getToEdgeID());
1018 : }
1019 : return nullptr;
1020 : }
1021 :
1022 :
1023 : /****************************************************************************/
|