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