Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GNENet.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2026 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/****************************************************************************/
28
60#include <netwrite/NWFrame.h>
69
71#include "GNENet.h"
72#include "GNEUndoList.h"
73#include "GNEViewParent.h"
74
75// ===========================================================================
76// FOX callback mapping
77// ===========================================================================
78
79FXIMPLEMENT_ABSTRACT(GNENetHelper::GNEChange_ReplaceEdgeInTLS, GNEChange, nullptr, 0)
80
81// ===========================================================================
82// static members
83// ===========================================================================
84const double GNENet::Z_INITIALIZED = 1;
85const std::map<SumoXMLAttr, std::string> GNENet::EMPTY_HEADER;
86
87
88// ===========================================================================
89// member method definitions
90// ===========================================================================
91#ifdef _MSC_VER
92#pragma warning(push)
93#pragma warning(disable: 4355) // mask warning about "this" in initializers
94#endif
95GNENet::GNENet(GNEApplicationWindow* applicationWindow, NBNetBuilder* netBuilder) :
96 GUIGlObject(GLO_NETWORK, "", nullptr),
97 myApplicationWindow(applicationWindow),
98 myNetBuilder(netBuilder),
99 myAttributeCarriers(new GNENetHelper::AttributeCarriers(this)),
100 myACTemplates(new GNENetHelper::ACTemplate(this)),
101 mySavingStatus(new GNENetHelper::SavingStatus(this)),
102 myNetworkPathManager(new GNEPathManager(this)),
103 myDemandPathManager(new GNEPathManager(this)),
104 myDataPathManager(new GNEPathManager(this)) {
105 // set net in gIDStorage
107 // build templates
109 // init junction and edges
111 // check Z boundary
112 if (myZBoundary.ymin() != Z_INITIALIZED) {
113 myZBoundary.add(0, 0);
114 }
115 // add default vTypes
117}
118#ifdef _MSC_VER
119#pragma warning(pop)
120#endif
121
122
124 // delete path managers
126 delete myDemandPathManager;
127 delete myDataPathManager;
128 // delete attribute carriers
129 delete myAttributeCarriers;
130 delete myACTemplates;
131 // delete saving status
132 delete mySavingStatus;
133 delete myNetBuilder;
134}
135
136
141
142
147
148
153
154
159
160
165
166
169 return myNetBuilder;
170}
171
172
177
178
181 return myACTemplates;
182}
183
184
187 return mySavingStatus;
188}
189
190
195
196
201
202
207
208
209const Boundary&
211 // SUMORTree is also a Boundary
212 return myGrid;
213}
214
215
218 return myGrid;
219}
220
221const std::map<std::string, int>&
225
226
229 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);
230 buildPopupHeader(ret, app);
232 buildPositionCopyEntry(ret, app);
233 if (GeoConvHelper::getFinal().usingGeoProjection()) {
234 GUIDesigns::buildFXMenuCommand(ret, TL("Copy view geo-boundary to clipboard"), nullptr, ret, MID_COPY_VIEW_GEOBOUNDARY);
235 }
236 return ret;
237}
238
239
242 // Nets lanes don't have attributes
244 // close building
245 ret->closeBuilding();
246 return ret;
247}
248
249
250void
252 // draw boundaries
254}
255
256
259 return getBoundary();
260}
261
262
263void
264GNENet::expandBoundary(const Boundary& newBoundary) {
265 myGrid.add(newBoundary);
266}
267
268
269const Boundary&
271 return myZBoundary;
272}
273
274
275void
277 // @todo let Boundary class track z-coordinate natively
278 if (z != 0) {
280 }
281}
282
283
287 // get junction prefix
288 const std::string junctionPrefix = oc.getString("prefix") + oc.getString("node-prefix");
289 // generate new ID
290 while (myAttributeCarriers->getJunctions().count(junctionPrefix + toString(myJunctionIDCounter)) != 0) {
292 }
293 SumoXMLNodeType type = SUMOXMLDefinitions::NodeTypes.hasString(oc.getString("default.junctions.type"))
295 // create new NBNode
296 NBNode* nbn = new NBNode(junctionPrefix + toString(myJunctionIDCounter), pos, type);
297 GNEJunction* junction = new GNEJunction(this, nbn);
298 undoList->add(new GNEChange_Junction(junction, true), true);
299 return junction;
300}
301
302
303GNEEdge*
304GNENet::createEdge(GNEJunction* src, GNEJunction* dest, GNEEdge* edgeTemplate, GNEUndoList* undoList,
305 const std::string& suggestedName, bool wasSplit, bool allowDuplicateGeom, bool recomputeConnections) {
306 // prevent duplicate edge (same geometry)
307 for (const auto& outgoingEdge : src->getNBNode()->getOutgoingEdges()) {
308 if (outgoingEdge->getToNode() == dest->getNBNode() && outgoingEdge->getGeometry().size() == 2) {
309 if (!allowDuplicateGeom) {
310 return nullptr;
311 }
312 }
313 }
314 // check if exist opposite edge
315 const auto oppositeEdges = myAttributeCarriers->retrieveEdges(dest, src);
316 // get edge prefix
317 const std::string edgePrefix = OptionsCont::getOptions().getString("prefix") + OptionsCont::getOptions().getString("edge-prefix");
318 // get edge infix
319 std::string edgeInfix = OptionsCont::getOptions().getString("edge-infix");
320 // declare edge id
321 std::string edgeID;
322 // update id
323 if (oppositeEdges.size() > 0) {
324 // avoid ids with "--..."
325 if ((oppositeEdges.front()->getID().size() > 1) && (oppositeEdges.front()->getID().front() == '-')) {
326 edgeID = oppositeEdges.front()->getID().substr(1);
327 } else {
328 edgeID = "-" + oppositeEdges.front()->getID();
329 }
330 // check if already exist an edge with edgeID
331 if (myAttributeCarriers->getEdges().count(edgeID) > 0) {
332 int counter = 0;
333 // generate new ID using edgeID and counter
334 while (myAttributeCarriers->getEdges().count(edgeID + toString(counter)) > 0) {
335 counter++;
336 }
337 edgeID = edgeID + toString(counter);
338 }
339 } else if ((suggestedName.size() > 0) && (myAttributeCarriers->retrieveEdge(suggestedName, false) == nullptr)) {
340 edgeID = suggestedName;
341 } else if (edgeInfix.size() > 0) {
342 // permit empty infix by setting it to <SPACE>
343 edgeInfix = StringUtils::trim(edgeInfix);
344 // check if exist edge with id <fromNodeID><infix><toNodeID>
345 if (myAttributeCarriers->getEdges().count(src->getID() + edgeInfix + dest->getID()) == 0) {
346 edgeID = src->getID() + edgeInfix + dest->getID();
347 } else {
348 int counter = 0;
349 // generate new ID using edgeInfix and counter
350 while (myAttributeCarriers->getEdges().count(src->getID() + edgeInfix + toString(counter) + dest->getID()) != 0) {
352 }
353 edgeID = src->getID() + edgeInfix + toString(counter) + dest->getID();
354 }
355 } else {
357 }
358 GNEEdge* edge;
359 // check if there is a template edge
360 if (edgeTemplate) {
361 // create NBEdgeTemplate
362 NBEdge* nbe = new NBEdge(edgeID, src->getNBNode(), dest->getNBNode(), edgeTemplate->getNBEdge());
363 edge = new GNEEdge(this, nbe, wasSplit);
364 } else {
365 // default if no template is given
366 const auto& neteditOptions = OptionsCont::getOptions();
367 double defaultSpeed = neteditOptions.getFloat("default.speed");
368 const std::string defaultType = neteditOptions.getString("default.type");
369 const int defaultNrLanes = neteditOptions.getInt("default.lanenumber");
370 const int defaultPriority = neteditOptions.getInt("default.priority");
371 const double defaultWidth = NBEdge::UNSPECIFIED_WIDTH;
372 const double defaultOffset = NBEdge::UNSPECIFIED_OFFSET;
374 // build NBEdge
375 NBEdge* nbe = new NBEdge(edgeID, src->getNBNode(), dest->getNBNode(),
376 defaultType, defaultSpeed, NBEdge::UNSPECIFIED_FRICTION,
377 defaultNrLanes, defaultPriority,
378 defaultWidth, defaultOffset, spread);
379 // create edge
380 edge = new GNEEdge(this, nbe, wasSplit);
381 }
382 // add edge using undo list
383 undoList->begin(edge, TL("create edge"));
384 undoList->add(new GNEChange_Edge(edge, true), true);
385 // recompute connection
386 if (recomputeConnections) {
387 src->setLogicValid(false, undoList);
388 dest->setLogicValid(false, undoList);
389 }
391 undoList->end();
392 return edge;
393}
394
395
396void
398 if (networkElement->getTagProperty()->getTag() == SUMO_TAG_JUNCTION) {
399 // get junction (note: could be already removed if is a child, then hardfail=false)
400 GNEJunction* junction = myAttributeCarriers->retrieveJunction(networkElement->getID(), false);
401 // if exist, remove it
402 if (junction) {
403 deleteJunction(junction, undoList);
404 }
405 } else if (networkElement->getTagProperty()->getTag() == SUMO_TAG_CROSSING) {
406 // get crossing (note: could be already removed if is a child, then hardfail=false)
407 GNECrossing* crossing = myAttributeCarriers->retrieveCrossing(networkElement->getGUIGlObject(), false);
408 // if exist, remove it
409 if (crossing) {
410 deleteCrossing(crossing, undoList);
411 }
412 } else if (networkElement->getTagProperty()->getTag() == SUMO_TAG_EDGE) {
413 // get edge (note: could be already removed if is a child, then hardfail=false)
414 GNEEdge* edge = myAttributeCarriers->retrieveEdge(networkElement->getID(), false);
415 // if exist, remove it
416 if (edge) {
417 deleteEdge(edge, undoList, false);
418 }
419 } else if (networkElement->getTagProperty()->getTag() == SUMO_TAG_LANE) {
420 // get lane (note: could be already removed if is a child, then hardfail=false)
421 GNELane* lane = myAttributeCarriers->retrieveLane(networkElement->getGUIGlObject(), false);
422 // if exist, remove it
423 if (lane) {
424 deleteLane(lane, undoList, false);
425 }
426 } else if (networkElement->getTagProperty()->getTag() == SUMO_TAG_CONNECTION) {
427 // get connection (note: could be already removed if is a child, then hardfail=false)
428 GNEConnection* connection = myAttributeCarriers->retrieveConnection(networkElement->getGUIGlObject(), false);
429 // if exist, remove it
430 if (connection) {
431 deleteConnection(connection, undoList);
432 }
433 }
434}
435
436
437void
439 // we have to delete all incident edges because they cannot exist without that junction
440 // all deletions must be undone/redone together so we start a new command group
441 // @todo if any of those edges are dead-ends should we remove their orphan junctions as well?
442 undoList->begin(GUIIcon::MODEDELETE, TL("delete junction"));
443 // invalidate junction path elements
447 // delete junction child demand elements
448 while (junction->getChildDemandElements().size() > 0) {
449 deleteDemandElement(junction->getChildDemandElements().front(), undoList);
450 }
451 // delete all crossings vinculated with junction
452 while (junction->getGNECrossings().size() > 0) {
453 deleteCrossing(junction->getGNECrossings().front(), undoList);
454 }
455 // find all crossings of neighbour junctions that shares an edge of this junction
456 std::vector<GNECrossing*> crossingsToRemove;
457 std::vector<GNEJunction*> junctionNeighbours = junction->getJunctionNeighbours();
458 for (const auto& junctionNeighbour : junctionNeighbours) {
459 // iterate over crossing of neighbour junction
460 for (const auto& crossing : junctionNeighbour->getGNECrossings()) {
461 // if at least one of the edges of junction to remove belongs to a crossing of the neighbour junction, delete it
462 if (crossing->checkEdgeBelong(junction->getChildEdges())) {
463 crossingsToRemove.push_back(crossing);
464 }
465 }
466 }
467 // delete collected crossings
468 for (const auto& crossing : crossingsToRemove) {
469 deleteCrossing(crossing, undoList);
470 }
471 // deleting edges changes in the underlying EdgeVector so we have to make a copy
472 const EdgeVector incidentEdges = junction->getNBNode()->getEdges();
473 for (const auto& edge : incidentEdges) {
474 deleteEdge(myAttributeCarriers->getEdges().at(edge->getID()), undoList, true);
475 }
476 // remove any traffic lights from the traffic light container (avoids lots of warnings)
478 // delete edge
479 undoList->add(new GNEChange_Junction(junction, false), true);
480 undoList->end();
481}
482
483
484void
485GNENet::deleteEdge(GNEEdge* edge, GNEUndoList* undoList, bool recomputeConnections) {
486 undoList->begin(GUIIcon::MODEDELETE, TL("delete edge"));
487 // iterate over lanes
488 for (const auto& lane : edge->getChildLanes()) {
489 // invalidate lane path elements
493 // delete lane additionals
494 while (lane->getChildAdditionals().size() > 0) {
495 deleteAdditional(lane->getChildAdditionals().front(), undoList);
496 }
497 // delete lane demand elements
498 while (lane->getChildDemandElements().size() > 0) {
499 deleteDemandElement(lane->getChildDemandElements().front(), undoList);
500 }
501 // delete lane generic data elements
502 while (lane->getChildGenericDatas().size() > 0) {
503 deleteGenericData(lane->getChildGenericDatas().front(), undoList);
504 }
505 }
506 // delete edge child additionals
507 while (edge->getChildAdditionals().size() > 0) {
508 deleteAdditional(edge->getChildAdditionals().front(), undoList);
509 }
510 // delete TAZSourceSink children
511 while (edge->getChildTAZSourceSinks().size() > 0) {
512 deleteTAZSourceSink(*edge->getChildTAZSourceSinks().begin(), undoList);
513 }
514 // delete edge child demand elements
515 while (edge->getChildDemandElements().size() > 0) {
516 // special case for embedded routes
517 if (edge->getChildDemandElements().front()->getTagProperty()->getTag() == GNE_TAG_ROUTE_EMBEDDED) {
518 deleteDemandElement(edge->getChildDemandElements().front()->getParentDemandElements().front(), undoList);
519 } else if (edge->getChildDemandElements().front()->getTagProperty()->isPlan()) {
520 const auto planParent = edge->getChildDemandElements().front()->getParentDemandElements().front();
521 // if this is the last person child, remove plan parent (person/container) instead plan element
522 if (planParent->getChildDemandElements().size() == 1) {
523 deleteDemandElement(planParent, undoList);
524 } else {
525 deleteDemandElement(edge->getChildDemandElements().front(), undoList);
526 }
527 } else {
528 deleteDemandElement(edge->getChildDemandElements().front(), undoList);
529 }
530 }
531 // delete edge child generic datas
532 while (edge->getChildGenericDatas().size() > 0) {
533 deleteGenericData(edge->getChildGenericDatas().front(), undoList);
534 }
535 // remove edge from crossings related with this edge
536 edge->getFromJunction()->removeEdgeFromCrossings(edge, undoList);
537 edge->getToJunction()->removeEdgeFromCrossings(edge, undoList);
538 // update affected connections
539 if (recomputeConnections) {
540 edge->getFromJunction()->setLogicValid(false, undoList);
541 edge->getToJunction()->setLogicValid(false, undoList);
542 } else {
543 edge->getFromJunction()->removeConnectionsTo(edge, undoList, true);
544 edge->getToJunction()->removeConnectionsFrom(edge, undoList, true);
545 }
546 // if junction source is a TLS and after deletion will have only an edge, remove TLS
547 if (edge->getFromJunction()->getNBNode()->isTLControlled() && (edge->getFromJunction()->getGNEOutgoingEdges().size() <= 1)) {
549 }
550 // if junction destination is a TLS and after deletion will have only an edge, remove TLS
551 if (edge->getToJunction()->getNBNode()->isTLControlled() && (edge->getToJunction()->getGNEIncomingEdges().size() <= 1)) {
553 }
554 const std::string oppLaneID = edge->getChildLanes().back()->getAttribute(GNE_ATTR_OPPOSITE);
555 if (oppLaneID != "") {
556 GNELane* lane = myAttributeCarriers->retrieveLane(oppLaneID, false);
557 if (lane != nullptr) {
558 lane->setAttribute(GNE_ATTR_OPPOSITE, "", undoList);
559 }
560 }
561 // Delete edge
562 undoList->add(new GNEChange_Edge(edge, false), true);
563 // remove edge requires always a recompute (due geometry and connections)
565 // finish delete edge
566 undoList->end();
567}
568
569
570void
572 undoList->begin(which, TL("replace edge"));
574 // iterate over lane
575 for (const auto& lane : which->getChildLanes()) {
576 // replace in additionals
577 std::vector<GNEAdditional*> copyOfLaneAdditionals = lane->getChildAdditionals();
578 for (const auto& additional : copyOfLaneAdditionals) {
579 GNEChange_Attribute::changeAttribute(additional, SUMO_ATTR_LANE, by->getNBEdge()->getLaneID(lane->getIndex()), undoList);
580 if (additional->hasAttribute(SUMO_ATTR_STARTPOS)) {
582 toString(StringUtils::toDouble(additional->getAttribute(SUMO_ATTR_STARTPOS)) + which->getNBEdge()->getFinalLength()),
583 undoList);
584 }
585 if (additional->hasAttribute(SUMO_ATTR_ENDPOS)) {
587 toString(StringUtils::toDouble(additional->getAttribute(SUMO_ATTR_ENDPOS)) + which->getNBEdge()->getFinalLength()),
588 undoList);
589 }
590 }
591 // replace in demand elements
592 std::vector<GNEDemandElement*> copyOfLaneDemandElements = lane->getChildDemandElements();
593 for (const auto& demandElement : copyOfLaneDemandElements) {
594 GNEChange_Attribute::changeAttribute(demandElement, SUMO_ATTR_LANE, by->getNBEdge()->getLaneID(lane->getIndex()), undoList);
595 }
596 // replace in generic datas
597 std::vector<GNEGenericData*> copyOfLaneGenericDatas = lane->getChildGenericDatas();
598 for (const auto& demandElement : copyOfLaneGenericDatas) {
599 GNEChange_Attribute::changeAttribute(demandElement, SUMO_ATTR_LANE, by->getNBEdge()->getLaneID(lane->getIndex()), undoList);
600 }
601 }
602 // replace in edge additionals children
603 std::vector<GNEAdditional*> addElements = which->getChildAdditionals();
604 for (GNEAdditional* add : addElements) {
605 if (add->hasAttribute(SUMO_ATTR_EDGE)) {
607 }
608 }
609 // replace in edge demand elements children
610 const std::vector<GNEDemandElement*> demandElements = which->getChildDemandElements();
611 for (GNEDemandElement* demandElement : demandElements) {
612 if (demandElement->hasAttribute(SUMO_ATTR_EDGE)) {
613 GNEChange_Attribute::changeAttribute(demandElement, SUMO_ATTR_EDGE, by->getID(), undoList);
614 }
615 if (demandElement->hasAttribute(SUMO_ATTR_EDGES)) {
616 replaceInListAttribute(demandElement, SUMO_ATTR_EDGES, which->getID(), by->getID(), undoList);
617 }
618 if (demandElement->hasAttribute(SUMO_ATTR_VIA)) {
619 replaceInListAttribute(demandElement, SUMO_ATTR_VIA, which->getID(), by->getID(), undoList);
620 }
621 if (demandElement->hasAttribute(SUMO_ATTR_FROM) && demandElement->getAttribute(SUMO_ATTR_FROM) == which->getID()) {
622 GNEChange_Attribute::changeAttribute(demandElement, SUMO_ATTR_FROM, by->getID(), undoList);
623 }
624 if (demandElement->hasAttribute(SUMO_ATTR_TO) && demandElement->getAttribute(SUMO_ATTR_TO) == which->getID()) {
625 GNEChange_Attribute::changeAttribute(demandElement, SUMO_ATTR_TO, by->getID(), undoList);
626 }
627 }
628 // replace in data
629 const std::vector<GNEGenericData*> dataElements = which->getChildGenericDatas();
630 for (GNEGenericData* dataElement : dataElements) {
631 if (dataElement->hasAttribute(SUMO_ATTR_EDGE)) {
632 GNEChange_Attribute::changeAttribute(dataElement, SUMO_ATTR_EDGE, by->getID(), undoList);
633 }
634 }
635 // replace in rerouters
636 addElements = which->getParentAdditionals();
637 for (GNEAdditional* add : addElements) {
638 if (add->hasAttribute(SUMO_ATTR_EDGES)) {
639 replaceInListAttribute(add, SUMO_ATTR_EDGES, which->getID(), by->getID(), undoList);
640 }
641 }
642 // replace in crossings
643 for (const auto& crossing : which->getToJunction()->getGNECrossings()) {
644 // if at least one of the edges of junction to remove belongs to a crossing of the source junction, delete it
645 replaceInListAttribute(crossing, SUMO_ATTR_EDGES, which->getID(), by->getID(), undoList);
646 }
647 // fix connections (make a copy because they will be modified
648 std::vector<NBEdge::Connection> NBConnections = which->getNBEdge()->getConnections();
649 for (const auto& NBConnection : NBConnections) {
650 if (NBConnection.toEdge != nullptr) {
651 undoList->add(new GNEChange_Connection(which, NBConnection, false, false), true);
652 undoList->add(new GNEChange_Connection(by, NBConnection, false, true), true);
653 }
654 }
655 undoList->add(new GNENetHelper::GNEChange_ReplaceEdgeInTLS(getTLLogicCont(), which->getNBEdge(), by->getNBEdge()), true);
656 // Delete edge
657 undoList->add(new GNEChange_Edge(which, false), true);
658 // finish replace edge
659 undoList->end();
660}
661
662
663void
664GNENet::deleteLane(GNELane* lane, GNEUndoList* undoList, bool recomputeConnections) {
665 GNEEdge* edge = lane->getParentEdge();
666 if (edge->getNBEdge()->getNumLanes() == 1) {
667 // remove the whole edge instead
668 deleteEdge(edge, undoList, recomputeConnections);
669 } else {
670 undoList->begin(GUIIcon::MODEDELETE, TL("delete lane"));
671 // invalidate lane path elements
675 // delete lane additional children
676 while (lane->getChildAdditionals().size() > 0) {
677 deleteAdditional(lane->getChildAdditionals().front(), undoList);
678 }
679 // delete lane demand element children
680 while (lane->getChildDemandElements().size() > 0) {
681 deleteDemandElement(lane->getChildDemandElements().front(), undoList);
682 }
683 // delete lane generic data children
684 while (lane->getChildGenericDatas().size() > 0) {
685 deleteGenericData(lane->getChildGenericDatas().front(), undoList);
686 }
687 // update affected connections
688 if (recomputeConnections) {
689 edge->getFromJunction()->setLogicValid(false, undoList);
690 edge->getToJunction()->setLogicValid(false, undoList);
691 } else {
692 edge->getFromJunction()->removeConnectionsTo(edge, undoList, true, lane->getIndex());
693 edge->getToJunction()->removeConnectionsFrom(edge, undoList, true, lane->getIndex());
694 }
695 // delete lane
696 const NBEdge::Lane& laneAttrs = edge->getNBEdge()->getLaneStruct(lane->getIndex());
697 undoList->add(new GNEChange_Lane(edge, lane, laneAttrs, false, recomputeConnections), true);
698 // remove lane requires always a recompute (due geometry and connections)
700 undoList->end();
701 }
702}
703
704
705void
707 undoList->begin(GUIIcon::MODEDELETE, TL("delete connection"));
708 // obtain NBConnection to remove
709 NBConnection deleted = connection->getNBConnection();
710 GNEJunction* junctionDestination = connection->getEdgeFrom()->getToJunction();
711 junctionDestination->markAsModified(undoList);
712 undoList->add(new GNEChange_Connection(connection->getEdgeFrom(), connection->getNBEdgeConnection(), connection->isAttributeCarrierSelected(), false), true);
713 junctionDestination->invalidateTLS(undoList, deleted);
714 // remove connection requires always a recompute (due geometry and connections)
716 undoList->end();
717}
718
719
720void
722 undoList->begin(GUIIcon::MODEDELETE, TL("delete crossing"));
723 // remove it using GNEChange_Crossing
724 undoList->add(new GNEChange_Crossing(
725 crossing->getParentJunctions().front(), crossing->getNBCrossing()->edges,
726 crossing->getNBCrossing()->width, crossing->getNBCrossing()->priority,
727 crossing->getNBCrossing()->customTLIndex,
728 crossing->getNBCrossing()->customTLIndex2,
729 crossing->getNBCrossing()->customShape,
730 crossing->isAttributeCarrierSelected(),
731 false), true);
732 // remove crossing requires always a recompute (due geometry and connections)
734 undoList->end();
735}
736
737
738void
740 undoList->begin(GUIIcon::MODEDELETE, TL("delete ") + additional->getTagStr());
741 // remove all demand element children
742 while (additional->getChildDemandElements().size() > 0) {
743 deleteDemandElement(additional->getChildDemandElements().front(), undoList);
744 }
745 // remove all generic data children
746 while (additional->getChildGenericDatas().size() > 0) {
747 deleteGenericData(additional->getChildGenericDatas().front(), undoList);
748 }
749 // remove all additional children
750 while (additional->getChildAdditionals().size() > 0) {
751 deleteAdditional(additional->getChildAdditionals().front(), undoList);
752 }
753 // remove all TAZSourceSinks children
754 while (additional->getChildTAZSourceSinks().size() > 0) {
755 deleteTAZSourceSink(*additional->getChildTAZSourceSinks().begin(), undoList);
756 }
757 // remove additional
758 undoList->add(new GNEChange_Additional(additional, false), true);
759 undoList->end();
760}
761
762
763void
765 undoList->begin(GUIIcon::MODEDELETE, TL("delete ") + TAZSourceSink->getTagStr());
766 // remove additional
767 undoList->add(new GNEChange_TAZSourceSink(TAZSourceSink, false), true);
768 undoList->end();
769}
770
771
772void
774 // check that default VTypes aren't removed
775 if ((demandElement->getTagProperty()->getTag() == SUMO_TAG_VTYPE) && (GNEAttributeCarrier::parse<bool>(demandElement->getAttribute(GNE_ATTR_DEFAULT_VTYPE)))) {
776 throw ProcessError(TL("Trying to delete a default Vehicle Type"));
777 } else {
778 undoList->begin(GUIIcon::MODEDELETE, TL("delete ") + demandElement->getTagStr());
779 // remove all child additional elements of this demandElement calling this function recursively
780 while (demandElement->getChildAdditionals().size() > 0) {
781 deleteAdditional(demandElement->getChildAdditionals().front(), undoList);
782 }
783 // remove all child demand elements of this demandElement calling this function recursively
784 while (demandElement->getChildDemandElements().size() > 0) {
785 deleteDemandElement(demandElement->getChildDemandElements().front(), undoList);
786 }
787 // remove all generic data children of this additional deleteGenericData this function recursively
788 while (demandElement->getChildGenericDatas().size() > 0) {
789 deleteGenericData(demandElement->getChildGenericDatas().front(), undoList);
790 }
791 // remove demandElement
792 undoList->add(new GNEChange_DemandElement(demandElement, false), true);
793 undoList->end();
794 }
795}
796
797
798void
800 undoList->begin(GUIIcon::MODEDELETE, TL("delete ") + dataSet->getTagStr());
801 // make a copy of all generic data children
802 auto copyOfDataIntervalChildren = dataSet->getDataIntervalChildren();
803 // clear all data intervals (this will be delete also the dataSet)
804 for (const auto& dataInterval : copyOfDataIntervalChildren) {
805 deleteDataInterval(dataInterval.second, undoList);
806 }
807 undoList->end();
808}
809
810
811void
813 undoList->begin(GUIIcon::MODEDELETE, TL("delete ") + dataInterval->getTagStr());
814 // make a copy of all generic data children
815 auto copyOfGenericDataChildren = dataInterval->getGenericDataChildren();
816 // clear all generic datas (this will be delete also the data intervals)
817 for (const auto& genericData : copyOfGenericDataChildren) {
818 deleteGenericData(genericData, undoList);
819 }
820 undoList->end();
821}
822
823
824void
826 undoList->begin(GUIIcon::MODEDELETE, TL("delete ") + genericData->getTagStr());
827 // remove all child demand elements of this demandElement calling this function recursively
828 while (genericData->getChildDemandElements().size() > 0) {
829 deleteDemandElement(genericData->getChildDemandElements().front(), undoList);
830 }
831 // remove all generic data children of this additional deleteGenericData this function recursively
832 while (genericData->getChildGenericDatas().size() > 0) {
833 deleteGenericData(genericData->getChildGenericDatas().front(), undoList);
834 }
835 // get pointer to dataInterval and dataSet
836 GNEDataInterval* dataInterval = genericData->getDataIntervalParent();
837 GNEDataSet* dataSet = dataInterval->getDataSetParent();
838 // remove generic data
839 undoList->add(new GNEChange_GenericData(genericData, false), true);
840 // check if data interval is empty
841 if (dataInterval->getGenericDataChildren().empty()) {
842 // remove data interval
843 undoList->add(new GNEChange_DataInterval(genericData->getDataIntervalParent(), false), true);
844 // now check if data set is empty
845 if (dataSet->getDataIntervalChildren().empty()) {
846 // remove data set
847 undoList->add(new GNEChange_DataSet(genericData->getDataIntervalParent()->getDataSetParent(), false), true);
848 }
849 }
850 undoList->end();
851}
852
853
854void
856 undoList->begin(GUIIcon::MODEDELETE, TL("delete ") + meanData->getTagStr());
857 // remove mean data
858 undoList->add(new GNEChange_MeanData(meanData, false), true);
859 undoList->end();
860}
861
862
863void
864GNENet::duplicateLane(GNELane* lane, GNEUndoList* undoList, bool recomputeConnections) {
865 undoList->begin(lane, TL("duplicate lane"));
866 GNEEdge* edge = lane->getParentEdge();
867 const NBEdge::Lane& laneAttrs = edge->getNBEdge()->getLaneStruct(lane->getIndex());
868 if (recomputeConnections) {
869 edge->getFromJunction()->setLogicValid(false, undoList);
870 edge->getToJunction()->setLogicValid(false, undoList);
871 }
872 GNELane* newLane = new GNELane(edge, lane->getIndex());
873 undoList->add(new GNEChange_Lane(edge, newLane, laneAttrs, true, recomputeConnections), true);
875 undoList->end();
876}
877
878
879bool
881 bool addRestriction = true;
882 if (vclass == SVC_PEDESTRIAN) {
883 GNEEdge* edge = lane->getParentEdge();
884 for (const auto& edgeLane : edge->getChildLanes()) {
885 if (edgeLane->isRestricted(SVC_PEDESTRIAN)) {
886 // prevent adding a 2nd sidewalk
887 addRestriction = false;
888 } else {
889 // ensure that the sidewalk is used exclusively
890 const SVCPermissions allOldWithoutPeds = edge->getNBEdge()->getPermissions(edgeLane->getIndex()) & ~SVC_PEDESTRIAN;
891 edgeLane->setAttribute(SUMO_ATTR_ALLOW, getVehicleClassNames(allOldWithoutPeds), undoList);
892 }
893 }
894 }
895 // restrict the lane
896 if (addRestriction) {
897 double width;
898 if (vclass == SVC_PEDESTRIAN) {
899 width = OptionsCont::getOptions().getFloat("default.sidewalk-width");
900 } else if (vclass == SVC_BICYCLE) {
901 width = OptionsCont::getOptions().getFloat("default.bikelane-width");
902 } else {
903 width = OptionsCont::getOptions().getFloat("default.lanewidth");
904 }
905 lane->setAttribute(SUMO_ATTR_ALLOW, toString(vclass), undoList);
906 lane->setAttribute(SUMO_ATTR_WIDTH, toString(width), undoList);
907 if ((vclass & ~SVC_PEDESTRIAN) == 0) {
908 std::vector<GNEConnection*> cons;
910 if (reguess) {
911 // remove all connections and rebuild from scratch
912 cons = lane->getParentEdge()->getGNEConnections();
913 } else {
914 // remove connections that have become invalid (pedestrians are
915 // connected via walkingareas somewhere else)
916 cons = lane->getGNEOutcomingConnections();
917 }
918 for (auto c : cons) {
919 undoList->add(new GNEChange_Connection(lane->getParentEdge(), c->getNBEdgeConnection(), false, false), true);
920 }
921 if (reguess) {
923 }
924 }
925 return true;
926 } else {
927 return false;
928 }
929}
930
931
932bool
933GNENet::addRestrictedLane(SUMOVehicleClass vclass, GNEEdge* edge, int index, GNEUndoList* undoList) {
934 // First check that edge don't have a restricted lane of the given vclass
935 for (const auto& lane : edge->getChildLanes()) {
936 if (lane->isRestricted(vclass)) {
937 return false;
938 }
939 }
940 // check that index is correct (index == size adds to the left of the leftmost lane)
941 const int numLanes = (int)edge->getChildLanes().size();
942 if (index > numLanes) {
943 return false;
944 }
945 if (index < 0) {
946 // for pedestrians and greenVerge, always index 0
947 index = 0;
948 // guess index from vclass
949 if (vclass == SVC_BICYCLE) {
950 // add bikelanes to the left of an existing sidewalk
951 index = edge->getChildLanes()[0]->isRestricted(SVC_PEDESTRIAN) ? 1 : 0;
952 } else if (vclass == SVC_BUS) {
953 // add greenVerge to the left of an existing sidewalk or bikeLane
954 // add busLane to the left of an existing sidewalk, bikeLane or greenVerge
955 index = 0;
956 while (index < numLanes && (edge->getNBEdge()->getPermissions(index) & ~(SVC_PEDESTRIAN | SVC_BICYCLE)) == 0) {
957 index++;
958 }
959 }
960 }
961 // duplicate selected lane
962 duplicateLane(edge->getChildLanes().at(MIN2(index, numLanes - 1)), undoList, true);
963 // transform the created lane
964 return restrictLane(vclass, edge->getChildLanes().at(index), undoList);
965}
966
967
968bool
969GNENet::addGreenVergeLane(GNEEdge* edge, int index, GNEUndoList* undoList) {
970 // check that index is correct (index == size adds to the left of the leftmost lane)
971 const int numLanes = (int)edge->getChildLanes().size();
972 if (index > numLanes) {
973 index = numLanes;
974 }
975 if (index < 0) {
976 index = 0;
977 }
978 // duplicate selected lane
979 duplicateLane(edge->getChildLanes().at(MIN2(index, numLanes - 1)), undoList, true);
980 // transform the created lane
981 return restrictLane(SVC_IGNORING, edge->getChildLanes().at(index), undoList);
982}
983
984
985bool
987 // iterate over lanes of edge
988 for (const auto& lane : edge->getChildLanes()) {
989 if (lane->isRestricted(vclass)) {
990 // Delete lane
991 deleteLane(lane, undoList, true);
992 return true;
993 }
994 }
995 return false;
996}
997
998
999std::pair<GNEJunction*, GNEEdge*>
1000GNENet::splitEdge(GNEEdge* edge, const Position& pos, GNEUndoList* undoList, GNEJunction* newJunction) {
1001 // begin undo list
1002 undoList->begin(edge, TL("split edge"));
1003 // check if we have to create a new edge
1004 if (newJunction == nullptr) {
1005 newJunction = createJunction(pos, undoList);
1006 }
1007 // obtain edge geometry and split position
1008 const PositionVector& oldEdgeGeometry = edge->getNBEdge()->getGeometry();
1009 const double edgeSplitPosition = oldEdgeGeometry.nearest_offset_to_point2D(pos, false);
1010 // obtain lane geometry and split position (needed for adjust additional and demand childs)
1011 const PositionVector& oldLaneGeometry = edge->getChildLanes().front()->getLaneShape();
1012 const double laneSplitPosition = oldLaneGeometry.nearest_offset_to_point2D(pos, false);
1013 // split edge geometry in two new geometries using edgeSplitPosition
1014 std::pair<PositionVector, PositionVector> newGeoms = oldEdgeGeometry.splitAt(edgeSplitPosition);
1015 const double oldLength = oldEdgeGeometry.length();
1016 const double relativeLength1 = oldLength != 0 ? newGeoms.first.length() / oldLength : 1;
1017 const double relativeLength2 = oldLength != 0 ? newGeoms.second.length() / oldLength : 1;
1018 // get shape end
1019 const std::string shapeEnd = edge->getAttribute(GNE_ATTR_SHAPE_END);
1020 // figure out the new name
1021 int posBase = 0;
1022 // set baseName
1023 std::string baseName = edge->getMicrosimID();
1024 if (edge->wasSplit()) {
1025 const std::string::size_type sep_index = baseName.rfind('.');
1026 // edge may have been renamed in between
1027 if (sep_index != std::string::npos) {
1028 std::string posString = baseName.substr(sep_index + 1);
1029 if (GNEAttributeCarrier::canParse<int>(posString.c_str())) {
1030 ;
1031 posBase = GNEAttributeCarrier::parse<int>(posString.c_str());
1032 baseName = baseName.substr(0, sep_index); // includes the .
1033 }
1034 }
1035 }
1036 baseName += '.';
1037 // create a new edge from the new junction to the previous destination
1038 GNEEdge* secondPart = createEdge(newJunction, edge->getToJunction(), edge,
1039 undoList, baseName + toString(posBase + (int)edgeSplitPosition), true, false, false);
1040 // fix connections from the split edge (must happen before changing SUMO_ATTR_TO)
1041 edge->getToJunction()->replaceIncomingConnections(edge, secondPart, undoList);
1042 // remove affected crossings from junction (must happen before changing SUMO_ATTR_TO)
1043 std::vector<NBNode::Crossing> affectedCrossings;
1044 for (GNECrossing* crossing : edge->getToJunction()->getGNECrossings()) {
1045 if (crossing->checkEdgeBelong(edge)) {
1046 NBNode::Crossing nbC = *crossing->getNBCrossing();
1047 undoList->add(new GNEChange_Crossing(edge->getToJunction(), nbC, false), true);
1048 EdgeVector newEdges;
1049 for (NBEdge* nbEdge : nbC.edges) {
1050 if (nbEdge == edge->getNBEdge()) {
1051 newEdges.push_back(secondPart->getNBEdge());
1052 } else {
1053 newEdges.push_back(nbEdge);
1054 }
1055 }
1056 nbC.edges = newEdges;
1057 affectedCrossings.push_back(nbC);
1058 }
1059 }
1060 // modify the edge so that it ends at the new junction (and all incoming connections are preserved
1061 GNEChange_Attribute::changeAttribute(edge, SUMO_ATTR_TO, newJunction->getID(), undoList);
1062 // set first part of geometry
1063 newGeoms.first.pop_back();
1064 newGeoms.first.erase(newGeoms.first.begin());
1065 edge->setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
1066 edge->setAttribute(SUMO_ATTR_SHAPE, toString(newGeoms.first), undoList);
1067 // set second part of geometry
1068 secondPart->setAttribute(GNE_ATTR_SHAPE_END, shapeEnd, undoList);
1069 newGeoms.second.pop_back();
1070 newGeoms.second.erase(newGeoms.second.begin());
1071 secondPart->setAttribute(SUMO_ATTR_SHAPE, toString(newGeoms.second), undoList);
1072 // fix custom length
1073 if (edge->getNBEdge()->hasLoadedLength()) {
1074 // split in proportion to geometry lengths
1075 const double loadedLength = edge->getNBEdge()->getLoadedLength();
1076 edge->setAttribute(SUMO_ATTR_LENGTH, toString(relativeLength1 * loadedLength), undoList);
1077 secondPart->setAttribute(SUMO_ATTR_LENGTH, toString(relativeLength2 * loadedLength), undoList);
1078 }
1079 // reconnect across the split
1080 for (int i = 0; i < (int)edge->getChildLanes().size(); ++i) {
1081 undoList->add(new GNEChange_Connection(edge, NBEdge::Connection(i, secondPart->getNBEdge(), i), false, true), true);
1082 }
1083 // re-add modified crossings
1084 for (const auto& nbC : affectedCrossings) {
1085 undoList->add(new GNEChange_Crossing(secondPart->getToJunction(), nbC, true), true);
1086 }
1087 // Split geometry of all child additional
1088 auto childAdditionals = edge->getChildAdditionals();
1089 for (const auto& additional : childAdditionals) {
1090 additional->splitEdgeGeometry(edgeSplitPosition, edge, secondPart, undoList);
1091 }
1092 // Split geometry of all child lane additional
1093 for (int i = 0; i < (int)edge->getChildLanes().size(); i++) {
1094 for (const auto& additional : edge->getChildLanes().at(i)->getChildAdditionals()) {
1095 additional->splitEdgeGeometry(laneSplitPosition, edge->getChildLanes().at(i), secondPart->getChildLanes().at(i), undoList);
1096 }
1097 }
1098 // Split geometry of all child demand elements
1099 auto childDemandElements = edge->getChildDemandElements();
1100 for (const auto& demandElement : childDemandElements) {
1101 demandElement->splitEdgeGeometry(edgeSplitPosition, edge, secondPart, undoList);
1102 }
1103 // Split geometry of all child lane demand elements
1104 for (int i = 0; i < (int)edge->getChildLanes().size(); i++) {
1105 for (const auto& demandElement : edge->getChildLanes().at(i)->getChildDemandElements()) {
1106 demandElement->splitEdgeGeometry(laneSplitPosition, edge->getChildLanes().at(i), secondPart->getChildLanes().at(i), undoList);
1107 }
1108 }
1109 // finish undo list
1110 undoList->end();
1111 // return new junction
1112 return std::make_pair(newJunction, secondPart);
1113}
1114
1115
1116void
1117GNENet::splitEdgesBidi(GNEEdge* edge, GNEEdge* oppositeEdge, const Position& pos, GNEUndoList* undoList) {
1118 GNEJunction* newJunction = nullptr;
1119 undoList->begin(edge, TL("split edges"));
1120 // split edge and save created junction
1121 auto newStuff = splitEdge(edge, pos, undoList, newJunction);
1122 newJunction = newStuff.first;
1123 // split second edge
1124 splitEdge(oppositeEdge, pos, undoList, newJunction);
1125 if (edge->getChildLanes().back()->getAttribute(GNE_ATTR_OPPOSITE) != "") {
1126 // restore opposite lane information
1127 for (const auto& nbEdge : newJunction->getNBNode()->getEdges()) {
1128 GNEEdge* e = myAttributeCarriers->retrieveEdge(nbEdge->getID());
1129 // store old attribute before it's changed by guess opposite
1130 e->getChildLanes().back()->setAttribute(GNE_ATTR_OPPOSITE, "", undoList);
1131 if (nbEdge->guessOpposite(true)) {
1132 e->getChildLanes().back()->setAttribute(GNE_ATTR_OPPOSITE, nbEdge->getLanes().back().oppositeID, undoList);
1133 }
1134 }
1135 }
1136 undoList->end();
1137}
1138
1139
1140void
1142 undoList->begin(edge, TL("reverse edge"));
1143 auto fromJunction = edge->getFromJunction();
1144 auto ToJunction = edge->getToJunction();
1145 deleteEdge(edge, undoList, false); // still exists. we delete it so we can reuse the name in case of resplit
1146 GNEEdge* reversed = createEdge(ToJunction, fromJunction, edge, undoList, edge->getID(), false, true);
1147 if (reversed) {
1148 reversed->setAttribute(SUMO_ATTR_SHAPE, toString(edge->getNBEdge()->getInnerGeometry().reverse()), undoList);
1151 }
1152 undoList->end();
1153}
1154
1155
1156GNEEdge*
1157GNENet::addReversedEdge(GNEEdge* edge, const bool disconnected, GNEUndoList* undoList) {
1158 GNEEdge* reversed = edge->getReverseEdge();
1159 if (reversed != nullptr) {
1160 return reversed;
1161 }
1162 undoList->begin(edge, TL("add reversed edge"));
1163 if (!disconnected) {
1164 // for rail edges, we assume bi-directional tracks are wanted
1165 reversed = createEdge(edge->getToJunction(), edge->getFromJunction(), edge, undoList, "-" + edge->getID(), false, true);
1166 assert(reversed != 0);
1167 reversed->setAttribute(SUMO_ATTR_SHAPE, toString(edge->getNBEdge()->getInnerGeometry().reverse()), undoList);
1170 } else {
1171 // if the edge is centered it should probably connect somewhere else
1172 // make it easy to move and reconnect it
1173 PositionVector orig = edge->getNBEdge()->getGeometry();
1174 PositionVector origInner = edge->getNBEdge()->getInnerGeometry();
1175 const double tentativeShift = edge->getNBEdge()->getTotalWidth() + 2;
1176 orig.move2side(-tentativeShift);
1177 origInner.move2side(-tentativeShift);
1178 GNEJunction* src = createJunction(orig.back(), undoList);
1179 GNEJunction* dest = createJunction(orig.front(), undoList);
1180 reversed = createEdge(src, dest, edge, undoList, "-" + edge->getID(), false, true);
1181 assert(reversed != 0);
1182 reversed->setAttribute(SUMO_ATTR_SHAPE, toString(origInner.reverse()), undoList);
1183 reversed->setAttribute(SUMO_ATTR_SHAPE, toString(origInner.reverse()), undoList);
1184 // select the new edge and its nodes
1185 reversed->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1186 src->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1187 dest->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1188 }
1189 undoList->end();
1190 return reversed;
1191}
1192
1193
1194void
1196 undoList->begin(moved, TL("merge junctions"));
1197 // deleting edges changes in the underlying EdgeVector so we have to make a copy
1198 const EdgeVector incomingNBEdges = moved->getNBNode()->getIncomingEdges();
1199 for (const auto& incomingNBEdge : incomingNBEdges) {
1200 // delete edges between the merged junctions
1201 GNEEdge* edge = myAttributeCarriers->getEdges().at(incomingNBEdge->getID());
1202 if (edge->getFromJunction() == target) {
1203 deleteEdge(edge, undoList, false);
1204 } else {
1205 edge->setAttribute(SUMO_ATTR_TO, target->getID(), undoList);
1206 }
1207 }
1208 // deleting edges changes in the underlying EdgeVector so we have to make a copy
1209 const EdgeVector outgoingNBEdges = moved->getNBNode()->getOutgoingEdges();
1210 for (const auto& outgoingNBEdge : outgoingNBEdges) {
1211 // delete edges between the merged junctions
1212 GNEEdge* edge = myAttributeCarriers->getEdges().at(outgoingNBEdge->getID());
1213 if (edge->getToJunction() == target) {
1214 deleteEdge(edge, undoList, false);
1215 } else {
1216 edge->setAttribute(SUMO_ATTR_FROM, target->getID(), undoList);
1217 }
1218 }
1219 // deleted moved junction
1220 deleteJunction(moved, undoList);
1221 undoList->end();
1222}
1223
1224
1225void
1227 for (const EdgeSet& roundabout : myNetBuilder->getEdgeCont().getRoundabouts()) {
1228 for (NBEdge* edge : roundabout) {
1229 if (edge->getFromNode() == junction->getNBNode()) {
1230 undoList->begin(junction, TL("select roundabout"));
1231 for (const auto& roundaboutEdge : roundabout) {
1232 GNEEdge* e = myAttributeCarriers->retrieveEdge(roundaboutEdge->getID());
1233 e->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1234 e->getToJunction()->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1235 }
1236 undoList->end();
1237 return;
1238 }
1239 }
1240 }
1241}
1242
1243
1244void
1246 undoList->begin(junction, TL("create roundabout"));
1247 // reset shape end from incoming edges
1248 for (const auto& incomingEdge : junction->getGNEIncomingEdges()) {
1249 incomingEdge->setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
1250 }
1251 // reset shape start from outgoing edges
1252 for (const auto& outgoingEdge : junction->getGNEOutgoingEdges()) {
1253 outgoingEdge->setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
1254 }
1255 junction->getNBNode()->updateSurroundingGeometry();
1256 double radius = junction->getNBNode()->getRadius();
1257 if (radius == NBNode::UNSPECIFIED_RADIUS) {
1258 radius = OptionsCont::getOptions().getFloat("default.junctions.radius");
1259 }
1260 std::vector<GNEEdge*> edges;
1261 // use clockwise sorting
1262 for (const auto& nbEdge : junction->getNBNode()->getEdges()) {
1263 edges.push_back(myAttributeCarriers->retrieveEdge(nbEdge->getID()));
1264 }
1265 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
1266 if (lefthand) {
1267 std::reverse(edges.begin(), edges.end());
1268 }
1269 const double lefthandSign = lefthand ? -1 : 1;
1270 std::vector<GNEJunction*> newJunctions;
1271 GNEEdge* templateEdge = nullptr;
1272 GNEEdge* prevOpposite = nullptr;
1273 // store old crossings edges as ids because edges are renamed and pointers will be invalid
1274 std::vector<std::pair<NBNode::Crossing, std::vector<std::string>>> oldCrossings;
1275 for (const auto& crossing : junction->getGNECrossings()) {
1276 std::vector<std::string> edgeIDs;
1277 for (auto e : crossing->getCrossingEdges()) {
1278 edgeIDs.push_back(e->getID());
1279 }
1280 oldCrossings.push_back(std::make_pair(*crossing->getNBCrossing(), edgeIDs));
1281 }
1282 std::map<std::string, std::string> edgeRename;
1283 // split incoming/outgoing edges
1284 for (GNEEdge* edge : edges) {
1285 GNEJunction* newJunction = nullptr;
1286 if (edge == prevOpposite) {
1287 newJunction = newJunctions.back();
1288 }
1289 // update template (most "important" incoming edge)
1290 if (edge->getToJunction() == junction) {
1291 if (templateEdge == nullptr) {
1292 templateEdge = edge;
1293 } else {
1294 NBEdge* tpl = templateEdge->getNBEdge();
1295 NBEdge* e = edge->getNBEdge();
1296 if (tpl->getNumLanes() < e->getNumLanes()
1297 || (tpl->getNumLanes() == e->getNumLanes()
1298 && tpl->getPriority() < e->getPriority())) {
1299 templateEdge = edge;
1300 }
1301 }
1302 }
1303 //std::cout << " edge=" << edge->getID() << " prevOpposite=" << Named::getIDSecure(prevOpposite) << " newJunction=" << Named::getIDSecure(newJunction) << "\n";
1304 prevOpposite = edge->getOppositeEdges().size() > 0 ? edge->getOppositeEdges().front() : nullptr;
1305 const double geomLength = edge->getNBEdge()->getGeometry().length2D();
1306 const double splitOffset = (edge->getToJunction() == junction
1307 ? MAX2(POSITION_EPS, geomLength - radius)
1308 : MIN2(geomLength - POSITION_EPS, radius));
1309 Position pos = edge->getNBEdge()->getGeometry().positionAtOffset2D(splitOffset);
1310 auto newStuff = splitEdge(edge, pos, undoList, newJunction);
1311 newJunction = newStuff.first;
1312 if (edge->getFromJunction() == junction) {
1313 // edge will be deleted and the new part after the split kept. Preserve edge id
1314 edgeRename[newStuff.second->getID()] = edge->getID();
1315 }
1316 if (newJunctions.empty() || newJunction != newJunctions.back()) {
1317 newJunctions.push_back(newJunction);
1318 }
1319 }
1320
1321 Position center = junction->getPositionInView();
1322 deleteJunction(junction, undoList);
1323 // rename edges after the originals have been deleted
1324 for (auto item : edgeRename) {
1325 GNEEdge* outgoing = myAttributeCarriers->retrieveEdge(item.first);
1326 outgoing->setAttribute(SUMO_ATTR_ID, item.second, undoList);
1327 }
1328 // restore crossings (after rename)
1329 for (auto nbCItem : oldCrossings) {
1330 for (GNEJunction* nj : newJunctions) {
1331 nbCItem.first.edges.clear();
1332 // check whether this junction has all the edges of the crossing
1333 for (const std::string& ce : nbCItem.second) {
1334 bool foundCE = false;
1335 for (NBEdge* je : nj->getNBNode()->getEdges()) {
1336 if (je->getID() == ce) {
1337 foundCE = true;
1338 nbCItem.first.edges.push_back(je);
1339 break;
1340 }
1341 }
1342 if (!foundCE) {
1343 break;
1344 }
1345 }
1346 if (nbCItem.first.edges.size() == nbCItem.second.size()) {
1347 undoList->add(new GNEChange_Crossing(nj, nbCItem.first, true), true);
1348 break;
1349 }
1350 }
1351 }
1352 // create new edges to connect roundabout junctions (counter-clockwise)
1353 const double resolution = OptionsCont::getOptions().getFloat("opendrive.curve-resolution") * 3;
1354 for (int i = 0; i < (int)newJunctions.size(); i++) {
1355 GNEJunction* from = newJunctions[(i + 1) % newJunctions.size()];
1356 GNEJunction* to = newJunctions[i];
1357 GNEEdge* newEdge = createEdge(from, to, nullptr, undoList);
1358 const double angle1 = center.angleTo2D(from->getPositionInView());
1359 const double angle2 = center.angleTo2D(to->getPositionInView());
1360 // insert geometry points every resolution meters
1361 const double angleDiff = fabs(GeomHelper::angleDiff(angle2, angle1));
1362 // circumference = 2 * M_PI * radius, angularFraction = angleDiff / 2 * M_PI
1363 int numSegments = MAX2(2, (int)ceil(angleDiff * radius / resolution));
1364 PositionVector innerGeom;
1365 for (int j = 1; j < numSegments; j++) {
1366 const double angle = angle1 + lefthandSign * j * angleDiff / numSegments;
1367 innerGeom.push_back(center + Position(cos(angle) * radius, sin(angle) * radius));
1368 }
1369 //std::cout << " newEdge=" << newEdge->getID() << " angle1=" << angle1 << " angle2=" << angle2 << " angleDiff=" << angleDiff
1370 // << " numSegments=" << numSegments << " innerGeom=" << innerGeom << "\n";
1371 newEdge->setAttribute(SUMO_ATTR_SHAPE, toString(innerGeom), undoList);
1372 if (templateEdge) {
1373 GNEEdgeTemplate t(templateEdge);
1374 newEdge->copyTemplate(&t, undoList);
1375 }
1376 }
1377 undoList->end();
1378}
1379
1380
1381bool
1383 // Check that there isn't another junction in the same position as Pos
1384 for (auto& junction : myAttributeCarriers->getJunctions()) {
1385 if (junction.second->getPositionInView() == pos) {
1386 return false;
1387 }
1388 }
1389 return true;
1390}
1391
1392
1393void
1395 auto& neteditOptions = OptionsCont::getOptions();
1396 auto& sumoOptions = myApplicationWindow->getSumoOptions();
1397 // begin save network
1398 myApplicationWindow->getApp()->beginWaitCursor();
1399 // set output file in SUMO and netedit options
1400 neteditOptions.resetWritable();
1402 // compute without volatile options and update network
1403 if (!isNetRecomputed()) {
1404 computeAndUpdate(neteditOptions, false);
1405 }
1406 // clear typeContainer
1408 // now update typeContainer with edgeTypes
1409 for (const auto& edgeType : myAttributeCarriers->getEdgeTypes()) {
1410 myNetBuilder->getTypeCont().insertEdgeType(edgeType.first, edgeType.second);
1411 for (int i = 0; i < (int)edgeType.second->getLaneTypes().size(); i++) {
1412 myNetBuilder->getTypeCont().insertLaneType(edgeType.first, i,
1413 edgeType.second->getLaneTypes().at(i)->speed,
1414 edgeType.second->getLaneTypes().at(i)->permissions,
1415 edgeType.second->getLaneTypes().at(i)->width,
1416 edgeType.second->getLaneTypes().at(i)->attrs);
1417 }
1418 }
1419 // write network
1420 NWFrame::writeNetwork(neteditOptions, *myNetBuilder);
1421 // reset output file
1422 sumoOptions.resetWritable();
1423 neteditOptions.resetDefault("output-file");
1424 // mark network as saved
1426 // end save network
1427 myApplicationWindow->getApp()->endWaitCursor();
1428}
1429
1430
1431void
1432GNENet::savePlain(const std::string& prefix, const OptionsCont& netconvertOptions) {
1433 // compute without volatile options
1435 // check if we need to filter netedit options to netconvert
1436 if (netconvertOptions.getFullName().find("netedit") != std::string::npos) {
1437 OptionsCont* tmp = netconvertOptions.clone();
1438 tmp->setApplicationName("netconvert", StringUtils::replace(netconvertOptions.getFullName(), "netedit", "netconvert"));
1439 const std::vector<std::string> toReset = {
1440 "sumo-net-file", "plain-output-prefix",
1441 "additional-files", "route-files", "data-files", "meandata-files",
1442 "sumocfg-file", "netecfg-file", "netccfg-file", "gui-settings-file",
1443 "selection-file", "test-file", "tls-file", "edgetypes-file",
1444 "ignore-missing-inputs", "autosave-netconvert-file",
1445 "default.action-step-length", "default.speeddev"
1446 };
1447 for (const std::string& opt : toReset) {
1448 if (tmp->exists(opt)) {
1449 tmp->resetDefault(opt);
1450 tmp->removeOption(opt);
1451 }
1452 }
1453 tmp->removeSubTopic("Netedit");
1454 tmp->removeSubTopic("Visualisation");
1455 tmp->removeSubTopic("Visualization");
1456 tmp->removeSubTopic("Time");
1457 // save netconvert options
1459 delete tmp;
1460 } else {
1461 // save netconvert options
1462 NWWriter_XML::writeNetwork(netconvertOptions, prefix, *myNetBuilder);
1463 }
1464}
1465
1466
1467void
1468GNENet::saveJoined(const std::string& filename) {
1469 // compute without volatile options
1472}
1473
1474
1475void
1477 // check if object must be inserted in RTREE
1478 if (AC->getTagProperty()->isPlacedInRTree() && !AC->inGrid()) {
1480 AC->setInGrid(true);
1481 }
1482}
1483
1484
1485void
1487 // check if object must be inserted in RTREE
1488 if (AC->getTagProperty()->isPlacedInRTree() && AC->inGrid()) {
1490 AC->setInGrid(false);
1491 }
1492}
1493
1494
1495void
1496GNENet::computeNetwork(GNEApplicationWindow* window, bool force, bool volatileOptions) {
1497 if (!myNeedRecompute) {
1498 if (force) {
1499 if (volatileOptions) {
1500 window->setStatusBarText(TL("Forced computing junctions with volatile options ..."));
1501 } else {
1502 window->setStatusBarText(TL("Forced computing junctions ..."));
1503 }
1504 } else {
1505 return;
1506 }
1507 } else {
1508 if (volatileOptions) {
1509 window->setStatusBarText(TL("Computing junctions with volatile options ..."));
1510 } else {
1511 window->setStatusBarText(TL("Computing junctions ..."));
1512 }
1513 }
1514 // start recomputing
1515 myApplicationWindow->getApp()->beginWaitCursor();
1516 // save current number of lanes for every edge if recomputing is with volatile options
1517 if (volatileOptions) {
1518 for (const auto& edge : myAttributeCarriers->getEdges()) {
1519 myEdgesAndNumberOfLanes[edge.second->getID()] = (int)edge.second->getChildLanes().size();
1520 }
1521 }
1522 // compute and update
1523 auto& neteditOptions = OptionsCont::getOptions();
1524 computeAndUpdate(neteditOptions, volatileOptions);
1525 // load additionals if was recomputed with volatile options
1526 if (volatileOptions) {
1528 if (bucket->getFilename().size() > 0) {
1529 // Create general handler
1530 GNEGeneralHandler generalHandler(this, bucket, myApplicationWindow->isUndoRedoAllowed());
1531 // Run parser
1532 if (!generalHandler.parse()) {
1533 WRITE_ERROR(TL("Loading of additional file failed: ") + bucket->getFilename());
1534 } else {
1535 WRITE_MESSAGE(TL("Loading of additional file successfully: ") + bucket->getFilename());
1536 }
1537 }
1538 }
1539 }
1540 // load demand elements if was recomputed with volatile options
1541 if (volatileOptions) {
1543 if (bucket->getFilename().size() > 0) {
1544 // Create general handler
1545 GNEGeneralHandler generalHandler(this, bucket, myApplicationWindow->isUndoRedoAllowed());
1546 // Run parser
1547 if (!generalHandler.parse()) {
1548 WRITE_ERROR(TL("Loading of route file failed: ") + bucket->getFilename());
1549 } else {
1550 WRITE_MESSAGE(TL("Loading of route file successfully: ") + bucket->getFilename());
1551 }
1552 }
1553 }
1554 }
1555 // load datas if was recomputed with volatile options
1556 if (volatileOptions) {
1558 if (bucket->getFilename().size() > 0) {
1559 // Create general handler
1560 GNEDataHandler dataHandler(this, bucket, myApplicationWindow->isUndoRedoAllowed());
1561 // Run parser
1562 if (!dataHandler.parse()) {
1563 WRITE_ERROR(TL("Loading of data file failed: ") + bucket->getFilename());
1564 } else {
1565 WRITE_MESSAGE(TL("Loading of data file successfully: ") + bucket->getFilename());
1566 }
1567 }
1568 }
1569 }
1570 // load meanDatas if was recomputed with volatile options
1571 if (volatileOptions) {
1573 if (bucket->getFilename().size() > 0) {
1574 // Create general handler
1575 GNEGeneralHandler generalHandler(this, bucket, myApplicationWindow->isUndoRedoAllowed());
1576 // Run parser
1577 if (!generalHandler.parse()) {
1578 WRITE_ERROR(TL("Loading of meandata file failed: ") + bucket->getFilename());
1579 } else {
1580 WRITE_MESSAGE(TL("Loading of meandata file successfully: ") + bucket->getFilename());
1581 }
1582 }
1583 }
1584 }
1585 // clear myEdgesAndNumberOfLanes after reload additionals
1587 // end recomputing
1588 myApplicationWindow->getApp()->endWaitCursor();
1589 // update status bar
1590 window->setStatusBarText(TL("Finished computing junctions."));
1591}
1592
1593
1594void
1596 window->setStatusBarText(TL("Computing demand elements ..."));
1597 // if we aren't in Demand mode, update path calculator
1601 }
1602 // clear demand paths
1604 // iterate over all demand elements and compute
1605 for (const auto& demandElements : myAttributeCarriers->getDemandElements()) {
1606 for (const auto& demandElement : demandElements.second) {
1607 demandElement.second->computePathElement();
1608 }
1609 }
1610 window->setStatusBarText(TL("Finished computing demand elements."));
1611}
1612
1613
1614void
1616 window->setStatusBarText(TL("Computing data elements ..."));
1617 // iterate over all demand elements and compute
1618 for (const auto& genericDataTag : myAttributeCarriers->getGenericDatas()) {
1619 for (const auto& genericData : genericDataTag.second) {
1620 genericData.second->computePathElement();
1621 }
1622 }
1623 window->setStatusBarText(TL("Finished computing data elements."));
1624}
1625
1626
1627void
1629 // recompute tl-logics
1630 auto& neteditOptions = OptionsCont::getOptions();
1632 // iterate over traffic lights definitions. Make a copy because invalid
1633 // definitions will be removed (and would otherwise destroy the iterator)
1634 const std::set<NBTrafficLightDefinition*> tlsDefs = junction->getNBNode()->getControllingTLS();
1635 for (auto it : tlsDefs) {
1636 it->setParticipantsInformation();
1637 it->setTLControllingInformation();
1638 tllCont.computeSingleLogic(neteditOptions, it);
1639 }
1640
1641 // @todo compute connections etc...
1642}
1643
1644
1645void
1646GNENet::requireRecompute(const bool requireSaving) {
1647 myNeedRecompute = true;
1648 if (requireSaving) {
1650 }
1651}
1652
1653
1654bool
1656 return !myNeedRecompute;
1657}
1658
1659
1660bool
1662 const auto selectedJunctions = myAttributeCarriers->getSelectedJunctions();
1663 if (selectedJunctions.size() < 2) {
1664 return false;
1665 }
1666 EdgeVector allIncoming;
1667 EdgeVector allOutgoing;
1668 std::set<NBNode*, ComparatorIdLess> cluster;
1669 for (const auto& selectedJunction : selectedJunctions) {
1670 cluster.insert(selectedJunction->getNBNode());
1671 const EdgeVector& incoming = selectedJunction->getNBNode()->getIncomingEdges();
1672 allIncoming.insert(allIncoming.end(), incoming.begin(), incoming.end());
1673 const EdgeVector& outgoing = selectedJunction->getNBNode()->getOutgoingEdges();
1674 allOutgoing.insert(allOutgoing.end(), outgoing.begin(), outgoing.end());
1675 }
1676 // create new junction
1677 Position pos;
1678 Position oldPos;
1679 bool setTL = false;
1680 std::string id = "cluster";
1681 TrafficLightType type;
1683 myNetBuilder->getNodeCont().analyzeCluster(cluster, id, pos, setTL, type, nodeType);
1684 // save position
1685 oldPos = pos;
1686 // Check that there isn't another junction in the same position as Pos but doesn't belong to cluster
1687 for (const auto& junction : myAttributeCarriers->getJunctions()) {
1688 if ((junction.second->getPositionInView() == pos) && (cluster.find(junction.second->getNBNode()) == cluster.end())) {
1689 // open dialog
1691 TL("Position of joined junction"),
1692 TL("There is another unselected junction in the same position of joined junction."),
1693 TL("It will be joined with the other selected junctions. Continue?"));
1694 // check dialog result
1695 if (questionDialog.getResult() == GNEDialog::Result::ACCEPT) {
1696 // select conflicted junction an join all again
1697 junction.second->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1698 return joinSelectedJunctions(undoList);
1699 } else {
1700 return false;
1701 }
1702 }
1703 }
1704 // use checkJunctionPosition to avoid conflicts with junction in the same position as others
1705 while (!checkJunctionPosition(pos)) {
1706 pos.setx(pos.x() + 0.1);
1707 pos.sety(pos.y() + 0.1);
1708 }
1709 // start with the join selected junctions
1710 undoList->begin(GUIIcon::JUNCTION, "Join selected " + toString(SUMO_TAG_JUNCTION) + "s");
1711 GNEJunction* joined = createJunction(pos, undoList);
1712 joined->setAttribute(SUMO_ATTR_ID, id, undoList);
1713 // id must be set before type because it is used when creating a new tls
1714 joined->setAttribute(SUMO_ATTR_TYPE, toString(nodeType), undoList); // i.e. rail crossing
1715 if (setTL) {
1716 joined->setAttribute(SUMO_ATTR_TLTYPE, toString(type), undoList);
1717 }
1719 // first remove all crossing of the involved junctions and edges
1720 // (otherwise edge removal will trigger discarding)
1721 std::vector<NBNode::Crossing> oldCrossings;
1722 for (const auto& selectedJunction : selectedJunctions) {
1723 const auto crossings = selectedJunction->getGNECrossings();
1724 for (auto crossing : crossings) {
1725 deleteCrossing(crossing, undoList);
1726 }
1727 }
1728 // preserve old connections
1729 for (const auto& selectedJunction : selectedJunctions) {
1730 selectedJunction->setLogicValid(false, undoList);
1731 }
1732 // remap edges
1733 for (const auto& incomingEdge : allIncoming) {
1734 if (std::find(allOutgoing.begin(), allOutgoing.end(), incomingEdge) == allOutgoing.end()) {
1735 GNEChange_Attribute::changeAttribute(myAttributeCarriers->getEdges().at(incomingEdge->getID()), SUMO_ATTR_TO, joined->getID(), undoList);
1736 }
1737 }
1738 EdgeSet edgesWithin;
1739 for (const auto& outgoingEdge : allOutgoing) {
1740 // delete edges within the cluster
1741 GNEEdge* edge = myAttributeCarriers->getEdges().at(outgoingEdge->getID());
1742 if (edge->getToJunction() == joined) {
1743 edgesWithin.insert(outgoingEdge);
1744 deleteEdge(edge, undoList, false);
1745 } else {
1746 GNEChange_Attribute::changeAttribute(myAttributeCarriers->getEdges().at(outgoingEdge->getID()), SUMO_ATTR_FROM, joined->getID(), undoList);
1747 }
1748 }
1749 // remap all crossing of the involved junctions and edges
1750 for (const auto& nbc : oldCrossings) {
1751 bool keep = true;
1752 for (NBEdge* e : nbc.edges) {
1753 if (edgesWithin.count(e) != 0) {
1754 keep = false;
1755 break;
1756 }
1757 };
1758 if (keep) {
1759 undoList->add(new GNEChange_Crossing(joined, nbc.edges, nbc.width,
1760 nbc.priority || joined->getNBNode()->isTLControlled(),
1761 nbc.customTLIndex, nbc.customTLIndex2, nbc.customShape,
1762 false, true), true);
1763 }
1764 }
1765 // delete original junctions
1766 for (const auto& selectedJunction : selectedJunctions) {
1767 deleteJunction(selectedJunction, undoList);
1768 }
1769 // check if joined junction had to change their original position to avoid errors
1770 if (pos != oldPos) {
1771 joined->setAttribute(SUMO_ATTR_POSITION, toString(oldPos), undoList);
1772 }
1773 undoList->end();
1774 return true;
1775}
1776
1777
1778bool
1780 // obtain current net's crossings
1781 std::vector<GNECrossing*> myNetCrossings;
1782 for (const auto& junction : myAttributeCarriers->getJunctions()) {
1783 myNetCrossings.reserve(myNetCrossings.size() + junction.second->getGNECrossings().size());
1784 myNetCrossings.insert(myNetCrossings.end(), junction.second->getGNECrossings().begin(), junction.second->getGNECrossings().end());
1785 }
1786 // obtain invalid crossings
1787 std::vector<GNECrossing*> myInvalidCrossings;
1788 for (auto i = myNetCrossings.begin(); i != myNetCrossings.end(); i++) {
1789 if (!(*i)->getNBCrossing()->valid) {
1790 myInvalidCrossings.push_back(*i);
1791 }
1792 }
1793 // continue depending of invalid crossings
1794 if (myInvalidCrossings.empty()) {
1795 // open a warning dialog informing that there isn't crossing to remove
1797 TL("Clear crossings"),
1798 TL("There are no invalid crossings to remove."));
1799 } else {
1800 std::string plural = myInvalidCrossings.size() == 1 ? ("") : ("s");
1801 // Ask confirmation to user
1802 const GNEQuestionBasicDialog questionDialog(myApplicationWindow,
1803 GNEDialog::Buttons::YES_NO, TL("Clear crossings"),
1804 TL("Crossings will be cleared. Continue?"));
1805 // 1:yes, 2:no, 4:esc
1806 if (questionDialog.getResult() == GNEDialog::Result::ACCEPT) {
1807 undoList->begin(GUIIcon::MODEDELETE, TL("clear crossings"));
1808 for (const auto& crossing : myInvalidCrossings) {
1809 deleteCrossing(crossing, undoList);
1810 }
1811 undoList->end();
1812 } else {
1813 return false;
1814 }
1815 }
1816 return true;
1817}
1818
1819
1820void
1822 undoList->begin(GUIIcon::MODEDELETE, TL("clear junctions"));
1823 std::vector<GNEJunction*> toRemove;
1824 for (auto& junction : myAttributeCarriers->getJunctions()) {
1825 if (junction.second->getNBNode()->getEdges().size() == 0) {
1826 toRemove.push_back(junction.second);
1827 }
1828 }
1829 for (auto junction : toRemove) {
1830 deleteJunction(junction, undoList);
1831 }
1832 undoList->end();
1833}
1834
1835
1836void
1838 // first declare a vector to save all routes without children
1839 std::vector<GNEDemandElement*> routesWithoutChildren;
1840 routesWithoutChildren.reserve(myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE).size());
1841 // iterate over routes
1842 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
1843 if (route.second->getChildDemandElements().empty()) {
1844 routesWithoutChildren.push_back(route.second);
1845 }
1846 }
1847 // finally remove all routesWithoutChildren
1848 if (routesWithoutChildren.size() > 0) {
1849 // begin undo list
1850 undoList->begin(GUIIcon::MODEDELETE, TL("clear unused routes"));
1851 // iterate over routesWithoutChildren
1852 for (const auto& i : routesWithoutChildren) {
1853 // due route doesn't have children, simply call GNEChange_DemandElement
1854 undoList->add(new GNEChange_DemandElement(i, false), true);
1855 }
1856 // end undo list
1857 undoList->end();
1858 }
1859}
1860
1861
1862void
1864 // first declare a sorted set of sorted route's edges in string format
1865 std::set<std::pair<std::string, GNEDemandElement*> > mySortedRoutes;
1866 // iterate over routes and save it in mySortedRoutes (only if it doesn't have Stop Children)
1867 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
1868 // first check route has stops
1869 bool hasStops = false;
1870 for (const auto& stop : route.second->getChildDemandElements()) {
1871 if (stop->getTagProperty()->isVehicleStop()) {
1872 hasStops = true;
1873 }
1874 }
1875 if (!hasStops) {
1876 mySortedRoutes.insert(std::make_pair(GNEAttributeCarrier::parseIDs(route.second->getParentEdges()), route.second));
1877 }
1878 }
1879 // now declare a matrix in which organize routes to be merged
1880 std::vector<std::vector<GNEDemandElement*> > routesToMerge;
1881 auto index = mySortedRoutes.begin();
1882 // iterate over mySortedRoutes
1883 for (auto i = mySortedRoutes.begin(); i != mySortedRoutes.end(); i++) {
1884 if (routesToMerge.empty()) {
1885 routesToMerge.push_back({i->second});
1886 } else {
1887 if (index->first == i->first) {
1888 routesToMerge.back().push_back(i->second);
1889 } else {
1890 routesToMerge.push_back({i->second});
1891 index = i;
1892 }
1893 }
1894 }
1895 // now check if there is routes to merge
1896 bool thereIsRoutesToMerge = false;
1897 for (const auto& i : routesToMerge) {
1898 if (i.size() > 1) {
1899 thereIsRoutesToMerge = true;
1900 }
1901 }
1902 // if exist
1903 if (thereIsRoutesToMerge) {
1904 // begin undo list
1905 undoList->begin(GUIIcon::ROUTE, TL("merge routes"));
1906 // iterate over route to edges
1907 for (const auto& routes : routesToMerge) {
1908 if (routes.size() > 1) {
1909 // iterate over duplicated routes
1910 for (int i = 1; i < (int)routes.size(); i++) {
1911 // move all vehicles of every duplicated route
1912 while (routes.at(i)->getChildDemandElements().size() > 0) {
1913 routes.at(i)->getChildDemandElements().front()->setAttribute(SUMO_ATTR_ROUTE, routes.at(0)->getID(), undoList);
1914 }
1915 // finally remove route
1916 undoList->add(new GNEChange_DemandElement(routes.at(i), false), true);
1917 }
1918 }
1919 }
1920 // end undo list
1921 undoList->end();
1922 }
1923}
1924
1925
1926void
1928 // declare personPlan-pos map
1929 std::map<GNEDemandElement*, std::string> personPlanMap;
1930 // iterate over persons
1931 for (const auto& persontag : {
1933 }) {
1934 for (const auto& person : myAttributeCarriers->getDemandElements().at(persontag)) {
1935 if (person.second->getChildDemandElements().size() > 0) {
1936 // get person plan
1937 GNEDemandElement* personPlan = person.second->getChildDemandElements().front();
1938 // iterate over all personPlans
1939 while (personPlan) {
1940 // check if personPlan is a stopPerson over edge
1941 if (personPlan->getTagProperty()->getTag() == GNE_TAG_STOPPERSON_EDGE) {
1942 // get previous person plan
1943 GNEDemandElement* previousPersonPlan = person.second->getPreviousChildDemandElement(personPlan);
1944 // check if arrivalPos of previous personPlan is different of endPos of stopPerson
1945 if (previousPersonPlan && previousPersonPlan->getTagProperty()->hasAttribute(SUMO_ATTR_ARRIVALPOS) &&
1946 (previousPersonPlan->getAttribute(SUMO_ATTR_ARRIVALPOS) != personPlan->getAttribute(SUMO_ATTR_ENDPOS))) {
1947 personPlanMap[previousPersonPlan] = personPlan->getAttribute(SUMO_ATTR_ENDPOS);
1948 }
1949 }
1950 // go to next person plan
1951 personPlan = person.second->getNextChildDemandElement(personPlan);
1952 }
1953 }
1954 }
1955 }
1956 // continue if there is personPlanMap to adjust
1957 if (personPlanMap.size() > 0) {
1958 // begin undo list
1959 undoList->begin(GUIIcon::MODEPERSONPLAN, TL("adjust person plans"));
1960 // iterate over invalidDemandElements
1961 for (const auto& personPlan : personPlanMap) {
1962 // set arrivalPos attribute
1963 personPlan.first->setAttribute(SUMO_ATTR_ARRIVALPOS, personPlan.second, undoList);
1964 }
1965 // end undo list
1966 undoList->end();
1967 }
1968}
1969
1970
1971void
1973 // first declare a vector to save all invalid demand elements
1974 std::vector<GNEDemandElement*> invalidDemandElements;
1975 invalidDemandElements.reserve(myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE).size() +
1978 // iterate over routes
1979 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
1980 if (route.second->isDemandElementValid() != GNEDemandElement::Problem::OK) {
1981 invalidDemandElements.push_back(route.second);
1982 }
1983 }
1984 // iterate over flows
1985 for (const auto& flow : myAttributeCarriers->getDemandElements().at(SUMO_TAG_FLOW)) {
1986 if (flow.second->isDemandElementValid() != GNEDemandElement::Problem::OK) {
1987 invalidDemandElements.push_back(flow.second);
1988 }
1989 }
1990 // iterate over trip
1991 for (const auto& trip : myAttributeCarriers->getDemandElements().at(SUMO_TAG_TRIP)) {
1992 if (trip.second->isDemandElementValid() != GNEDemandElement::Problem::OK) {
1993 invalidDemandElements.push_back(trip.second);
1994 }
1995 }
1996 // continue if there is invalidDemandElements to remove
1997 if (invalidDemandElements.size() > 0) {
1998 // begin undo list
1999 undoList->begin(GUIIcon::MODEDELETE, TL("remove invalid demand elements"));
2000 // iterate over invalidDemandElements
2001 for (const auto& invalidDemandElement : invalidDemandElements) {
2002 // simply call GNEChange_DemandElement
2003 undoList->add(new GNEChange_DemandElement(invalidDemandElement, false), true);
2004 }
2005 // end undo list
2006 undoList->end();
2007 }
2008}
2009
2010void
2012 if (junction->getNBNode()->checkIsRemovable()) {
2013 // start operation
2014 undoList->begin(junction, TL("replace junction by geometry"));
2015 // obtain Edges to join
2016 std::vector<std::pair<NBEdge*, NBEdge*> > edgesToJoin = junction->getNBNode()->getEdgesToJoin();
2017 // clear connections of junction to replace
2018 clearJunctionConnections(junction, undoList);
2019 // iterate over NBEdges to join
2020 for (auto edgePair : edgesToJoin) {
2021 // obtain GNEEdges
2022 GNEEdge* begin = myAttributeCarriers->getEdges().at(edgePair.first->getID());
2023 GNEEdge* continuation = myAttributeCarriers->getEdges().at(edgePair.second->getID());
2024 // remove connections between the edges
2025 std::vector<NBEdge::Connection> connections = begin->getNBEdge()->getConnections();
2026 for (auto con : connections) {
2027 undoList->add(new GNEChange_Connection(begin, con, false, false), true);
2028 }
2029 // fix shape of replaced edge
2030 PositionVector newShape = begin->getNBEdge()->getInnerGeometry();
2031 newShape.push_back(junction->getNBNode()->getPosition());
2032 // replace incoming edge
2033 replaceIncomingEdge(continuation, begin, undoList);
2034
2035 newShape.append(continuation->getNBEdge()->getInnerGeometry());
2036 begin->setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
2037 begin->setAttribute(SUMO_ATTR_ENDOFFSET, continuation->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
2038 begin->setAttribute(SUMO_ATTR_SHAPE, toString(newShape), undoList);
2039 begin->getNBEdge()->resetNodeBorder(begin->getNBEdge()->getToNode());
2040 // fix loaded lengths
2041 if (begin->getNBEdge()->hasLoadedLength() || continuation->getNBEdge()->hasLoadedLength()) {
2042 begin->setAttribute(SUMO_ATTR_LENGTH, toString(begin->getNBEdge()->getLoadedLength() + continuation->getNBEdge()->getLoadedLength()), undoList);
2043 }
2044 }
2045 //delete replaced junction
2046 deleteJunction(junction, undoList);
2047 // finish operation
2048 undoList->end();
2049 } else {
2050 throw ProcessError(TL("Junction isn't removable"));
2051 }
2052}
2053
2054
2055void
2056GNENet::splitJunction(GNEJunction* junction, bool reconnect, GNEUndoList* undoList) {
2057 std::vector<std::pair<Position, std::string> > endpoints = junction->getNBNode()->getEndPoints();
2058 if (endpoints.size() < 2) {
2059 return;
2060 }
2061 // start operation
2062 undoList->begin(junction, TL("split junction"));
2063 // record connections
2064 std::map<std::pair<std::string, GNEEdge*>, std::vector<NBEdge::Connection>> straightConnections;
2065 for (GNEEdge* e : junction->getGNEIncomingEdges()) {
2066 for (const auto& c : e->getNBEdge()->getConnections()) {
2067 if (c.fromLane >= 0 && junction->getNBNode()->getDirection(e->getNBEdge(), c.toEdge) == LinkDirection::STRAIGHT) {
2068 straightConnections[std::make_pair(e->getID(), e)].push_back(c);
2069 }
2070 };
2071 }
2072 junction->setLogicValid(false, undoList);
2073 for (const auto& pair : endpoints) {
2074 const Position& pos = pair.first;
2075 const std::string& origID = pair.second;
2076 GNEJunction* newJunction = createJunction(pos, undoList);
2077 std::string newID = origID != "" ? origID : newJunction->getID();
2078 // make a copy because the original vectors are modified during iteration
2079 const std::vector<GNEEdge*> incoming = junction->getGNEIncomingEdges();
2080 const std::vector<GNEEdge*> outgoing = junction->getGNEOutgoingEdges();
2081 //std::cout << " checkEndpoint " << pair.first << " " << pair.second << " newID=" << newID << "\n";
2082 for (GNEEdge* e : incoming) {
2083 //std::cout << " incoming " << e->getID() << " pos=" << pos << " origTo=" << e->getNBEdge()->getParameter("origTo") << " newID=" << newID << "\n";
2084 if (e->getNBEdge()->getGeometry().back().almostSame(pos) || e->getNBEdge()->getParameter("origTo") == newID) {
2085 //std::cout << " match\n";
2086 GNEChange_Attribute::changeAttribute(e, SUMO_ATTR_TO, newJunction->getID(), undoList);
2087 }
2088 }
2089 for (GNEEdge* e : outgoing) {
2090 //std::cout << " outgoing " << e->getID() << " pos=" << pos << " origFrom=" << e->getNBEdge()->getParameter("origFrom") << " newID=" << newID << "\n";
2091 if (e->getNBEdge()->getGeometry().front().almostSame(pos) || e->getNBEdge()->getParameter("origFrom") == newID) {
2092 //std::cout << " match\n";
2093 GNEChange_Attribute::changeAttribute(e, SUMO_ATTR_FROM, newJunction->getID(), undoList);
2094 }
2095 }
2096 if (newID != newJunction->getID()) {
2097 if (newJunction->isValid(SUMO_ATTR_ID, newID)) {
2098 GNEChange_Attribute::changeAttribute(newJunction, SUMO_ATTR_ID, newID, undoList);
2099 } else {
2100 WRITE_WARNINGF(TL("Could not rename split node to '%'"), newID);
2101 }
2102 }
2103 }
2104 // recreate edges from straightConnections
2105 if (reconnect) {
2106 for (const auto& item : straightConnections) {
2107 GNEEdge* in = item.first.second;
2108 std::map<std::pair<std::string, NBEdge*>, GNEEdge*> newEdges;
2109 for (auto& c : item.second) {
2110 GNEEdge* out = myAttributeCarriers->retrieveEdge(c.toEdge->getID());
2111 GNEEdge* newEdge = nullptr;
2112 if (in->getToJunction() == out->getFromJunction()) {
2113 continue;
2114 }
2115 if (newEdges.count(std::make_pair(c.toEdge->getID(), c.toEdge)) == 0) {
2116 newEdge = createEdge(in->getToJunction(), out->getFromJunction(), in, undoList);
2117 if (newEdge) {
2118 newEdges[std::make_pair(c.toEdge->getID(), c.toEdge)] = newEdge;
2119 newEdge->setAttribute(SUMO_ATTR_NUMLANES, "1", undoList);
2120 }
2121 } else {
2122 newEdge = newEdges[std::make_pair(c.toEdge->getID(), c.toEdge)];
2123 duplicateLane(newEdge->getChildLanes().back(), undoList, true);
2124 }
2125 if (newEdge) {
2126 // copy permissions
2127 newEdge->getChildLanes().back()->setAttribute(SUMO_ATTR_ALLOW,
2128 in->getChildLanes()[c.fromLane]-> getAttribute(SUMO_ATTR_ALLOW), undoList);
2129 }
2130 }
2131 }
2132 }
2133 deleteJunction(junction, undoList);
2134 // finish operation
2135 undoList->end();
2136}
2137
2138
2139
2140void
2142 undoList->begin(GUIIcon::MODEDELETE, TL("clear junction connections"));
2143 std::vector<GNEConnection*> connections = junction->getGNEConnections();
2144 // Iterate over all connections and clear it
2145 for (auto i : connections) {
2146 deleteConnection(i, undoList);
2147 }
2148 undoList->end();
2149}
2150
2151
2152void
2154 undoList->begin(junction, TL("reset junction connections"));
2155 // first clear connections
2156 clearJunctionConnections(junction, undoList);
2157 // invalidate logic to create new connections in the next recomputing
2158 junction->setLogicValid(false, undoList);
2159 undoList->end();
2160}
2161
2162
2163void
2165 undoList->begin(GUIIcon::MODEDELETE, TL("clear additional elements"));
2166 // clear additionals
2167 for (const auto& additionalMap : myAttributeCarriers->getAdditionals()) {
2168 while (additionalMap.second.size() > 0) {
2169 deleteAdditional(additionalMap.second.begin()->second, undoList);
2170 }
2171 }
2172 undoList->end();
2173}
2174
2175
2176void
2178 undoList->begin(GUIIcon::MODEDELETE, TL("clear demand elements"));
2179 // clear demand elements
2180 for (const auto& demandElementsMap : myAttributeCarriers->getDemandElements()) {
2181 if (demandElementsMap.first != SUMO_TAG_VTYPE) {
2182 while (demandElementsMap.second.size() > 0) {
2183 deleteDemandElement(demandElementsMap.second.begin()->second, undoList);
2184 }
2185 }
2186 }
2187 // special case for vTypes
2188 const std::unordered_map<const GUIGlObject*, GNEDemandElement*> types = myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE);
2189 for (const auto& type : types) {
2190 if (type.second->getAttribute(GNE_ATTR_DEFAULT_VTYPE) == GNEAttributeCarrier::FALSE_STR) {
2191 deleteDemandElement(type.second, undoList);
2192 }
2193 }
2194 undoList->end();
2195}
2196
2197
2198void
2200 undoList->begin(GUIIcon::MODEDELETE, TL("clear data elements"));
2201 // clear data sets
2202 while (myAttributeCarriers->getDataSets().size() > 0) {
2203 deleteDataSet(myAttributeCarriers->getDataSets().begin()->second, undoList);
2204 }
2205 undoList->end();
2206}
2207
2208
2209void
2211 undoList->begin(GUIIcon::MODEDELETE, TL("clear meanData elements"));
2212 // clear meanDatas
2213 for (const auto& meanDataMap : myAttributeCarriers->getMeanDatas()) {
2214 while (meanDataMap.second.size() > 0) {
2215 deleteMeanData(meanDataMap.second.begin()->second, undoList);
2216 }
2217 }
2218 undoList->end();
2219}
2220
2221
2222void
2223GNENet::changeEdgeEndpoints(GNEEdge* edge, const std::string& newSource, const std::string& newDest) {
2226 edge->getNBEdge()->reinitNodes(from, to);
2228}
2229
2230
2235
2236
2241
2242
2243void
2247
2248
2249void
2251 myExplicitTurnarounds.erase(id);
2252}
2253
2254
2255bool
2257 // obtain invalid additionals depending of number of their parent lanes
2258 std::vector<GNEAdditional*> invalidAdditionals;
2259 // iterate over additionals and obtain invalids
2260 for (const auto& additionalPair : myAttributeCarriers->getAdditionals()) {
2261 for (const auto& addditional : additionalPair.second) {
2262 // check if has to be fixed
2263 if (!addditional.second->isAdditionalValid()) {
2264 invalidAdditionals.push_back(addditional.second);
2265 }
2266 }
2267 }
2268 // if there are invalid additionls, open GNEFixAdditionalElementsDialog
2269 if (invalidAdditionals.size() > 0) {
2270 // open fix additional elements dialog
2271 const GNEFixAdditionalElementsDialog fixAdditionalElements(myApplicationWindow, invalidAdditionals);
2272 if (fixAdditionalElements.getResult() != GNEDialog::Result::ACCEPT) {
2273 return false;
2274 }
2275 }
2276 // Start saving additionals
2277 myApplicationWindow->getApp()->beginWaitCursor();
2278 // iterate over all elements and save files
2280 // only write buckets with elements
2281 if ((bucket->getNumElements() > 0) || (bucket->isDefaultBucket() && (bucket->getFilename().size() > 0))) {
2282 // open file
2283 OutputDevice& device = OutputDevice::getDevice(bucket->getFilename());
2284 // open header
2285 device.writeXMLHeader("additional", "additional_file.xsd", EMPTY_HEADER, false);
2286 // save additionals, demand elements and meanDatas
2287 writeAdditionalFileElements(device, bucket);
2288 // close device
2289 device.close();
2290 }
2291 }
2292 // mark additionals as saved
2294 // end saving additionals
2295 myApplicationWindow->getApp()->endWaitCursor();
2296 return true;
2297}
2298
2299
2300bool
2301GNENet::saveJuPedSimElements(const std::string& filename) {
2302 OutputDevice& device = OutputDevice::getDevice(filename);
2303 // open header
2304 device.writeXMLHeader("additional", "additional_file.xsd", EMPTY_HEADER, false);
2305 // juPedSim elements
2306 writeJuPedSimComment(device, nullptr);
2308 writeAdditionalByType(device, nullptr, {GNE_TAG_JPS_OBSTACLE});
2309 // close device
2310 device.close();
2311 // set focus again in net
2312 myApplicationWindow->getViewNet()->setFocus();
2313 return true;
2314}
2315
2316
2317bool
2319 // first recompute demand elements
2321 // obtain invalid demandElements depending of number of their parent lanes
2322 std::vector<GNEDemandElement*> invalidSingleLaneDemandElements;
2323 // iterate over demandElements and obtain invalids
2324 for (const auto& demandElementSet : myAttributeCarriers->getDemandElements()) {
2325 for (const auto& demandElement : demandElementSet.second) {
2326 // compute before check if demand element is valid
2327 demandElement.second->computePathElement();
2328 // check if has to be fixed
2329 if (demandElement.second->isDemandElementValid() != GNEDemandElement::Problem::OK) {
2330 invalidSingleLaneDemandElements.push_back(demandElement.second);
2331 }
2332 }
2333 }
2334 // if there are invalid demand elements, open GNEFixDemandElementsDialog
2335 if (invalidSingleLaneDemandElements.size() > 0) {
2336 // open fix demand elements dialog
2337 const GNEFixDemandElementsDialog fixDemandElement(myApplicationWindow, invalidSingleLaneDemandElements);
2338 if (fixDemandElement.getResult() != GNEDialog::Result::ACCEPT) {
2339 return false;
2340 }
2341 }
2342 // Start saving additionals
2343 myApplicationWindow->getApp()->beginWaitCursor();
2344 // iterate over all elements and save files
2346 // only write buckets with elements
2347 if ((bucket->getNumElements() > 0) || (bucket->isDefaultBucket() && (bucket->getFilename().size() > 0))) {
2348 // open file
2349 OutputDevice& device = OutputDevice::getDevice(bucket->getFilename());
2350 // open header
2351 device.writeXMLHeader("routes", "routes_file.xsd", EMPTY_HEADER, false);
2352 // save additionals, demand elements and meanDatas
2353 writeAdditionalFileElements(device, bucket);
2354 // close device
2355 device.close();
2356 }
2357 }
2358 // mark demand elements as saved
2360 // end saving additionals
2361 myApplicationWindow->getApp()->endWaitCursor();
2362 return true;
2363}
2364
2365
2366bool
2368 // first recompute data sets
2370 // Start saving data elements
2371 myApplicationWindow->getApp()->beginWaitCursor();
2372 // iterate over all elements and save files
2374 // only write buckets with elements
2375 if ((bucket->getNumElements() > 0) || (bucket->isDefaultBucket() && (bucket->getFilename().size() > 0))) {
2376 // open file
2377 OutputDevice& device = OutputDevice::getDevice(bucket->getFilename());
2378 // write header
2379 device.writeXMLHeader("data", "datamode_file.xsd", EMPTY_HEADER, false);
2380 for (const auto& dataSet : myAttributeCarriers->getDataSets()) {
2381 if (dataSet.second->getFileBucket() == bucket) {
2382 dataSet.second->writeDataSet(device);
2383 }
2384 }
2385 // close device
2386 device.close();
2387 }
2388 }
2389 // mark data element as saved
2391 // end saving additionals
2392 myApplicationWindow->getApp()->endWaitCursor();
2393 return true;
2394}
2395
2396
2397double
2399 double minimumBegin = 0;
2400 // update with first minimum (if exist)
2401 if (myAttributeCarriers->getDataIntervals().size() > 0) {
2402 minimumBegin = myAttributeCarriers->getDataIntervals().begin()->second->getAttributeDouble(SUMO_ATTR_BEGIN);
2403 }
2404 // iterate over interval
2405 for (const auto& interval : myAttributeCarriers->getDataIntervals()) {
2406 if (interval.second->getAttributeDouble(SUMO_ATTR_BEGIN) < minimumBegin) {
2407 minimumBegin = interval.second->getAttributeDouble(SUMO_ATTR_BEGIN);
2408 }
2409 }
2410 return minimumBegin;
2411}
2412
2413
2414double
2416 double maximumEnd = 0;
2417 // update with first maximum (if exist)
2418 if (myAttributeCarriers->getDataIntervals().size() > 0) {
2419 maximumEnd = myAttributeCarriers->getDataIntervals().begin()->second->getAttributeDouble(SUMO_ATTR_END);
2420 }
2421 // iterate over intervals
2422 for (const auto& interval : myAttributeCarriers->getDataIntervals()) {
2423 if (interval.second->getAttributeDouble(SUMO_ATTR_END) > maximumEnd) {
2424 maximumEnd = interval.second->getAttributeDouble(SUMO_ATTR_END);
2425 }
2426 }
2427 return maximumEnd;
2428}
2429
2430
2431bool
2433 // Start saving additionals
2434 myApplicationWindow->getApp()->beginWaitCursor();
2435 // iterate over all elements and save files
2437 // only write buckets with elements
2438 if ((bucket->getNumElements() > 0) || (bucket->isDefaultBucket() && (bucket->getFilename().size() > 0))) {
2439 // open file
2440 OutputDevice& device = OutputDevice::getDevice(bucket->getFilename());
2441 // open header
2442 device.writeXMLHeader("additional", "additional_file.xsd", EMPTY_HEADER, false);
2443 // save additionals, demand elements and meanDatas
2444 writeAdditionalFileElements(device, bucket);
2445 // close device
2446 device.close();
2447 }
2448 }
2449 // mark mean datas as saved
2451 // end saving additionals
2452 myApplicationWindow->getApp()->endWaitCursor();
2453 return true;
2454}
2455
2456
2457void
2459 // 1) stoppingPlaces
2460 writeStoppingPlaceComment(device, fileBucket);
2461 writeAdditionalByType(device, fileBucket, {SUMO_TAG_BUS_STOP});
2462 writeAdditionalByType(device, fileBucket, {SUMO_TAG_TRAIN_STOP});
2463 writeAdditionalByType(device, fileBucket, {SUMO_TAG_CONTAINER_STOP});
2464 writeAdditionalByType(device, fileBucket, {SUMO_TAG_PARKING_AREA});
2465 writeAdditionalByType(device, fileBucket, {SUMO_TAG_CHARGING_STATION});
2466 // detectors
2467 writeDetectorComment(device, fileBucket);
2468 writeAdditionalByType(device, fileBucket, {SUMO_TAG_INDUCTION_LOOP});
2472 // variable speed signs
2473 writeVariableSpeedSignComment(device, fileBucket);
2474 writeAdditionalByType(device, fileBucket, {SUMO_TAG_VSS});
2475 // routeProbes
2476 writeRouteProbeComment(device, fileBucket);
2477 writeAdditionalByType(device, fileBucket, {SUMO_TAG_ROUTEPROBE});
2478 // vaporizers
2479 writeVaporizerComment(device, fileBucket);
2480 writeAdditionalByType(device, fileBucket, {SUMO_TAG_VAPORIZER});
2481 // Wire element
2482 writeWireComment(device, fileBucket);
2486 // shapes
2487 writeShapesComment(device, fileBucket);
2488 writeAdditionalByType(device, fileBucket, {SUMO_TAG_POLY});
2490 // juPedSim elements
2491 writeJuPedSimComment(device, fileBucket);
2492 writeAdditionalByType(device, fileBucket, {GNE_TAG_JPS_WALKABLEAREA});
2493 writeAdditionalByType(device, fileBucket, {GNE_TAG_JPS_OBSTACLE});
2494 // TAZs
2495 writeTAZComment(device, fileBucket);
2496 writeAdditionalByType(device, fileBucket, {SUMO_TAG_TAZ});
2497 // vtypes
2498 writeVTypeComment(device, fileBucket);
2499 writeVTypes(device, fileBucket);
2500 writeVTypeDistributions(device, fileBucket);
2501 // now write all routes (and their associated stops), except routes with additional children (due routeProbReroutes)
2502 writeRouteComment(device, fileBucket);
2503 writeRoutes(device, fileBucket);
2504 writeRouteDistributions(device, fileBucket);
2505 // sort vehicles/persons by depart
2506 std::map<double, std::map<std::pair<SumoXMLTag, std::string>, GNEDemandElement*> > vehiclesSortedByDepart;
2507 for (const auto& demandElementTag : myAttributeCarriers->getDemandElements()) {
2508 for (const auto& demandElement : demandElementTag.second) {
2509 if ((demandElement.second->getFileBucket() == fileBucket) &&
2510 (demandElement.second->getTagProperty()->isVehicle() || demandElement.second->getTagProperty()->isPerson() || demandElement.second->getTagProperty()->isContainer())) {
2511 vehiclesSortedByDepart[demandElement.second->getAttributeDouble(SUMO_ATTR_DEPART)][std::make_pair(demandElement.second->getTagProperty()->getTag(), demandElement.second->getID())] = demandElement.second;
2512 }
2513 }
2514 }
2515 // finally write all vehicles, persons and containers sorted by depart time (and their associated stops, personPlans, etc.)
2516 if (vehiclesSortedByDepart.size() > 0) {
2517 device << (" <!-- Vehicles, persons and containers (sorted by depart) -->\n");
2518 for (const auto& vehicleTag : vehiclesSortedByDepart) {
2519 for (const auto& vehicle : vehicleTag.second) {
2520 vehicle.second->writeDemandElement(device);
2521 }
2522 }
2523 }
2524 // calibrator
2525 writeCalibratorComment(device, fileBucket);
2527 // rerouters
2528 writeRerouterComment(device, fileBucket);
2529 writeAdditionalByType(device, fileBucket, {SUMO_TAG_REROUTER});
2530 // MeanDataEdges
2531 writeMeanDataEdgeComment(device, fileBucket);
2532 writeMeanDatas(device, fileBucket, SUMO_TAG_MEANDATA_EDGE);
2533 // MeanDataLanes
2534 writeMeanDataLaneComment(device, fileBucket);
2535 writeMeanDatas(device, fileBucket, SUMO_TAG_MEANDATA_LANE);
2536}
2537
2538
2539void
2540GNENet::writeAdditionalByType(OutputDevice& device, const FileBucket* fileBucket, const std::vector<SumoXMLTag> tags) const {
2541 std::map<std::string, std::vector<GNEAdditional*> > sortedAdditionals;
2542 for (const auto& tag : tags) {
2543 for (const auto& additional : myAttributeCarriers->getAdditionals().at(tag)) {
2544 if ((fileBucket == nullptr) || (additional.second->getFileBucket() == fileBucket)) {
2545 if ((tag == SUMO_TAG_VAPORIZER) || (sortedAdditionals.count(additional.second->getID()) == 0)) {
2546 sortedAdditionals[additional.second->getID()].push_back(additional.second);
2547 } else {
2548 throw ProcessError(TL("Duplicated ID"));
2549 }
2550 }
2551 }
2552 }
2553 for (const auto& additionalVector : sortedAdditionals) {
2554 for (const auto& additional : additionalVector.second) {
2555 additional->writeAdditional(device);
2556 }
2557 }
2558}
2559
2560
2561void
2562GNENet::writeDemandByType(OutputDevice& device, const FileBucket* fileBucket, SumoXMLTag tag) const {
2563 std::map<std::string, GNEDemandElement*> sortedDemandElements;
2564 for (const auto& demandElement : myAttributeCarriers->getDemandElements().at(tag)) {
2565 if (demandElement.second->getFileBucket() == fileBucket) {
2566 sortedDemandElements[demandElement.second->getID()] = demandElement.second;
2567 }
2568 }
2569 for (const auto& demandElement : sortedDemandElements) {
2570 demandElement.second->writeDemandElement(device);
2571 }
2572}
2573
2574
2575void
2577 std::map<std::string, GNEDemandElement*> sortedElements;
2578 // first write route Distributions
2579 for (const auto& routeDistribution : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE_DISTRIBUTION)) {
2580 if (routeDistribution.second->getFileBucket() == fileBucket) {
2581 sortedElements[routeDistribution.second->getID()] = routeDistribution.second;
2582 }
2583 }
2584 for (const auto& element : sortedElements) {
2585 element.second->writeDemandElement(device);
2586 }
2587}
2588
2589
2590void
2591GNENet::writeRoutes(OutputDevice& device, const FileBucket* fileBucket) const {
2592 std::map<std::string, GNEDemandElement*> sortedRoutes;
2593 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
2594 if (route.second->getFileBucket() == fileBucket) {
2595 sortedRoutes[route.second->getID()] = route.second;
2596 }
2597 }
2598 for (const auto& route : sortedRoutes) {
2599 route.second->writeDemandElement(device);
2600 }
2601}
2602
2603
2604void
2606 std::map<std::string, GNEDemandElement*> sortedElements;
2607 // first write vType Distributions
2608 for (const auto& vTypeDistribution : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE_DISTRIBUTION)) {
2609 if (vTypeDistribution.second->getFileBucket() == fileBucket) {
2610 sortedElements[vTypeDistribution.second->getID()] = vTypeDistribution.second;
2611 }
2612 }
2613 for (const auto& element : sortedElements) {
2614 element.second->writeDemandElement(device);
2615 }
2616}
2617
2618
2619void
2620GNENet::writeVTypes(OutputDevice& device, const FileBucket* fileBucket) const {
2621 std::map<std::string, GNEDemandElement*> sortedVTypes;
2622 for (const auto& vType : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE)) {
2623 if (vType.second->getFileBucket() == fileBucket) {
2624 sortedVTypes[vType.second->getID()] = vType.second;
2625 }
2626 }
2627 for (const auto& vType : sortedVTypes) {
2628 vType.second->writeDemandElement(device);
2629 }
2630}
2631
2632
2633void
2634GNENet::writeMeanDatas(OutputDevice& device, const FileBucket* fileBucket, SumoXMLTag tag) const {
2635 std::map<std::string, GNEMeanData*> sortedMeanDatas;
2636 for (const auto& meanData : myAttributeCarriers->getMeanDatas().at(tag)) {
2637 if (meanData.second->getFileBucket() == fileBucket) {
2638 if (sortedMeanDatas.count(meanData.second->getID()) == 0) {
2639 sortedMeanDatas[meanData.second->getID()] = meanData.second;
2640 } else {
2641 throw ProcessError(TL("Duplicated ID"));
2642 }
2643 }
2644 }
2645 for (const auto& additional : sortedMeanDatas) {
2646 additional.second->writeMeanData(device);
2647 }
2648}
2649
2650bool
2651GNENet::writeVTypeComment(OutputDevice& device, const FileBucket* fileBucket) const {
2652 // vTypes
2653 for (const auto& vType : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE)) {
2654 // special case for default vTypes
2655 const bool defaultVType = GNEAttributeCarrier::parse<bool>(vType.second->getAttribute(GNE_ATTR_DEFAULT_VTYPE));
2656 const bool defaultVTypeModified = GNEAttributeCarrier::parse<bool>(vType.second->getAttribute(GNE_ATTR_DEFAULT_VTYPE_MODIFIED));
2657 // only write default vType modified
2658 if ((vType.second->getParentDemandElements().size() == 0) && (!defaultVType || (defaultVType && defaultVTypeModified))) {
2659 if (vType.second->getFileBucket() == fileBucket) {
2660 device << (" <!-- VTypes -->\n");
2661 return true;
2662 }
2663 }
2664 }
2665 return false;
2666}
2667
2668
2669bool
2670GNENet::writeRouteComment(OutputDevice& device, const FileBucket* fileBucket) const {
2671 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
2672 if (route.second->getFileBucket() == fileBucket) {
2673 device << (" <!-- Routes -->\n");
2674 return true;
2675 }
2676 }
2677 return false;
2678}
2679
2680
2681bool
2682GNENet::writeRerouterComment(OutputDevice& device, const FileBucket* fileBucket) const {
2683 for (const auto& routeProbe : myAttributeCarriers->getAdditionals().at(SUMO_TAG_REROUTER)) {
2684 if (routeProbe.second->getFileBucket() == fileBucket) {
2685 device << (" <!-- Rerouter -->\n");
2686 return true;
2687 }
2688 }
2689 return false;
2690}
2691
2692
2693bool
2695 for (const auto& routeProbe : myAttributeCarriers->getAdditionals().at(SUMO_TAG_VSS)) {
2696 if (routeProbe.second->getFileBucket() == fileBucket) {
2697 device << (" <!-- VariableSpeedSigns -->\n");
2698 return true;
2699 }
2700 }
2701 return false;
2702}
2703
2704
2705bool
2706GNENet::writeRouteProbeComment(OutputDevice& device, const FileBucket* fileBucket) const {
2707 for (const auto& routeProbe : myAttributeCarriers->getAdditionals().at(SUMO_TAG_ROUTEPROBE)) {
2708 if (routeProbe.second->getFileBucket() == fileBucket) {
2709 device << (" <!-- RouteProbes -->\n");
2710 return true;
2711 }
2712 }
2713 return false;
2714}
2715
2716
2717bool
2718GNENet::writeVaporizerComment(OutputDevice& device, const FileBucket* fileBucket) const {
2719 for (const auto& routeProbe : myAttributeCarriers->getAdditionals().at(SUMO_TAG_VAPORIZER)) {
2720 if (routeProbe.second->getFileBucket() == fileBucket) {
2721 device << (" <!-- Vaporizers -->\n");
2722 return true;
2723 }
2724 }
2725 return false;
2726}
2727
2728
2729bool
2730GNENet::writeCalibratorComment(OutputDevice& device, const FileBucket* fileBucket) const {
2731 for (const auto& additionalTag : myAttributeCarriers->getAdditionals()) {
2732 for (const auto& additional : additionalTag.second) {
2733 if (additional.second->getTagProperty()->isCalibrator() &&
2734 (additional.second->getFileBucket() == fileBucket)) {
2735 device << (" <!-- Calibrators -->\n");
2736 return true;
2737 }
2738 }
2739 }
2740 return false;
2741}
2742
2743
2744bool
2746 for (const auto& additionalTag : myAttributeCarriers->getAdditionals()) {
2747 for (const auto& additional : additionalTag.second) {
2748 if (additional.second->getTagProperty()->isStoppingPlace() &&
2749 (additional.second->getFileBucket() == fileBucket)) {
2750 device << (" <!-- StoppingPlaces -->\n");
2751 return true;
2752 }
2753 }
2754 }
2755 return false;
2756}
2757
2758
2759bool
2760GNENet::writeDetectorComment(OutputDevice& device, const FileBucket* fileBucket) const {
2761 for (const auto& additionalTag : myAttributeCarriers->getAdditionals()) {
2762 for (const auto& additional : additionalTag.second) {
2763 if (additional.second->getTagProperty()->isDetector() &&
2764 (additional.second->getFileBucket() == fileBucket)) {
2765 device << (" <!-- Detectors -->\n");
2766 return true;
2767 }
2768 }
2769 }
2770 return false;
2771}
2772
2773
2774bool
2775GNENet::writeShapesComment(OutputDevice& device, const FileBucket* fileBucket) const {
2776 for (const auto& additionalTag : myAttributeCarriers->getAdditionals()) {
2777 for (const auto& additional : additionalTag.second) {
2778 if (additional.second->getTagProperty()->isShapeElement() &&
2779 (additional.second->getFileBucket() == fileBucket) &&
2780 !additional.second->getTagProperty()->isJuPedSimElement()) {
2781 device << (" <!-- Shapes -->\n");
2782 return true;
2783 }
2784 }
2785 }
2786 return false;
2787}
2788
2789
2790bool
2791GNENet::writeJuPedSimComment(OutputDevice& device, const FileBucket* fileBucket) const {
2792 for (const auto& additionalTag : myAttributeCarriers->getAdditionals()) {
2793 for (const auto& additional : additionalTag.second) {
2794 if (additional.second->getTagProperty()->isJuPedSimElement() &&
2795 ((fileBucket == nullptr) || (additional.second->getFileBucket() == fileBucket))) {
2796 device << (" <!-- JuPedSim elements -->\n");
2797 return true;
2798 }
2799 }
2800 }
2801 return false;
2802}
2803
2804
2805bool
2806GNENet::writeTAZComment(OutputDevice& device, const FileBucket* fileBucket) const {
2807 for (const auto& TAZ : myAttributeCarriers->getAdditionals().at(SUMO_TAG_TAZ)) {
2808 if (TAZ.second->getFileBucket() == fileBucket) {
2809 device << (" <!-- TAZs -->\n");
2810 return true;
2811 }
2812 }
2813 return false;
2814}
2815
2816
2817bool
2818GNENet::writeWireComment(OutputDevice& device, const FileBucket* fileBucket) const {
2819 for (const auto& additionalTag : myAttributeCarriers->getAdditionals()) {
2820 for (const auto& additional : additionalTag.second) {
2821 if (additional.second->getTagProperty()->isWireElement() &&
2822 (additional.second->getFileBucket() == fileBucket)) {
2823 device << (" <!-- Wires -->\n");
2824 return true;
2825 }
2826 }
2827 }
2828 return false;
2829}
2830
2831
2832bool
2834 for (const auto& meanDataEdge : myAttributeCarriers->getMeanDatas().at(SUMO_TAG_MEANDATA_EDGE)) {
2835 if (meanDataEdge.second->getFileBucket() == fileBucket) {
2836 device << (" <!-- MeanDataEdges -->\n");
2837 return true;
2838 }
2839 }
2840 return false;
2841}
2842
2843
2844bool
2846 for (const auto& meanDataLane : myAttributeCarriers->getMeanDatas().at(SUMO_TAG_MEANDATA_LANE)) {
2847 if (meanDataLane.second->getFileBucket() == fileBucket) {
2848 device << (" <!-- MeanDataLanes -->\n");
2849 return true;
2850 }
2851 }
2852 return false;
2853}
2854
2855
2856void
2857GNENet::saveTLSPrograms(const std::string& filename) {
2858 // open output device
2859 OutputDevice& device = OutputDevice::getDevice(filename);
2860 device.openTag("additionals");
2861 // write traffic lights using NWWriter
2863 device.close();
2864 // change save status
2866}
2867
2868
2869int
2871 return -1;
2872}
2873
2874
2875void
2876GNENet::saveEdgeTypes(const std::string& filename) {
2877 // first clear typeContainer
2879 // now update typeContainer with edgeTypes
2880 for (const auto& edgeType : myAttributeCarriers->getEdgeTypes()) {
2881 myNetBuilder->getTypeCont().insertEdgeType(edgeType.first, edgeType.second);
2882 for (int i = 0; i < (int)edgeType.second->getLaneTypes().size(); i++) {
2883 myNetBuilder->getTypeCont().insertLaneType(edgeType.first, i,
2884 edgeType.second->getLaneTypes().at(i)->speed,
2885 edgeType.second->getLaneTypes().at(i)->permissions,
2886 edgeType.second->getLaneTypes().at(i)->width,
2887 edgeType.second->getLaneTypes().at(i)->attrs);
2888 }
2889 }
2890 // open device
2891 OutputDevice& device = OutputDevice::getDevice(filename);
2892 // open tag
2893 device.openTag(SUMO_TAG_TYPES);
2894 // write edge types
2896 // close tag
2897 device.closeTag();
2898 // close device
2899 device.close();
2900}
2901
2902
2903void
2907
2908
2909void
2913
2914
2915bool
2919
2920
2921void
2923 myUpdateDataEnabled = true;
2924 // update data elements
2925 for (const auto& dataInterval : myAttributeCarriers->getDataIntervals()) {
2926 dataInterval.second->updateGenericDataIDs();
2927 dataInterval.second->updateAttributeColors();
2928 }
2929}
2930
2931
2932void
2936
2937
2938bool
2942
2943
2944unsigned int&
2948
2949
2950unsigned int&
2954
2955// ===========================================================================
2956// private
2957// ===========================================================================
2958
2959void
2961 // init edge types
2962 for (const auto& edgeType : myNetBuilder->getTypeCont()) {
2963 // register edge type
2964 myAttributeCarriers->registerEdgeType(new GNEEdgeType(this, edgeType.first, edgeType.second));
2965 }
2966 // init junctions (by default Crossing and walking areas aren't created)
2967 for (const auto& nodeName : myNetBuilder->getNodeCont().getAllNames()) {
2968 // create and register junction
2969 myAttributeCarriers->registerJunction(new GNEJunction(this, myNetBuilder->getNodeCont().retrieve(nodeName), true), afterVolatile);
2970 }
2971 // init edges
2972 for (const auto& edgeName : myNetBuilder->getEdgeCont().getAllNames()) {
2973 // create edge using NBEdge
2974 GNEEdge* edge = new GNEEdge(this, myNetBuilder->getEdgeCont().retrieve(edgeName), false, true);
2975 // register edge
2977 // add manually child references due initJunctionsAndEdges doesn't use undo-redo
2978 edge->getFromJunction()->addChildElement(edge);
2979 edge->getToJunction()->addChildElement(edge);
2980 // check grid
2981 if (myGrid.getWidth() > 10e16 || myGrid.getHeight() > 10e16) {
2982 throw ProcessError(TL("Network size exceeds 1 Lightyear. Please reconsider your inputs.") + std::string("\n"));
2983 }
2984 }
2985 // make sure myGrid is initialized even for an empty net. This ensure that the network starts with a zoom of 100
2986 if (myAttributeCarriers->getEdges().size() == 0) {
2987 myGrid.add(Boundary(-50, -50, 50, 50));
2988 }
2989 // recalculate all lane2lane connections
2990 for (const auto& edge : myAttributeCarriers->getEdges()) {
2991 for (const auto& lane : edge.second->getChildLanes()) {
2992 lane->updateGeometry();
2993 }
2994 }
2995 // sort nodes edges so that arrows can be drawn correctly
2997}
2998
2999
3000void
3002 for (const auto& edge : myAttributeCarriers->getEdges()) {
3003 // remake connections
3004 edge.second->remakeGNEConnections();
3005 // update geometry of connections
3006 for (const auto& connection : edge.second->getGNEConnections()) {
3007 connection->updateGeometry();
3008 }
3009 }
3010}
3011
3012
3013void
3014GNENet::computeAndUpdate(OptionsCont& neteditOptions, bool volatileOptions) {
3015 // make sure we only add turn arounds to edges which currently exist within the network
3016 std::set<std::string> liveExplicitTurnarounds;
3017 for (const auto& explicitTurnarounds : myExplicitTurnarounds) {
3018 if (myAttributeCarriers->getEdges().count(explicitTurnarounds) > 0) {
3019 liveExplicitTurnarounds.insert(explicitTurnarounds);
3020 }
3021 }
3022 // removes all junctions of grid
3023 for (const auto& junction : myAttributeCarriers->getJunctions()) {
3024 removeGLObjectFromGrid(junction.second);
3025 }
3026 // remove all edges from grid
3027 for (const auto& edge : myAttributeCarriers->getEdges()) {
3028 removeGLObjectFromGrid(edge.second);
3029 }
3030 // compute using NetBuilder
3031 myNetBuilder->compute(neteditOptions, liveExplicitTurnarounds, volatileOptions);
3032 // remap ids if necessary
3033 if (neteditOptions.getBool("numerical-ids") || neteditOptions.isSet("reserved-ids")) {
3035 }
3036 // update rtree if necessary
3037 if (!neteditOptions.getBool("offset.disable-normalization")) {
3038 for (const auto& edge : myAttributeCarriers->getEdges()) {
3039 // refresh edge geometry
3040 edge.second->updateGeometry();
3041 }
3042 }
3043 // Clear current inspected ACs in inspectorFrame if a previous net was loaded
3044 if (myApplicationWindow->getViewNet() != nullptr) {
3046 }
3047 // Reset Grid
3048 myGrid.reset();
3051 }
3052 // make sure myGrid is initialized even for an empty net. This ensures that recentering an empty view uses a zoom of 100
3053 if (myAttributeCarriers->getEdges().size() == 0) {
3054 myGrid.add(Boundary(-50, -50, 50, 50));
3055 }
3056 // if volatile options are true
3057 if (volatileOptions) {
3058 // check that net exist
3059 if (myApplicationWindow->getViewNet() == nullptr) {
3060 throw ProcessError("ViewNet doesn't exist");
3061 }
3062 // disable update geometry before clear undo list
3064 // destroy Popup
3066 // clear undo list (This will be remove additionals and shapes)
3068 // clear all elements (it will also removed from grid)
3073 // enable update geometry again
3075 // init again junction an edges (Additionals and shapes will be loaded after the end of this function)
3077 // init default vTypes again
3079 // require save network
3081 } else {
3082 // insert all junctions of grid again
3083 for (const auto& junction : myAttributeCarriers->getJunctions()) {
3084 // update centering boundary
3085 junction.second->updateCenteringBoundary(false);
3086 // add junction in grid again
3087 addGLObjectIntoGrid(junction.second);
3088 }
3089 // insert all edges from grid again
3090 for (const auto& edge : myAttributeCarriers->getEdges()) {
3091 // update centeting boundary
3092 edge.second->updateCenteringBoundary(false);
3093 // add edge in grid again
3094 addGLObjectIntoGrid(edge.second);
3095 }
3096 // remake connections
3097 for (const auto& edge : myAttributeCarriers->getEdges()) {
3098 edge.second->remakeGNEConnections(true);
3099 }
3100 // iterate over junctions of net
3101 for (const auto& junction : myAttributeCarriers->getJunctions()) {
3102 // undolist may not yet exist but is also not needed when just marking junctions as valid
3103 junction.second->setLogicValid(true, nullptr);
3104 // updated geometry
3105 junction.second->updateGeometryAfterNetbuild();
3106 // rebuild walking areas
3107 junction.second->rebuildGNEWalkingAreas();
3108 }
3109 // iterate over all edges of net
3110 for (const auto& edge : myAttributeCarriers->getEdges()) {
3111 // update geometry
3112 edge.second->updateGeometry();
3113 }
3114 }
3115 // net recomputed, then return false;
3116 myNeedRecompute = false;
3117}
3118
3119
3120void
3121GNENet::replaceInListAttribute(GNEAttributeCarrier* ac, SumoXMLAttr key, const std::string& which, const std::string& by, GNEUndoList* undoList) {
3122 assert(ac->getTagProperty()->getAttributeProperties(key)->isList());
3123 std::vector<std::string> values = GNEAttributeCarrier::parse<std::vector<std::string> >(ac->getAttribute(key));
3124 std::vector<std::string> newValues;
3125 bool lastBy = false;
3126 for (auto v : values) {
3127 if (v == which && !lastBy) {
3128 // avoid duplicate occurence of the 'by' edge (i.e. in routes)
3129 newValues.push_back(by);
3130 } else {
3131 newValues.push_back(v);
3132 }
3133 lastBy = v == by;
3134 }
3135 ac->setAttribute(key, toString(newValues), undoList);
3136}
3137
3138
3139/****************************************************************************/
@ MID_COPY_VIEW_GEOBOUNDARY
Copy view geo-coordinate boundary - popup entry.
Definition GUIAppEnum.h:471
@ GLO_NETWORK
The network - empty.
@ MODEPERSONPLAN
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:288
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:304
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 ' '.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
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
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_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_MEANDATA_LANE
a lane based mean data detector
@ SUMO_TAG_ROUTE_DISTRIBUTION
distribution of a route
@ 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 definition using from and to edges or a route
@ SUMO_TAG_CONNECTION
connectioon between two lanes
@ SUMO_TAG_PARKING_AREA
A parking area.
@ GNE_TAG_CALIBRATOR_LANE
A calibrator placed over lane.
@ SUMO_TAG_TYPES
types (edge)
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ SUMO_TAG_CROSSING
crossing between edges for pedestrians
@ SUMO_TAG_ROUTE
description of a route
@ SUMO_TAG_MEANDATA_EDGE
an edge based mean data detector
@ 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.
@ GNE_TAG_JPS_OBSTACLE
polygon used for draw juPedSim obstacles
@ SUMO_TAG_PERSON
@ SUMO_TAG_VAPORIZER
vaporizer of vehicles
@ SUMO_TAG_LANE_AREA_DETECTOR
alternative tag for e2 detector
@ GNE_TAG_ROUTE_EMBEDDED
embedded route
@ SUMO_TAG_INDUCTION_LOOP
alternative tag for e1 detector
@ GNE_TAG_JPS_WALKABLEAREA
polygon used for draw juPedSim walkable areas
@ 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_STARTPOS
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_LANE
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_VIA
@ GNE_ATTR_OPPOSITE
to busStop (used by personPlans)
@ 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
@ GNE_ATTR_DEFAULT_VTYPE
Flag to check if VType is a default VType.
@ GNE_ATTR_MODIFICATION_STATUS
whether a feature has been loaded,guessed,modified or approved
@ 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
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:57
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:75
bool isInitialised() const
check if Boundary is Initialised
Definition Boundary.cpp:256
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:127
void reset()
Resets the boundary.
Definition Boundary.cpp:63
double getHeight() const
Returns the height of the boundary (y-axis)
Definition Boundary.cpp:157
double getWidth() const
Returns the width of the boudary (x-axis)
Definition Boundary.cpp:151
bool parse()
parse
static void drawBoundary(const GUIVisualizationSettings &s, const Boundary &b)
Draw a boundary (used for debugging)
Definition GLHelper.cpp:952
std::string getDefaultFilename(const FileBucket::Type type) const
functions related with filenames
const std::vector< FileBucket * > & getFileBuckets(const FileBucket::Type type) const
get vector with all fileBuckets related with the given file type
OptionsCont & getSumoOptions()
get SUMO options container
void setStatusBarText(const std::string &statusBarText)
set text of the statusBar
GNEUndoList * getUndoList()
get pointer to undoList
GNEViewNet * getViewNet()
get pointer to viewNet
GNEApplicationWindowHelper::FileBucketHandler * getFileBucketHandler() const
get file bucket handler
const GNETagPropertiesDatabase * getTagPropertiesDatabase() const
get tag properties database
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
void setInGrid(bool value)
mark if this AC was inserted in grid or not
static const std::string FALSE_STR
true value in string format(used for comparing boolean values in getAttribute(...))
const std::string getID() const override
get ID (all Attribute Carriers have one)
const std::string & getTagStr() const
get tag assigned to this object in string format
static const std::string FEATURE_GUESSED
feature has been reguessed (may still be unchanged be we can't tell (yet)
const GNETagProperties * getTagProperty() const
get tagProperty associated with this Attribute Carrier
bool inGrid() const
check if this AC was inserted in grid
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
get GUIGlObject associated with this AttributeCarrier
static void changeAttribute(GNEAttributeCarrier *AC, SumoXMLAttr key, const std::string &value, GNEUndoList *undoList, const bool force=false)
change attribute
static void registerJoin(const std::set< NBNode *, ComparatorIdLess > &cluster, NBNodeCont &nc, GNEUndoList *undoList)
change attribute
the function-object for an editing operation (abstract base)
Definition GNEChange.h:56
NBConnection getNBConnection() const
get NBConnection
GNEEdge * getEdgeFrom() const
get the name of the edge the vehicles leave
NBEdge::Connection & getNBEdgeConnection() const
get Edge::Connection
NBNode::Crossing * getNBCrossing() const
get referente to NBode::Crossing
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
GNEDemandElement * getNextChildDemandElement(const GNEDemandElement *demandElement) const
get next child demand element to the given demand element
GNEDemandElement * getPreviousChildDemandElement(const GNEDemandElement *demandElement) const
get previous child demand element to the given demand element
Result getResult() const
get result to indicate if this dialog was closed accepting or rejecting changes
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList) override
Definition GNEEdge.cpp:1251
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition GNEEdge.cpp:773
GNEEdge * getReverseEdge() const
get reverse edge (if exist)
Definition GNEEdge.cpp:1789
std::vector< GNEEdge * > getOppositeEdges() const
get opposite edges
Definition GNEEdge.cpp:707
GNEJunction * getFromJunction() const
get from Junction (only used to increase readability)
Definition GNEEdge.h:87
bool wasSplit()
whether this edge was created from a split
Definition GNEEdge.cpp:1116
void copyTemplate(const GNEEdgeTemplate *edgeTemplate, GNEUndoList *undoList)
copy edge attributes from edgetemplate
Definition GNEEdge.cpp:1045
const std::vector< GNEConnection * > & getGNEConnections() const
returns a reference to the GNEConnection vector
Definition GNEEdge.cpp:1110
GNEJunction * getToJunction() const
get from Junction (only used to increase readability)
Definition GNEEdge.h:92
std::string getAttribute(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1122
GNEDataInterval * getDataIntervalParent() const
get data interval parent
const GNEHierarchicalContainerChildren< GNEEdge * > & getChildEdges() const
get child edges
const GNEHierarchicalContainerParents< GNEAdditional * > & getParentAdditionals() const
get parent additionals
const GNEHierarchicalContainerChildren< GNEGenericData * > & getChildGenericDatas() const
return child generic data elements
const GNEHierarchicalContainerChildren< GNELane * > & getChildLanes() const
get child lanes
const GNEHierarchicalContainerChildren< GNEAdditional * > & getChildAdditionals() const
return child additionals
const GNEHierarchicalContainerChildrenSet< GNETAZSourceSink * > & getChildTAZSourceSinks() const
return child TAZSourceSinks (Set)
void addChildElement(ChildType *element)
add child without updating parent (ONLY used if we're creating elements without undo-redo)
const GNEHierarchicalContainerParents< GNEJunction * > & getParentJunctions() const
get parent junctions
const GNEHierarchicalContainerChildren< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
void clearInspection()
clear inspection
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
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 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.
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList) override
Position getPositionInView() const
Returns position of hierarchical element in view.
bool isValid(SumoXMLAttr key, const std::string &value) override
void removeConnectionsFrom(GNEEdge *edge, GNEUndoList *undoList, bool updateTLS, int lane=-1)
remove all connections from the given edge
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
int getIndex() const
returns the index of the lane
Definition GNELane.cpp:641
std::vector< GNEConnection * > getGNEOutcomingConnections()
returns a vector with the outgoing GNEConnections of this lane
Definition GNELane.cpp:1964
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList) override
Definition GNELane.cpp:780
GNEEdge * getParentEdge() const
get parent edge
Definition GNELane.cpp:216
modul for AC Templates
void buildTemplates()
build templates
struct used for saving all attribute carriers of net, in different formats
std::vector< GNEEdge * > retrieveEdges(GNEJunction *from, GNEJunction *to) const
get all edges by from and to GNEJunction
const std::unordered_map< SumoXMLTag, std::unordered_map< const GUIGlObject *, GNEDemandElement * >, std::hash< int > > & getDemandElements() const
get demand elements
GNEEdgeType * registerEdgeType(GNEEdgeType *edgeType)
registers a edge in containers
GNELane * retrieveLane(const std::string &id, bool hardFail=true, bool checkVolatileChange=false) const
get lane by id
void clearDemandElements()
clear demand elements
GNEEdge * registerEdge(GNEEdge *edge)
registers an edge with containers
const std::unordered_map< SumoXMLTag, std::unordered_map< const GUIGlObject *, GNEGenericData * >, std::hash< int > > & getGenericDatas() const
get all generic datas
GNECrossing * retrieveCrossing(const GUIGlObject *glObject, bool hardFail=true) const
get Crossing by AC
void remapJunctionAndEdgeIds()
remap junction and edge IDs
std::string generateEdgeID() const
generate edge ID
void clearAdditionals()
clear additionals
const std::unordered_map< SumoXMLTag, std::map< const std::string, GNEMeanData * >, std::hash< int > > & getMeanDatas() const
get meanDatas
GNEJunction * registerJunction(GNEJunction *junction, bool afterVolatile)
registers a junction in containers
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
const std::map< const std::string, GNEDataSet * > & getDataSets() const
get demand elements
const std::map< std::string, GNEEdge * > & getEdges() const
map with the ID and pointer to edges of net
void addDefaultVTypes()
add default VTypes
std::vector< GNEJunction * > getSelectedJunctions() const
return selected junctions
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
const std::unordered_map< const GNEAttributeCarrier *, GNEDataInterval * > & getDataIntervals() const
get all data intervals of network
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
void clearJunctions()
clear junctions
const std::unordered_map< SumoXMLTag, std::unordered_map< const GUIGlObject *, GNEAdditional * >, std::hash< int > > & getAdditionals() const
get additionals
GNEConnection * retrieveConnection(const std::string &id, bool hardFail=true) const
get Connection by id
class for GNEChange_ReplaceEdgeInTLS
modul for Saving status
void dataElementsSaved()
mark demand elements as saved
void requireSaveNetwork()
inform that network has to be saved
void demandElementsSaved()
mark demand elements as saved
void additionalsSaved()
mark additionals as saved
void TLSSaved()
mark TLS as saved
void meanDatasSaved()
mark mean data elements as saved
void networkSaved()
mark network as saved
void clearAdditionalElements(GNEUndoList *undoList)
clear additionals
Definition GNENet.cpp:2164
void removeSolitaryJunctions(GNEUndoList *undoList)
removes junctions that have no edges
Definition GNENet.cpp:1821
GNEPathManager * myDataPathManager
Data path manager.
Definition GNENet.h:533
void deleteEdge(GNEEdge *edge, GNEUndoList *undoList, bool recomputeConnections)
removes edge
Definition GNENet.cpp:485
void writeAdditionalByType(OutputDevice &device, const FileBucket *fileBucket, const std::vector< SumoXMLTag > tags) const
write additional element by type and sorted by ID
Definition GNENet.cpp:2540
bool joinSelectedJunctions(GNEUndoList *undoList)
join selected junctions
Definition GNENet.cpp:1661
bool writeJuPedSimComment(OutputDevice &device, const FileBucket *fileBucket) const
write JuPedSim comment
Definition GNENet.cpp:2791
double getDataSetIntervalMaximumEnd() const
get maximum interval
Definition GNENet.cpp:2415
void deleteLane(GNELane *lane, GNEUndoList *undoList, bool recomputeConnections)
removes lane
Definition GNENet.cpp:664
static const double Z_INITIALIZED
marker for whether the z-boundary is initialized
Definition GNENet.h:639
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition GNENet.cpp:721
SUMORTree & getGrid()
Returns the RTree used for visualisation speed-up.
Definition GNENet.cpp:217
bool writeRouteProbeComment(OutputDevice &device, const FileBucket *fileBucket) const
write routeProbe comment
Definition GNENet.cpp:2706
void deleteAdditional(GNEAdditional *additional, GNEUndoList *undoList)
remove additional
Definition GNENet.cpp:739
bool saveMeanDatas()
save meanData elements of the network
Definition GNENet.cpp:2432
void disableUpdateGeometry()
disable update geometry of elements after inserting or removing an element in net
Definition GNENet.cpp:2910
void saveTLSPrograms(const std::string &filename)
save TLS Programs elements of the network
Definition GNENet.cpp:2857
void computeAndUpdate(OptionsCont &neteditOptions, bool volatileOptions)
recompute the network and update lane geometries
Definition GNENet.cpp:3014
NBNetBuilder * getNetBuilder() const
get net builder
Definition GNENet.cpp:168
void writeVTypeDistributions(OutputDevice &device, const FileBucket *fileBucket) const
write vTypeDistributions sorted by ID
Definition GNENet.cpp:2605
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1476
GNEPathManager * getDataPathManager()
get data path manager
Definition GNENet.cpp:204
void reverseEdge(GNEEdge *edge, GNEUndoList *undoList)
reverse edge
Definition GNENet.cpp:1141
bool writeTAZComment(OutputDevice &device, const FileBucket *fileBucket) const
write TAZ comment
Definition GNENet.cpp:2806
void requireRecompute(const bool requireSaving=true)
inform the net about the need for recomputation
Definition GNENet.cpp:1646
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1486
void saveJoined(const std::string &filename)
save log of joined junctions (and nothing else)
Definition GNENet.cpp:1468
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition GNENet.cpp:2232
bool restrictLane(SUMOVehicleClass vclass, GNELane *lane, GNEUndoList *undoList)
transform lane to restricted lane
Definition GNENet.cpp:880
GNENetHelper::SavingStatus * getSavingStatus() const
get saving status
Definition GNENet.cpp:186
void enableUpdateData()
Definition GNENet.cpp:2922
void mergeJunctions(GNEJunction *moved, const GNEJunction *target, GNEUndoList *undoList)
merge the given junctions edges between the given junctions will be deleted
Definition GNENet.cpp:1195
void writeAdditionalFileElements(OutputDevice &device, const FileBucket *fileBucket)
write additionals demand elements and meanData in output device
Definition GNENet.cpp:2458
bool myNeedRecompute
whether the net needs recomputation
Definition GNENet.h:545
void deleteDemandElement(GNEDemandElement *demandElement, GNEUndoList *undoList)
remove demand element
Definition GNENet.cpp:773
void duplicateLane(GNELane *lane, GNEUndoList *undoList, bool recomputeConnections)
duplicates lane
Definition GNENet.cpp:864
const Boundary & getZBoundary() const
Returns the Z boundary (stored in the x() coordinate) values of 0 do not affect the boundary.
Definition GNENet.cpp:270
const Boundary & getBoundary() const
returns the bounder of the network
Definition GNENet.cpp:210
void saveEdgeTypes(const std::string &filename)
save edgeTypes elements of the network
Definition GNENet.cpp:2876
void deleteNetworkElement(GNENetworkElement *networkElement, GNEUndoList *undoList)
delete network element
Definition GNENet.cpp:397
void writeMeanDatas(OutputDevice &device, const FileBucket *fileBucket, SumoXMLTag tag) const
write meanData element by type and sorted by ID
Definition GNENet.cpp:2634
bool writeStoppingPlaceComment(OutputDevice &device, const FileBucket *fileBucket) const
write stoppingPlace comment
Definition GNENet.cpp:2745
SUMORTree myGrid
the rtree which contains all GUIGlObjects (so named for historical reasons)
Definition GNENet.h:509
void clearDataElements(GNEUndoList *undoList)
clear data elements
Definition GNENet.cpp:2199
void deleteDataInterval(GNEDataInterval *dataInterval, GNEUndoList *undoList)
remove data interval
Definition GNENet.cpp:812
bool saveDataElements()
save data set elements of the network
Definition GNENet.cpp:2367
void deleteConnection(GNEConnection *connection, GNEUndoList *undoList)
remove connection
Definition GNENet.cpp:706
void clearDemandElements(GNEUndoList *undoList)
clear demand elements
Definition GNENet.cpp:2177
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:198
void adjustPersonPlans(GNEUndoList *undoList)
adjust person plans
Definition GNENet.cpp:1927
GNENetHelper::ACTemplate * getACTemplates() const
get all attribute carriers templates used in this net
Definition GNENet.cpp:180
void computeNetwork(GNEApplicationWindow *window, bool force=false, bool volatileOptions=false)
trigger full netbuild computation param[in] window The window to inform about delay param[in] force W...
Definition GNENet.cpp:1496
void cleanInvalidDemandElements(GNEUndoList *undoList)
clean invalid demand elements
Definition GNENet.cpp:1972
bool myUpdateDataEnabled
Flag to enable or disable update data elements after inserting or removing element in net.
Definition GNENet.h:551
void cleanUnusedRoutes(GNEUndoList *undoList)
clean unused routes
Definition GNENet.cpp:1837
NBNetBuilder * myNetBuilder
The internal netbuilder.
Definition GNENet.h:515
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition GNENet.cpp:2250
bool writeCalibratorComment(OutputDevice &device, const FileBucket *fileBucket) const
write calibrator comment
Definition GNENet.cpp:2730
void computeJunction(GNEJunction *junction)
trigger recomputation of junction shape and logic param[in] window The window to inform about delay
Definition GNENet.cpp:1628
void resetJunctionConnections(GNEJunction *junction, GNEUndoList *undoList)
reset junction's connections
Definition GNENet.cpp:2153
bool writeRouteComment(OutputDevice &device, const FileBucket *fileBucket) const
write route comment
Definition GNENet.cpp:2670
void deleteMeanData(GNEMeanData *meanData, GNEUndoList *undoList)
remove generic data
Definition GNENet.cpp:855
void replaceIncomingEdge(GNEEdge *which, GNEEdge *by, GNEUndoList *undoList)
replaces edge
Definition GNENet.cpp:571
void deleteGenericData(GNEGenericData *genericData, GNEUndoList *undoList)
remove generic data
Definition GNENet.cpp:825
std::pair< GNEJunction *, GNEEdge * > splitEdge(GNEEdge *edge, const Position &pos, GNEUndoList *undoList, GNEJunction *newJunction=0)
split edge at position by inserting a new junction
Definition GNENet.cpp:1000
Boundary getCenteringBoundary() const override
Returns the boundary to which the view shall be centered in order to show the object.
Definition GNENet.cpp:258
bool writeShapesComment(OutputDevice &device, const FileBucket *fileBucket) const
write shape comment
Definition GNENet.cpp:2775
bool writeMeanDataEdgeComment(OutputDevice &device, const FileBucket *fileBucket) const
write meanDataEdge comment
Definition GNENet.cpp:2833
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition GNENet.cpp:174
void writeRoutes(OutputDevice &device, const FileBucket *fileBucket) const
write route sorted by ID
Definition GNENet.cpp:2591
bool writeMeanDataLaneComment(OutputDevice &device, const FileBucket *fileBucket) const
write Wire comment
Definition GNENet.cpp:2845
GNEEdge * addReversedEdge(GNEEdge *edge, const bool disconnected, GNEUndoList *undoList)
add reversed edge
Definition GNENet.cpp:1157
GNEApplicationWindow * getGNEApplicationWindow() const
get tag properties database
Definition GNENet.cpp:138
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition GNENet.cpp:2223
bool myUpdateGeometryEnabled
Flag to enable or disable update geometry of elements after inserting or removing element in net.
Definition GNENet.h:548
void splitEdgesBidi(GNEEdge *edge, GNEEdge *oppositeEdge, const Position &pos, GNEUndoList *undoList)
split all edges at position by inserting one new junction
Definition GNENet.cpp:1117
GNENetHelper::SavingStatus * mySavingStatus
saving status module
Definition GNENet.h:524
void clearMeanDataElements(GNEUndoList *undoList)
clear meanDatas
Definition GNENet.cpp:2210
unsigned int myEdgeIDCounter
Definition GNENet.h:538
void expandBoundary(const Boundary &newBoundary)
expand boundary
Definition GNENet.cpp:264
void writeVTypes(OutputDevice &device, const FileBucket *fileBucket) const
write vTypes sorted by ID
Definition GNENet.cpp:2620
void disableUpdateData()
disable update data elements after inserting or removing an element in net
Definition GNENet.cpp:2933
bool writeRerouterComment(OutputDevice &device, const FileBucket *fileBucket) const
write rerouter comment
Definition GNENet.cpp:2682
bool removeRestrictedLane(SUMOVehicleClass vclass, GNEEdge *edge, GNEUndoList *undoList)
remove restricted lane
Definition GNENet.cpp:986
void deleteTAZSourceSink(GNETAZSourceSink *TAZSourceSink, GNEUndoList *undoList)
remove TAZSourceSink
Definition GNENet.cpp:764
~GNENet()
Destructor.
Definition GNENet.cpp:123
GNEApplicationWindow * myApplicationWindow
pointer to application window
Definition GNENet.h:512
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:304
std::set< std::string > myExplicitTurnarounds
list of edge ids for which turn-arounds must be added explicitly
Definition GNENet.h:542
bool saveAdditionals()
save additional elements
Definition GNENet.cpp:2256
const std::map< std::string, int > & getEdgesAndNumberOfLanes() const
et edges and number of lanes
Definition GNENet.cpp:222
void writeRouteDistributions(OutputDevice &device, const FileBucket *fileBucket) const
write route distributions sorted by ID
Definition GNENet.cpp:2576
void addZValueInBoundary(const double z)
add Z in net boundary
Definition GNENet.cpp:276
static const std::map< SumoXMLAttr, std::string > EMPTY_HEADER
variable used for write headers in additional, demand and data elements
Definition GNENet.h:505
bool isUpdateGeometryEnabled() const
check if update geometry after inserting or removing has to be updated
Definition GNENet.cpp:2916
bool addRestrictedLane(SUMOVehicleClass vclass, GNEEdge *edge, int index, GNEUndoList *undoList)
add restricted lane to edge
Definition GNENet.cpp:933
void saveNetwork()
save the network
Definition GNENet.cpp:1394
bool writeVTypeComment(OutputDevice &device, const FileBucket *fileBucket) const
write vType comment
Definition GNENet.cpp:2651
bool saveJuPedSimElements(const std::string &filename)
save JuPedSim elements
Definition GNENet.cpp:2301
bool checkJunctionPosition(const Position &pos)
return true if there are already a Junction in the given position, false in other case
Definition GNENet.cpp:1382
bool addGreenVergeLane(GNEEdge *edge, int index, GNEUndoList *undoList)
add restricted lane to edge
Definition GNENet.cpp:969
const GNETagPropertiesDatabase * getTagPropertiesDatabase() const
get tag properties database (used for simplify code)
Definition GNENet.cpp:162
bool isNetRecomputed() const
check if net require recomputing
Definition GNENet.cpp:1655
GNEPathManager * myNetworkPathManager
Network path manager.
Definition GNENet.h:527
bool isUpdateDataEnabled() const
check if update data after inserting or removing has to be updated
Definition GNENet.cpp:2939
void deleteDataSet(GNEDataSet *dataSet, GNEUndoList *undoList)
remove data set
Definition GNENet.cpp:799
static void replaceInListAttribute(GNEAttributeCarrier *ac, SumoXMLAttr key, const std::string &which, const std::string &by, GNEUndoList *undoList)
replace in list attribute
Definition GNENet.cpp:3121
bool writeWireComment(OutputDevice &device, const FileBucket *fileBucket) const
write Wire comment
Definition GNENet.cpp:2818
void initJunctionsAndEdges(bool afterVolatile)
Init Junctions and edges.
Definition GNENet.cpp:2960
bool cleanInvalidCrossings(GNEUndoList *undoList)
clear invalid crossings
Definition GNENet.cpp:1779
GNEPathManager * getNetworkPathManager()
get network path manager
Definition GNENet.cpp:192
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:2056
void selectRoundabout(GNEJunction *junction, GNEUndoList *undoList)
select all roundabout edges and junctions for the current roundabout
Definition GNENet.cpp:1226
void joinRoutes(GNEUndoList *undoList)
join routes
Definition GNENet.cpp:1863
void replaceJunctionByGeometry(GNEJunction *junction, GNEUndoList *undoList)
replace the selected junction by geometry node(s) and merge the edges
Definition GNENet.cpp:2011
void createRoundabout(GNEJunction *junction, GNEUndoList *undoList)
transform the given junction into a roundabout
Definition GNENet.cpp:1245
GNEViewParent * getViewParent() const
get view parent (used for simplify code)
Definition GNENet.cpp:150
GNEJunction * createJunction(const Position &pos, GNEUndoList *undoList)
creates a new junction
Definition GNENet.cpp:285
void savePlain(const std::string &prefix, const OptionsCont &netconvertOptions)
save plain xml representation of the network (and nothing else)
Definition GNENet.cpp:1432
unsigned int myJunctionIDCounter
Definition GNENet.h:537
bool writeDetectorComment(OutputDevice &device, const FileBucket *fileBucket) const
write detector comment
Definition GNENet.cpp:2760
std::map< std::string, int > myEdgesAndNumberOfLanes
map with the Edges and their number of lanes
Definition GNENet.h:636
bool writeVariableSpeedSignComment(OutputDevice &device, const FileBucket *fileBucket) const
write variable speed sign comment
Definition GNENet.cpp:2694
GNEPathManager * myDemandPathManager
Demand path manager.
Definition GNENet.h:530
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition GNENet.cpp:2244
void initGNEConnections()
initialize GNEConnections
Definition GNENet.cpp:3001
void deleteJunction(GNEJunction *junction, GNEUndoList *undoList)
removes junction and all incident edges
Definition GNENet.cpp:438
NBEdgeCont & getEdgeCont()
returns the NBEdgeCont of the underlying netbuilder
Definition GNENet.cpp:2238
GNENet()=delete
Invalidated default constructor.
unsigned int & getJunctionIDCounter()
Definition GNENet.cpp:2945
bool saveDemandElements()
save demand element elements of the network
Definition GNENet.cpp:2318
GNENetHelper::AttributeCarriers * myAttributeCarriers
attributeCarriers module
Definition GNENet.h:518
void computeDataElements(GNEApplicationWindow *window)
compute data elements param[in] window The window to inform about delay
Definition GNENet.cpp:1615
GNENetHelper::ACTemplate * myACTemplates
attributeCarriers templates
Definition GNENet.h:521
GNEUndoList * getUndoList() const
get undo list(used for simplify code)
Definition GNENet.cpp:156
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent) override
Returns an own parameter window.
Definition GNENet.cpp:241
void writeDemandByType(OutputDevice &device, const FileBucket *fileBucket, SumoXMLTag tag) const
write demand element by type and sorted by ID
Definition GNENet.cpp:2562
void drawGL(const GUIVisualizationSettings &s) const override
Draws the object.
Definition GNENet.cpp:251
int getNumberOfTLSPrograms() const
get number of TLS Programs
Definition GNENet.cpp:2870
GNEViewNet * getViewNet() const
get view net (used for simplify code)
Definition GNENet.cpp:144
bool writeVaporizerComment(OutputDevice &device, const FileBucket *fileBucket) const
write vaporizer comment
Definition GNENet.cpp:2718
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent) override
Returns an own popup-menu.
Definition GNENet.cpp:228
void enableUpdateGeometry()
Definition GNENet.cpp:2904
void clearJunctionConnections(GNEJunction *junction, GNEUndoList *undoList)
clear junction's connections
Definition GNENet.cpp:2141
Boundary myZBoundary
the z boundary (stored in the x-coordinate), values of 0 are ignored
Definition GNENet.h:633
double getDataSetIntervalMinimumBegin() const
get minimum interval
Definition GNENet.cpp:2398
void computeDemandElements(GNEApplicationWindow *window)
compute demand elements param[in] window The window to inform about delay
Definition GNENet.cpp:1595
unsigned int & getEdgeIDCounter()
Definition GNENet.cpp:2951
GUIGlObject * getGUIGlObject() override
get GUIGlObject associated with this AttributeCarrier
void updatePathCalculator()
update DijkstraRouter (needed a good calculation of dijkstra path after modifying network)
bool isPathCalculatorUpdated() const
check if pathCalculator is updated
PathCalculator * getPathCalculator()
obtain instance of PathCalculator
void invalidateJunctionPath(const GNEJunction *junction)
invalidate junction path
void clearSegments()
clear segments
void invalidateLanePath(const GNELane *lane)
invalidate lane path
bool isPlacedInRTree() const
return true if Tag correspond to an element that has to be placed in RTREE
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
const std::vector< const GNEAttributeProperties * > & getAttributeProperties() const
get all attribute properties
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...
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
GNEViewParent * getViewParent() const
get the net object
GNEUndoList * getUndoList() const
get the undoList object
A single child window which contains a view of the simulation area.
GNEInspectorFrame * getInspectorFrame() const
get frame for inspect elements
static FXMenuCommand * buildFXMenuCommand(FXComposite *p, const std::string &text, FXIcon *icon, FXObject *tgt, FXSelector sel, const bool disable=false)
build menu command
The popup menu of a globject.
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, const GUIMainWindow &app, bool addSeparator=true) const
Builds an entry which allows to copy the cursor position if geo projection is used,...
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 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...
const Boundary & getConvBoundary() const
Returns the converted boundary.
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
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.
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
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:4543
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition NBEdge.h:1047
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:437
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:355
Lane & getLaneStruct(int lane)
Definition NBEdge.h:1451
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition NBEdge.h:789
EdgeBuildingStep getStep() const
The building step of this edge.
Definition NBEdge.h:641
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition NBEdge.h:618
@ LANES2LANES_RECHECK
Lanes to lanes - relationships are computed; should be rechecked.
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:526
void resetNodeBorder(const NBNode *node)
Definition NBEdge.cpp:761
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition NBEdge.cpp:4381
std::string getLaneID(int lane) const
get lane ID
Definition NBEdge.cpp:4181
int getPriority() const
Returns the priority of the edge.
Definition NBEdge.h:533
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition NBEdge.h:346
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition NBEdge.h:349
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition NBEdge.cpp:613
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition NBEdge.cpp:4894
Instance responsible for building networks.
NBNodeCont & getNodeCont()
Returns a reference to the node container.
NBEdgeCont & getEdgeCont()
NBTypeCont & getTypeCont()
Returns a reference to the type container.
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
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:137
PositionVector customShape
optional customShape for this crossing
Definition NBNode.h:162
int customTLIndex
the custom traffic light index of this crossing (if controlled)
Definition NBNode.h:167
bool priority
whether the pedestrians have priority
Definition NBNode.h:160
EdgeVector edges
The edges being crossed.
Definition NBNode.h:144
double width
This crossing's width.
Definition NBNode.h:152
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
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:2507
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:347
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition NBNode.h:222
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition NBNode.h:270
std::vector< std::pair< Position, std::string > > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
Definition NBNode.cpp:4379
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
Definition NBNode.cpp:2756
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition NBNode.h:275
const Position & getPosition() const
Definition NBNode.h:262
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
Definition NBNode.h:280
void updateSurroundingGeometry()
update geometry of node and surrounding edges
Definition NBNode.cpp:1194
double getRadius() const
Returns the turning radius of this node.
Definition NBNode.h:292
bool checkIsRemovable() const
check if node is removable
Definition NBNode.cpp:2673
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition NBNode.h:338
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 std::set< std::string > &typeIDs=std::set< std::string >()) const
writes all EdgeTypes (and their lanes) as XML
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.
void clearTypes()
clear types
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.
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network stored in the given net builder.
Definition NWFrame.cpp:203
static void writeTrafficLights(OutputDevice &into, const NBTrafficLightLogicCont &tllCont, ConnectionStyle style=SUMONET)
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
void resetDefault()
Resets all options to default.
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)
void setApplicationName(const std::string &appName, const std::string &fullName)
Sets the application name.
OptionsCont * clone() const
make a copy of this OptionsCont instance
void removeSubTopic(const std::string &topic)
Removes the given sub-topic.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
void removeOption(const std::string &name)
Removes an option from its subtopic.
bool exists(const std::string &name) const
Returns the information whether the named option is known.
const std::string & getFullName() const
get options full name
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.
Static storage of an output device and its base (abstract) implementation.
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:67
double x() const
Returns the x-position.
Definition Position.h:52
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position (in radians bet...
Definition Position.h:283
void sety(double y)
set position y
Definition Position.h:72
double y() const
Returns the y-position.
Definition Position.h:57
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 amount
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:122
void removeAdditionalGLObject(GUIGlObject *o, const double exaggeration=1)
Removes an additional object (detector/shape/trigger) from being visualised.
Definition SUMORTree.h:158
static StringBijection< SumoXMLNodeType > NodeTypes
node types
bool hasString(const std::string &str) const
check if the given string exist
T get(const std::string &str) const
get key
static std::string trim(const std::string s, const std::string &t=" \t\n")
remove leading and trailing whitespace
static std::string replace(std::string str, const std::string &what, const std::string &by)
Replaces all occurrences of the second string by the third string within the first string.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
Definition json.hpp:5639
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