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