Eclipse SUMO - Simulation of Urban MObility
GNENet.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2001-2022 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/****************************************************************************/
18// A visual container for GNE-network-components such as GNEEdge and GNEJunction.
19// GNE components wrap netbuild-components and supply visualisation and editing
20// capabilities (adapted from GUINet)
21//
22// WorkrouteFlow (rough draft)
23// use NILoader to fill
24// do netedit stuff
25// call compute to save results
26//
27/****************************************************************************/
50#include <netwrite/NWFrame.h>
57
59#include "GNENet.h"
60#include "GNEViewNet.h"
61#include "GNEUndoList.h"
62#include "GNEViewParent.h"
63
64
65// ===========================================================================
66// FOX callback mapping
67// ===========================================================================
68
69FXIMPLEMENT_ABSTRACT(GNENetHelper::GNEChange_ReplaceEdgeInTLS, GNEChange, nullptr, 0)
70
71// ===========================================================================
72// static members
73// ===========================================================================
74
75const double GNENet::Z_INITIALIZED = 1;
76const std::map<SumoXMLAttr, std::string> GNENet::EMPTY_HEADER;
77
78// ===========================================================================
79// member method definitions
80// ===========================================================================
81
82#ifdef _MSC_VER
83#pragma warning(push)
84/* Disable warning about using "this" in the constructor */
85#pragma warning(disable: 4355)
86#endif
88 GUIGlObject(GLO_NETWORK, "", nullptr),
89 myViewNet(nullptr),
90 myNetBuilder(netBuilder),
91 myAttributeCarriers(new GNENetHelper::AttributeCarriers(this)),
92 myPathManager(new GNEPathManager(this)), // TODO a little dangerous to use "this" here, it makes access to the net and the netBuilder
93 myJunctionIDCounter(0),
94 myEdgeIDCounter(0),
95 myNeedRecompute(true),
96 myNetSaved(true),
97 myAdditionalsSaved(true),
98 myTLSProgramsSaved(true),
99 myDemandElementsSaved(true),
100 myDataElementsSaved(true),
101 myUpdateGeometryEnabled(true),
102 myUpdateDataEnabled(true) {
103 // set net in gIDStorage
105 // Write GL debug information
106 WRITE_GLDEBUG("initJunctionsAndEdges function called in GNENet constructor");
107 // init junction and edges
109 // check Z boundary
110 if (myZBoundary.ymin() != Z_INITIALIZED) {
111 myZBoundary.add(0, 0);
112 }
113
114}
115#ifdef _MSC_VER
116#pragma warning(pop)
117#endif
118
119
121 // delete path manager
122 delete myPathManager;
123 // delete AttributeCarriers
124 delete myAttributeCarriers;
125 // show extra information for tests
126 WRITE_DEBUG("Deleting net builder in GNENet destructor");
127 delete myNetBuilder;
128}
129
130
133 return myAttributeCarriers;
134}
135
136
139 return myPathManager;
140}
141
142
143const Boundary&
145 // SUMORTree is also a Boundary
146 return myGrid;
147}
148
149
152 return myGrid;
153}
154
155const std::map<std::string, int>&
158}
159
160
163 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
164 buildPopupHeader(ret, app);
166 buildPositionCopyEntry(ret, app);
167 return ret;
168}
169
170
173 // Nets lanes don't have attributes
175 // close building
176 ret->closeBuilding();
177 return ret;
178}
179
180
181void
183 // nothing to drawn
184}
185
186
187double
189 return 1;
190}
191
192
195 return getBoundary();
196}
197
198
199void
200GNENet::expandBoundary(const Boundary& newBoundary) {
201 myGrid.add(newBoundary);
202}
203
204
205const Boundary&
207 return myZBoundary;
208}
209
210
211void
213 // @todo let Boundary class track z-coordinate natively
214 if (z != 0) {
216 }
217}
218
219
222 // get junction prefix
223 const std::string junctionPrefix = OptionsCont::getOptions().getString("node-prefix");
224 // generate new ID
225 while (myAttributeCarriers->getJunctions().count(junctionPrefix + toString(myJunctionIDCounter)) != 0) {
227 }
228 // create new NBNode
229 NBNode* nbn = new NBNode(junctionPrefix + toString(myJunctionIDCounter), pos);
230 GNEJunction* junction = new GNEJunction(this, nbn);
231 undoList->add(new GNEChange_Junction(junction, true), true);
232 return junction;
233}
234
235
236GNEEdge*
237GNENet::createEdge(GNEJunction* src, GNEJunction* dest, GNEEdge* edgeTemplate, GNEUndoList* undoList,
238 const std::string& suggestedName, bool wasSplit, bool allowDuplicateGeom, bool recomputeConnections) {
239 // get edge prefix
240 const std::string edgePrefix = OptionsCont::getOptions().getString("edge-prefix");
241 // get edge infix
242 std::string edgeInfix = OptionsCont::getOptions().getString("edge-infix");
243 // prevent duplicate edge (same geometry)
244 for (const auto& outgoingEdge : src->getNBNode()->getOutgoingEdges()) {
245 if (outgoingEdge->getToNode() == dest->getNBNode() && outgoingEdge->getGeometry().size() == 2) {
246 if (!allowDuplicateGeom) {
247 return nullptr;
248 }
249 }
250 }
251 // check if exist opposite edge
252 const auto oppositeEdges = myAttributeCarriers->retrieveEdges(dest, src);
253 // declare edge id
254 std::string edgeID;
255 // update id
256 if (oppositeEdges.size() > 0) {
257 // avoid ids with "--..."
258 if ((oppositeEdges.front()->getID().size() > 1) && (oppositeEdges.front()->getID().front() == '-')) {
259 edgeID = oppositeEdges.front()->getID().substr(1);
260 } else {
261 edgeID = "-" + oppositeEdges.front()->getID();
262 }
263 // check if already exist an edge with edgeID
264 if (myAttributeCarriers->getEdges().count(edgeID) > 0) {
265 int counter = 0;
266 // generate new ID using edgeID and counter
267 while (myAttributeCarriers->getEdges().count(edgeID + toString(counter)) > 0) {
268 counter++;
269 }
270 edgeID = edgeID + toString(counter);
271 }
272 } else if ((suggestedName.size() > 0) && (myAttributeCarriers->retrieveEdge(suggestedName, false) == nullptr)) {
273 edgeID = suggestedName;
274 } else if (edgeInfix.size() > 0) {
275 // permit empty infix by setting it to <SPACE>
276 edgeInfix = StringUtils::trim(edgeInfix);
277 // check if exist edge with id <fromNodeID><infix><toNodeID>
278 if (myAttributeCarriers->getEdges().count(src->getID() + edgeInfix + dest->getID()) == 0) {
279 edgeID = src->getID() + edgeInfix + dest->getID();
280 } else {
281 int counter = 0;
282 // generate new ID using edgeInfix and counter
283 while (myAttributeCarriers->getEdges().count(src->getID() + edgeInfix + toString(counter) + dest->getID()) != 0) {
285 }
286 edgeID = src->getID() + edgeInfix + toString(counter) + dest->getID();
287 }
288 } else {
289 // generate new ID
290 while (myAttributeCarriers->getEdges().count(edgePrefix + toString(myEdgeIDCounter)) != 0) {
292 }
293 edgeID = edgePrefix + toString(myEdgeIDCounter);
294 }
295 GNEEdge* edge;
296 // check if there is a template edge
297 if (edgeTemplate) {
298 // create NBEdgeTemplate
299 NBEdge* nbe = new NBEdge(edgeID, src->getNBNode(), dest->getNBNode(), edgeTemplate->getNBEdge());
300 edge = new GNEEdge(this, nbe, wasSplit);
301 } else {
302 // default if no template is given
304 double defaultSpeed = oc.getFloat("default.speed");
305 const std::string defaultType = oc.getString("default.type");
306 const int defaultNrLanes = oc.getInt("default.lanenumber");
307 const int defaultPriority = oc.getInt("default.priority");
308 const double defaultWidth = NBEdge::UNSPECIFIED_WIDTH;
309 const double defaultOffset = NBEdge::UNSPECIFIED_OFFSET;
311 // build NBEdge
312 NBEdge* nbe = new NBEdge(edgeID, src->getNBNode(), dest->getNBNode(),
313 defaultType, defaultSpeed, NBEdge::UNSPECIFIED_FRICTION,
314 defaultNrLanes, defaultPriority,
315 defaultWidth, defaultOffset, spread);
316 // create edge
317 edge = new GNEEdge(this, nbe, wasSplit);
318 }
319 // add edge using undo list
320 undoList->begin(GUIIcon::EDGE, "create " + toString(SUMO_TAG_EDGE));
321 undoList->add(new GNEChange_Edge(edge, true), true);
322 // recompute connection
323 if (recomputeConnections) {
324 src->setLogicValid(false, undoList);
325 dest->setLogicValid(false, undoList);
326 }
328 undoList->end();
329 return edge;
330}
331
332
333void
335 if (networkElement->getTagProperty().getTag() == SUMO_TAG_JUNCTION) {
336 // get junction (note: could be already removed if is a child, then hardfail=false)
337 GNEJunction* junction = myAttributeCarriers->retrieveJunction(networkElement->getID(), false);
338 // if exist, remove it
339 if (junction) {
340 deleteJunction(junction, undoList);
341 }
342 } else if (networkElement->getTagProperty().getTag() == SUMO_TAG_CROSSING) {
343 // get crossing (note: could be already removed if is a child, then hardfail=false)
344 GNECrossing* crossing = myAttributeCarriers->retrieveCrossing(networkElement, false);
345 // if exist, remove it
346 if (crossing) {
347 deleteCrossing(crossing, undoList);
348 }
349 } else if (networkElement->getTagProperty().getTag() == SUMO_TAG_EDGE) {
350 // get edge (note: could be already removed if is a child, then hardfail=false)
351 GNEEdge* edge = myAttributeCarriers->retrieveEdge(networkElement->getID(), false);
352 // if exist, remove it
353 if (edge) {
354 deleteEdge(edge, undoList, false);
355 }
356 } else if (networkElement->getTagProperty().getTag() == SUMO_TAG_LANE) {
357 // get lane (note: could be already removed if is a child, then hardfail=false)
358 GNELane* lane = myAttributeCarriers->retrieveLane(networkElement, false);
359 // if exist, remove it
360 if (lane) {
361 deleteLane(lane, undoList, false);
362 }
363 } else if (networkElement->getTagProperty().getTag() == SUMO_TAG_CONNECTION) {
364 // get connection (note: could be already removed if is a child, then hardfail=false)
365 GNEConnection* connection = myAttributeCarriers->retrieveConnection(networkElement, false);
366 // if exist, remove it
367 if (connection) {
368 deleteConnection(connection, undoList);
369 }
370 }
371}
372
373
374void
376 // we have to delete all incident edges because they cannot exist without that junction
377 // all deletions must be undone/redone together so we start a new command group
378 // @todo if any of those edges are dead-ends should we remove their orphan junctions as well?
379 undoList->begin(GUIIcon::MODEDELETE, "delete " + toString(SUMO_TAG_JUNCTION));
380 // invalidate junction path elements
382 // delete junction child demand elements
383 while (junction->getChildDemandElements().size() > 0) {
384 deleteDemandElement(junction->getChildDemandElements().front(), undoList);
385 }
386 // delete all crossings vinculated with junction
387 while (junction->getGNECrossings().size() > 0) {
388 deleteCrossing(junction->getGNECrossings().front(), undoList);
389 }
390 // find all crossings of neighbour junctions that shares an edge of this junction
391 std::vector<GNECrossing*> crossingsToRemove;
392 std::vector<GNEJunction*> junctionNeighbours = junction->getJunctionNeighbours();
393 for (const auto& junctionNeighbour : junctionNeighbours) {
394 // iterate over crossing of neighbour junction
395 for (const auto& crossing : junctionNeighbour->getGNECrossings()) {
396 // if at least one of the edges of junction to remove belongs to a crossing of the neighbour junction, delete it
397 if (crossing->checkEdgeBelong(junctionNeighbour->getChildEdges())) {
398 crossingsToRemove.push_back(crossing);
399 }
400 }
401 }
402 // delete crossings top remove
403 for (const auto& crossing : crossingsToRemove) {
404 deleteCrossing(crossing, undoList);
405 }
406 // deleting edges changes in the underlying EdgeVector so we have to make a copy
407 const EdgeVector incidentEdges = junction->getNBNode()->getEdges();
408 for (const auto& edge : incidentEdges) {
409 deleteEdge(myAttributeCarriers->getEdges().at(edge->getID()), undoList, true);
410 }
411 // remove any traffic lights from the traffic light container (avoids lots of warnings)
413 // delete edge
414 undoList->add(new GNEChange_Junction(junction, false), true);
415 undoList->end();
416}
417
418
419void
420GNENet::deleteEdge(GNEEdge* edge, GNEUndoList* undoList, bool recomputeConnections) {
421 undoList->begin(GUIIcon::MODEDELETE, "delete " + toString(SUMO_TAG_EDGE));
422 // iterate over lanes
423 for (const auto& lane : edge->getLanes()) {
424 // invalidate lane path elements
426 // delete lane additionals
427 while (lane->getChildAdditionals().size() > 0) {
428 deleteAdditional(lane->getChildAdditionals().front(), undoList);
429 }
430 // delete lane demand elements
431 while (lane->getChildDemandElements().size() > 0) {
432 deleteDemandElement(lane->getChildDemandElements().front(), undoList);
433 }
434 // delete lane generic data elements
435 while (lane->getChildGenericDatas().size() > 0) {
436 deleteGenericData(lane->getChildGenericDatas().front(), undoList);
437 }
438 }
439 // delete edge child additionals
440 while (edge->getChildAdditionals().size() > 0) {
441 deleteAdditional(edge->getChildAdditionals().front(), undoList);
442 }
443 // delete edge child demand elements
444 while (edge->getChildDemandElements().size() > 0) {
445 // special case for embedded routes
446 if (edge->getChildDemandElements().front()->getTagProperty().getTag() == GNE_TAG_ROUTE_EMBEDDED) {
447 deleteDemandElement(edge->getChildDemandElements().front()->getParentDemandElements().front(), undoList);
448 } else if (edge->getChildDemandElements().front()->getTagProperty().isPersonPlan()) {
449 const auto person = edge->getChildDemandElements().front()->getParentDemandElements().front();
450 if (person->getChildDemandElements().size() == 1) {
451 deleteDemandElement(person, undoList);
452 } else {
453 deleteDemandElement(edge->getChildDemandElements().front(), undoList);
454 }
455 } else if (edge->getChildDemandElements().front()->getTagProperty().isContainerPlan()) {
456 const auto container = edge->getChildDemandElements().front()->getParentDemandElements().front();
457 if (container->getChildDemandElements().size() == 1) {
458 deleteDemandElement(container, undoList);
459 } else {
460 deleteDemandElement(edge->getChildDemandElements().front(), undoList);
461 }
462 } else {
463 deleteDemandElement(edge->getChildDemandElements().front(), undoList);
464 }
465 }
466 // delete edge child generic datas
467 while (edge->getChildGenericDatas().size() > 0) {
468 deleteGenericData(edge->getChildGenericDatas().front(), undoList);
469 }
470 // remove edge from crossings related with this edge
471 edge->getFromJunction()->removeEdgeFromCrossings(edge, undoList);
472 edge->getToJunction()->removeEdgeFromCrossings(edge, undoList);
473 // update affected connections
474 if (recomputeConnections) {
475 edge->getFromJunction()->setLogicValid(false, undoList);
476 edge->getToJunction()->setLogicValid(false, undoList);
477 } else {
478 edge->getFromJunction()->removeConnectionsTo(edge, undoList, true);
479 edge->getToJunction()->removeConnectionsFrom(edge, undoList, true);
480 }
481 // if junction source is a TLS and after deletion will have only an edge, remove TLS
482 if (edge->getFromJunction()->getNBNode()->isTLControlled() && (edge->getFromJunction()->getGNEOutgoingEdges().size() <= 1)) {
484 }
485 // if junction destiny is a TLS and after deletion will have only an edge, remove TLS
486 if (edge->getToJunction()->getNBNode()->isTLControlled() && (edge->getToJunction()->getGNEIncomingEdges().size() <= 1)) {
488 }
489 // Delete edge
490 undoList->add(new GNEChange_Edge(edge, false), true);
491 // remove edge requires always a recompute (due geometry and connections)
493 // finish delete edge
494 undoList->end();
495}
496
497
498void
500 undoList->begin(GUIIcon::EDGE, "replace " + toString(SUMO_TAG_EDGE));
502 // iterate over lane
503 for (const auto& lane : which->getLanes()) {
504 // replace in additionals
505 std::vector<GNEAdditional*> copyOfLaneAdditionals = lane->getChildAdditionals();
506 for (const auto& additional : copyOfLaneAdditionals) {
507 undoList->changeAttribute(new GNEChange_Attribute(additional, SUMO_ATTR_LANE, by->getNBEdge()->getLaneID(lane->getIndex())));
508 }
509 // replace in demand elements
510 std::vector<GNEDemandElement*> copyOfLaneDemandElements = lane->getChildDemandElements();
511 for (const auto& demandElement : copyOfLaneDemandElements) {
512 undoList->changeAttribute(new GNEChange_Attribute(demandElement, SUMO_ATTR_LANE, by->getNBEdge()->getLaneID(lane->getIndex())));
513 }
514 // replace in generic datas
515 std::vector<GNEGenericData*> copyOfLaneGenericDatas = lane->getChildGenericDatas();
516 for (const auto& demandElement : copyOfLaneGenericDatas) {
517 undoList->changeAttribute(new GNEChange_Attribute(demandElement, SUMO_ATTR_LANE, by->getNBEdge()->getLaneID(lane->getIndex())));
518 }
519 }
520 // replace in edge additionals children
521 while (which->getChildAdditionals().size() > 0) {
522 undoList->changeAttribute(new GNEChange_Attribute(which->getChildAdditionals().front(), SUMO_ATTR_EDGE, by->getID()));
523 }
524 // replace in edge demand elements children
525 while (which->getChildDemandElements().size() > 0) {
526 undoList->changeAttribute(new GNEChange_Attribute(which->getChildDemandElements().front(), SUMO_ATTR_EDGE, by->getID()));
527 }
528 // replace in edge demand elements children
529 while (which->getChildGenericDatas().size() > 0) {
530 undoList->changeAttribute(new GNEChange_Attribute(which->getChildGenericDatas().front(), SUMO_ATTR_EDGE, by->getID()));
531 }
532 // replace in rerouters
533 for (const auto& rerouter : which->getParentAdditionals()) {
534 replaceInListAttribute(rerouter, SUMO_ATTR_EDGES, which->getID(), by->getID(), undoList);
535 }
536 // replace in crossings
537 for (const auto& crossing : which->getToJunction()->getGNECrossings()) {
538 // if at least one of the edges of junction to remove belongs to a crossing of the source junction, delete it
539 replaceInListAttribute(crossing, SUMO_ATTR_EDGES, which->getID(), by->getID(), undoList);
540 }
541 // fix connections (make a copy because they will be modified
542 std::vector<NBEdge::Connection> NBConnections = which->getNBEdge()->getConnections();
543 for (const auto& NBConnection : NBConnections) {
544 undoList->add(new GNEChange_Connection(which, NBConnection, false, false), true);
545 undoList->add(new GNEChange_Connection(by, NBConnection, false, true), true);
546 }
547 undoList->add(new GNENetHelper::GNEChange_ReplaceEdgeInTLS(getTLLogicCont(), which->getNBEdge(), by->getNBEdge()), true);
548 // Delete edge
549 undoList->add(new GNEChange_Edge(which, false), true);
550 // finish replace edge
551 undoList->end();
552}
553
554
555void
556GNENet::deleteLane(GNELane* lane, GNEUndoList* undoList, bool recomputeConnections) {
557 GNEEdge* edge = lane->getParentEdge();
558 if (edge->getNBEdge()->getNumLanes() == 1) {
559 // remove the whole edge instead
560 deleteEdge(edge, undoList, recomputeConnections);
561 } else {
562 undoList->begin(GUIIcon::MODEDELETE, "delete " + toString(SUMO_TAG_LANE));
563 // invalidate lane path elements
565 // delete lane additional children
566 while (lane->getChildAdditionals().size() > 0) {
567 deleteAdditional(lane->getChildAdditionals().front(), undoList);
568 }
569 // delete lane demand element children
570 while (lane->getChildDemandElements().size() > 0) {
571 deleteDemandElement(lane->getChildDemandElements().front(), undoList);
572 }
573 // delete lane generic data children
574 while (lane->getChildGenericDatas().size() > 0) {
575 deleteGenericData(lane->getChildGenericDatas().front(), undoList);
576 }
577 // update affected connections
578 if (recomputeConnections) {
579 edge->getFromJunction()->setLogicValid(false, undoList);
580 edge->getToJunction()->setLogicValid(false, undoList);
581 } else {
582 edge->getFromJunction()->removeConnectionsTo(edge, undoList, true, lane->getIndex());
583 edge->getToJunction()->removeConnectionsFrom(edge, undoList, true, lane->getIndex());
584 }
585 // delete lane
586 const NBEdge::Lane& laneAttrs = edge->getNBEdge()->getLaneStruct(lane->getIndex());
587 undoList->add(new GNEChange_Lane(edge, lane, laneAttrs, false, recomputeConnections), true);
588 // remove lane requires always a recompute (due geometry and connections)
590 undoList->end();
591 }
592}
593
594
595void
597 undoList->begin(GUIIcon::MODEDELETE, "delete " + toString(SUMO_TAG_CONNECTION));
598 // obtain NBConnection to remove
599 NBConnection deleted = connection->getNBConnection();
600 GNEJunction* junctionDestiny = connection->getEdgeFrom()->getToJunction();
601 junctionDestiny->markAsModified(undoList);
602 undoList->add(new GNEChange_Connection(connection->getEdgeFrom(), connection->getNBEdgeConnection(), connection->isAttributeCarrierSelected(), false), true);
603 junctionDestiny->invalidateTLS(undoList, deleted);
604 // remove connection requires always a recompute (due geometry and connections)
606 undoList->end();
607}
608
609
610void
612 undoList->begin(GUIIcon::MODEDELETE, "delete crossing");
613 // remove it using GNEChange_Crossing
614 undoList->add(new GNEChange_Crossing(
615 crossing->getParentJunction(), crossing->getNBCrossing()->edges,
616 crossing->getNBCrossing()->width, crossing->getNBCrossing()->priority,
617 crossing->getNBCrossing()->customTLIndex,
618 crossing->getNBCrossing()->customTLIndex2,
619 crossing->getNBCrossing()->customShape,
620 crossing->isAttributeCarrierSelected(),
621 false), true);
622 // remove crossing requires always a recompute (due geometry and connections)
624 undoList->end();
625}
626
627
628void
630 undoList->begin(GUIIcon::MODEDELETE, "delete " + additional->getTagStr());
631 // remove all demand element children of this additional deleteDemandElement this function recursively
632 while (additional->getChildDemandElements().size() > 0) {
633 deleteDemandElement(additional->getChildDemandElements().front(), undoList);
634 }
635 // remove all generic data children of this additional deleteGenericData this function recursively
636 while (additional->getChildGenericDatas().size() > 0) {
637 deleteGenericData(additional->getChildGenericDatas().front(), undoList);
638 }
639 // remove all additional children of this additional calling this function recursively
640 while (additional->getChildAdditionals().size() > 0) {
641 deleteAdditional(additional->getChildAdditionals().front(), undoList);
642 }
643 // remove additional
644 undoList->add(new GNEChange_Additional(additional, false), true);
645 undoList->end();
646}
647
648
649void
651 // check that default VTypes aren't removed
652 if ((demandElement->getTagProperty().getTag() == SUMO_TAG_VTYPE) && (GNEAttributeCarrier::parse<bool>(demandElement->getAttribute(GNE_ATTR_DEFAULT_VTYPE)))) {
653 throw ProcessError("Trying to delete a default Vehicle Type");
654 } else {
655 // check if currently is being inspected
656 if (myViewNet->isAttributeCarrierInspected(demandElement)) {
658 }
659 undoList->begin(GUIIcon::MODEDELETE, "delete " + demandElement->getTagStr());
660 // remove all child additional elements of this demandElement calling this function recursively
661 while (demandElement->getChildAdditionals().size() > 0) {
662 deleteAdditional(demandElement->getChildAdditionals().front(), undoList);
663 }
664 // remove all child demand elements of this demandElement calling this function recursively
665 while (demandElement->getChildDemandElements().size() > 0) {
666 deleteDemandElement(demandElement->getChildDemandElements().front(), undoList);
667 }
668 // remove all generic data children of this additional deleteGenericData this function recursively
669 while (demandElement->getChildGenericDatas().size() > 0) {
670 deleteGenericData(demandElement->getChildGenericDatas().front(), undoList);
671 }
672 // remove demandElement
673 undoList->add(new GNEChange_DemandElement(demandElement, false), true);
674 undoList->end();
675 }
676}
677
678
679void
681 undoList->begin(GUIIcon::MODEDELETE, "delete " + dataSet->getTagStr());
682 // make a copy of all generic data children
683 auto copyOfDataIntervalChildren = dataSet->getDataIntervalChildren();
684 // clear all data intervals (this will be delete also the dataSet)
685 for (const auto& dataInterval : copyOfDataIntervalChildren) {
686 deleteDataInterval(dataInterval.second, undoList);
687 }
688 undoList->end();
689}
690
691
692void
694 undoList->begin(GUIIcon::MODEDELETE, "delete " + dataInterval->getTagStr());
695 // make a copy of all generic data children
696 auto copyOfGenericDataChildren = dataInterval->getGenericDataChildren();
697 // clear all generic datas (this will be delete also the data intervals)
698 for (const auto& genericData : copyOfGenericDataChildren) {
699 deleteGenericData(genericData, undoList);
700 }
701 undoList->end();
702}
703
704
705void
707 undoList->begin(GUIIcon::MODEDELETE, "delete " + genericData->getTagStr());
708 // remove all child demand elements of this demandElement calling this function recursively
709 while (genericData->getChildDemandElements().size() > 0) {
710 deleteDemandElement(genericData->getChildDemandElements().front(), undoList);
711 }
712 // remove all generic data children of this additional deleteGenericData this function recursively
713 while (genericData->getChildGenericDatas().size() > 0) {
714 deleteGenericData(genericData->getChildGenericDatas().front(), undoList);
715 }
716 // get pointer to dataInterval and dataSet
717 GNEDataInterval* dataInterval = genericData->getDataIntervalParent();
718 GNEDataSet* dataSet = dataInterval->getDataSetParent();
719 // remove generic data
720 undoList->add(new GNEChange_GenericData(genericData, false), true);
721 // check if data interval is empty
722 if (dataInterval->getGenericDataChildren().empty()) {
723 // remove data interval
724 undoList->add(new GNEChange_DataInterval(genericData->getDataIntervalParent(), false), true);
725 // now check if data set is empty
726 if (dataSet->getDataIntervalChildren().empty()) {
727 // remove data set
728 undoList->add(new GNEChange_DataSet(genericData->getDataIntervalParent()->getDataSetParent(), false), true);
729 }
730 }
731 undoList->end();
732}
733
734
735void
736GNENet::duplicateLane(GNELane* lane, GNEUndoList* undoList, bool recomputeConnections) {
737 undoList->begin(GUIIcon::LANE, "duplicate " + toString(SUMO_TAG_LANE));
738 GNEEdge* edge = lane->getParentEdge();
739 const NBEdge::Lane& laneAttrs = edge->getNBEdge()->getLaneStruct(lane->getIndex());
740 if (recomputeConnections) {
741 edge->getFromJunction()->setLogicValid(false, undoList);
742 edge->getToJunction()->setLogicValid(false, undoList);
743 }
744 GNELane* newLane = new GNELane(edge, lane->getIndex());
745 undoList->add(new GNEChange_Lane(edge, newLane, laneAttrs, true, recomputeConnections), true);
747 undoList->end();
748}
749
750
751bool
753 bool addRestriction = true;
754 if (vclass == SVC_PEDESTRIAN) {
755 GNEEdge* edge = lane->getParentEdge();
756 for (const auto& edgeLane : edge->getLanes()) {
757 if (edgeLane->isRestricted(SVC_PEDESTRIAN)) {
758 // prevent adding a 2nd sidewalk
759 addRestriction = false;
760 } else {
761 // ensure that the sidewalk is used exclusively
762 const SVCPermissions allOldWithoutPeds = edge->getNBEdge()->getPermissions(edgeLane->getIndex()) & ~SVC_PEDESTRIAN;
763 edgeLane->setAttribute(SUMO_ATTR_ALLOW, getVehicleClassNames(allOldWithoutPeds), undoList);
764 }
765 }
766 }
767 // restrict the lane
768 if (addRestriction) {
769 double width;
770 if (vclass == SVC_PEDESTRIAN) {
771 width = OptionsCont::getOptions().getFloat("default.sidewalk-width");
772 } else if (vclass == SVC_BICYCLE) {
773 width = OptionsCont::getOptions().getFloat("default.bikelane-width");
774 } else {
775 width = OptionsCont::getOptions().getFloat("default.lanewidth");
776 }
777 lane->setAttribute(SUMO_ATTR_ALLOW, toString(vclass), undoList);
778 lane->setAttribute(SUMO_ATTR_WIDTH, toString(width), undoList);
779 return true;
780 } else {
781 return false;
782 }
783}
784
785
786bool
787GNENet::addRestrictedLane(SUMOVehicleClass vclass, GNEEdge* edge, int index, GNEUndoList* undoList) {
788 // First check that edge don't have a restricted lane of the given vclass
789 for (const auto& lane : edge->getLanes()) {
790 if (lane->isRestricted(vclass)) {
791 return false;
792 }
793 }
794 // check that index is correct (index == size adds to the left of the leftmost lane)
795 const int numLanes = (int)edge->getLanes().size();
796 if (index > numLanes) {
797 return false;
798 }
799 if (index < 0) {
800 // guess index from vclass
801 if (vclass == SVC_PEDESTRIAN) {
802 index = 0;
803 } else if (vclass == SVC_BICYCLE) {
804 // add bikelanes to the left of an existing sidewalk
805 index = edge->getLanes()[0]->isRestricted(SVC_PEDESTRIAN) ? 1 : 0;
806 } else if (vclass == SVC_BUS) {
807 // add greenVerge to the left of an existing sidewalk or bikeLane
808 // add busLane to the left of an existing sidewalk, bikeLane or greenVerge
809 index = 0;
810 while (index < numLanes && (edge->getNBEdge()->getPermissions(index) & ~(SVC_PEDESTRIAN | SVC_BICYCLE)) == 0) {
811 index++;
812 }
813 }
814 }
815 // duplicate selected lane
816 duplicateLane(edge->getLanes().at(MIN2(index, numLanes - 1)), undoList, true);
817 // transform the created lane
818 return restrictLane(vclass, edge->getLanes().at(index), undoList);
819}
820
821
822bool
823GNENet::addGreenVergeLane(GNEEdge* edge, int index, GNEUndoList* undoList) {
824 // check that index is correct (index == size adds to the left of the leftmost lane)
825 const int numLanes = (int)edge->getLanes().size();
826 if (index > numLanes) {
827 index = numLanes;
828 }
829 if (index < 0) {
830 index = 0;
831 }
832 // duplicate selected lane
833 duplicateLane(edge->getLanes().at(MIN2(index, numLanes - 1)), undoList, true);
834 // transform the created lane
835 return restrictLane(SVC_IGNORING, edge->getLanes().at(index), undoList);
836}
837
838
839bool
841 // iterate over lanes of edge
842 for (const auto& lane : edge->getLanes()) {
843 if (lane->isRestricted(vclass)) {
844 // Delete lane
845 deleteLane(lane, undoList, true);
846 return true;
847 }
848 }
849 return false;
850}
851
852
854GNENet::splitEdge(GNEEdge* edge, const Position& pos, GNEUndoList* undoList, GNEJunction* newJunction) {
855 // begin undo list
856 undoList->begin(GUIIcon::EDGE, "split " + toString(SUMO_TAG_EDGE));
857 // check if we have to create a new edge
858 if (newJunction == nullptr) {
859 newJunction = createJunction(pos, undoList);
860 }
861 // obtain edge geometry and split position
862 const PositionVector& oldEdgeGeometry = edge->getNBEdge()->getGeometry();
863 const double edgeSplitPosition = oldEdgeGeometry.nearest_offset_to_point2D(pos, false);
864 // obtain lane geometry and split position (needed for adjust additional and demand childs)
865 const PositionVector& oldLaneGeometry = edge->getLanes().front()->getLaneShape();
866 const double laneSplitPosition = oldLaneGeometry.nearest_offset_to_point2D(pos, false);
867 // split edge geometry in two new geometries using edgeSplitPosition
868 std::pair<PositionVector, PositionVector> newGeoms = oldEdgeGeometry.splitAt(edgeSplitPosition);
869 const double oldLength = oldEdgeGeometry.length();
870 const double relativeLength1 = oldLength != 0 ? newGeoms.first.length() / oldLength : 1;
871 const double relativeLength2 = oldLength != 0 ? newGeoms.second.length() / oldLength : 1;
872 // get shape end
873 const std::string shapeEnd = edge->getAttribute(GNE_ATTR_SHAPE_END);
874 // figure out the new name
875 int posBase = 0;
876 // set baseName
877 std::string baseName = edge->getMicrosimID();
878 if (edge->wasSplit()) {
879 const std::string::size_type sep_index = baseName.rfind('.');
880 // edge may have been renamed in between
881 if (sep_index != std::string::npos) {
882 std::string posString = baseName.substr(sep_index + 1);
883 if (GNEAttributeCarrier::canParse<int>(posString.c_str())) {
884 ;
885 posBase = GNEAttributeCarrier::parse<int>(posString.c_str());
886 baseName = baseName.substr(0, sep_index); // includes the .
887 }
888 }
889 }
890 baseName += '.';
891 // create a new edge from the new junction to the previous destination
892 GNEEdge* secondPart = createEdge(newJunction, edge->getToJunction(), edge,
893 undoList, baseName + toString(posBase + (int)edgeSplitPosition), true, false, false);
894 // fix connections from the split edge (must happen before changing SUMO_ATTR_TO)
895 edge->getToJunction()->replaceIncomingConnections(edge, secondPart, undoList);
896 // remove affected crossings from junction (must happen before changing SUMO_ATTR_TO)
897 std::vector<NBNode::Crossing> affectedCrossings;
898 for (GNECrossing* crossing : edge->getToJunction()->getGNECrossings()) {
899 if (crossing->checkEdgeBelong(edge)) {
900 NBNode::Crossing nbC = *crossing->getNBCrossing();
901 undoList->add(new GNEChange_Crossing(edge->getToJunction(), nbC, false), true);
902 EdgeVector newEdges;
903 for (NBEdge* nbEdge : nbC.edges) {
904 if (nbEdge == edge->getNBEdge()) {
905 newEdges.push_back(secondPart->getNBEdge());
906 } else {
907 newEdges.push_back(nbEdge);
908 }
909 }
910 nbC.edges = newEdges;
911 affectedCrossings.push_back(nbC);
912 }
913 }
914 // modify the edge so that it ends at the new junction (and all incoming connections are preserved
915 undoList->changeAttribute(new GNEChange_Attribute(edge, SUMO_ATTR_TO, newJunction->getID()));
916 // set first part of geometry
917 newGeoms.first.pop_back();
918 newGeoms.first.erase(newGeoms.first.begin());
919 edge->setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
920 edge->setAttribute(SUMO_ATTR_SHAPE, toString(newGeoms.first), undoList);
921 // set second part of geometry
922 secondPart->setAttribute(GNE_ATTR_SHAPE_END, shapeEnd, undoList);
923 newGeoms.second.pop_back();
924 newGeoms.second.erase(newGeoms.second.begin());
925 secondPart->setAttribute(SUMO_ATTR_SHAPE, toString(newGeoms.second), undoList);
926 // fix custom length
927 if (edge->getNBEdge()->hasLoadedLength()) {
928 // split in proportion to geometry lengths
929 const double loadedLength = edge->getNBEdge()->getLoadedLength();
930 edge->setAttribute(SUMO_ATTR_LENGTH, toString(relativeLength1 * loadedLength), undoList);
931 secondPart->setAttribute(SUMO_ATTR_LENGTH, toString(relativeLength2 * loadedLength), undoList);
932 }
933 // reconnect across the split
934 for (int i = 0; i < (int)edge->getLanes().size(); ++i) {
935 undoList->add(new GNEChange_Connection(edge, NBEdge::Connection(i, secondPart->getNBEdge(), i), false, true), true);
936 }
937 // re-add modified crossings
938 for (const auto& nbC : affectedCrossings) {
939 undoList->add(new GNEChange_Crossing(secondPart->getToJunction(), nbC, true), true);
940 }
941 // Split geometry of all child additional
942 auto childAdditionals = edge->getChildAdditionals();
943 for (const auto& additional : childAdditionals) {
944 additional->splitEdgeGeometry(edgeSplitPosition, edge, secondPart, undoList);
945 }
946 // Split geometry of all child lane additional
947 for (int i = 0; i < (int)edge->getLanes().size(); i++) {
948 for (const auto& additional : edge->getLanes().at(i)->getChildAdditionals()) {
949 additional->splitEdgeGeometry(laneSplitPosition, edge->getLanes().at(i), secondPart->getLanes().at(i), undoList);
950 }
951 }
952 // Split geometry of all child demand elements
953 auto childDemandElements = edge->getChildDemandElements();
954 for (const auto& demandElement : childDemandElements) {
955 demandElement->splitEdgeGeometry(edgeSplitPosition, edge, secondPart, undoList);
956 }
957 // Split geometry of all child lane demand elements
958 for (int i = 0; i < (int)edge->getLanes().size(); i++) {
959 for (const auto& demandElement : edge->getLanes().at(i)->getChildDemandElements()) {
960 demandElement->splitEdgeGeometry(laneSplitPosition, edge->getLanes().at(i), secondPart->getLanes().at(i), undoList);
961 }
962 }
963 // finish undo list
964 undoList->end();
965 // return new junction
966 return newJunction;
967}
968
969
970void
971GNENet::splitEdgesBidi(GNEEdge* edge, GNEEdge* oppositeEdge, const Position& pos, GNEUndoList* undoList) {
972 GNEJunction* newJunction = nullptr;
973 undoList->begin(GUIIcon::EDGE, "split " + toString(SUMO_TAG_EDGE) + "s");
974 // split edge and save created junction
975 newJunction = splitEdge(edge, pos, undoList, newJunction);
976 // split second edge
977 splitEdge(oppositeEdge, pos, undoList, newJunction);
978 if (edge->getLanes().back()->getAttribute(GNE_ATTR_OPPOSITE) != "") {
979 // restore opposite lane information
980 for (const auto& nbEdge : newJunction->getNBNode()->getEdges()) {
981 GNEEdge* e = myAttributeCarriers->retrieveEdge(nbEdge->getID());
982 // store old attribute before it's changed by guess opposite
983 e->getLanes().back()->setAttribute(GNE_ATTR_OPPOSITE, "", undoList);
984 if (nbEdge->guessOpposite(true)) {
985 e->getLanes().back()->setAttribute(GNE_ATTR_OPPOSITE, nbEdge->getLanes().back().oppositeID, undoList);
986 }
987 }
988 }
989 undoList->end();
990}
991
992
993void
995 undoList->begin(GUIIcon::EDGE, "reverse " + toString(SUMO_TAG_EDGE));
996 deleteEdge(edge, undoList, false); // still exists. we delete it so we can reuse the name in case of resplit
997 GNEEdge* reversed = createEdge(edge->getToJunction(), edge->getFromJunction(), edge, undoList, edge->getID(), false, true);
998 assert(reversed != 0);
999 reversed->setAttribute(SUMO_ATTR_SHAPE, toString(edge->getNBEdge()->getInnerGeometry().reverse()), undoList);
1002 undoList->end();
1003}
1004
1005
1006GNEEdge*
1007GNENet::addReversedEdge(GNEEdge* edge, const bool disconnected, GNEUndoList* undoList) {
1008 undoList->begin(GUIIcon::EDGE, "add reversed " + toString(SUMO_TAG_EDGE));
1009 GNEEdge* reversed = nullptr;
1010 if (!disconnected) {
1011 // for rail edges, we assume bi-directional tracks are wanted
1012 reversed = createEdge(edge->getToJunction(), edge->getFromJunction(), edge, undoList, "-" + edge->getID(), false, true);
1013 assert(reversed != 0);
1014 reversed->setAttribute(SUMO_ATTR_SHAPE, toString(edge->getNBEdge()->getInnerGeometry().reverse()), undoList);
1017 } else {
1018 // if the edge is centered it should probably connect somewhere else
1019 // make it easy to move and reconnect it
1020 PositionVector orig = edge->getNBEdge()->getGeometry();
1021 PositionVector origInner = edge->getNBEdge()->getInnerGeometry();
1022 const double tentativeShift = edge->getNBEdge()->getTotalWidth() + 2;
1023 orig.move2side(-tentativeShift);
1024 origInner.move2side(-tentativeShift);
1025 GNEJunction* src = createJunction(orig.back(), undoList);
1026 GNEJunction* dest = createJunction(orig.front(), undoList);
1027 reversed = createEdge(src, dest, edge, undoList, "-" + edge->getID(), false, true);
1028 assert(reversed != 0);
1029 reversed->setAttribute(SUMO_ATTR_SHAPE, toString(origInner.reverse()), undoList);
1030 reversed->setAttribute(SUMO_ATTR_SHAPE, toString(origInner.reverse()), undoList);
1031 // select the new edge and its nodes
1032 reversed->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1033 src->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1034 dest->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1035 }
1036 undoList->end();
1037 return reversed;
1038}
1039
1040
1041void
1043 undoList->begin(GUIIcon::JUNCTION, "merge " + toString(SUMO_TAG_JUNCTION) + "s");
1044 // place moved junction in the same position of target junction
1046 // deleting edges changes in the underlying EdgeVector so we have to make a copy
1047 const EdgeVector incomingNBEdges = moved->getNBNode()->getIncomingEdges();
1048 for (const auto& incomingNBEdge : incomingNBEdges) {
1049 // delete edges between the merged junctions
1050 GNEEdge* edge = myAttributeCarriers->getEdges().at(incomingNBEdge->getID());
1051 if (edge->getFromJunction() == target) {
1052 deleteEdge(edge, undoList, false);
1053 } else {
1054 undoList->changeAttribute(new GNEChange_Attribute(edge, SUMO_ATTR_TO, target->getID()));
1055 }
1056 }
1057 // deleting edges changes in the underlying EdgeVector so we have to make a copy
1058 const EdgeVector outgoingNBEdges = moved->getNBNode()->getOutgoingEdges();
1059 for (const auto& outgoingNBEdge : outgoingNBEdges) {
1060 // delete edges between the merged junctions
1061 GNEEdge* edge = myAttributeCarriers->getEdges().at(outgoingNBEdge->getID());
1062 if (edge->getToJunction() == target) {
1063 deleteEdge(edge, undoList, false);
1064 } else {
1065 undoList->changeAttribute(new GNEChange_Attribute(edge, SUMO_ATTR_FROM, target->getID()));
1066 }
1067 }
1068 // deleted moved junction
1069 deleteJunction(moved, undoList);
1070 undoList->end();
1071}
1072
1073
1074void
1076 for (const EdgeSet& roundabout : myNetBuilder->getEdgeCont().getRoundabouts()) {
1077 for (NBEdge* edge : roundabout) {
1078 if (edge->getFromNode() == junction->getNBNode()) {
1079 undoList->begin(GUIIcon::JUNCTION, "select roundabout");
1080 for (const auto& roundaboutEdge : roundabout) {
1081 GNEEdge* e = myAttributeCarriers->retrieveEdge(roundaboutEdge->getID());
1082 e->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1083 e->getToJunction()->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1084 }
1085 undoList->end();
1086 return;
1087 }
1088 }
1089 }
1090}
1091
1092
1093void
1095 undoList->begin(GUIIcon::JUNCTION, "create roundabout");
1096 // reset shape end from incoming edges
1097 for (const auto& incomingEdge : junction->getGNEIncomingEdges()) {
1098 incomingEdge->setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
1099 }
1100 // reset shape start from outgoing edges
1101 for (const auto& outgoingEdge : junction->getGNEOutgoingEdges()) {
1102 outgoingEdge->setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
1103 }
1104 junction->getNBNode()->updateSurroundingGeometry();
1105 double radius = junction->getNBNode()->getRadius();
1106 if (radius == NBNode::UNSPECIFIED_RADIUS) {
1107 radius = OptionsCont::getOptions().getFloat("default.junctions.radius");
1108 }
1109 std::vector<GNEEdge*> edges;
1110 // use clockwise sorting
1111 for (const auto& nbEdge : junction->getNBNode()->getEdges()) {
1112 edges.push_back(myAttributeCarriers->retrieveEdge(nbEdge->getID()));
1113 }
1114 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
1115 if (lefthand) {
1116 std::reverse(edges.begin(), edges.end());
1117 }
1118 const double lefthandSign = lefthand ? -1 : 1;
1119 std::vector<GNEJunction*> newJunctions;
1120 GNEEdge* prevOpposite = nullptr;
1121 // split incoming/outgoing edges
1122 for (GNEEdge* edge : edges) {
1123 GNEJunction* newJunction = nullptr;
1124 if (edge == prevOpposite) {
1125 newJunction = newJunctions.back();
1126 }
1127 //std::cout << " edge=" << edge->getID() << " prevOpposite=" << Named::getIDSecure(prevOpposite) << " newJunction=" << Named::getIDSecure(newJunction) << "\n";
1128 prevOpposite = edge->getOppositeEdges().front();
1129 const double geomLength = edge->getNBEdge()->getGeometry().length2D();
1130 const double splitOffset = (edge->getToJunction() == junction
1131 ? MAX2(POSITION_EPS, geomLength - radius)
1132 : MIN2(geomLength - POSITION_EPS, radius));
1133 Position pos = edge->getNBEdge()->getGeometry().positionAtOffset2D(splitOffset);
1134 newJunction = splitEdge(edge, pos, undoList, newJunction);
1135 if (newJunctions.empty() || newJunction != newJunctions.back()) {
1136 newJunctions.push_back(newJunction);
1137 }
1138 }
1139 Position center = junction->getPositionInView();
1140 deleteJunction(junction, undoList);
1141 // create new edges to connect roundabout junctions (counter-clockwise)
1142 const double resolution = OptionsCont::getOptions().getFloat("opendrive.curve-resolution") * 3;
1143 for (int i = 0; i < (int)newJunctions.size(); i++) {
1144 GNEJunction* from = newJunctions[(i + 1) % newJunctions.size()];
1145 GNEJunction* to = newJunctions[i];
1146 GNEEdge* newEdge = createEdge(from, to, nullptr, undoList);
1147 const double angle1 = center.angleTo2D(from->getPositionInView());
1148 const double angle2 = center.angleTo2D(to->getPositionInView());
1149 // insert geometry points every resolution meters
1150 const double angleDiff = fabs(GeomHelper::angleDiff(angle2, angle1));
1151 // circumference = 2 * M_PI * radius, angularFraction = angleDiff / 2 * M_PI
1152 int numSegments = MAX2(2, (int)ceil(angleDiff * radius / resolution));
1153 PositionVector innerGeom;
1154 for (int j = 1; j < numSegments; j++) {
1155 const double angle = angle1 + lefthandSign * j * angleDiff / numSegments;
1156 innerGeom.push_back(center + Position(cos(angle) * radius, sin(angle) * radius));
1157 }
1158 //std::cout << " newEdge=" << newEdge->getID() << " angle1=" << angle1 << " angle2=" << angle2 << " angleDiff=" << angleDiff
1159 // << " numSegments=" << numSegments << " innerGeom=" << innerGeom << "\n";
1160 newEdge->setAttribute(SUMO_ATTR_SHAPE, toString(innerGeom), undoList);
1161 }
1162 undoList->end();
1163}
1164
1165
1166bool
1168 // Check that there isn't another junction in the same position as Pos
1169 for (auto i : myAttributeCarriers->getJunctions()) {
1170 if (i.second->getPositionInView() == pos) {
1171 return false;
1172 }
1173 }
1174 return true;
1175}
1176
1177
1178void
1180 myNetSaved = !value;
1181}
1182
1183
1184bool
1186 return myNetSaved;
1187}
1188
1189
1190void
1192 // compute without volatile options and update network
1193 computeAndUpdate(oc, false);
1194 // clear typeContainer
1196 // now update typeContainer with edgeTypes
1197 for (const auto& edgeType : myAttributeCarriers->getEdgeTypes()) {
1198 myNetBuilder->getTypeCont().insertEdgeType(edgeType.first, edgeType.second);
1199 for (int i = 0; i < (int)edgeType.second->getLaneTypes().size(); i++) {
1200 myNetBuilder->getTypeCont().insertLaneType(edgeType.first, i,
1201 edgeType.second->getLaneTypes().at(i)->speed,
1202 edgeType.second->getLaneTypes().at(i)->permissions,
1203 edgeType.second->getLaneTypes().at(i)->width,
1204 edgeType.second->getLaneTypes().at(i)->attrs);
1205 }
1206 }
1207 // write network
1209 myNetSaved = true;
1210}
1211
1212
1213void
1214GNENet::savePlain(OptionsCont& oc, const std::string& prefix) {
1215 // compute without volatile options
1216 computeAndUpdate(oc, false);
1218}
1219
1220
1221void
1222GNENet::saveJoined(OptionsCont& oc, const std::string& filename) {
1223 // compute without volatile options
1224 computeAndUpdate(oc, false);
1226}
1227
1228
1229void
1231 // set view net
1232 myViewNet = viewNet;
1233 // add default vTypes
1235 // update geometry of all lanes (needed for dotted geometry)
1236 for (const auto& edge : myAttributeCarriers->getEdges()) {
1237 for (const auto& lane : edge.second->getLanes()) {
1238 lane->updateGeometry();
1239 }
1240 }
1241}
1242
1243
1244void
1246 // first check if given object has an associated GUIGlObject
1247 if (AC->getGUIGlObject()) {
1248 // check if object must be inserted in RTREE
1249 if (AC->getTagProperty().isPlacedInRTree()) {
1251 }
1252 }
1253}
1254
1255
1256void
1258 // first check if given object has an associated GUIGlObject
1259 if (AC->getGUIGlObject()) {
1260 // check if object must be inserted in RTREE
1261 if (AC->getTagProperty().isPlacedInRTree()) {
1263 }
1264 }
1265}
1266
1267
1268void
1269GNENet::computeNetwork(GNEApplicationWindow* window, bool force, bool volatileOptions, std::string additionalPath, std::string demandPath, std::string dataPath) {
1270 if (!myNeedRecompute) {
1271 if (force) {
1272 if (volatileOptions) {
1273 window->setStatusBarText("Forced computing junctions with volatile options ...");
1274 } else {
1275 window->setStatusBarText("Forced computing junctions ...");
1276 }
1277 } else {
1278 return;
1279 }
1280 } else {
1281 if (volatileOptions) {
1282 window->setStatusBarText("Computing junctions with volatile options ...");
1283 } else {
1284 window->setStatusBarText("Computing junctions ...");
1285 }
1286 }
1287 // save current number of lanes for every edge if recomputing is with volatile options
1288 if (volatileOptions) {
1289 for (auto it : myAttributeCarriers->getEdges()) {
1290 myEdgesAndNumberOfLanes[it.second->getID()] = (int)it.second->getLanes().size();
1291 }
1292 }
1293 // compute and update
1295 computeAndUpdate(oc, volatileOptions);
1296 // load additionals if was recomputed with volatile options
1297 if (additionalPath != "") {
1298 // Create additional handler
1299 GNEGeneralHandler generalHandler(this, additionalPath, false, false);
1300 // Run parser
1301 if (!generalHandler.parse()) {
1302 WRITE_MESSAGE("Loading of " + additionalPath + " failed.");
1303 }
1304 // clear myEdgesAndNumberOfLanes after reload additionals
1306 }
1307 // load demand elements if was recomputed with volatile options
1308 if (demandPath != "") {
1309 // Create general handler
1310 GNEGeneralHandler handler(this, demandPath, false, false);
1311 // Run parser
1312 if (!handler.parse()) {
1313 WRITE_MESSAGE("Loading of " + demandPath + " failed.");
1314 }
1315 // clear myEdgesAndNumberOfLanes after reload demandElements
1317 }
1318 UNUSED_PARAMETER(dataPath);
1319 window->getApp()->endWaitCursor();
1320 window->setStatusBarText("Finished computing junctions.");
1321}
1322
1323
1324void
1326 window->setStatusBarText("Computing demand elements ...");
1327 // if we aren't in Demand mode, update path calculator
1331 }
1332 // clear demand paths
1334 // iterate over all demand elements and compute
1335 for (const auto& demandElements : myAttributeCarriers->getDemandElements()) {
1336 for (const auto& demandElement : demandElements.second) {
1337 demandElement->computePathElement();
1338 }
1339 }
1340 window->setStatusBarText("Finished computing demand elements.");
1341}
1342
1343
1344void
1346 window->setStatusBarText("Computing data elements ...");
1347 // iterate over all demand elements and compute
1348 for (const auto& genericDataTag : myAttributeCarriers->getGenericDatas()) {
1349 for (const auto& genericData : genericDataTag.second) {
1350 genericData->computePathElement();
1351 }
1352 }
1353 window->setStatusBarText("Finished computing data elements.");
1354}
1355
1356
1357void
1359 // recompute tl-logics
1362 // iterate over traffic lights definitions. Make a copy because invalid
1363 // definitions will be removed (and would otherwise destroy the iterator)
1364 const std::set<NBTrafficLightDefinition*> tlsDefs = junction->getNBNode()->getControllingTLS();
1365 for (auto it : tlsDefs) {
1366 it->setParticipantsInformation();
1367 it->setTLControllingInformation();
1368 tllCont.computeSingleLogic(oc, it);
1369 }
1370
1371 // @todo compute connections etc...
1372}
1373
1374
1375void
1377 myNeedRecompute = true;
1378}
1379
1380
1381bool
1383 return (myNeedRecompute == false);
1384}
1385
1386
1387FXApp*
1389 return myViewNet->getApp();
1390}
1391
1392
1395 return myNetBuilder;
1396}
1397
1398
1399bool
1401 const auto selectedJunctions = myAttributeCarriers->getSelectedJunctions();
1402 if (selectedJunctions.size() < 2) {
1403 return false;
1404 }
1405 EdgeVector allIncoming;
1406 EdgeVector allOutgoing;
1407 std::set<NBNode*, ComparatorIdLess> cluster;
1408 for (auto it : selectedJunctions) {
1409 cluster.insert(it->getNBNode());
1410 const EdgeVector& incoming = it->getNBNode()->getIncomingEdges();
1411 allIncoming.insert(allIncoming.end(), incoming.begin(), incoming.end());
1412 const EdgeVector& outgoing = it->getNBNode()->getOutgoingEdges();
1413 allOutgoing.insert(allOutgoing.end(), outgoing.begin(), outgoing.end());
1414 }
1415 // create new junction
1416 Position pos;
1417 Position oldPos;
1418 bool setTL = false;
1419 std::string id = "cluster";
1420 TrafficLightType type;
1422 myNetBuilder->getNodeCont().analyzeCluster(cluster, id, pos, setTL, type, nodeType);
1423 // save position
1424 oldPos = pos;
1425
1426 // Check that there isn't another junction in the same position as Pos but doesn't belong to cluster
1427 for (auto i : myAttributeCarriers->getJunctions()) {
1428 if ((i.second->getPositionInView() == pos) && (cluster.find(i.second->getNBNode()) == cluster.end())) {
1429 // show warning in gui testing debug mode
1430 WRITE_DEBUG("Opening FXMessageBox 'Join non-selected junction'");
1431 // Ask confirmation to user
1432 FXuint answer = FXMessageBox::question(getApp(), MBOX_YES_NO,
1433 ("Position of joined " + toString(SUMO_TAG_JUNCTION)).c_str(), "%s",
1434 ("There is another unselected " + toString(SUMO_TAG_JUNCTION) + " in the same position of joined " + toString(SUMO_TAG_JUNCTION) +
1435 + ".\nIt will be joined with the other selected " + toString(SUMO_TAG_JUNCTION) + "s. Continue?").c_str());
1436 if (answer != 1) { // 1:yes, 2:no, 4:esc
1437 // write warning if netedit is running in testing mode
1438 if (answer == 2) {
1439 WRITE_DEBUG("Closed FXMessageBox 'Join non-selected junction' with 'No'");
1440 } else if (answer == 4) {
1441 WRITE_DEBUG("Closed FXMessageBox 'Join non-selected junction' with 'ESC'");
1442 }
1443 return false;
1444 } else {
1445 // write warning if netedit is running in testing mode
1446 WRITE_DEBUG("Closed FXMessageBox 'Join non-selected junction' with 'Yes'");
1447 // select conflicted junction an join all again
1448 i.second->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1449 return joinSelectedJunctions(undoList);
1450 }
1451 }
1452 }
1453
1454 // use checkJunctionPosition to avoid conflicts with junction in the same position as others
1455 while (checkJunctionPosition(pos) == false) {
1456 pos.setx(pos.x() + 0.1);
1457 pos.sety(pos.y() + 0.1);
1458 }
1459
1460 // start with the join selected junctions
1461 undoList->begin(GUIIcon::JUNCTION, "Join selected " + toString(SUMO_TAG_JUNCTION) + "s");
1462 GNEJunction* joined = createJunction(pos, undoList);
1463 joined->setAttribute(SUMO_ATTR_TYPE, toString(nodeType), undoList); // i.e. rail crossing
1464 if (setTL) {
1465 joined->setAttribute(SUMO_ATTR_TLTYPE, toString(type), undoList);
1466 }
1467
1468 // #3128 this is not undone when calling 'undo'
1470
1471 // first remove all crossing of the involved junctions and edges
1472 // (otherwise edge removal will trigger discarding)
1473 std::vector<NBNode::Crossing> oldCrossings;
1474 for (auto i : selectedJunctions) {
1475 while (i->getGNECrossings().size() > 0) {
1476 GNECrossing* crossing = i->getGNECrossings().front();
1477 oldCrossings.push_back(*crossing->getNBCrossing());
1478 deleteCrossing(crossing, undoList);
1479 }
1480 }
1481
1482 // preserve old connections
1483 for (auto it : selectedJunctions) {
1484 it->setLogicValid(false, undoList);
1485 }
1486 // remap edges
1487 for (auto it : allIncoming) {
1488 undoList->changeAttribute(new GNEChange_Attribute(myAttributeCarriers->getEdges().at(it->getID()), SUMO_ATTR_TO, joined->getID()));
1489 }
1490
1491 EdgeSet edgesWithin;
1492 for (auto it : allOutgoing) {
1493 // delete edges within the cluster
1494 GNEEdge* edge = myAttributeCarriers->getEdges().at(it->getID());
1495 if (edge->getToJunction() == joined) {
1496 edgesWithin.insert(it);
1497 deleteEdge(edge, undoList, false);
1498 } else {
1499 undoList->changeAttribute(new GNEChange_Attribute(myAttributeCarriers->getEdges().at(it->getID()), SUMO_ATTR_FROM, joined->getID()));
1500 }
1501 }
1502
1503 // remap all crossing of the involved junctions and edges
1504 for (auto nbc : oldCrossings) {
1505 bool keep = true;
1506 for (NBEdge* e : nbc.edges) {
1507 if (edgesWithin.count(e) != 0) {
1508 keep = false;
1509 break;
1510 }
1511 };
1512 if (keep) {
1513 undoList->add(new GNEChange_Crossing(joined, nbc.edges, nbc.width,
1514 nbc.priority || joined->getNBNode()->isTLControlled(),
1515 nbc.customTLIndex, nbc.customTLIndex2, nbc.customShape,
1516 false, true), true);
1517 }
1518 }
1519
1520 // delete original junctions
1521 for (auto it : selectedJunctions) {
1522 deleteJunction(it, undoList);
1523 }
1524 joined->setAttribute(SUMO_ATTR_ID, id, undoList);
1525
1526
1527 // check if joined junction had to change their original position to avoid errors
1528 if (pos != oldPos) {
1529 joined->setAttribute(SUMO_ATTR_POSITION, toString(oldPos), undoList);
1530 }
1531 undoList->end();
1532 return true;
1533}
1534
1535
1536bool
1538 // obtain current net's crossings
1539 std::vector<GNECrossing*> myNetCrossings;
1540 for (auto it : myAttributeCarriers->getJunctions()) {
1541 myNetCrossings.reserve(myNetCrossings.size() + it.second->getGNECrossings().size());
1542 myNetCrossings.insert(myNetCrossings.end(), it.second->getGNECrossings().begin(), it.second->getGNECrossings().end());
1543 }
1544 // obtain invalid crossings
1545 std::vector<GNECrossing*> myInvalidCrossings;
1546 for (auto i = myNetCrossings.begin(); i != myNetCrossings.end(); i++) {
1547 if ((*i)->getNBCrossing()->valid == false) {
1548 myInvalidCrossings.push_back(*i);
1549 }
1550 }
1551
1552 if (myInvalidCrossings.empty()) {
1553 // show warning in gui testing debug mode
1554 WRITE_DEBUG("Opening FXMessageBox 'No crossing to remove'");
1555 // open a dialog informing that there isn't crossing to remove
1556 FXMessageBox::warning(getApp(), MBOX_OK,
1557 ("Clear " + toString(SUMO_TAG_CROSSING) + "s").c_str(), "%s",
1558 ("There is no invalid " + toString(SUMO_TAG_CROSSING) + "s to remove").c_str());
1559 // show warning in gui testing debug mode
1560 WRITE_DEBUG("Closed FXMessageBox 'No crossing to remove' with 'OK'");
1561 } else {
1562 std::string plural = myInvalidCrossings.size() == 1 ? ("") : ("s");
1563 // show warning in gui testing debug mode
1564 WRITE_DEBUG("Opening FXMessageBox 'clear crossings'");
1565 // Ask confirmation to user
1566 FXuint answer = FXMessageBox::question(getApp(), MBOX_YES_NO,
1567 ("Clear " + toString(SUMO_TAG_CROSSING) + "s").c_str(), "%s",
1568 ("Clear " + toString(SUMO_TAG_CROSSING) + plural + " will be removed. Continue?").c_str());
1569 if (answer != 1) { // 1:yes, 2:no, 4:esc
1570 // write warning if netedit is running in testing mode
1571 if (answer == 2) {
1572 WRITE_DEBUG("Closed FXMessageBox 'clear crossings' with 'No'");
1573 } else if (answer == 4) {
1574 WRITE_DEBUG("Closed FXMessageBox 'clear crossings' with 'ESC'");
1575 }
1576 } else {
1577 undoList->begin(GUIIcon::MODEDELETE, "Clean " + toString(SUMO_TAG_CROSSING) + "s");
1578 for (auto i = myInvalidCrossings.begin(); i != myInvalidCrossings.end(); i++) {
1579 deleteCrossing((*i), undoList);
1580 }
1581 undoList->end();
1582 }
1583 }
1584 return 1;
1585}
1586
1587
1588void
1590 undoList->begin(GUIIcon::MODEDELETE, "Clean " + toString(SUMO_TAG_JUNCTION) + "s");
1591 std::vector<GNEJunction*> toRemove;
1592 for (auto it : myAttributeCarriers->getJunctions()) {
1593 GNEJunction* junction = it.second;
1594 if (junction->getNBNode()->getEdges().size() == 0) {
1595 toRemove.push_back(junction);
1596 }
1597 }
1598 for (auto it : toRemove) {
1599 deleteJunction(it, undoList);
1600 }
1601 undoList->end();
1602}
1603
1604
1605void
1607 // first declare a vector to save all routes without children
1608 std::vector<GNEDemandElement*> routesWithoutChildren;
1609 routesWithoutChildren.reserve(myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE).size());
1610 // iterate over routes
1611 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
1612 if (route->getChildDemandElements().empty()) {
1613 routesWithoutChildren.push_back(route);
1614 }
1615 }
1616 // finally remove all routesWithoutChildren
1617 if (routesWithoutChildren.size() > 0) {
1618 // begin undo list
1619 undoList->begin(GUIIcon::MODEDELETE, "clean unused routes");
1620 // iterate over routesWithoutChildren
1621 for (const auto& i : routesWithoutChildren) {
1622 // due route doesn't have children, simply call GNEChange_DemandElement
1623 undoList->add(new GNEChange_DemandElement(i, false), true);
1624 }
1625 // end undo list
1626 undoList->end();
1627 }
1628}
1629
1630
1631void
1633 // first declare a sorted set of sorted route's edges in string format
1634 std::set<std::pair<std::string, GNEDemandElement*> > mySortedRoutes;
1635 // iterate over routes and save it in mySortedRoutes (only if it doesn't have Stop Children)
1636 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
1637 // first check route has stops
1638 bool hasStops = false;
1639 for (const auto& stop : route->getChildDemandElements()) {
1640 if (stop->getTagProperty().isStop()) {
1641 hasStops = true;
1642 }
1643 }
1644 if (!hasStops) {
1645 mySortedRoutes.insert(std::make_pair(GNEAttributeCarrier::parseIDs(route->getParentEdges()), route));
1646 }
1647 }
1648 // now declare a matrix in which organize routes to be merged
1649 std::vector<std::vector<GNEDemandElement*> > routesToMerge;
1650 auto index = mySortedRoutes.begin();
1651 // iterate over mySortedRoutes
1652 for (auto i = mySortedRoutes.begin(); i != mySortedRoutes.end(); i++) {
1653 if (routesToMerge.empty()) {
1654 routesToMerge.push_back({i->second});
1655 } else {
1656 if (index->first == i->first) {
1657 routesToMerge.back().push_back(i->second);
1658 } else {
1659 routesToMerge.push_back({i->second});
1660 index = i;
1661 }
1662 }
1663 }
1664 // now check if there is routes to merge
1665 bool thereIsRoutesToMerge = false;
1666 for (const auto& i : routesToMerge) {
1667 if (i.size() > 1) {
1668 thereIsRoutesToMerge = true;
1669 }
1670 }
1671 // if exist
1672 if (thereIsRoutesToMerge) {
1673 // begin undo list
1674 undoList->begin(GUIIcon::ROUTE, "merge routes");
1675 // iterate over route to edges
1676 for (const auto& i : routesToMerge) {
1677 if (i.size() > 1) {
1678 // iterate over duplicated routes
1679 for (int j = 1; j < (int)i.size(); j++) {
1680 // move all vehicles of every duplicated route
1681 while (i.at(j)->getChildDemandElements().size() > 0) {
1682 i.at(j)->getChildDemandElements().front()->setAttribute(SUMO_ATTR_ROUTE, i.at(0)->getID(), undoList);
1683 }
1684 // finally remove route
1685 undoList->add(new GNEChange_DemandElement(i.at(j), false), true);
1686 }
1687 }
1688 }
1689 // end undo list
1690 undoList->end();
1691 }
1692}
1693
1694
1695void
1697 // declare personPlan-pos map
1698 std::map<GNEDemandElement*, std::string> personPlanMap;
1699 // iterate over persons
1700 for (const auto& persontag : {
1702 }) {
1703 for (const auto& person : myAttributeCarriers->getDemandElements().at(persontag)) {
1704 if (person->getChildDemandElements().size() > 0) {
1705 // get person plan
1706 GNEDemandElement* personPlan = person->getChildDemandElements().front();
1707 // iterate over all personPlans
1708 while (personPlan) {
1709 // check if personPlan is a stopPerson over edge
1710 if (personPlan->getTagProperty().getTag() == GNE_TAG_STOPPERSON_EDGE) {
1711 // get previous person plan
1712 GNEDemandElement* previousPersonPlan = person->getPreviousChildDemandElement(personPlan);
1713 // check if arrivalPos of previous personPlan is different of endPos of stopPerson
1714 if (previousPersonPlan && previousPersonPlan->getTagProperty().hasAttribute(SUMO_ATTR_ARRIVALPOS) &&
1715 (previousPersonPlan->getAttribute(SUMO_ATTR_ARRIVALPOS) != personPlan->getAttribute(SUMO_ATTR_ENDPOS))) {
1716 personPlanMap[previousPersonPlan] = personPlan->getAttribute(SUMO_ATTR_ENDPOS);
1717 }
1718 }
1719 // go to next person plan
1720 personPlan = person->getNextChildDemandElement(personPlan);
1721 }
1722 }
1723 }
1724 }
1725 // continue if there is personPlanMap to adjust
1726 if (personPlanMap.size() > 0) {
1727 // begin undo list
1728 undoList->begin(GUIIcon::MODEPERSONPLAN, "adjust person plans");
1729 // iterate over invalidDemandElements
1730 for (const auto& personPlan : personPlanMap) {
1731 // set arrivalPos attribute
1732 personPlan.first->setAttribute(SUMO_ATTR_ARRIVALPOS, personPlan.second, undoList);
1733 }
1734 // end undo list
1735 undoList->end();
1736 }
1737}
1738
1739
1740void
1742 // first declare a vector to save all invalid demand elements
1743 std::vector<GNEDemandElement*> invalidDemandElements;
1744 invalidDemandElements.reserve(myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE).size() +
1747 // iterate over routes
1748 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
1749 if (route->isDemandElementValid() != GNEDemandElement::Problem::OK) {
1750 invalidDemandElements.push_back(route);
1751 }
1752 }
1753 // iterate over flows
1754 for (const auto& flow : myAttributeCarriers->getDemandElements().at(SUMO_TAG_FLOW)) {
1755 if (flow->isDemandElementValid() != GNEDemandElement::Problem::OK) {
1756 invalidDemandElements.push_back(flow);
1757 }
1758 }
1759 // iterate over trip
1760 for (const auto& trip : myAttributeCarriers->getDemandElements().at(SUMO_TAG_TRIP)) {
1761 if (trip->isDemandElementValid() != GNEDemandElement::Problem::OK) {
1762 invalidDemandElements.push_back(trip);
1763 }
1764 }
1765 // continue if there is invalidDemandElements to remove
1766 if (invalidDemandElements.size() > 0) {
1767 // begin undo list
1768 undoList->begin(GUIIcon::MODEDELETE, "remove invalid demand elements");
1769 // iterate over invalidDemandElements
1770 for (const auto& invalidDemandElement : invalidDemandElements) {
1771 // simply call GNEChange_DemandElement
1772 undoList->add(new GNEChange_DemandElement(invalidDemandElement, false), true);
1773 }
1774 // end undo list
1775 undoList->end();
1776 }
1777}
1778
1779void
1781 if (junction->getNBNode()->checkIsRemovable()) {
1782 // start operation
1783 undoList->begin(GUIIcon::JUNCTION, "Replace junction by geometry");
1784 // obtain Edges to join
1785 std::vector<std::pair<NBEdge*, NBEdge*> > toJoin = junction->getNBNode()->getEdgesToJoin();
1786 // clear connections of junction to replace
1787 clearJunctionConnections(junction, undoList);
1788 // iterate over NBEdges to join
1789 for (auto j : toJoin) {
1790 // obtain GNEEdges
1791 GNEEdge* begin = myAttributeCarriers->getEdges().at(j.first->getID());
1792 GNEEdge* continuation = myAttributeCarriers->getEdges().at(j.second->getID());
1793 // remove connections between the edges
1794 std::vector<NBEdge::Connection> connections = begin->getNBEdge()->getConnections();
1795 for (auto con : connections) {
1796 undoList->add(new GNEChange_Connection(begin, con, false, false), true);
1797 }
1798 // fix shape of replaced edge
1799 PositionVector newShape = begin->getNBEdge()->getInnerGeometry();
1801 newShape.push_back(junction->getNBNode()->getPosition());
1802 } else {
1803 newShape.push_back(begin->getNBEdge()->getGeometry()[-1]);
1804 }
1805 if (continuation->getNBEdge()->hasDefaultGeometryEndpointAtNode(begin->getNBEdge()->getToNode())) {
1806 newShape.push_back_noDoublePos(junction->getNBNode()->getPosition());
1807 } else {
1808 newShape.push_back_noDoublePos(continuation->getNBEdge()->getGeometry()[0]);
1809 }
1810 // replace incoming edge
1811 replaceIncomingEdge(continuation, begin, undoList);
1812
1813 newShape.append(continuation->getNBEdge()->getInnerGeometry());
1814 begin->setAttribute(GNE_ATTR_SHAPE_END, continuation->getAttribute(GNE_ATTR_SHAPE_END), undoList);
1815 begin->setAttribute(SUMO_ATTR_ENDOFFSET, continuation->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
1816 begin->setAttribute(SUMO_ATTR_SHAPE, toString(newShape), undoList);
1817 begin->getNBEdge()->resetNodeBorder(begin->getNBEdge()->getToNode());
1818 // fix loaded lengths
1819 if (begin->getNBEdge()->hasLoadedLength() || continuation->getNBEdge()->hasLoadedLength()) {
1820 begin->setAttribute(SUMO_ATTR_LENGTH, toString(begin->getNBEdge()->getLoadedLength() + continuation->getNBEdge()->getLoadedLength()), undoList);
1821 }
1822 }
1823 //delete replaced junction
1824 deleteJunction(junction, undoList);
1825 // finish operation
1826 undoList->end();
1827 } else {
1828 throw ProcessError("Junction isn't removable");
1829 }
1830}
1831
1832
1833void
1834GNENet::splitJunction(GNEJunction* junction, bool reconnect, GNEUndoList* undoList) {
1835 std::vector<std::pair<Position, std::string> > endpoints = junction->getNBNode()->getEndPoints();
1836 if (endpoints.size() < 2) {
1837 return;
1838 }
1839 // start operation
1840 undoList->begin(GUIIcon::JUNCTION, "Split junction");
1841 // record connections
1842 std::map<GNEEdge*, std::vector<NBEdge::Connection>> straightConnections;
1843 for (GNEEdge* e : junction->getGNEIncomingEdges()) {
1844 for (const auto& c : e->getNBEdge()->getConnections()) {
1845 if (c.fromLane >= 0 && junction->getNBNode()->getDirection(e->getNBEdge(), c.toEdge) == LinkDirection::STRAIGHT) {
1846 straightConnections[e].push_back(c);
1847 }
1848 };
1849 }
1850 //std::cout << "split junction at endpoints:\n";
1851
1852 junction->setLogicValid(false, undoList);
1853 for (const auto& pair : endpoints) {
1854 const Position& pos = pair.first;
1855 const std::string& origID = pair.second;
1856 GNEJunction* newJunction = createJunction(pos, undoList);
1857 std::string newID = origID != "" ? origID : newJunction->getID();
1858 // make a copy because the original vectors are modified during iteration
1859 const std::vector<GNEEdge*> incoming = junction->getGNEIncomingEdges();
1860 const std::vector<GNEEdge*> outgoing = junction->getGNEOutgoingEdges();
1861 //std::cout << " checkEndpoint " << pair.first << " " << pair.second << " newID=" << newID << "\n";
1862 for (GNEEdge* e : incoming) {
1863 //std::cout << " incoming " << e->getID() << " pos=" << pos << " origTo=" << e->getNBEdge()->getParameter("origTo") << " newID=" << newID << "\n";
1864 if (e->getNBEdge()->getGeometry().back().almostSame(pos) || e->getNBEdge()->getParameter("origTo") == newID) {
1865 //std::cout << " match\n";
1866 undoList->changeAttribute(new GNEChange_Attribute(e, SUMO_ATTR_TO, newJunction->getID()));
1867 }
1868 }
1869 for (GNEEdge* e : outgoing) {
1870 //std::cout << " outgoing " << e->getID() << " pos=" << pos << " origFrom=" << e->getNBEdge()->getParameter("origFrom") << " newID=" << newID << "\n";
1871 if (e->getNBEdge()->getGeometry().front().almostSame(pos) || e->getNBEdge()->getParameter("origFrom") == newID) {
1872 //std::cout << " match\n";
1873 undoList->changeAttribute(new GNEChange_Attribute(e, SUMO_ATTR_FROM, newJunction->getID()));
1874 }
1875 }
1876 if (newID != newJunction->getID()) {
1877 if (newJunction->isValid(SUMO_ATTR_ID, newID)) {
1878 undoList->changeAttribute(new GNEChange_Attribute(newJunction, SUMO_ATTR_ID, newID));
1879 } else {
1880 WRITE_WARNING("Could not rename split node to '" + newID + "'");
1881 }
1882 }
1883 }
1884 // recreate edges from straightConnections
1885 if (reconnect) {
1886 for (const auto& item : straightConnections) {
1887 GNEEdge* in = item.first;
1888 std::map<NBEdge*, GNEEdge*> newEdges;
1889 for (auto& c : item.second) {
1890 GNEEdge* out = myAttributeCarriers->retrieveEdge(c.toEdge->getID());
1891 GNEEdge* newEdge = nullptr;
1892 if (in->getToJunction() == out->getFromJunction()) {
1893 continue;
1894 }
1895 if (newEdges.count(c.toEdge) == 0) {
1896 newEdge = createEdge(in->getToJunction(), out->getFromJunction(), in, undoList);
1897 newEdges[c.toEdge] = newEdge;
1898 newEdge->setAttribute(SUMO_ATTR_NUMLANES, "1", undoList);
1899 } else {
1900 newEdge = newEdges[c.toEdge];
1901 duplicateLane(newEdge->getLanes().back(), undoList, true);
1902 }
1903 // copy permissions
1904 newEdge->getLanes().back()->setAttribute(SUMO_ATTR_ALLOW,
1905 in->getLanes()[c.fromLane]-> getAttribute(SUMO_ATTR_ALLOW), undoList);
1906 }
1907 }
1908 }
1909
1910 deleteJunction(junction, undoList);
1911 // finish operation
1912 undoList->end();
1913}
1914
1915
1916
1917void
1919 undoList->begin(GUIIcon::MODEDELETE, "clear junction connections");
1920 std::vector<GNEConnection*> connections = junction->getGNEConnections();
1921 // Iterate over all connections and clear it
1922 for (auto i : connections) {
1923 deleteConnection(i, undoList);
1924 }
1925 undoList->end();
1926}
1927
1928
1929void
1931 undoList->begin(GUIIcon::CONNECTION, "reset junction connections");
1932 // first clear connections
1933 clearJunctionConnections(junction, undoList);
1934 // invalidate logic to create new connections in the next recomputing
1935 junction->setLogicValid(false, undoList);
1936 undoList->end();
1937}
1938
1939
1940void
1942 undoList->begin(GUIIcon::MODEADDITIONAL, "clear additional elements");
1943 // clear additionals
1944 for (const auto& additionalMap : myAttributeCarriers->getAdditionals()) {
1945 while (additionalMap.second.size() > 0) {
1946 deleteAdditional(*additionalMap.second.begin(), undoList);
1947 }
1948 }
1949 undoList->end();
1950}
1951
1952
1953void
1955 undoList->begin(GUIIcon::MODEDELETE, "clear demand elements");
1956 // clear demand elements
1957 for (const auto& demandElementsMap : myAttributeCarriers->getDemandElements()) {
1958 while (demandElementsMap.second.size() > 0) {
1959 deleteDemandElement(*demandElementsMap.second.begin(), undoList);
1960 }
1961 }
1962 undoList->end();
1963}
1964
1965
1966void
1968 undoList->begin(GUIIcon::MODEDELETE, "clear data elements");
1969 // clear data sets
1970 for (const auto& dataSet : myAttributeCarriers->getDataSets()) {
1971 deleteDataSet(dataSet, undoList);
1972 }
1973 undoList->end();
1974}
1975
1976
1977void
1978GNENet::changeEdgeEndpoints(GNEEdge* edge, const std::string& newSource, const std::string& newDest) {
1981 edge->getNBEdge()->reinitNodes(from, to);
1983}
1984
1985
1988 return myViewNet;
1989}
1990
1991
1994 return myNetBuilder->getTLLogicCont();
1995}
1996
1997
2000 return myNetBuilder->getEdgeCont();
2001}
2002
2003
2004void
2006 myExplicitTurnarounds.insert(id);
2007}
2008
2009
2010void
2012 myExplicitTurnarounds.erase(id);
2013}
2014
2015
2016void
2018 myAdditionalsSaved = !value;
2019 if (myViewNet != nullptr) {
2020 if (myAdditionalsSaved) {
2022 } else {
2024 }
2025 }
2026}
2027
2028
2029void
2030GNENet::saveAdditionals(const std::string& filename) {
2031 if (filename.size() > 0) {
2032 // obtain invalid additionals depending of number of their parent lanes
2033 std::vector<GNEAdditional*> invalidSingleLaneAdditionals;
2034 std::vector<GNEAdditional*> invalidMultiLaneAdditionals;
2035 // iterate over additionals and obtain invalids
2036 for (const auto& additionalPair : myAttributeCarriers->getAdditionals()) {
2037 for (const auto& addditional : additionalPair.second) {
2038 // check if has to be fixed
2039 if (addditional->getTagProperty().hasAttribute(SUMO_ATTR_LANE) && !addditional->isAdditionalValid()) {
2040 invalidSingleLaneAdditionals.push_back(addditional);
2041 } else if (addditional->getTagProperty().hasAttribute(SUMO_ATTR_LANES) && !addditional->isAdditionalValid()) {
2042 invalidMultiLaneAdditionals.push_back(addditional);
2043 }
2044 }
2045 }
2046 // if there are invalid StoppingPlaces or detectors, open GNEFixAdditionalElements
2047 if (invalidSingleLaneAdditionals.size() > 0 || invalidMultiLaneAdditionals.size() > 0) {
2048 // 0 -> Canceled Saving, with or without selecting invalid stopping places and E2
2049 // 1 -> Invalid stoppingPlaces and E2 fixed, friendlyPos enabled, or saved with invalid positions
2050 GNEFixAdditionalElements fixAdditionalElementsDialog(myViewNet, invalidSingleLaneAdditionals, invalidMultiLaneAdditionals);
2051 if (fixAdditionalElementsDialog.execute() == 0) {
2052 // show debug information
2053 WRITE_DEBUG("Additionals saving aborted");
2054 } else {
2055 saveAdditionalsConfirmed(filename);
2056 // change value of flag
2057 myAdditionalsSaved = true;
2058 // show debug information
2059 WRITE_DEBUG("Additionals saved after dialog");
2060 }
2061 // update view
2063 // set focus again in net
2064 myViewNet->setFocus();
2065 } else {
2066 saveAdditionalsConfirmed(filename);
2067 // change value of flag
2068 myAdditionalsSaved = true;
2069 // show debug information
2070 WRITE_DEBUG("Additionals saved");
2071 }
2072 }
2073}
2074
2075
2076bool
2078 return myAdditionalsSaved;
2079}
2080
2081
2082void
2084 myDemandElementsSaved = !value;
2085 if (myViewNet != nullptr) {
2088 } else {
2090 }
2091 }
2092}
2093
2094
2095void
2096GNENet::saveDemandElements(const std::string& filename) {
2097 if (filename.size() > 0) {
2098 // first recompute demand elements
2100 // obtain invalid demandElements depending of number of their parent lanes
2101 std::vector<GNEDemandElement*> invalidSingleLaneDemandElements;
2102 // iterate over demandElements and obtain invalids
2103 for (const auto& demandElementSet : myAttributeCarriers->getDemandElements()) {
2104 for (const auto& demandElement : demandElementSet.second) {
2105 // compute before check if demand element is valid
2106 demandElement->computePathElement();
2107 // check if has to be fixed
2108 if (demandElement->isDemandElementValid() != GNEDemandElement::Problem::OK) {
2109 invalidSingleLaneDemandElements.push_back(demandElement);
2110 }
2111 }
2112 }
2113 // if there are invalid demand elements, open GNEFixDemandElements
2114 if (invalidSingleLaneDemandElements.size() > 0) {
2115 // 0 -> Canceled Saving, with or without selecting invalid demand elements
2116 // 1 -> Invalid demand elements fixed, friendlyPos enabled, or saved with invalid positions
2117 GNEFixDemandElements fixDemandElementsDialog(myViewNet, invalidSingleLaneDemandElements);
2118 if (fixDemandElementsDialog.execute() == 0) {
2119 // show debug information
2120 WRITE_DEBUG("demand elements saving aborted");
2121 } else {
2123 // change value of flag
2124 myDemandElementsSaved = true;
2125 // show debug information
2126 WRITE_DEBUG("demand elements saved after dialog");
2127 }
2128 // update view
2130 // set focus again in net
2131 myViewNet->setFocus();
2132 } else {
2134 // change value of flag
2135 myDemandElementsSaved = true;
2136 // show debug information
2137 WRITE_DEBUG("demand elements saved");
2138 }
2139 }
2140}
2141
2142
2143bool
2145 return myDemandElementsSaved;
2146}
2147
2148
2149void
2151 myDataElementsSaved = !value;
2152 if (myViewNet != nullptr) {
2153 if (myDataElementsSaved) {
2155 } else {
2157 }
2158 }
2159}
2160
2161
2162void
2163GNENet::saveDataElements(const std::string& filename) {
2164 if (filename.size() > 0) {
2165 // first recompute data sets
2167 // save data elements
2168 saveDataElementsConfirmed(filename);
2169 // change value of flag
2170 myDataElementsSaved = true;
2171 // show debug information
2172 WRITE_DEBUG("data sets saved");
2173 }
2174}
2175
2176
2177bool
2179 return myDataElementsSaved;
2180}
2181
2182
2183double
2185 double minimumBegin = 0;
2186 // update with first minimum (if exist)
2187 if (myAttributeCarriers->getDataIntervals().size() > 0) {
2188 minimumBegin = (*myAttributeCarriers->getDataIntervals().begin())->getAttributeDouble(SUMO_ATTR_BEGIN);
2189 }
2190 // iterate over interval
2191 for (const auto& interval : myAttributeCarriers->getDataIntervals()) {
2192 if (interval->getAttributeDouble(SUMO_ATTR_BEGIN) < minimumBegin) {
2193 minimumBegin = interval->getAttributeDouble(SUMO_ATTR_BEGIN);
2194 }
2195 }
2196 return minimumBegin;
2197}
2198
2199
2200double
2202 double maximumEnd = 0;
2203 // update with first maximum (if exist)
2204 if (myAttributeCarriers->getDataIntervals().size() > 0) {
2205 maximumEnd = (*myAttributeCarriers->getDataIntervals().begin())->getAttributeDouble(SUMO_ATTR_END);
2206 }
2207 // iterate over intervals
2208 for (const auto& interval : myAttributeCarriers->getDataIntervals()) {
2209 if (interval->getAttributeDouble(SUMO_ATTR_END) > maximumEnd) {
2210 maximumEnd = interval->getAttributeDouble(SUMO_ATTR_END);
2211 }
2212 }
2213 return maximumEnd;
2214}
2215
2216
2217void
2218GNENet::saveAdditionalsConfirmed(const std::string& filename) {
2219 OutputDevice& device = OutputDevice::getDevice(filename);
2220 // open header
2221 device.writeXMLHeader("additional", "additional_file.xsd", EMPTY_HEADER, false);
2222 // write vTypes with additional childrens (due calibrators)
2223 writeVTypeComment(device, true);
2224 writeVTypes(device, true);
2225 // write routes with additional children (due route prob reroutes)
2226 writeRouteComment(device, true);
2227 writeRoutes(device, true);
2228 // routeProbes
2229 writeRouteProbeComment(device);
2231 // calibrator
2232 writeCalibratorComment(device);
2234 // stoppingPlaces
2241 // detectors
2242 writeDetectorComment(device);
2247 // Other additionals
2252 // shapes
2253 writeShapesComment(device);
2256 // TAZs
2257 writeTAZComment(device);
2259 // Wire element
2260 writeWireComment(device);
2264 // close device
2265 device.close();
2266}
2267
2268
2269void
2270GNENet::saveDemandElementsConfirmed(const std::string& filename) {
2271 OutputDevice& device = OutputDevice::getDevice(filename);
2272 // open header
2273 device.writeXMLHeader("routes", "routes_file.xsd", EMPTY_HEADER, false);
2274 // first write all vTypeDistributions (and their vTypes)
2275 writeVTypeComment(device, false);
2276 writeVTypes(device, false);
2277 // now write all routes (and their associated stops), except routes with additional children (due routeProbReroutes)
2278 writeRouteComment(device, false);
2279 writeRoutes(device, false);
2280 // sort vehicles/persons by depart
2281 std::map<double, std::map<std::pair<SumoXMLTag, std::string>, GNEDemandElement*> > vehiclesSortedByDepart;
2282 for (const auto& demandElementTag : myAttributeCarriers->getDemandElements()) {
2283 for (const auto& demandElement : demandElementTag.second) {
2284 if (demandElement->getTagProperty().isVehicle() || demandElement->getTagProperty().isPerson() || demandElement->getTagProperty().isContainer()) {
2285 // get depart
2286 const auto depart = GNEAttributeCarrier::parse<double>(demandElement->getBegin());
2287 // save it in myVehiclesSortedByDepart
2288 vehiclesSortedByDepart[depart][std::make_pair(demandElement->getTagProperty().getTag(), demandElement->getID())] = demandElement;
2289 }
2290 }
2291 }
2292 // finally write all vehicles, persons and containers sorted by depart time (and their associated stops, personPlans, etc.)
2293 if (vehiclesSortedByDepart.size() > 0) {
2294 device << (" <!-- Vehicles, persons and containers (sorted by depart) -->\n");
2295 for (const auto& vehicleTag : vehiclesSortedByDepart) {
2296 for (const auto& vehicle : vehicleTag.second) {
2297 vehicle.second->writeDemandElement(device);
2298 }
2299 }
2300 }
2301 // close device
2302 device.close();
2303}
2304
2305
2306void
2307GNENet::saveDataElementsConfirmed(const std::string& filename) {
2308 OutputDevice& device = OutputDevice::getDevice(filename);
2309 device.writeXMLHeader("data", "datamode_file.xsd", EMPTY_HEADER, false);
2310 // write all data sets
2311 for (const auto& dataSet : myAttributeCarriers->getDataSets()) {
2312 dataSet->writeDataSet(device);
2313 }
2314 // close device
2315 device.close();
2316}
2317
2318
2319void
2320GNENet::writeAdditionalByType(OutputDevice& device, const std::vector<SumoXMLTag> tags) const {
2321 std::map<std::string, GNEAdditional*> sortedAdditionals;
2322 for (const auto& tag : tags) {
2323 for (const auto& additional : myAttributeCarriers->getAdditionals().at(tag)) {
2324 if (sortedAdditionals.count(additional->getID()) == 0) {
2325 sortedAdditionals[additional->getID()] = additional;
2326 } else {
2327 throw ProcessError("Duplicated ID");
2328 }
2329 }
2330 }
2331 for (const auto& additional : sortedAdditionals) {
2332 additional.second->writeAdditional(device);
2333 }
2334}
2335
2336
2337void
2339 std::map<std::string, GNEDemandElement*> sortedDemandElements;
2340 for (const auto& demandElement : myAttributeCarriers->getDemandElements().at(tag)) {
2341 sortedDemandElements[demandElement->getID()] = demandElement;
2342 }
2343 for (const auto& demandElement : sortedDemandElements) {
2344 demandElement.second->writeDemandElement(device);
2345 }
2346}
2347
2348
2349void
2350GNENet::writeRoutes(OutputDevice& device, const bool additionalFile) const {
2351 std::map<std::string, GNEDemandElement*> sortedRoutes;
2352 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
2353 if ((additionalFile && (route->getChildAdditionals().size() > 0)) ||
2354 (!additionalFile && (route->getChildAdditionals().size() == 0))) {
2355 sortedRoutes[route->getID()] = route;
2356 }
2357 }
2358 for (const auto& route : sortedRoutes) {
2359 route.second->writeDemandElement(device);
2360 }
2361}
2362
2363
2364void
2365GNENet::writeVTypes(OutputDevice& device, const bool additionalFile) const {
2366 std::map<std::string, GNEDemandElement*> sortedElements;
2367 // write vType Distributions
2368 for (const auto& vTypeDistribution : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE_DISTRIBUTION)) {
2369 if ((additionalFile && (vTypeDistribution->getChildAdditionals().size() > 0)) ||
2370 (!additionalFile && (vTypeDistribution->getChildAdditionals().size() == 0))) {
2371 sortedElements[vTypeDistribution->getID()] = vTypeDistribution;
2372 }
2373 }
2374 for (const auto& element : sortedElements) {
2375 element.second->writeDemandElement(device);
2376 }
2377 sortedElements.clear();
2378 // write vTypes
2379 for (const auto& vType : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE)) {
2380 // special case for default vTypes
2381 const bool defaultVType = GNEAttributeCarrier::parse<bool>(vType->getAttribute(GNE_ATTR_DEFAULT_VTYPE));
2382 const bool defaultVTypeModified = GNEAttributeCarrier::parse<bool>(vType->getAttribute(GNE_ATTR_DEFAULT_VTYPE_MODIFIED));
2383 // only write default vType modified
2384 if ((vType->getParentDemandElements().size() == 0) && (!defaultVType || (defaultVType && defaultVTypeModified))) {
2385 if ((additionalFile && (vType->getChildAdditionals().size() > 0)) ||
2386 (!additionalFile && (vType->getChildAdditionals().size() == 0))) {
2387 sortedElements[vType->getID()] = vType;
2388 }
2389 }
2390 }
2391 for (const auto& element : sortedElements) {
2392 element.second->writeDemandElement(device);
2393 }
2394}
2395
2396
2397bool
2398GNENet::writeVTypeComment(OutputDevice& device, const bool additionalFile) const {
2399 // vType Distributions
2400 for (const auto& vTypeDistribution : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE_DISTRIBUTION)) {
2401 if (additionalFile && (vTypeDistribution->getChildAdditionals().size() > 0)) {
2402 device << (" <!-- VTypes (used in calibratorFlows) -->\n");
2403 return true;
2404 } else if (!additionalFile && (vTypeDistribution->getChildAdditionals().size() == 0)) {
2405 device << (" <!-- VTypes -->\n");
2406 return true;
2407 }
2408 }
2409 // vTypes
2410 for (const auto& vType : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE)) {
2411 // special case for default vTypes
2412 const bool defaultVType = GNEAttributeCarrier::parse<bool>(vType->getAttribute(GNE_ATTR_DEFAULT_VTYPE));
2413 const bool defaultVTypeModified = GNEAttributeCarrier::parse<bool>(vType->getAttribute(GNE_ATTR_DEFAULT_VTYPE_MODIFIED));
2414 // only write default vType modified
2415 if ((vType->getParentDemandElements().size() == 0) && (!defaultVType || (defaultVType && defaultVTypeModified))) {
2416 if (additionalFile && (vType->getChildAdditionals().size() > 0)) {
2417 device << (" <!-- VTypes (used in calibratorFlows) -->\n");
2418 return true;
2419 } else if (!additionalFile && (vType->getChildAdditionals().size() == 0)) {
2420 device << (" <!-- VTypes -->\n");
2421 return true;
2422 }
2423 }
2424 }
2425 return false;
2426}
2427
2428
2429bool
2430GNENet::writeRouteComment(OutputDevice& device, const bool additionalFile) const {
2431 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
2432 if (additionalFile && (route->getChildAdditionals().size() > 0)) {
2433 device << (" <!-- Routes (used in RouteProbReroutes and calibratorFlows) -->\n");
2434 return true;
2435 } else if (!additionalFile && (route->getChildAdditionals().size() == 0)) {
2436 device << (" <!-- Routes -->\n");
2437 return true;
2438 }
2439 }
2440 return false;
2441}
2442
2443
2444bool
2447 device << (" <!-- RouteProbes -->\n");
2448 return true;
2449 }
2450 return false;
2451}
2452
2453
2454bool
2456 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2457 if (GNEAttributeCarrier::getTagProperty(additionals.first).isCalibrator() && (additionals.second.size() > 0)) {
2458 device << (" <!-- Calibrators -->\n");
2459 return true;
2460 }
2461 }
2462 return false;
2463}
2464
2465
2466bool
2468 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2469 if (GNEAttributeCarrier::getTagProperty(additionals.first).isStoppingPlace() && (additionals.second.size() > 0)) {
2470 device << (" <!-- StoppingPlaces -->\n");
2471 return true;
2472 }
2473 }
2474 return false;
2475}
2476
2477
2478bool
2480 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2481 if (GNEAttributeCarrier::getTagProperty(additionals.first).isDetector() && (additionals.second.size() > 0)) {
2482 device << (" <!-- Detectors -->\n");
2483 return true;
2484 }
2485 }
2486 return false;
2487}
2488
2489
2490bool
2492 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2495 !GNEAttributeCarrier::getTagProperty(additionals.first).isDetector() &&
2496 !GNEAttributeCarrier::getTagProperty(additionals.first).isCalibrator() &&
2497 (additionals.first != SUMO_TAG_ROUTEPROBE) && (additionals.first != SUMO_TAG_ACCESS) &&
2498 (additionals.first != SUMO_TAG_PARKING_SPACE) && (additionals.second.size() > 0)) {
2499 device << (" <!-- Other additionals -->\n");
2500 return true;
2501 }
2502 }
2503 return false;
2504}
2505
2506
2507bool
2509 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2510 if (GNEAttributeCarrier::getTagProperty(additionals.first).isShapeElement() && (additionals.second.size() > 0)) {
2511 device << (" <!-- Shapes -->\n");
2512 return true;
2513 }
2514 }
2515 return false;
2516}
2517
2518
2519bool
2521 if (myAttributeCarriers->getAdditionals().at(SUMO_TAG_TAZ).size() > 0) {
2522 device << (" <!-- TAZs -->\n");
2523 return true;
2524 }
2525 return false;
2526}
2527
2528
2529bool
2532 device << (" <!-- Wires -->\n");
2533 return true;
2534 }
2535 return false;
2536}
2537
2538
2539void
2541 if (myTLSProgramsSaved == true) {
2542 WRITE_DEBUG("TLSPrograms has to be saved");
2543 }
2544 myTLSProgramsSaved = false;
2546}
2547
2548
2549void
2550GNENet::saveTLSPrograms(const std::string& filename) {
2551 // open output device
2552 OutputDevice& device = OutputDevice::getDevice(filename);
2553 device.openTag("additionals");
2554 // write traffic lights using NWWriter
2556 device.close();
2557 // change flag to true
2558 myTLSProgramsSaved = true;
2559 // show debug information
2560 WRITE_DEBUG("TLSPrograms saved");
2561}
2562
2563
2564int
2566 return -1;
2567}
2568
2569
2570void
2571GNENet::saveEdgeTypes(const std::string& filename) {
2572 // first clear typeContainer
2574 // now update typeContainer with edgeTypes
2575 for (const auto& edgeType : myAttributeCarriers->getEdgeTypes()) {
2576 myNetBuilder->getTypeCont().insertEdgeType(edgeType.first, edgeType.second);
2577 for (int i = 0; i < (int)edgeType.second->getLaneTypes().size(); i++) {
2578 myNetBuilder->getTypeCont().insertLaneType(edgeType.first, i,
2579 edgeType.second->getLaneTypes().at(i)->speed,
2580 edgeType.second->getLaneTypes().at(i)->permissions,
2581 edgeType.second->getLaneTypes().at(i)->width,
2582 edgeType.second->getLaneTypes().at(i)->attrs);
2583 }
2584 }
2585 // open device
2586 OutputDevice& device = OutputDevice::getDevice(filename);
2587 // open tag
2588 device.openTag(SUMO_TAG_TYPE);
2589 // write edge types
2591 // close tag
2592 device.closeTag();
2593 // close device
2594 device.close();
2595}
2596
2597
2598void
2601}
2602
2603
2604void
2607}
2608
2609
2610bool
2613}
2614
2615
2616void
2618 myUpdateDataEnabled = true;
2619 // update data elements
2620 for (const auto& dataInterval : myAttributeCarriers->getDataIntervals()) {
2621 dataInterval->updateGenericDataIDs();
2622 dataInterval->updateAttributeColors();
2623 }
2624}
2625
2626
2627void
2629 myUpdateDataEnabled = false;
2630}
2631
2632
2633bool
2635 return myUpdateDataEnabled;
2636}
2637
2638// ===========================================================================
2639// private
2640// ===========================================================================
2641
2642void
2644 // init edge types
2645 for (const auto& edgeType : myNetBuilder->getTypeCont()) {
2646 // register edge type
2647 myAttributeCarriers->registerEdgeType(new GNEEdgeType(this, edgeType.first, edgeType.second));
2648 }
2649 // init junctions (by default Crossing and walking areas aren't created)
2650 for (const auto& nodeName : myNetBuilder->getNodeCont().getAllNames()) {
2651 // create and register junction
2653 }
2654 // init edges
2655 for (const auto& edgeName : myNetBuilder->getEdgeCont().getAllNames()) {
2656 // create edge using NBEdge
2657 GNEEdge* edge = new GNEEdge(this, myNetBuilder->getEdgeCont().retrieve(edgeName), false, true);
2658 // register edge
2660 // add manually child references due initJunctionsAndEdges doesn't use undo-redo
2661 edge->getFromJunction()->addChildElement(edge);
2662 edge->getToJunction()->addChildElement(edge);
2663 // check grid
2664 if (myGrid.getWidth() > 10e16 || myGrid.getHeight() > 10e16) {
2665 throw ProcessError("Network size exceeds 1 Lightyear. Please reconsider your inputs.\n");
2666 }
2667 }
2668 // make sure myGrid is initialized even for an empty net
2669 if (myAttributeCarriers->getEdges().size() == 0) {
2670 myGrid.add(Boundary(0, 0, 100, 100));
2671 }
2672 // recalculate all lane2lane connections
2673 for (const auto& edge : myAttributeCarriers->getEdges()) {
2674 for (const auto& lane : edge.second->getLanes()) {
2675 lane->updateGeometry();
2676 }
2677 }
2678 // sort nodes edges so that arrows can be drawn correctly
2680}
2681
2682
2683void
2685 for (const auto& edge : myAttributeCarriers->getEdges()) {
2686 // remake connections
2687 edge.second->remakeGNEConnections();
2688 // update geometry of connections
2689 for (const auto& connection : edge.second->getGNEConnections()) {
2690 connection->updateGeometry();
2691 }
2692 }
2693}
2694
2695
2696void
2697GNENet::computeAndUpdate(OptionsCont& oc, bool volatileOptions) {
2698 // make sure we only add turn arounds to edges which currently exist within the network
2699 std::set<std::string> liveExplicitTurnarounds;
2700 for (const auto& explicitTurnarounds : myExplicitTurnarounds) {
2701 if (myAttributeCarriers->getEdges().count(explicitTurnarounds) > 0) {
2702 liveExplicitTurnarounds.insert(explicitTurnarounds);
2703 }
2704 }
2705 // removes all junctions of grid
2706 WRITE_GLDEBUG("Removing junctions during recomputing");
2707 for (const auto& it : myAttributeCarriers->getJunctions()) {
2709 }
2710 // remove all edges from grid
2711 WRITE_GLDEBUG("Removing edges during recomputing");
2712 for (const auto& it : myAttributeCarriers->getEdges()) {
2714 }
2715 // compute using NetBuilder
2716 myNetBuilder->compute(oc, liveExplicitTurnarounds, volatileOptions);
2717 // remap ids if necessary
2718 if (oc.getBool("numerical-ids") || oc.isSet("reserved-ids")) {
2720 }
2721 // update rtree if necessary
2722 if (!oc.getBool("offset.disable-normalization")) {
2723 for (const auto& edge : myAttributeCarriers->getEdges()) {
2724 // refresh edge geometry
2725 edge.second->updateGeometry();
2726 }
2727 }
2728 // Clear current inspected ACs in inspectorFrame if a previous net was loaded
2729 if (myViewNet != nullptr) {
2731 }
2732 // Reset Grid
2733 myGrid.reset();
2734 myGrid.add(GeoConvHelper::getFinal().getConvBoundary());
2735 // if volatile options are true
2736 if (volatileOptions) {
2737 // check that net exist
2738 if (myViewNet == nullptr) {
2739 throw ProcessError("ViewNet doesn't exist");
2740 }
2741 // disable update geometry before clear undo list
2743 // destroy Popup
2745 // clear undo list (This will be remove additionals and shapes)
2747 // clear all elements (it will also removed from grid)
2752 // enable update geometry again
2754 // Write GL debug information
2755 WRITE_GLDEBUG("initJunctionsAndEdges function called in computeAndUpdate(...) due recomputing with volatile options");
2756 // init again junction an edges (Additionals and shapes will be loaded after the end of this function)
2758 // init default vTypes again
2760 } else {
2761 // insert all junctions of grid again
2762 WRITE_GLDEBUG("Add junctions during recomputing after calling myNetBuilder->compute(...)");
2763 for (const auto& junction : myAttributeCarriers->getJunctions()) {
2764 // update centering boundary
2765 junction.second->updateCenteringBoundary(false);
2766 // add junction in grid again
2767 myGrid.addAdditionalGLObject(junction.second);
2768 }
2769 // insert all edges from grid again
2770 WRITE_GLDEBUG("Add edges during recomputing after calling myNetBuilder->compute(...)");
2771 for (const auto& edge : myAttributeCarriers->getEdges()) {
2772 // update centeting boundary
2773 edge.second->updateCenteringBoundary(false);
2774 // add edge in grid again
2775 myGrid.addAdditionalGLObject(edge.second);
2776 }
2777 // remake connections
2778 for (const auto& connection : myAttributeCarriers->getEdges()) {
2779 connection.second->remakeGNEConnections(true);
2780 }
2781 // iterate over junctions of net
2782 for (const auto& junction : myAttributeCarriers->getJunctions()) {
2783 // undolist may not yet exist but is also not needed when just marking junctions as valid
2784 junction.second->setLogicValid(true, nullptr);
2785 // updated geometry
2786 junction.second->updateGeometryAfterNetbuild();
2787 // rebuild walking areas
2788 junction.second->rebuildGNEWalkingAreas();
2789 }
2790 // iterate over all edges of net
2791 for (const auto& edge : myAttributeCarriers->getEdges()) {
2792 // update geometry
2793 edge.second->updateGeometry();
2794 }
2795 }
2796 // net recomputed, then return false;
2797 myNeedRecompute = false;
2798}
2799
2800
2801void
2802GNENet::replaceInListAttribute(GNEAttributeCarrier* ac, SumoXMLAttr key, const std::string& which, const std::string& by, GNEUndoList* undoList) {
2803 assert(ac->getTagProperty().getAttributeProperties(key).isList());
2804 std::vector<std::string> values = GNEAttributeCarrier::parse<std::vector<std::string> >(ac->getAttribute(key));
2805 std::vector<std::string> newValues;
2806 for (auto v : values) {
2807 newValues.push_back(v == which ? by : v);
2808 }
2809 ac->setAttribute(key, toString(newValues), undoList);
2810}
2811
2812
2813/****************************************************************************/
@ GLO_NETWORK
The network - empty.
@ MODEPERSONPLAN
@ MODEADDITIONAL
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:276
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:267
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define WRITE_GLDEBUG(msg)
Definition: MsgHandler.h:277
std::set< NBEdge * > EdgeSet
container for unique edges
Definition: NBCont.h:50
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:42
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
TrafficLightType
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_TRACTION_SUBSTATION
A traction substation.
@ SUMO_TAG_REROUTER
A rerouter.
@ GNE_TAG_MULTI_LANE_AREA_DETECTOR
an e2 detector over multiple lanes (placed here due create Additional Frame)
@ SUMO_TAG_ROUTEPROBE
a routeprobe detector
@ SUMO_TAG_TAZ
a traffic assignment zone
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_VTYPE
description of a vehicle/person/container type
@ SUMO_TAG_ACCESS
An access point for a train stop.
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_POI
begin/end of the description of a Point of interest
@ SUMO_TAG_OVERHEAD_WIRE_CLAMP
An overhead wire clamp (connection of wires in opposite directions)
@ GNE_TAG_POIGEO
Point of interest over view with GEO attributes.
@ SUMO_TAG_FLOW
a flow definitio nusing a from-to edges instead of a route (used by router)
@ SUMO_TAG_CONNECTION
connectio between two lanes
@ SUMO_TAG_PARKING_AREA
A parking area.
@ GNE_TAG_CALIBRATOR_LANE
A calibrator placed over lane.
@ SUMO_TAG_PARKING_SPACE
A parking space for a single vehicle within a parking area.
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ SUMO_TAG_CROSSING
crossing between edges for pedestrians
@ SUMO_TAG_ROUTE
begin/end of the description of a route
@ SUMO_TAG_POLY
begin/end of the description of a polygon
@ SUMO_TAG_OVERHEAD_WIRE_SECTION
An overhead wire section.
@ SUMO_TAG_TRAIN_STOP
A train stop (alias for bus stop)
@ SUMO_TAG_VTYPE_DISTRIBUTION
distribution of a vehicle type
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_INSTANT_INDUCTION_LOOP
An instantenous induction loop.
@ GNE_TAG_POILANE
Point of interest over Lane.
@ SUMO_TAG_PERSON
@ SUMO_TAG_TYPE
type (edge)
@ SUMO_TAG_VAPORIZER
vaporizer of vehicles
@ SUMO_TAG_LANE_AREA_DETECTOR
alternative tag for e2 detector
@ GNE_TAG_ROUTE_EMBEDDED
embedded route (used in NETEDIT)
@ SUMO_TAG_INDUCTION_LOOP
alternative tag for e1 detector
@ SUMO_TAG_CALIBRATOR
A calibrator placed over edge.
@ SUMO_TAG_ENTRY_EXIT_DETECTOR
alternative tag for e3 detector
@ SUMO_TAG_VSS
A variable speed sign.
@ GNE_TAG_STOPPERSON_EDGE
@ SUMO_TAG_PERSONFLOW
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_TAG_EDGE
begin/end of the description of an edge
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge's lateral offset shal...
@ STRAIGHT
The link is a straight direction.
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_LANE
@ GNE_ATTR_OPPOSITE
neighboring lane, simplified lane attr instead of child element
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_ARRIVALPOS
@ GNE_ATTR_SELECTED
element is selected
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_NUMLANES
@ SUMO_ATTR_LANES
@ GNE_ATTR_DEFAULT_VTYPE
Flag to check if VType is a default VType.
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_TLTYPE
node: the type of traffic light
@ SUMO_ATTR_ENDOFFSET
@ GNE_ATTR_SHAPE_END
last coordinate of edge shape
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_ID
@ GNE_ATTR_DEFAULT_VTYPE_MODIFIED
Flag to check if a default VType was modified.
@ GNE_ATTR_SHAPE_START
first coordinate of edge shape
@ SUMO_ATTR_WIDTH
@ SUMO_ATTR_POSITION
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:71
T MAX2(T a, T b)
Definition: StdDefs.h:77
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:78
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:130
void reset()
Resets the boundary.
Definition: Boundary.cpp:66
double getHeight() const
Returns the height of the boundary (y-axis)
Definition: Boundary.cpp:160
double getWidth() const
Returns the width of the boudary (x-axis)
Definition: Boundary.cpp:154
An Element which don't belong to GNENet but has influence in the simulation.
Definition: GNEAdditional.h:48
The main window of the Netedit.
void enableSaveAdditionalsMenu()
enable save additionals
void setStatusBarText(const std::string &statusBarText)
set text of the statusBar
void disableSaveDemandElementsMenu()
disable save demand elements
void enableSaveDataElementsMenu()
enable save data elements
void disableSaveAdditionalsMenu()
disable save additionals
void enableSaveTLSProgramsMenu()
enable save TLS Programs
void disableSaveDataElementsMenu()
disable save data elements
void enableSaveDemandElementsMenu()
enable save demand elements
const std::string getID() const
get ID (all Attribute Carriers have one)
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
const std::string & getTagStr() const
get tag assigned to this object in string format
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
static std::string parseIDs(const std::vector< T > &ACs)
parses a list of specific Attribute Carriers into a string of IDs
virtual void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)=0
virtual std::string getAttribute(SumoXMLAttr key) const =0
virtual GUIGlObject * getGUIGlObject()=0
bool isList() const
return true if atribute is a list
the function-object for an editing operation (abstract base)
the function-object for an editing operation (abstract base)
Definition: GNEChange.h:60
NBConnection getNBConnection() const
get NBConnection
GNEEdge * getEdgeFrom() const
get the name of the edge the vehicles leave
NBEdge::Connection & getNBEdgeConnection() const
get Edge::Connection
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
Definition: GNECrossing.h:42
GNEJunction * getParentJunction() const
get parent Junction
NBNode::Crossing * getNBCrossing() const
get referente to NBode::Crossing
An Element which don't belong to GNENet but has influence in the simulation.
GNEDataSet * getDataSetParent() const
Returns a pointer to GNEDataSet parent.
const std::vector< GNEGenericData * > & getGenericDataChildren() const
get generic data children
const std::map< const double, GNEDataInterval * > & getDataIntervalChildren() const
get data interval children
Definition: GNEDataSet.cpp:292
An Element which don't belong to GNENet but has influence in the simulation.
GNEDemandElement * getNextChildDemandElement(const GNEDemandElement *demandElement) const
get next child demand element to the given demand element
virtual std::string getAttribute(SumoXMLAttr key) const =0
GNEDemandElement * getPreviousChildDemandElement(const GNEDemandElement *demandElement) const
get previous child demand element to the given demand element
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:53
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition: GNEEdge.cpp:481
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:839
std::vector< GNEEdge * > getOppositeEdges() const
get opposite edges
Definition: GNEEdge.cpp:404
GNEJunction * getFromJunction() const
get from Junction (only used to increase readability)
Definition: GNEEdge.h:77
bool wasSplit()
whether this edge was created from a split
Definition: GNEEdge.cpp:851
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEEdge.cpp:857
GNEJunction * getToJunction() const
get from Junction (only used to increase readability)
Definition: GNEEdge.h:82
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNEEdge.cpp:957
Dialog for edit rerouters.
Dialog for edit rerouters.
An Element which don't belong to GNENet but has influence in the simulation.
GNEDataInterval * getDataIntervalParent() const
get data interval parent
void addChildElement(T *element)
add child element
const std::vector< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
const std::vector< GNEAdditional * > & getParentAdditionals() const
get parent additionals
const std::vector< GNEAdditional * > & getChildAdditionals() const
return child additionals
const std::vector< GNEGenericData * > & getChildGenericDatas() const
return child generic data elements
void clearInspectedAC()
Clear all current inspected ACs.
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
std::string getAttribute(SumoXMLAttr key) const
void replaceIncomingConnections(GNEEdge *which, GNEEdge *by, GNEUndoList *undoList)
replace one edge by another in all tls connections
void markAsModified(GNEUndoList *undoList)
prevent re-guessing connections at this junction
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
void invalidateTLS(GNEUndoList *undoList, const NBConnection &deletedConnection=NBConnection::InvalidConnection, const NBConnection &addedConnection=NBConnection::InvalidConnection)
std::vector< GNEConnection * > getGNEConnections() const
Returns all GNEConnections vinculated with this junction.
Position getPositionInView() const
Returns position of hierarchical element in view.
void removeConnectionsFrom(GNEEdge *edge, GNEUndoList *undoList, bool updateTLS, int lane=-1)
remove all connections from the given edge
bool isValid(SumoXMLAttr key, const std::string &value)
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
void removeEdgeFromCrossings(GNEEdge *edge, GNEUndoList *undoList)
removes the given edge from all pedestrian crossings
NBNode * getNBNode() const
Return net build node.
std::vector< GNEJunction * > getJunctionNeighbours() const
return GNEJunction neighbours
void setLogicValid(bool valid, GNEUndoList *undoList, const std::string &status=FEATURE_GUESSED)
void removeConnectionsTo(GNEEdge *edge, GNEUndoList *undoList, bool updateTLS, int lane=-1)
remove all connections to the given edge
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:46
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:876
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNELane.cpp:988
GNEEdge * getParentEdge() const
get parent edge
Definition: GNELane.cpp:124
struct used for saving all attribute carriers of net, in different formats
Definition: GNENetHelper.h:71
std::vector< GNEEdge * > retrieveEdges(GNEJunction *from, GNEJunction *to) const
get all edges by from and to GNEJunction
const std::map< SumoXMLTag, std::set< GNEGenericData * > > & getGenericDatas() const
get all generic datas
GNEEdgeType * registerEdgeType(GNEEdgeType *edgeType)
registers a edge in GNENet containers
GNELane * retrieveLane(const std::string &id, bool hardFail=true, bool checkVolatileChange=false) const
get lane by id
const std::map< SumoXMLTag, std::set< GNEDemandElement * > > & getDemandElements() const
get demand elements
void clearDemandElements()
clear demand elements
GNEEdge * registerEdge(GNEEdge *edge)
registers an edge with GNENet containers
void remapJunctionAndEdgeIds()
remap junction and edge IDs
void clearAdditionals()
clear additionals
GNEJunction * registerJunction(GNEJunction *junction)
registers a junction in GNENet containers
const std::set< GNEDataSet * > & getDataSets() const
get demand elements
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
const std::map< std::string, GNEEdge * > & getEdges() const
map with the ID and pointer to edges of net
void addDefaultVTypes()
add default VTypes
const std::set< GNEDataInterval * > & getDataIntervals() const
get all data intervals of network
std::vector< GNEJunction * > getSelectedJunctions() const
return selected junctions
const std::map< SumoXMLTag, std::set< GNEAdditional * > > & getAdditionals() const
get additionals
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
const std::map< std::string, GNEJunction * > & getJunctions() const
get junctions
const std::map< std::string, GNEEdgeType * > & getEdgeTypes() const
map with the ID and pointer to edgeTypes of net
GNECrossing * retrieveCrossing(GNEAttributeCarrier *AC, bool hardFail=true) const
get Crossing by AC
void clearJunctions()
clear junctions
GNEConnection * retrieveConnection(const std::string &id, bool hardFail=true) const
get Connection by id
class for GNEChange_ReplaceEdgeInTLS
Definition: GNENetHelper.h:697
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:42
void clearAdditionalElements(GNEUndoList *undoList)
clear additionals
Definition: GNENet.cpp:1941
void removeSolitaryJunctions(GNEUndoList *undoList)
removes junctions that have no edges
Definition: GNENet.cpp:1589
void deleteEdge(GNEEdge *edge, GNEUndoList *undoList, bool recomputeConnections)
removes edge
Definition: GNENet.cpp:420
void saveJoined(OptionsCont &oc, const std::string &filename)
save log of joined junctions (and nothing else)
Definition: GNENet.cpp:1222
bool joinSelectedJunctions(GNEUndoList *undoList)
join selected junctions
Definition: GNENet.cpp:1400
double getDataSetIntervalMaximumEnd() const
get maximum interval
Definition: GNENet.cpp:2201
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GNENet.cpp:194
void saveDemandElements(const std::string &filename)
save demand element elements of the network
Definition: GNENet.cpp:2096
void deleteLane(GNELane *lane, GNEUndoList *undoList, bool recomputeConnections)
removes lane
Definition: GNENet.cpp:556
bool writeRouteProbeComment(OutputDevice &device) const
write routeProbe comment
Definition: GNENet.cpp:2445
static const double Z_INITIALIZED
marker for whether the z-boundary is initialized
Definition: GNENet.h:626
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:611
SUMORTree & getGrid()
Returns the RTree used for visualisation speed-up.
Definition: GNENet.cpp:151
GNEViewNet * myViewNet
The net to be notified of about changes.
Definition: GNENet.h:514
void deleteAdditional(GNEAdditional *additional, GNEUndoList *undoList)
remove additional
Definition: GNENet.cpp:629
bool myDataElementsSaved
Flag to check if data elements has to be saved.
Definition: GNENet.h:550
void disableUpdateGeometry()
disable update geometry of elements after inserting or removing an element in net
Definition: GNENet.cpp:2605
void saveTLSPrograms(const std::string &filename)
save TLS Programs elements of the network
Definition: GNENet.cpp:2550
NBNetBuilder * getNetBuilder() const
get net builder
Definition: GNENet.cpp:1394
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1245
void reverseEdge(GNEEdge *edge, GNEUndoList *undoList)
reverse edge
Definition: GNENet.cpp:994
bool writeTAZComment(OutputDevice &device) const
write TAZ comment
Definition: GNENet.cpp:2520
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1257
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:1993
bool restrictLane(SUMOVehicleClass vclass, GNELane *lane, GNEUndoList *undoList)
transform lane to restricted lane
Definition: GNENet.cpp:752
bool isNetSaved() const
return if net has to be saved
Definition: GNENet.cpp:1185
bool myNetSaved
Flag to check if net has to be saved.
Definition: GNENet.h:538
bool myTLSProgramsSaved
Flag to check if shapes has to be saved.
Definition: GNENet.h:544
void enableUpdateData()
Definition: GNENet.cpp:2617
void savePlain(OptionsCont &oc, const std::string &prefix)
save plain xml representation of the network (and nothing else)
Definition: GNENet.cpp:1214
void requireSaveNet(bool value)
inform that net has to be saved
Definition: GNENet.cpp:1179
GNEJunction * splitEdge(GNEEdge *edge, const Position &pos, GNEUndoList *undoList, GNEJunction *newJunction=0)
split edge at position by inserting a new junction
Definition: GNENet.cpp:854
void setViewNet(GNEViewNet *viewNet)
Set the net to be notified of network changes.
Definition: GNENet.cpp:1230
bool writeCalibratorComment(OutputDevice &device) const
write calibrator comment
Definition: GNENet.cpp:2455
bool myNeedRecompute
whether the net needs recomputation
Definition: GNENet.h:535
void saveAdditionalsConfirmed(const std::string &filename)
save additionals after confirming invalid objects
Definition: GNENet.cpp:2218
void deleteDemandElement(GNEDemandElement *demandElement, GNEUndoList *undoList)
remove demand element
Definition: GNENet.cpp:650
void duplicateLane(GNELane *lane, GNEUndoList *undoList, bool recomputeConnections)
duplicates lane
Definition: GNENet.cpp:736
const Boundary & getZBoundary() const
Returns the Z boundary (stored in the x() coordinate) values of 0 do not affect the boundary.
Definition: GNENet.cpp:206
const Boundary & getBoundary() const
returns the bounder of the network
Definition: GNENet.cpp:144
void saveEdgeTypes(const std::string &filename)
save edgeTypes elements of the network
Definition: GNENet.cpp:2571
void deleteNetworkElement(GNENetworkElement *networkElement, GNEUndoList *undoList)
delete network element
Definition: GNENet.cpp:334
void computeAndUpdate(OptionsCont &oc, bool volatileOptions)
recompute the network and update lane geometries
Definition: GNENet.cpp:2697
SUMORTree myGrid
the rtree which contains all GUIGlObjects (so named for historical reasons)
Definition: GNENet.h:511
void writeVTypes(OutputDevice &device, const bool additionalFile) const
write vTypes sorted by ID
Definition: GNENet.cpp:2365
void clearDataElements(GNEUndoList *undoList)
clear data elements
Definition: GNENet.cpp:1967
void deleteDataInterval(GNEDataInterval *dataInterval, GNEUndoList *undoList)
remove data interval
Definition: GNENet.cpp:693
void deleteConnection(GNEConnection *connection, GNEUndoList *undoList)
remove connection
Definition: GNENet.cpp:596
void clearDemandElements(GNEUndoList *undoList)
clear demand elements
Definition: GNENet.cpp:1954
void adjustPersonPlans(GNEUndoList *undoList)
adjust person plans
Definition: GNENet.cpp:1696
void requireSaveAdditionals(bool value)
inform that additionals has to be saved
Definition: GNENet.cpp:2017
void writeRoutes(OutputDevice &device, const bool additionalFile) const
write route sorted by ID
Definition: GNENet.cpp:2350
void cleanInvalidDemandElements(GNEUndoList *undoList)
clean invalid demand elements
Definition: GNENet.cpp:1741
bool myUpdateDataEnabled
Flag to enable or disable update data elements after inserting or removing element in net.
Definition: GNENet.h:556
void cleanUnusedRoutes(GNEUndoList *undoList)
clean unused routes
Definition: GNENet.cpp:1606
NBNetBuilder * myNetBuilder
The internal netbuilder.
Definition: GNENet.h:517
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition: GNENet.cpp:2011
void computeJunction(GNEJunction *junction)
trigger recomputation of junction shape and logic param[in] window The window to inform about delay
Definition: GNENet.cpp:1358
void resetJunctionConnections(GNEJunction *junction, GNEUndoList *undoList)
reset junction's connections
Definition: GNENet.cpp:1930
void replaceIncomingEdge(GNEEdge *which, GNEEdge *by, GNEUndoList *undoList)
replaces edge
Definition: GNENet.cpp:499
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNENet.cpp:182
void deleteGenericData(GNEGenericData *genericData, GNEUndoList *undoList)
remove generic data
Definition: GNENet.cpp:706
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:132
void computeNetwork(GNEApplicationWindow *window, bool force=false, bool volatileOptions=false, std::string additionalPath="", std::string demandPath="", std::string dataPath="")
trigger full netbuild computation param[in] window The window to inform about delay param[in] force W...
Definition: GNENet.cpp:1269
GNEEdge * addReversedEdge(GNEEdge *edge, const bool disconnected, GNEUndoList *undoList)
add reversed edge
Definition: GNENet.cpp:1007
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition: GNENet.cpp:1978
bool myUpdateGeometryEnabled
Flag to enable or disable update geometry of elements after inserting or removing element in net.
Definition: GNENet.h:553
bool isAdditionalsSaved() const
check if additionals are saved
Definition: GNENet.cpp:2077
void initJunctionsAndEdges()
Init Junctions and edges.
Definition: GNENet.cpp:2643
bool writeWireComment(OutputDevice &device) const
write Wire comment
Definition: GNENet.cpp:2530
void splitEdgesBidi(GNEEdge *edge, GNEEdge *oppositeEdge, const Position &pos, GNEUndoList *undoList)
split all edges at position by inserting one new junction
Definition: GNENet.cpp:971
void requireSaveTLSPrograms()
inform that TLS Programs has to be saved
Definition: GNENet.cpp:2540
unsigned int myEdgeIDCounter
Definition: GNENet.h:528
void expandBoundary(const Boundary &newBoundary)
expand boundary
Definition: GNENet.cpp:200
void disableUpdateData()
disable update data elements after inserting or removing an element in net
Definition: GNENet.cpp:2628
bool removeRestrictedLane(SUMOVehicleClass vclass, GNEEdge *edge, GNEUndoList *undoList)
remove restricted lane
Definition: GNENet.cpp:840
~GNENet()
Destructor.
Definition: GNENet.cpp:120
void mergeJunctions(GNEJunction *moved, GNEJunction *target, GNEUndoList *undoList)
merge the given junctions edges between the given junctions will be deleted
Definition: GNENet.cpp:1042
GNEEdge * createEdge(GNEJunction *src, GNEJunction *dest, GNEEdge *edgeTemplate, GNEUndoList *undoList, const std::string &suggestedName="", bool wasSplit=false, bool allowDuplicateGeom=false, bool recomputeConnections=true)
creates a new edge (unless an edge with the same geometry already exists)
Definition: GNENet.cpp:237
std::set< std::string > myExplicitTurnarounds
list of edge ids for which turn-arounds must be added explicitly
Definition: GNENet.h:532
const std::map< std::string, int > & getEdgesAndNumberOfLanes() const
et edges and number of lanes
Definition: GNENet.cpp:156
bool myAdditionalsSaved
Flag to check if additionals has to be saved.
Definition: GNENet.h:541
bool writeStoppingPlaceComment(OutputDevice &device) const
write stoppingPlace comment
Definition: GNENet.cpp:2467
void addZValueInBoundary(const double z)
add Z in net boundary
Definition: GNENet.cpp:212
static const std::map< SumoXMLAttr, std::string > EMPTY_HEADER
variable used for write headers in additional, demand and data elements
Definition: GNENet.h:629
bool isUpdateGeometryEnabled() const
check if update geometry after inserting or removing has to be updated
Definition: GNENet.cpp:2611
bool addRestrictedLane(SUMOVehicleClass vclass, GNEEdge *edge, int index, GNEUndoList *undoList)
add restricted lane to edge
Definition: GNENet.cpp:787
bool checkJunctionPosition(const Position &pos)
return true if there are already a Junction in the given position, false in other case
Definition: GNENet.cpp:1167
bool addGreenVergeLane(GNEEdge *edge, int index, GNEUndoList *undoList)
add restricted lane to edge
Definition: GNENet.cpp:823
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
Definition: GNENet.cpp:172
bool isNetRecomputed() const
check if net require recomputing
Definition: GNENet.cpp:1382
void writeAdditionalByType(OutputDevice &device, const std::vector< SumoXMLTag > tags) const
write additional element by type and sorted by ID
Definition: GNENet.cpp:2320
bool isUpdateDataEnabled() const
check if update data after inserting or removing has to be updated
Definition: GNENet.cpp:2634
bool writeShapesComment(OutputDevice &device) const
write shape comment
Definition: GNENet.cpp:2508
void deleteDataSet(GNEDataSet *dataSet, GNEUndoList *undoList)
remove data set
Definition: GNENet.cpp:680
static void replaceInListAttribute(GNEAttributeCarrier *ac, SumoXMLAttr key, const std::string &which, const std::string &by, GNEUndoList *undoList)
replace in list attribute
Definition: GNENet.cpp:2802
bool cleanInvalidCrossings(GNEUndoList *undoList)
clear invalid crossings
Definition: GNENet.cpp:1537
void splitJunction(GNEJunction *junction, bool reconnect, GNEUndoList *undoList)
replace the selected junction by a list of junctions for each unique edge endpoint
Definition: GNENet.cpp:1834
void selectRoundabout(GNEJunction *junction, GNEUndoList *undoList)
select all roundabout edges and junctions for the current roundabout
Definition: GNENet.cpp:1075
void joinRoutes(GNEUndoList *undoList)
join routes
Definition: GNENet.cpp:1632
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNENet.cpp:162
bool writeRouteComment(OutputDevice &device, const bool additionalFile) const
write route comment
Definition: GNENet.cpp:2430
bool writeVTypeComment(OutputDevice &device, const bool additionalFile) const
write vType comment
Definition: GNENet.cpp:2398
void replaceJunctionByGeometry(GNEJunction *junction, GNEUndoList *undoList)
replace the selected junction by geometry node(s) and merge the edges
Definition: GNENet.cpp:1780
void requireSaveDemandElements(bool value)
inform that demand elements has to be saved
Definition: GNENet.cpp:2083
GNEPathManager * myPathManager
Path manager.
Definition: GNENet.h:523
bool writeDetectorComment(OutputDevice &device) const
write detector comment
Definition: GNENet.cpp:2479
GNEPathManager * getPathManager()
get path manager
Definition: GNENet.cpp:138
void createRoundabout(GNEJunction *junction, GNEUndoList *undoList)
transform the given junction into a roundabout
Definition: GNENet.cpp:1094
void writeDemandByType(OutputDevice &device, SumoXMLTag tag) const
write demand element by type and sorted by ID
Definition: GNENet.cpp:2338
void requireSaveDataElements(bool value)
inform that data sets has to be saved
Definition: GNENet.cpp:2150
void requireRecompute()
inform the net about the need for recomputation
Definition: GNENet.cpp:1376
GNEJunction * createJunction(const Position &pos, GNEUndoList *undoList)
creates a new junction
Definition: GNENet.cpp:221
unsigned int myJunctionIDCounter
Definition: GNENet.h:527
bool writeOtherAdditionalsComment(OutputDevice &device) const
write other additional comment
Definition: GNENet.cpp:2491
std::map< std::string, int > myEdgesAndNumberOfLanes
map with the Edges and their number of lanes
Definition: GNENet.h:623
double getExaggeration(const GUIVisualizationSettings &s) const
return exaggeration associated with this GLObject
Definition: GNENet.cpp:188
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition: GNENet.cpp:2005
void saveDataElements(const std::string &filename)
save data set elements of the network
Definition: GNENet.cpp:2163
void initGNEConnections()
initialize GNEConnections
Definition: GNENet.cpp:2684
void saveAdditionals(const std::string &filename)
save additional elements of the network
Definition: GNENet.cpp:2030
void deleteJunction(GNEJunction *junction, GNEUndoList *undoList)
removes junction and all incident edges
Definition: GNENet.cpp:375
NBEdgeCont & getEdgeCont()
returns the NBEdgeCont of the underlying netbuilder
Definition: GNENet.cpp:1999
void saveNetwork(OptionsCont &oc)
save the network
Definition: GNENet.cpp:1191
GNENetHelper::AttributeCarriers * myAttributeCarriers
AttributeCarriers of net.
Definition: GNENet.h:520
void computeDataElements(GNEApplicationWindow *window)
compute data elements param[in] window The window to inform about delay
Definition: GNENet.cpp:1345
FXApp * getApp()
get pointer to the main App
Definition: GNENet.cpp:1388
bool isDataElementsSaved() const
check if data sets are saved
Definition: GNENet.cpp:2178
void saveDataElementsConfirmed(const std::string &filename)
save data elements after confirming invalid objects
Definition: GNENet.cpp:2307
bool myDemandElementsSaved
Flag to check if demand elements has to be saved.
Definition: GNENet.h:547
int getNumberOfTLSPrograms() const
get number of TLS Programs
Definition: GNENet.cpp:2565
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1987
void saveDemandElementsConfirmed(const std::string &filename)
save demand elements after confirming invalid objects
Definition: GNENet.cpp:2270
GNENet(NBNetBuilder *netBuilder)
Constructor.
Definition: GNENet.cpp:87
void enableUpdateGeometry()
Definition: GNENet.cpp:2599
void clearJunctionConnections(GNEJunction *junction, GNEUndoList *undoList)
clear junction's connections
Definition: GNENet.cpp:1918
Boundary myZBoundary
the z boundary (stored in the x-coordinate), values of 0 are ignored
Definition: GNENet.h:620
double getDataSetIntervalMinimumBegin() const
get minimum interval
Definition: GNENet.cpp:2184
void computeDemandElements(GNEApplicationWindow *window)
compute demand elements param[in] window The window to inform about delay
Definition: GNENet.cpp:1325
bool isDemandElementsSaved() const
check if demand elements are saved
Definition: GNENet.cpp:2144
void updatePathCalculator()
update path calculator (called when SuperModes Demand or Data is selected)
bool isPathCalculatorUpdated() const
check if pathCalculator is updated
PathCalculator * getPathCalculator()
obtain instance of PathCalculator
void invalidateJunctionPath(const GNEJunction *junction)
invalidate junction path
void invalidateLanePath(const GNELane *lane)
invalidate lane path
void clearDemandPaths()
clear demand paths
bool isShapeElement() const
return true if tag correspond to a shape
const GNEAttributeProperties & getAttributeProperties(SumoXMLAttr attr) const
get attribute (throw error if doesn't exist)
bool isPlacedInRTree() const
return true if Tag correspond to an element that has to be placed in RTREE
bool isStoppingPlace() const
return true if tag correspond to a detector (Only used to group all stoppingPlaces in the output XML)
bool isCalibrator() const
return true if tag correspond to a calibrator (Only used to group all detectors in the XML)
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
bool isDetector() const
return true if tag correspond to a shape (Only used to group all detectors in the XML)
bool isAdditionalPureElement() const
return true if tag correspond to a pure additional element
bool hasAttribute(SumoXMLAttr attr) const
check if current TagProperties owns the attribute "attr"
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
void begin(GUIIcon icon, const std::string &description)
Begin undo command sub-group with current supermode. This begins a new group of commands that are tre...
void add(GNEChange *command, bool doit=false, bool merge=true)
Add new command, executing it if desired. The new command will be merged with the previous command if...
void changeAttribute(GNEChange_Attribute *change)
special method for change attributes, avoid empty changes, always execute
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:632
GNEViewParent * getViewParent() const
get the net object
GNEUndoList * getUndoList() const
get the undoList object
bool isAttributeCarrierInspected(const GNEAttributeCarrier *AC) const
check if attribute carrier is being inspected
void updateViewNet() const
Mark the entire GNEViewNet to be repainted later.
Definition: GNEViewNet.cpp:414
GNEApplicationWindow * getGNEAppWindows() const
get GNE Application Windows
GNEInspectorFrame * getInspectorFrame() const
get frame for inspect elements
The popup menu of a globject.
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
Definition: GUIGlObject.h:141
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, const GUIMainWindow &app) const
Builds an entry which allows to copy the cursor position if geo projection is used,...
void setNetObject(GUIGlObject *object)
Sets the given object as the "network" object.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
A window containing a gl-object's parameter.
void closeBuilding(const Parameterised *p=0)
Closes the building of the table.
void destroyPopup()
destroys the popup
Stores the information about how to visualize structures.
bool parse()
parse
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
Definition: GeomHelper.cpp:179
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:59
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:274
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:721
The representation of a single edge during network building.
Definition: NBEdge.h:92
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:4137
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:1043
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition: NBEdge.h:608
void reinitNodes(NBNode *from, NBNode *to)
Resets nodes but keeps all other values the same (used when joining)
Definition: NBEdge.cpp:471
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:552
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition: NBEdge.h:366
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1426
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:787
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:618
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:526
void resetNodeBorder(const NBNode *node)
Definition: NBEdge.cpp:751
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition: NBEdge.cpp:3975
std::string getLaneID(int lane) const
get lane ID
Definition: NBEdge.cpp:3776
bool hasDefaultGeometryEndpointAtNode(const NBNode *node) const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
Definition: NBEdge.cpp:634
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:357
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:360
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:615
Instance responsible for building networks.
Definition: NBNetBuilder.h:107
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:144
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:139
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:149
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:154
void compute(OptionsCont &oc, const std::set< std::string > &explicitTurnarounds=std::set< std::string >(), bool mayAddOrRemove=true)
Performs the network building steps.
A definition of a pedestrian crossing.
Definition: NBNode.h:129
PositionVector customShape
optional customShape for this crossing
Definition: NBNode.h:152
int customTLIndex
the custom traffic light index of this crossing (if controlled)
Definition: NBNode.h:157
int customTLIndex2
Definition: NBNode.h:158
bool priority
whether the pedestrians have priority
Definition: NBNode.h:150
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:136
double width
This crossing's width.
Definition: NBNode.h:142
void registerJoinedCluster(const NodeSet &cluster)
gets all joined clusters (see doc for myClusters2Join)
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:120
std::vector< std::string > getAllNames() const
get all node names
void analyzeCluster(NodeSet cluster, std::string &id, Position &pos, bool &hasTLS, TrafficLightType &type, SumoXMLNodeType &nodeType)
Represents a single node (junction) during network building.
Definition: NBNode.h:66
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:2229
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
Definition: NBNode.h:326
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition: NBNode.h:210
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:258
std::vector< std::pair< Position, std::string > > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
Definition: NBNode.cpp:3792
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
Definition: NBNode.cpp:2411
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:263
const Position & getPosition() const
Definition: NBNode.h:250
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
Definition: NBNode.h:268
void updateSurroundingGeometry()
update geometry of node and surrounding edges
Definition: NBNode.cpp:1067
double getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:280
bool checkIsRemovable() const
check if node is removable
Definition: NBNode.cpp:2328
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:321
static void sortNodesEdges(NBNodeCont &nc, bool useNodeShape=false)
Sorts a node's edges clockwise regarding driving direction.
A container for traffic light definitions and built programs.
bool computeSingleLogic(OptionsCont &oc, NBTrafficLightDefinition *def)
Computes a specific traffic light logic (using by NETEDIT)
void writeEdgeTypes(OutputDevice &into) const
writes all EdgeTypes (and their lanes) as XML
Definition: NBTypeCont.cpp:377
void insertEdgeType(const std::string &id, int numLanes, double maxSpeed, int prio, SVCPermissions permissions, LaneSpreadFunction spreadType, double width, bool oneWayIsDefault, double sidewalkWidth, double bikeLaneWidth, double widthResolution, double maxWidth, double minWidth)
Adds a edgeType into the list.
Definition: NBTypeCont.cpp:204
void clearTypes()
clear types
Definition: NBTypeCont.cpp:174
void insertLaneType(const std::string &edgeTypeID, int index, double maxSpeed, SVCPermissions permissions, double width, const std::set< SumoXMLAttr > &attrs)
Adds a laneType into the list.
Definition: NBTypeCont.cpp:243
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network stored in the given net builder.
Definition: NWFrame.cpp:174
static void writeTrafficLights(OutputDevice &into, const NBTrafficLightLogicCont &tllCont)
writes the traffic light logics to the given device
static void writeJoinedJunctions(const std::string &filename, NBNodeCont &nc)
Writes the joined-juncionts to file.
static void writeNetwork(const OptionsCont &oc, const std::string &prefix, NBNetBuilder &nb)
Writes the network into XML-files (nodes, edges, connections, traffic lights)
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:59
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
void setx(double x)
set position x
Definition: Position.h:70
double x() const
Returns the x-position.
Definition: Position.h:55
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position
Definition: Position.h:262
void sety(double y)
set position y
Definition: Position.h:75
double y() const
Returns the y-position.
Definition: Position.h:60
A list of positions.
void append(const PositionVector &v, double sameThreshold=2.0)
double length() const
Returns the length.
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
std::pair< PositionVector, PositionVector > splitAt(double where, bool use2D=false) const
Returns the two lists made when this list vector is splitted at the given point.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
void push_back_noDoublePos(const Position &p)
insert in back a non double position
PositionVector reverse() const
reverse position vector
A RT-tree for efficient storing of SUMO's GL-objects.
Definition: SUMORTree.h:66
void addAdditionalGLObject(GUIGlObject *o, const double exaggeration=1)
Adds an additional object (detector/shape/trigger) for visualisation.
Definition: SUMORTree.h:124
void removeAdditionalGLObject(GUIGlObject *o, const double exaggeration=1)
Removes an additional object (detector/shape/trigger) from being visualised.
Definition: SUMORTree.h:160
static std::string trim(const std::string s, const std::string &t=" \t\n")
remove leading and trailing whitespace
Definition: json.hpp:4471
bool isCurrentSupermodeDemand() const
@check if current supermode is Demand
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:201
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:143