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