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 // set output file in SUMO and netedit options
1321 neteditOptions.resetWritable();
1322 neteditOptions.set("output-file", neteditOptions.getString("net-file"));
1323 sumoOptions.resetWritable();
1324 sumoOptions.set("net-file", neteditOptions.getString("net-file"));
1325 // compute without volatile options and update network
1326 computeAndUpdate(neteditOptions, false);
1327 // clear typeContainer
1329 // now update typeContainer with edgeTypes
1330 for (const auto& edgeType : myAttributeCarriers->getEdgeTypes()) {
1331 myNetBuilder->getTypeCont().insertEdgeType(edgeType.first, edgeType.second);
1332 for (int i = 0; i < (int)edgeType.second->getLaneTypes().size(); i++) {
1333 myNetBuilder->getTypeCont().insertLaneType(edgeType.first, i,
1334 edgeType.second->getLaneTypes().at(i)->speed,
1335 edgeType.second->getLaneTypes().at(i)->permissions,
1336 edgeType.second->getLaneTypes().at(i)->width,
1337 edgeType.second->getLaneTypes().at(i)->attrs);
1338 }
1339 }
1340 // write network
1341 NWFrame::writeNetwork(neteditOptions, *myNetBuilder);
1342 // reset output file
1343 sumoOptions.resetWritable();
1344 neteditOptions.resetDefault("output-file");
1345 // mark network as saved
1347}
1348
1349
1350void
1351GNENet::savePlain(const std::string& prefix) {
1352 auto& neteditOptions = OptionsCont::getOptions();
1353 // compute without volatile options
1354 computeAndUpdate(neteditOptions, false);
1355 NWWriter_XML::writeNetwork(neteditOptions, prefix, *myNetBuilder);
1356}
1357
1358
1359void
1360GNENet::saveJoined(const std::string& filename) {
1361 // compute without volatile options
1364}
1365
1366
1367void
1369 // set view net
1370 myViewNet = viewNet;
1371 // add default vTypes
1373 // update all edge geometries
1374 for (const auto& edge : myAttributeCarriers->getEdges()) {
1375 edge.second->updateGeometry();
1376 }
1377 // update view Net and recalculate edge boundaries)
1378 myViewNet->update();
1379 for (const auto& edge : myAttributeCarriers->getEdges()) {
1380 edge.second->updateCenteringBoundary(true);
1381 }
1382}
1383
1384
1385void
1387 // check if object must be inserted in RTREE
1388 if (AC->getTagProperty().isPlacedInRTree() && !AC->inGrid()) {
1390 AC->setInGrid(true);
1391 }
1392}
1393
1394
1395void
1397 // check if object must be inserted in RTREE
1398 if (AC->getTagProperty().isPlacedInRTree() && AC->inGrid()) {
1400 AC->setInGrid(false);
1401 }
1402}
1403
1404
1405void
1406GNENet::computeNetwork(GNEApplicationWindow* window, bool force, bool volatileOptions) {
1407 if (!myNeedRecompute) {
1408 if (force) {
1409 if (volatileOptions) {
1410 window->setStatusBarText(TL("Forced computing junctions with volatile options ..."));
1411 } else {
1412 window->setStatusBarText(TL("Forced computing junctions ..."));
1413 }
1414 } else {
1415 return;
1416 }
1417 } else {
1418 if (volatileOptions) {
1419 window->setStatusBarText(TL("Computing junctions with volatile options ..."));
1420 } else {
1421 window->setStatusBarText(TL("Computing junctions ..."));
1422 }
1423 }
1424 // start recomputing
1425 window->getApp()->beginWaitCursor();
1426 // save current number of lanes for every edge if recomputing is with volatile options
1427 if (volatileOptions) {
1428 for (const auto& edge : myAttributeCarriers->getEdges()) {
1429 myEdgesAndNumberOfLanes[edge.second->getID()] = (int)edge.second->getLanes().size();
1430 }
1431 }
1432 // compute and update
1433 auto& neteditOptions = OptionsCont::getOptions();
1434 computeAndUpdate(neteditOptions, volatileOptions);
1435 // load additionals if was recomputed with volatile options
1436 if (volatileOptions && OptionsCont::getOptions().getString("additional-files").size() > 0) {
1437 // Create additional handler
1438 GNEGeneralHandler generalHandler(this, OptionsCont::getOptions().getString("additional-files"),
1440 // Run parser
1441 if (!generalHandler.parse()) {
1442 WRITE_ERROR(TL("Loading of additional file failed: ") + OptionsCont::getOptions().getString("additional-files"));
1443 } else {
1444 WRITE_MESSAGE(TL("Loading of additional file successfully: ") + OptionsCont::getOptions().getString("additional-files"));
1445 }
1446 }
1447 // load demand elements if was recomputed with volatile options
1448 if (volatileOptions && OptionsCont::getOptions().getString("route-files").size() > 0) {
1449 // Create general handler
1450 GNEGeneralHandler generalHandler(this, OptionsCont::getOptions().getString("route-files"), false, true);
1451 // Run parser
1452 if (!generalHandler.parse()) {
1453 WRITE_ERROR(TL("Loading of route file failed: ") + OptionsCont::getOptions().getString("route-files"));
1454 } else {
1455 WRITE_MESSAGE(TL("Loading of route file successfully: ") + OptionsCont::getOptions().getString("route-files"));
1456 }
1457 }
1458 // load datas if was recomputed with volatile options
1459 if (volatileOptions && OptionsCont::getOptions().getString("data-files").size() > 0) {
1460 // Create data handler
1461 GNEDataHandler dataHandler(this, OptionsCont::getOptions().getString("data-files"), false, true);
1462 // Run parser
1463 if (!dataHandler.parse()) {
1464 WRITE_ERROR(TL("Loading of data file failed: ") + OptionsCont::getOptions().getString("data-files"));
1465 } else {
1466 WRITE_MESSAGE(TL("Loading of data file successfully: ") + OptionsCont::getOptions().getString("data-files"));
1467 }
1468 }
1469 // load meanDatas if was recomputed with volatile options
1470 if (volatileOptions && OptionsCont::getOptions().getString("meandata-files").size() > 0) {
1471 // Create meanData handler
1472 GNEGeneralHandler generalHandler(this, OptionsCont::getOptions().getString("meandata-files"), false, true);
1473 // Run parser
1474 if (!generalHandler.parse()) {
1475 WRITE_ERROR(TL("Loading of meandata file failed: ") + OptionsCont::getOptions().getString("meandata-files"));
1476 } else {
1477 WRITE_MESSAGE(TL("Loading of meandata file successfully: ") + OptionsCont::getOptions().getString("meandata-files"));
1478 }
1479 }
1480 // clear myEdgesAndNumberOfLanes after reload additionals
1482 // end recomputing
1483 window->getApp()->endWaitCursor();
1484 // update status bar
1485 window->setStatusBarText(TL("Finished computing junctions."));
1486}
1487
1488
1489void
1491 window->setStatusBarText(TL("Computing demand elements ..."));
1492 // if we aren't in Demand mode, update path calculator
1496 }
1497 // clear demand paths
1499 // iterate over all demand elements and compute
1500 for (const auto& demandElements : myAttributeCarriers->getDemandElements()) {
1501 for (const auto& demandElement : demandElements.second) {
1502 demandElement.second->computePathElement();
1503 }
1504 }
1505 window->setStatusBarText(TL("Finished computing demand elements."));
1506}
1507
1508
1509void
1511 window->setStatusBarText(TL("Computing data elements ..."));
1512 // iterate over all demand elements and compute
1513 for (const auto& genericDataTag : myAttributeCarriers->getGenericDatas()) {
1514 for (const auto& genericData : genericDataTag.second) {
1515 genericData.second->computePathElement();
1516 }
1517 }
1518 window->setStatusBarText(TL("Finished computing data elements."));
1519}
1520
1521
1522void
1524 // recompute tl-logics
1525 auto& neteditOptions = OptionsCont::getOptions();
1527 // iterate over traffic lights definitions. Make a copy because invalid
1528 // definitions will be removed (and would otherwise destroy the iterator)
1529 const std::set<NBTrafficLightDefinition*> tlsDefs = junction->getNBNode()->getControllingTLS();
1530 for (auto it : tlsDefs) {
1531 it->setParticipantsInformation();
1532 it->setTLControllingInformation();
1533 tllCont.computeSingleLogic(neteditOptions, it);
1534 }
1535
1536 // @todo compute connections etc...
1537}
1538
1539
1540void
1544
1545
1546bool
1548 return !myNeedRecompute;
1549}
1550
1551
1552FXApp*
1554 return myViewNet->getApp();
1555}
1556
1557
1560 return myNetBuilder;
1561}
1562
1563
1564bool
1566 const auto selectedJunctions = myAttributeCarriers->getSelectedJunctions();
1567 if (selectedJunctions.size() < 2) {
1568 return false;
1569 }
1570 EdgeVector allIncoming;
1571 EdgeVector allOutgoing;
1572 std::set<NBNode*, ComparatorIdLess> cluster;
1573 for (const auto& selectedJunction : selectedJunctions) {
1574 cluster.insert(selectedJunction->getNBNode());
1575 const EdgeVector& incoming = selectedJunction->getNBNode()->getIncomingEdges();
1576 allIncoming.insert(allIncoming.end(), incoming.begin(), incoming.end());
1577 const EdgeVector& outgoing = selectedJunction->getNBNode()->getOutgoingEdges();
1578 allOutgoing.insert(allOutgoing.end(), outgoing.begin(), outgoing.end());
1579 }
1580 // create new junction
1581 Position pos;
1582 Position oldPos;
1583 bool setTL = false;
1584 std::string id = "cluster";
1585 TrafficLightType type;
1587 myNetBuilder->getNodeCont().analyzeCluster(cluster, id, pos, setTL, type, nodeType);
1588 // save position
1589 oldPos = pos;
1590 // Check that there isn't another junction in the same position as Pos but doesn't belong to cluster
1591 for (const auto& junction : myAttributeCarriers->getJunctions()) {
1592 if ((junction.second->getPositionInView() == pos) && (cluster.find(junction.second->getNBNode()) == cluster.end())) {
1593 // show warning in gui testing debug mode
1594 WRITE_DEBUG("Opening FXMessageBox 'Join non-selected junction'");
1595 // Ask confirmation to user
1596 const std::string header = TL("Position of joined junction");
1597 const std::string bodyA = TL("There is another unselected junction in the same position of joined junction.");
1598 const std::string bodyB = TL("It will be joined with the other selected junctions. Continue?");
1599 const auto answer = FXMessageBox::question(getApp(), MBOX_YES_NO, header.c_str(), "%s", (bodyA + std::string("\n") + bodyB).c_str());
1600 if (answer != 1) { // 1:yes, 2:no, 4:esc
1601 // write warning if netedit is running in testing mode
1602 if (answer == 2) {
1603 WRITE_DEBUG("Closed FXMessageBox 'Join non-selected junction' with 'No'");
1604 } else if (answer == 4) {
1605 WRITE_DEBUG("Closed FXMessageBox 'Join non-selected junction' with 'ESC'");
1606 }
1607 return false;
1608 } else {
1609 // write warning if netedit is running in testing mode
1610 WRITE_DEBUG("Closed FXMessageBox 'Join non-selected junction' with 'Yes'");
1611 // select conflicted junction an join all again
1612 junction.second->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1613 return joinSelectedJunctions(undoList);
1614 }
1615 }
1616 }
1617 // use checkJunctionPosition to avoid conflicts with junction in the same position as others
1618 while (!checkJunctionPosition(pos)) {
1619 pos.setx(pos.x() + 0.1);
1620 pos.sety(pos.y() + 0.1);
1621 }
1622 // start with the join selected junctions
1623 undoList->begin(GUIIcon::JUNCTION, "Join selected " + toString(SUMO_TAG_JUNCTION) + "s");
1624 GNEJunction* joined = createJunction(pos, undoList);
1625 joined->setAttribute(SUMO_ATTR_TYPE, toString(nodeType), undoList); // i.e. rail crossing
1626 if (setTL) {
1627 joined->setAttribute(SUMO_ATTR_TLTYPE, toString(type), undoList);
1628 }
1630 // first remove all crossing of the involved junctions and edges
1631 // (otherwise edge removal will trigger discarding)
1632 std::vector<NBNode::Crossing> oldCrossings;
1633 for (const auto& selectedJunction : selectedJunctions) {
1634 const auto crossings = selectedJunction->getGNECrossings();
1635 for (auto crossing : crossings) {
1636 deleteCrossing(crossing, undoList);
1637 }
1638 }
1639 // preserve old connections
1640 for (const auto& selectedJunction : selectedJunctions) {
1641 selectedJunction->setLogicValid(false, undoList);
1642 }
1643 // remap edges
1644 for (const auto& incomingEdge : allIncoming) {
1645 if (std::find(allOutgoing.begin(), allOutgoing.end(), incomingEdge) == allOutgoing.end()) {
1646 GNEChange_Attribute::changeAttribute(myAttributeCarriers->getEdges().at(incomingEdge->getID()), SUMO_ATTR_TO, joined->getID(), undoList);
1647 }
1648 }
1649 EdgeSet edgesWithin;
1650 for (const auto& outgoingEdge : allOutgoing) {
1651 // delete edges within the cluster
1652 GNEEdge* edge = myAttributeCarriers->getEdges().at(outgoingEdge->getID());
1653 if (edge->getToJunction() == joined) {
1654 edgesWithin.insert(outgoingEdge);
1655 deleteEdge(edge, undoList, false);
1656 } else {
1657 GNEChange_Attribute::changeAttribute(myAttributeCarriers->getEdges().at(outgoingEdge->getID()), SUMO_ATTR_FROM, joined->getID(), undoList);
1658 }
1659 }
1660 // remap all crossing of the involved junctions and edges
1661 for (const auto& nbc : oldCrossings) {
1662 bool keep = true;
1663 for (NBEdge* e : nbc.edges) {
1664 if (edgesWithin.count(e) != 0) {
1665 keep = false;
1666 break;
1667 }
1668 };
1669 if (keep) {
1670 undoList->add(new GNEChange_Crossing(joined, nbc.edges, nbc.width,
1671 nbc.priority || joined->getNBNode()->isTLControlled(),
1672 nbc.customTLIndex, nbc.customTLIndex2, nbc.customShape,
1673 false, true), true);
1674 }
1675 }
1676 // delete original junctions
1677 for (const auto& selectedJunction : selectedJunctions) {
1678 deleteJunction(selectedJunction, undoList);
1679 }
1680 joined->setAttribute(SUMO_ATTR_ID, id, undoList);
1681
1682 // check if joined junction had to change their original position to avoid errors
1683 if (pos != oldPos) {
1684 joined->setAttribute(SUMO_ATTR_POSITION, toString(oldPos), undoList);
1685 }
1686 undoList->end();
1687 return true;
1688}
1689
1690
1691bool
1693 // obtain current net's crossings
1694 std::vector<GNECrossing*> myNetCrossings;
1695 for (const auto& junction : myAttributeCarriers->getJunctions()) {
1696 myNetCrossings.reserve(myNetCrossings.size() + junction.second->getGNECrossings().size());
1697 myNetCrossings.insert(myNetCrossings.end(), junction.second->getGNECrossings().begin(), junction.second->getGNECrossings().end());
1698 }
1699 // obtain invalid crossings
1700 std::vector<GNECrossing*> myInvalidCrossings;
1701 for (auto i = myNetCrossings.begin(); i != myNetCrossings.end(); i++) {
1702 if (!(*i)->getNBCrossing()->valid) {
1703 myInvalidCrossings.push_back(*i);
1704 }
1705 }
1706
1707 if (myInvalidCrossings.empty()) {
1708 // show warning in gui testing debug mode
1709 WRITE_DEBUG("Opening FXMessageBox 'No crossing to remove'");
1710 // open a dialog informing that there isn't crossing to remove
1711 const std::string header = TL("Clear crossings");
1712 const std::string body = TL("There are no invalid crossings to remove.");
1713 FXMessageBox::warning(getApp(), MBOX_OK, (header).c_str(), "%s", (body).c_str());
1714 // show warning in gui testing debug mode
1715 WRITE_DEBUG("Closed FXMessageBox 'No crossing to remove' with 'OK'");
1716 } else {
1717 std::string plural = myInvalidCrossings.size() == 1 ? ("") : ("s");
1718 // show warning in gui testing debug mode
1719 WRITE_DEBUG("Opening FXMessageBox 'clear crossings'");
1720 // Ask confirmation to user
1721 const std::string header = TL("Clear crossings");
1722 const std::string body = TL("Crossings will be cleared. Continue?");
1723 const auto answer = FXMessageBox::question(getApp(), MBOX_YES_NO, header.c_str(), "%s", body.c_str());
1724 // 1:yes, 2:no, 4:esc
1725 if (answer != 1) {
1726 // write warning if netedit is running in testing mode
1727 if (answer == 2) {
1728 WRITE_DEBUG("Closed FXMessageBox 'clear crossings' with 'No'");
1729 } else if (answer == 4) {
1730 WRITE_DEBUG("Closed FXMessageBox 'clear crossings' with 'ESC'");
1731 }
1732 } else {
1733 undoList->begin(GUIIcon::MODEDELETE, TL("clear crossings"));
1734 for (auto i = myInvalidCrossings.begin(); i != myInvalidCrossings.end(); i++) {
1735 deleteCrossing((*i), undoList);
1736 }
1737 undoList->end();
1738 }
1739 }
1740 return 1;
1741}
1742
1743
1744void
1746 undoList->begin(GUIIcon::MODEDELETE, TL("clear junctions"));
1747 std::vector<GNEJunction*> toRemove;
1748 for (auto& junction : myAttributeCarriers->getJunctions()) {
1749 if (junction.second->getNBNode()->getEdges().size() == 0) {
1750 toRemove.push_back(junction.second);
1751 }
1752 }
1753 for (auto junction : toRemove) {
1754 deleteJunction(junction, undoList);
1755 }
1756 undoList->end();
1757}
1758
1759
1760void
1762 // first declare a vector to save all routes without children
1763 std::vector<GNEDemandElement*> routesWithoutChildren;
1764 routesWithoutChildren.reserve(myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE).size());
1765 // iterate over routes
1766 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
1767 if (route.second->getChildDemandElements().empty()) {
1768 routesWithoutChildren.push_back(route.second);
1769 }
1770 }
1771 // finally remove all routesWithoutChildren
1772 if (routesWithoutChildren.size() > 0) {
1773 // begin undo list
1774 undoList->begin(GUIIcon::MODEDELETE, TL("clear unused routes"));
1775 // iterate over routesWithoutChildren
1776 for (const auto& i : routesWithoutChildren) {
1777 // due route doesn't have children, simply call GNEChange_DemandElement
1778 undoList->add(new GNEChange_DemandElement(i, false), true);
1779 }
1780 // end undo list
1781 undoList->end();
1782 }
1783}
1784
1785
1786void
1788 // first declare a sorted set of sorted route's edges in string format
1789 std::set<std::pair<std::string, GNEDemandElement*> > mySortedRoutes;
1790 // iterate over routes and save it in mySortedRoutes (only if it doesn't have Stop Children)
1791 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
1792 // first check route has stops
1793 bool hasStops = false;
1794 for (const auto& stop : route.second->getChildDemandElements()) {
1795 if (stop->getTagProperty().isVehicleStop()) {
1796 hasStops = true;
1797 }
1798 }
1799 if (!hasStops) {
1800 mySortedRoutes.insert(std::make_pair(GNEAttributeCarrier::parseIDs(route.second->getParentEdges()), route.second));
1801 }
1802 }
1803 // now declare a matrix in which organize routes to be merged
1804 std::vector<std::vector<GNEDemandElement*> > routesToMerge;
1805 auto index = mySortedRoutes.begin();
1806 // iterate over mySortedRoutes
1807 for (auto i = mySortedRoutes.begin(); i != mySortedRoutes.end(); i++) {
1808 if (routesToMerge.empty()) {
1809 routesToMerge.push_back({i->second});
1810 } else {
1811 if (index->first == i->first) {
1812 routesToMerge.back().push_back(i->second);
1813 } else {
1814 routesToMerge.push_back({i->second});
1815 index = i;
1816 }
1817 }
1818 }
1819 // now check if there is routes to merge
1820 bool thereIsRoutesToMerge = false;
1821 for (const auto& i : routesToMerge) {
1822 if (i.size() > 1) {
1823 thereIsRoutesToMerge = true;
1824 }
1825 }
1826 // if exist
1827 if (thereIsRoutesToMerge) {
1828 // begin undo list
1829 undoList->begin(GUIIcon::ROUTE, TL("merge routes"));
1830 // iterate over route to edges
1831 for (const auto& routes : routesToMerge) {
1832 if (routes.size() > 1) {
1833 // iterate over duplicated routes
1834 for (int i = 1; i < (int)routes.size(); i++) {
1835 // move all vehicles of every duplicated route
1836 while (routes.at(i)->getChildDemandElements().size() > 0) {
1837 routes.at(i)->getChildDemandElements().front()->setAttribute(SUMO_ATTR_ROUTE, routes.at(0)->getID(), undoList);
1838 }
1839 // finally remove route
1840 undoList->add(new GNEChange_DemandElement(routes.at(i), false), true);
1841 }
1842 }
1843 }
1844 // end undo list
1845 undoList->end();
1846 }
1847}
1848
1849
1850void
1852 // declare personPlan-pos map
1853 std::map<GNEDemandElement*, std::string> personPlanMap;
1854 // iterate over persons
1855 for (const auto& persontag : {
1857 }) {
1858 for (const auto& person : myAttributeCarriers->getDemandElements().at(persontag)) {
1859 if (person.second->getChildDemandElements().size() > 0) {
1860 // get person plan
1861 GNEDemandElement* personPlan = person.second->getChildDemandElements().front();
1862 // iterate over all personPlans
1863 while (personPlan) {
1864 // check if personPlan is a stopPerson over edge
1865 if (personPlan->getTagProperty().getTag() == GNE_TAG_STOPPERSON_EDGE) {
1866 // get previous person plan
1867 GNEDemandElement* previousPersonPlan = person.second->getPreviousChildDemandElement(personPlan);
1868 // check if arrivalPos of previous personPlan is different of endPos of stopPerson
1869 if (previousPersonPlan && previousPersonPlan->getTagProperty().hasAttribute(SUMO_ATTR_ARRIVALPOS) &&
1870 (previousPersonPlan->getAttribute(SUMO_ATTR_ARRIVALPOS) != personPlan->getAttribute(SUMO_ATTR_ENDPOS))) {
1871 personPlanMap[previousPersonPlan] = personPlan->getAttribute(SUMO_ATTR_ENDPOS);
1872 }
1873 }
1874 // go to next person plan
1875 personPlan = person.second->getNextChildDemandElement(personPlan);
1876 }
1877 }
1878 }
1879 }
1880 // continue if there is personPlanMap to adjust
1881 if (personPlanMap.size() > 0) {
1882 // begin undo list
1883 undoList->begin(GUIIcon::MODEPERSONPLAN, TL("adjust person plans"));
1884 // iterate over invalidDemandElements
1885 for (const auto& personPlan : personPlanMap) {
1886 // set arrivalPos attribute
1887 personPlan.first->setAttribute(SUMO_ATTR_ARRIVALPOS, personPlan.second, undoList);
1888 }
1889 // end undo list
1890 undoList->end();
1891 }
1892}
1893
1894
1895void
1897 // first declare a vector to save all invalid demand elements
1898 std::vector<GNEDemandElement*> invalidDemandElements;
1899 invalidDemandElements.reserve(myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE).size() +
1902 // iterate over routes
1903 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
1904 if (route.second->isDemandElementValid() != GNEDemandElement::Problem::OK) {
1905 invalidDemandElements.push_back(route.second);
1906 }
1907 }
1908 // iterate over flows
1909 for (const auto& flow : myAttributeCarriers->getDemandElements().at(SUMO_TAG_FLOW)) {
1910 if (flow.second->isDemandElementValid() != GNEDemandElement::Problem::OK) {
1911 invalidDemandElements.push_back(flow.second);
1912 }
1913 }
1914 // iterate over trip
1915 for (const auto& trip : myAttributeCarriers->getDemandElements().at(SUMO_TAG_TRIP)) {
1916 if (trip.second->isDemandElementValid() != GNEDemandElement::Problem::OK) {
1917 invalidDemandElements.push_back(trip.second);
1918 }
1919 }
1920 // continue if there is invalidDemandElements to remove
1921 if (invalidDemandElements.size() > 0) {
1922 // begin undo list
1923 undoList->begin(GUIIcon::MODEDELETE, TL("remove invalid demand elements"));
1924 // iterate over invalidDemandElements
1925 for (const auto& invalidDemandElement : invalidDemandElements) {
1926 // simply call GNEChange_DemandElement
1927 undoList->add(new GNEChange_DemandElement(invalidDemandElement, false), true);
1928 }
1929 // end undo list
1930 undoList->end();
1931 }
1932}
1933
1934void
1936 if (junction->getNBNode()->checkIsRemovable()) {
1937 // start operation
1938 undoList->begin(junction, TL("replace junction by geometry"));
1939 // obtain Edges to join
1940 std::vector<std::pair<NBEdge*, NBEdge*> > toJoin = junction->getNBNode()->getEdgesToJoin();
1941 // clear connections of junction to replace
1942 clearJunctionConnections(junction, undoList);
1943 // iterate over NBEdges to join
1944 for (auto j : toJoin) {
1945 // obtain GNEEdges
1946 GNEEdge* begin = myAttributeCarriers->getEdges().at(j.first->getID());
1947 GNEEdge* continuation = myAttributeCarriers->getEdges().at(j.second->getID());
1948 // remove connections between the edges
1949 std::vector<NBEdge::Connection> connections = begin->getNBEdge()->getConnections();
1950 for (auto con : connections) {
1951 undoList->add(new GNEChange_Connection(begin, con, false, false), true);
1952 }
1953 // fix shape of replaced edge
1954 PositionVector newShape = begin->getNBEdge()->getInnerGeometry();
1956 newShape.push_back(junction->getNBNode()->getPosition());
1957 } else {
1958 newShape.push_back(begin->getNBEdge()->getGeometry()[-1]);
1959 }
1960 if (continuation->getNBEdge()->hasDefaultGeometryEndpointAtNode(begin->getNBEdge()->getToNode())) {
1961 newShape.push_back_noDoublePos(junction->getNBNode()->getPosition());
1962 } else {
1963 newShape.push_back_noDoublePos(continuation->getNBEdge()->getGeometry()[0]);
1964 }
1965 // replace incoming edge
1966 replaceIncomingEdge(continuation, begin, undoList);
1967
1968 newShape.append(continuation->getNBEdge()->getInnerGeometry());
1969 begin->setAttribute(GNE_ATTR_SHAPE_END, continuation->getAttribute(GNE_ATTR_SHAPE_END), undoList);
1970 begin->setAttribute(SUMO_ATTR_ENDOFFSET, continuation->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
1971 begin->setAttribute(SUMO_ATTR_SHAPE, toString(newShape), undoList);
1972 begin->getNBEdge()->resetNodeBorder(begin->getNBEdge()->getToNode());
1973 // fix loaded lengths
1974 if (begin->getNBEdge()->hasLoadedLength() || continuation->getNBEdge()->hasLoadedLength()) {
1975 begin->setAttribute(SUMO_ATTR_LENGTH, toString(begin->getNBEdge()->getLoadedLength() + continuation->getNBEdge()->getLoadedLength()), undoList);
1976 }
1977 }
1978 //delete replaced junction
1979 deleteJunction(junction, undoList);
1980 // finish operation
1981 undoList->end();
1982 } else {
1983 throw ProcessError(TL("Junction isn't removable"));
1984 }
1985}
1986
1987
1988void
1989GNENet::splitJunction(GNEJunction* junction, bool reconnect, GNEUndoList* undoList) {
1990 std::vector<std::pair<Position, std::string> > endpoints = junction->getNBNode()->getEndPoints();
1991 if (endpoints.size() < 2) {
1992 return;
1993 }
1994 // start operation
1995 undoList->begin(junction, TL("split junction"));
1996 // record connections
1997 std::map<GNEEdge*, std::vector<NBEdge::Connection>> straightConnections;
1998 for (GNEEdge* e : junction->getGNEIncomingEdges()) {
1999 for (const auto& c : e->getNBEdge()->getConnections()) {
2000 if (c.fromLane >= 0 && junction->getNBNode()->getDirection(e->getNBEdge(), c.toEdge) == LinkDirection::STRAIGHT) {
2001 straightConnections[e].push_back(c);
2002 }
2003 };
2004 }
2005 //std::cout << "split junction at endpoints:\n";
2006
2007 junction->setLogicValid(false, undoList);
2008 for (const auto& pair : endpoints) {
2009 const Position& pos = pair.first;
2010 const std::string& origID = pair.second;
2011 GNEJunction* newJunction = createJunction(pos, undoList);
2012 std::string newID = origID != "" ? origID : newJunction->getID();
2013 // make a copy because the original vectors are modified during iteration
2014 const std::vector<GNEEdge*> incoming = junction->getGNEIncomingEdges();
2015 const std::vector<GNEEdge*> outgoing = junction->getGNEOutgoingEdges();
2016 //std::cout << " checkEndpoint " << pair.first << " " << pair.second << " newID=" << newID << "\n";
2017 for (GNEEdge* e : incoming) {
2018 //std::cout << " incoming " << e->getID() << " pos=" << pos << " origTo=" << e->getNBEdge()->getParameter("origTo") << " newID=" << newID << "\n";
2019 if (e->getNBEdge()->getGeometry().back().almostSame(pos) || e->getNBEdge()->getParameter("origTo") == newID) {
2020 //std::cout << " match\n";
2021 GNEChange_Attribute::changeAttribute(e, SUMO_ATTR_TO, newJunction->getID(), undoList);
2022 }
2023 }
2024 for (GNEEdge* e : outgoing) {
2025 //std::cout << " outgoing " << e->getID() << " pos=" << pos << " origFrom=" << e->getNBEdge()->getParameter("origFrom") << " newID=" << newID << "\n";
2026 if (e->getNBEdge()->getGeometry().front().almostSame(pos) || e->getNBEdge()->getParameter("origFrom") == newID) {
2027 //std::cout << " match\n";
2028 GNEChange_Attribute::changeAttribute(e, SUMO_ATTR_FROM, newJunction->getID(), undoList);
2029 }
2030 }
2031 if (newID != newJunction->getID()) {
2032 if (newJunction->isValid(SUMO_ATTR_ID, newID)) {
2033 GNEChange_Attribute::changeAttribute(newJunction, SUMO_ATTR_ID, newID, undoList);
2034 } else {
2035 WRITE_WARNINGF(TL("Could not rename split node to '%'"), newID);
2036 }
2037 }
2038 }
2039 // recreate edges from straightConnections
2040 if (reconnect) {
2041 for (const auto& item : straightConnections) {
2042 GNEEdge* in = item.first;
2043 std::map<NBEdge*, GNEEdge*> newEdges;
2044 for (auto& c : item.second) {
2045 GNEEdge* out = myAttributeCarriers->retrieveEdge(c.toEdge->getID());
2046 GNEEdge* newEdge = nullptr;
2047 if (in->getToJunction() == out->getFromJunction()) {
2048 continue;
2049 }
2050 if (newEdges.count(c.toEdge) == 0) {
2051 newEdge = createEdge(in->getToJunction(), out->getFromJunction(), in, undoList);
2052 newEdges[c.toEdge] = newEdge;
2053 newEdge->setAttribute(SUMO_ATTR_NUMLANES, "1", undoList);
2054 } else {
2055 newEdge = newEdges[c.toEdge];
2056 duplicateLane(newEdge->getLanes().back(), undoList, true);
2057 }
2058 // copy permissions
2059 newEdge->getLanes().back()->setAttribute(SUMO_ATTR_ALLOW,
2060 in->getLanes()[c.fromLane]-> getAttribute(SUMO_ATTR_ALLOW), undoList);
2061 }
2062 }
2063 }
2064
2065 deleteJunction(junction, undoList);
2066 // finish operation
2067 undoList->end();
2068}
2069
2070
2071
2072void
2074 undoList->begin(GUIIcon::MODEDELETE, TL("clear junction connections"));
2075 std::vector<GNEConnection*> connections = junction->getGNEConnections();
2076 // Iterate over all connections and clear it
2077 for (auto i : connections) {
2078 deleteConnection(i, undoList);
2079 }
2080 undoList->end();
2081}
2082
2083
2084void
2086 undoList->begin(junction, TL("reset junction connections"));
2087 // first clear connections
2088 clearJunctionConnections(junction, undoList);
2089 // invalidate logic to create new connections in the next recomputing
2090 junction->setLogicValid(false, undoList);
2091 undoList->end();
2092}
2093
2094
2095void
2097 undoList->begin(GUIIcon::MODEDELETE, TL("clear additional elements"));
2098 // clear additionals
2099 for (const auto& additionalMap : myAttributeCarriers->getAdditionals()) {
2100 while (additionalMap.second.size() > 0) {
2101 deleteAdditional(additionalMap.second.begin()->second, undoList);
2102 }
2103 }
2104 undoList->end();
2105}
2106
2107
2108void
2110 undoList->begin(GUIIcon::MODEDELETE, TL("clear demand elements"));
2111 // clear demand elements
2112 for (const auto& demandElementsMap : myAttributeCarriers->getDemandElements()) {
2113 while (demandElementsMap.second.size() > 0) {
2114 deleteDemandElement(demandElementsMap.second.begin()->second, undoList);
2115 }
2116 }
2117 undoList->end();
2118}
2119
2120
2121void
2123 undoList->begin(GUIIcon::MODEDELETE, TL("clear data elements"));
2124 // clear data sets
2125 for (const auto& dataSet : myAttributeCarriers->getDataSets()) {
2126 deleteDataSet(dataSet.second, undoList);
2127 }
2128 undoList->end();
2129}
2130
2131
2132void
2134 undoList->begin(GUIIcon::MODEDELETE, TL("clear meanData elements"));
2135 // clear meanDatas
2136 for (const auto& meanDataMap : myAttributeCarriers->getMeanDatas()) {
2137 while (meanDataMap.second.size() > 0) {
2138 deleteMeanData(meanDataMap.second.begin()->second, undoList);
2139 }
2140 }
2141 undoList->end();
2142}
2143
2144
2145void
2146GNENet::changeEdgeEndpoints(GNEEdge* edge, const std::string& newSource, const std::string& newDest) {
2149 edge->getNBEdge()->reinitNodes(from, to);
2151}
2152
2153
2156 return myViewNet;
2157}
2158
2159
2164
2165
2170
2171
2172void
2176
2177
2178void
2180 myExplicitTurnarounds.erase(id);
2181}
2182
2183
2184void
2186 // obtain invalid additionals depending of number of their parent lanes
2187 std::vector<GNEAdditional*> invalidSingleLaneAdditionals;
2188 std::vector<GNEAdditional*> invalidMultiLaneAdditionals;
2189 // iterate over additionals and obtain invalids
2190 for (const auto& additionalPair : myAttributeCarriers->getAdditionals()) {
2191 for (const auto& addditional : additionalPair.second) {
2192 // check if has to be fixed
2193 if (addditional.second->getTagProperty().hasAttribute(SUMO_ATTR_LANE) && !addditional.second->isAdditionalValid()) {
2194 invalidSingleLaneAdditionals.push_back(addditional.second);
2195 } else if (addditional.second->getTagProperty().hasAttribute(SUMO_ATTR_LANES) && !addditional.second->isAdditionalValid()) {
2196 invalidMultiLaneAdditionals.push_back(addditional.second);
2197 }
2198 }
2199 }
2200 // if there are invalid StoppingPlaces or detectors, open GNEFixAdditionalElements
2201 if (invalidSingleLaneAdditionals.size() > 0 || invalidMultiLaneAdditionals.size() > 0) {
2202 // 0 -> Canceled Saving, with or without selecting invalid stopping places and E2
2203 // 1 -> Invalid stoppingPlaces and E2 fixed, friendlyPos enabled, or saved with invalid positions
2204 GNEFixAdditionalElements fixAdditionalElementsDialog(myViewNet, invalidSingleLaneAdditionals, invalidMultiLaneAdditionals);
2205 if (fixAdditionalElementsDialog.execute() == 0) {
2206 // show debug information
2207 WRITE_DEBUG("Additionals saving aborted");
2208 } else {
2210 // show debug information
2211 WRITE_DEBUG("Additionals saved after dialog");
2212 }
2213 // set focus again in net
2214 myViewNet->setFocus();
2215 } else {
2217 // show debug information
2218 WRITE_DEBUG("Additionals saved");
2219 }
2220}
2221
2222
2223void
2224GNENet::saveJuPedSimElements(const std::string& file) {
2225 OutputDevice& device = OutputDevice::getDevice(file);
2226 // open header
2227 device.writeXMLHeader("additional", "additional_file.xsd", EMPTY_HEADER, false);
2228 // juPedSim elements
2229 writeJuPedSimComment(device);
2232 // close device
2233 device.close();
2234}
2235
2236
2237void
2239 // first recompute demand elements
2241 // obtain invalid demandElements depending of number of their parent lanes
2242 std::vector<GNEDemandElement*> invalidSingleLaneDemandElements;
2243 // iterate over demandElements and obtain invalids
2244 for (const auto& demandElementSet : myAttributeCarriers->getDemandElements()) {
2245 for (const auto& demandElement : demandElementSet.second) {
2246 // compute before check if demand element is valid
2247 demandElement.second->computePathElement();
2248 // check if has to be fixed
2249 if (demandElement.second->isDemandElementValid() != GNEDemandElement::Problem::OK) {
2250 invalidSingleLaneDemandElements.push_back(demandElement.second);
2251 }
2252 }
2253 }
2254 // if there are invalid demand elements, open GNEFixDemandElements
2255 if (invalidSingleLaneDemandElements.size() > 0) {
2256 // 0 -> Canceled Saving, with or without selecting invalid demand elements
2257 // 1 -> Invalid demand elements fixed, friendlyPos enabled, or saved with invalid positions
2258 GNEFixDemandElements fixDemandElementsDialog(myViewNet, invalidSingleLaneDemandElements);
2259 if (fixDemandElementsDialog.execute() == 0) {
2260 // show debug information
2261 WRITE_DEBUG("demand elements saving aborted");
2262 } else {
2264 // show debug information
2265 WRITE_DEBUG("demand elements saved after dialog");
2266 }
2267 // set focus again in net
2268 myViewNet->setFocus();
2269 } else {
2271 // show debug information
2272 WRITE_DEBUG("demand elements saved");
2273 }
2274}
2275
2276
2277void
2279 // first recompute data sets
2281 // save data elements
2283 // show debug information
2284 WRITE_DEBUG("data sets saved");
2285}
2286
2287
2288double
2290 double minimumBegin = 0;
2291 // update with first minimum (if exist)
2292 if (myAttributeCarriers->getDataIntervals().size() > 0) {
2293 minimumBegin = myAttributeCarriers->getDataIntervals().begin()->second->getAttributeDouble(SUMO_ATTR_BEGIN);
2294 }
2295 // iterate over interval
2296 for (const auto& interval : myAttributeCarriers->getDataIntervals()) {
2297 if (interval.second->getAttributeDouble(SUMO_ATTR_BEGIN) < minimumBegin) {
2298 minimumBegin = interval.second->getAttributeDouble(SUMO_ATTR_BEGIN);
2299 }
2300 }
2301 return minimumBegin;
2302}
2303
2304
2305double
2307 double maximumEnd = 0;
2308 // update with first maximum (if exist)
2309 if (myAttributeCarriers->getDataIntervals().size() > 0) {
2310 maximumEnd = myAttributeCarriers->getDataIntervals().begin()->second->getAttributeDouble(SUMO_ATTR_END);
2311 }
2312 // iterate over intervals
2313 for (const auto& interval : myAttributeCarriers->getDataIntervals()) {
2314 if (interval.second->getAttributeDouble(SUMO_ATTR_END) > maximumEnd) {
2315 maximumEnd = interval.second->getAttributeDouble(SUMO_ATTR_END);
2316 }
2317 }
2318 return maximumEnd;
2319}
2320
2321
2322void
2325 // show debug information
2326 WRITE_DEBUG("MeanDatas saved");
2327}
2328
2329
2330void
2332 OutputDevice& device = OutputDevice::getDevice(OptionsCont::getOptions().getString("additional-files"));
2333 // open header
2334 device.writeXMLHeader("additional", "additional_file.xsd", EMPTY_HEADER, false);
2335 // write vTypes with additional childrens (due calibrators)
2336 writeVTypeComment(device, true);
2337 writeVTypeDistributions(device, true);
2338 writeVTypes(device, true);
2339 // write routes with additional children (due route prob reroutes)
2340 writeRouteComment(device, true);
2341 writeRouteDistributions(device, true);
2342 writeRoutes(device, true);
2343 // routeProbes
2344 writeRouteProbeComment(device);
2346 // calibrator
2347 writeCalibratorComment(device);
2349 // stoppingPlaces
2356 // detectors
2357 writeDetectorComment(device);
2362 // Other additionals
2367 // shapes
2368 writeShapesComment(device);
2371 // TAZs
2372 writeTAZComment(device);
2374 // Wire element
2375 writeWireComment(device);
2379 // juPedSim elements
2380 writeJuPedSimComment(device);
2383 // close device
2384 device.close();
2385 // mark additionals as saved
2387}
2388
2389
2390void
2392 OutputDevice& device = OutputDevice::getDevice(OptionsCont::getOptions().getString("route-files"));
2393 // open header
2394 device.writeXMLHeader("routes", "routes_file.xsd", EMPTY_HEADER, false);
2395 // first write all vTypeDistributions (and their vTypes)
2396 writeVTypeComment(device, false);
2397 writeVTypes(device, false);
2398 writeVTypeDistributions(device, false);
2399 // now write all routes (and their associated stops), except routes with additional children (due routeProbReroutes)
2400 writeRouteComment(device, false);
2401 writeRoutes(device, false);
2402 writeRouteDistributions(device, false);
2403 // sort vehicles/persons by depart
2404 std::map<double, std::map<std::pair<SumoXMLTag, std::string>, GNEDemandElement*> > vehiclesSortedByDepart;
2405 for (const auto& demandElementTag : myAttributeCarriers->getDemandElements()) {
2406 for (const auto& demandElement : demandElementTag.second) {
2407 if (demandElement.second->getTagProperty().isVehicle() || demandElement.second->getTagProperty().isPerson() || demandElement.second->getTagProperty().isContainer()) {
2408 vehiclesSortedByDepart[demandElement.second->getAttributeDouble(SUMO_ATTR_DEPART)][std::make_pair(demandElement.second->getTagProperty().getTag(), demandElement.second->getID())] = demandElement.second;
2409 }
2410 }
2411 }
2412 // finally write all vehicles, persons and containers sorted by depart time (and their associated stops, personPlans, etc.)
2413 if (vehiclesSortedByDepart.size() > 0) {
2414 device << (" <!-- Vehicles, persons and containers (sorted by depart) -->\n");
2415 for (const auto& vehicleTag : vehiclesSortedByDepart) {
2416 for (const auto& vehicle : vehicleTag.second) {
2417 vehicle.second->writeDemandElement(device);
2418 }
2419 }
2420 }
2421 // close device
2422 device.close();
2423 // mark demand elements as saved
2425}
2426
2427
2428void
2430 OutputDevice& device = OutputDevice::getDevice(OptionsCont::getOptions().getString("data-files"));
2431 device.writeXMLHeader("data", "datamode_file.xsd", EMPTY_HEADER, false);
2432 // write all data sets
2433 for (const auto& dataSet : myAttributeCarriers->getDataSets()) {
2434 dataSet.second->writeDataSet(device);
2435 }
2436 // close device
2437 device.close();
2438 // mark data element as saved
2440}
2441
2442
2443void
2445 OutputDevice& device = OutputDevice::getDevice(OptionsCont::getOptions().getString("meandata-files"));
2446 // open header
2447 device.writeXMLHeader("additional", "additional_file.xsd", EMPTY_HEADER, false);
2448 // MeanDataEdges
2451 // MeanDataLanes
2454 // close device
2455 device.close();
2456 // mark mean datas as saved
2458}
2459
2460
2461void
2462GNENet::writeAdditionalByType(OutputDevice& device, const std::vector<SumoXMLTag> tags) const {
2463 std::map<std::string, GNEAdditional*> sortedAdditionals;
2464 for (const auto& tag : tags) {
2465 for (const auto& additional : myAttributeCarriers->getAdditionals().at(tag)) {
2466 if (sortedAdditionals.count(additional.second->getID()) == 0) {
2467 sortedAdditionals[additional.second->getID()] = additional.second;
2468 } else {
2469 throw ProcessError(TL("Duplicated ID"));
2470 }
2471 }
2472 }
2473 for (const auto& additional : sortedAdditionals) {
2474 additional.second->writeAdditional(device);
2475 }
2476}
2477
2478
2479void
2481 std::map<std::string, GNEDemandElement*> sortedDemandElements;
2482 for (const auto& demandElement : myAttributeCarriers->getDemandElements().at(tag)) {
2483 sortedDemandElements[demandElement.second->getID()] = demandElement.second;
2484 }
2485 for (const auto& demandElement : sortedDemandElements) {
2486 demandElement.second->writeDemandElement(device);
2487 }
2488}
2489
2490
2491void
2492GNENet::writeRouteDistributions(OutputDevice& device, const bool additionalFile) const {
2493 std::map<std::string, GNEDemandElement*> sortedElements;
2494 // first write route Distributions
2495 for (const auto& routeDistribution : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE_DISTRIBUTION)) {
2496 // get number of additional children
2497 const auto numChildren = routeDistribution.second->getAttributeDouble(GNE_ATTR_ADDITIONALCHILDREN);
2498 if ((additionalFile && (numChildren != 0)) || (!additionalFile && (numChildren == 0))) {
2499 sortedElements[routeDistribution.second->getID()] = routeDistribution.second;
2500 }
2501 }
2502 for (const auto& element : sortedElements) {
2503 element.second->writeDemandElement(device);
2504 }
2505 sortedElements.clear();
2506}
2507
2508
2509void
2510GNENet::writeRoutes(OutputDevice& device, const bool additionalFile) const {
2511 std::map<std::string, GNEDemandElement*> sortedRoutes;
2512 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
2513 if ((additionalFile && (route.second->getChildAdditionals().size() > 0)) ||
2514 (!additionalFile && (route.second->getChildAdditionals().size() == 0))) {
2515 sortedRoutes[route.second->getID()] = route.second;
2516 }
2517 }
2518 for (const auto& route : sortedRoutes) {
2519 route.second->writeDemandElement(device);
2520 }
2521}
2522
2523
2524void
2525GNENet::writeVTypeDistributions(OutputDevice& device, const bool additionalFile) const {
2526 std::map<std::string, GNEDemandElement*> sortedElements;
2527 // first write vType Distributions
2528 for (const auto& vTypeDistribution : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE_DISTRIBUTION)) {
2529 // get number of additional children
2530 const auto numChildren = vTypeDistribution.second->getAttributeDouble(GNE_ATTR_ADDITIONALCHILDREN);
2531 if ((additionalFile && (numChildren != 0)) || (!additionalFile && (numChildren == 0))) {
2532 sortedElements[vTypeDistribution.second->getID()] = vTypeDistribution.second;
2533 }
2534 }
2535 for (const auto& element : sortedElements) {
2536 element.second->writeDemandElement(device);
2537 }
2538 sortedElements.clear();
2539}
2540
2541
2542void
2543GNENet::writeVTypes(OutputDevice& device, const bool additionalFile) const {
2544 std::map<std::string, GNEDemandElement*> sortedElements;
2545 // write vTypes
2546 for (const auto& vType : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE)) {
2547 // get number of additional children
2548 const auto numChildren = vType.second->getChildAdditionals().size();
2549 if ((additionalFile && (numChildren != 0)) || (!additionalFile && (numChildren == 0))) {
2550 sortedElements[vType.second->getID()] = vType.second;
2551 }
2552 }
2553 for (const auto& element : sortedElements) {
2554 element.second->writeDemandElement(device);
2555 }
2556}
2557
2558
2559void
2561 std::map<std::string, GNEMeanData*> sortedMeanDatas;
2562 for (const auto& meanData : myAttributeCarriers->getMeanDatas().at(tag)) {
2563 if (sortedMeanDatas.count(meanData.second->getID()) == 0) {
2564 sortedMeanDatas[meanData.second->getID()] = meanData.second;
2565 } else {
2566 throw ProcessError(TL("Duplicated ID"));
2567 }
2568 }
2569 for (const auto& additional : sortedMeanDatas) {
2570 additional.second->writeMeanData(device);
2571 }
2572}
2573
2574bool
2575GNENet::writeVTypeComment(OutputDevice& device, const bool additionalFile) const {
2576 // vTypes
2577 for (const auto& vType : myAttributeCarriers->getDemandElements().at(SUMO_TAG_VTYPE)) {
2578 // special case for default vTypes
2579 const bool defaultVType = GNEAttributeCarrier::parse<bool>(vType.second->getAttribute(GNE_ATTR_DEFAULT_VTYPE));
2580 const bool defaultVTypeModified = GNEAttributeCarrier::parse<bool>(vType.second->getAttribute(GNE_ATTR_DEFAULT_VTYPE_MODIFIED));
2581 // only write default vType modified
2582 if ((vType.second->getParentDemandElements().size() == 0) && (!defaultVType || (defaultVType && defaultVTypeModified))) {
2583 if (additionalFile && (vType.second->getChildAdditionals().size() != 0)) {
2584 device << (" <!-- VTypes (used in calibratorFlows) -->\n");
2585 return true;
2586 } else if (!additionalFile && (vType.second->getChildAdditionals().size() == 0)) {
2587 device << (" <!-- VTypes -->\n");
2588 return true;
2589 }
2590 }
2591 }
2592 return false;
2593}
2594
2595
2596bool
2597GNENet::writeRouteComment(OutputDevice& device, const bool additionalFile) const {
2598 for (const auto& route : myAttributeCarriers->getDemandElements().at(SUMO_TAG_ROUTE)) {
2599 if (additionalFile && (route.second->getChildAdditionals().size() != 0)) {
2600 device << (" <!-- Routes (used in RouteProbReroutes and calibratorFlows) -->\n");
2601 return true;
2602 } else if (!additionalFile && (route.second->getChildAdditionals().size() == 0)) {
2603 device << (" <!-- Routes -->\n");
2604 return true;
2605 }
2606 }
2607 return false;
2608}
2609
2610
2611bool
2614 device << (" <!-- RouteProbes -->\n");
2615 return true;
2616 }
2617 return false;
2618}
2619
2620
2621bool
2623 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2624 if (GNEAttributeCarrier::getTagProperty(additionals.first).isCalibrator() && (additionals.second.size() > 0)) {
2625 device << (" <!-- Calibrators -->\n");
2626 return true;
2627 }
2628 }
2629 return false;
2630}
2631
2632
2633bool
2635 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2636 if (GNEAttributeCarrier::getTagProperty(additionals.first).isStoppingPlace() && (additionals.second.size() > 0)) {
2637 device << (" <!-- StoppingPlaces -->\n");
2638 return true;
2639 }
2640 }
2641 return false;
2642}
2643
2644
2645bool
2647 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2648 if (GNEAttributeCarrier::getTagProperty(additionals.first).isDetector() && (additionals.second.size() > 0)) {
2649 device << (" <!-- Detectors -->\n");
2650 return true;
2651 }
2652 }
2653 return false;
2654}
2655
2656
2657bool
2659 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2662 !GNEAttributeCarrier::getTagProperty(additionals.first).isDetector() &&
2663 !GNEAttributeCarrier::getTagProperty(additionals.first).isCalibrator() &&
2664 (additionals.first != SUMO_TAG_ROUTEPROBE) && (additionals.first != SUMO_TAG_ACCESS) &&
2665 (additionals.first != SUMO_TAG_PARKING_SPACE) && (additionals.second.size() > 0)) {
2666 device << (" <!-- Other additionals -->\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).isShapeElement() &&
2679 (additionals.second.size() > 0)) {
2680 device << (" <!-- Shapes -->\n");
2681 return true;
2682 }
2683 }
2684 return false;
2685}
2686
2687
2688bool
2690 for (const auto& additionals : myAttributeCarriers->getAdditionals()) {
2691 if (GNEAttributeCarrier::getTagProperty(additionals.first).isJuPedSimElement() && (additionals.second.size() > 0)) {
2692 device << (" <!-- JuPedSim elements -->\n");
2693 return true;
2694 }
2695 }
2696 return false;
2697}
2698
2699
2700bool
2702 if (myAttributeCarriers->getAdditionals().at(SUMO_TAG_TAZ).size() > 0) {
2703 device << (" <!-- TAZs -->\n");
2704 return true;
2705 }
2706 return false;
2707}
2708
2709
2710bool
2713 device << (" <!-- Wires -->\n");
2714 return true;
2715 }
2716 return false;
2717}
2718
2719
2720bool
2723 device << (" <!-- MeanDataEdges -->\n");
2724 return true;
2725 }
2726 return false;
2727}
2728
2729
2730bool
2733 device << (" <!-- MeanDataLanes -->\n");
2734 return true;
2735 }
2736 return false;
2737}
2738
2739
2740void
2741GNENet::saveTLSPrograms(const std::string& filename) {
2742 // open output device
2743 OutputDevice& device = OutputDevice::getDevice(filename);
2744 device.openTag("additionals");
2745 // write traffic lights using NWWriter
2747 device.close();
2748 // change save status
2750 // show debug information
2751 WRITE_DEBUG("TLSPrograms saved");
2752}
2753
2754
2755int
2757 return -1;
2758}
2759
2760
2761void
2762GNENet::saveEdgeTypes(const std::string& filename) {
2763 // first clear typeContainer
2765 // now update typeContainer with edgeTypes
2766 for (const auto& edgeType : myAttributeCarriers->getEdgeTypes()) {
2767 myNetBuilder->getTypeCont().insertEdgeType(edgeType.first, edgeType.second);
2768 for (int i = 0; i < (int)edgeType.second->getLaneTypes().size(); i++) {
2769 myNetBuilder->getTypeCont().insertLaneType(edgeType.first, i,
2770 edgeType.second->getLaneTypes().at(i)->speed,
2771 edgeType.second->getLaneTypes().at(i)->permissions,
2772 edgeType.second->getLaneTypes().at(i)->width,
2773 edgeType.second->getLaneTypes().at(i)->attrs);
2774 }
2775 }
2776 // open device
2777 OutputDevice& device = OutputDevice::getDevice(filename);
2778 // open tag
2779 device.openTag(SUMO_TAG_TYPE);
2780 // write edge types
2782 // close tag
2783 device.closeTag();
2784 // close device
2785 device.close();
2786}
2787
2788
2789void
2793
2794
2795void
2799
2800
2801bool
2805
2806
2807void
2809 myUpdateDataEnabled = true;
2810 // update data elements
2811 for (const auto& dataInterval : myAttributeCarriers->getDataIntervals()) {
2812 dataInterval.second->updateGenericDataIDs();
2813 dataInterval.second->updateAttributeColors();
2814 }
2815}
2816
2817
2818void
2822
2823
2824bool
2828
2829// ===========================================================================
2830// private
2831// ===========================================================================
2832
2833void
2835 // init edge types
2836 for (const auto& edgeType : myNetBuilder->getTypeCont()) {
2837 // register edge type
2838 myAttributeCarriers->registerEdgeType(new GNEEdgeType(this, edgeType.first, edgeType.second));
2839 }
2840 // init junctions (by default Crossing and walking areas aren't created)
2841 for (const auto& nodeName : myNetBuilder->getNodeCont().getAllNames()) {
2842 // create and register junction
2844 }
2845 // init edges
2846 for (const auto& edgeName : myNetBuilder->getEdgeCont().getAllNames()) {
2847 // create edge using NBEdge
2848 GNEEdge* edge = new GNEEdge(this, myNetBuilder->getEdgeCont().retrieve(edgeName), false, true);
2849 // register edge
2851 // add manually child references due initJunctionsAndEdges doesn't use undo-redo
2852 edge->getFromJunction()->addChildElement(edge);
2853 edge->getToJunction()->addChildElement(edge);
2854 // check grid
2855 if (myGrid.getWidth() > 10e16 || myGrid.getHeight() > 10e16) {
2856 throw ProcessError(TL("Network size exceeds 1 Lightyear. Please reconsider your inputs.") + std::string("\n"));
2857 }
2858 }
2859 // make sure myGrid is initialized even for an empty net. This ensure that the network starts with a zoom of 100
2860 if (myAttributeCarriers->getEdges().size() == 0) {
2861 myGrid.add(Boundary(-50, -50, 50, 50));
2862 }
2863 // recalculate all lane2lane connections
2864 for (const auto& edge : myAttributeCarriers->getEdges()) {
2865 for (const auto& lane : edge.second->getLanes()) {
2866 lane->updateGeometry();
2867 }
2868 }
2869 // sort nodes edges so that arrows can be drawn correctly
2871}
2872
2873
2874void
2876 for (const auto& edge : myAttributeCarriers->getEdges()) {
2877 // remake connections
2878 edge.second->remakeGNEConnections();
2879 // update geometry of connections
2880 for (const auto& connection : edge.second->getGNEConnections()) {
2881 connection->updateGeometry();
2882 }
2883 }
2884}
2885
2886
2887void
2888GNENet::computeAndUpdate(OptionsCont& neteditOptions, bool volatileOptions) {
2889 // make sure we only add turn arounds to edges which currently exist within the network
2890 std::set<std::string> liveExplicitTurnarounds;
2891 for (const auto& explicitTurnarounds : myExplicitTurnarounds) {
2892 if (myAttributeCarriers->getEdges().count(explicitTurnarounds) > 0) {
2893 liveExplicitTurnarounds.insert(explicitTurnarounds);
2894 }
2895 }
2896 // removes all junctions of grid
2897 WRITE_GLDEBUG("Removing junctions during recomputing");
2898 for (const auto& junction : myAttributeCarriers->getJunctions()) {
2899 removeGLObjectFromGrid(junction.second);
2900 }
2901 // remove all edges from grid
2902 WRITE_GLDEBUG("Removing edges during recomputing");
2903 for (const auto& edge : myAttributeCarriers->getEdges()) {
2904 removeGLObjectFromGrid(edge.second);
2905 }
2906 // compute using NetBuilder
2907 myNetBuilder->compute(neteditOptions, liveExplicitTurnarounds, volatileOptions);
2908 // remap ids if necessary
2909 if (neteditOptions.getBool("numerical-ids") || neteditOptions.isSet("reserved-ids")) {
2911 }
2912 // update rtree if necessary
2913 if (!neteditOptions.getBool("offset.disable-normalization")) {
2914 for (const auto& edge : myAttributeCarriers->getEdges()) {
2915 // refresh edge geometry
2916 edge.second->updateGeometry();
2917 }
2918 }
2919 // Clear current inspected ACs in inspectorFrame if a previous net was loaded
2920 if (myViewNet != nullptr) {
2922 }
2923 // Reset Grid
2924 myGrid.reset();
2926 // if volatile options are true
2927 if (volatileOptions) {
2928 // check that net exist
2929 if (myViewNet == nullptr) {
2930 throw ProcessError("ViewNet doesn't exist");
2931 }
2932 // disable update geometry before clear undo list
2934 // destroy Popup
2936 // clear undo list (This will be remove additionals and shapes)
2938 // clear all elements (it will also removed from grid)
2943 // enable update geometry again
2945 // Write GL debug information
2946 WRITE_GLDEBUG("initJunctionsAndEdges function called in computeAndUpdate(...) due recomputing with volatile options");
2947 // init again junction an edges (Additionals and shapes will be loaded after the end of this function)
2949 // init default vTypes again
2951 } else {
2952 // insert all junctions of grid again
2953 WRITE_GLDEBUG("Add junctions during recomputing after calling myNetBuilder->compute(...)");
2954 for (const auto& junction : myAttributeCarriers->getJunctions()) {
2955 // update centering boundary
2956 junction.second->updateCenteringBoundary(false);
2957 // add junction in grid again
2958 addGLObjectIntoGrid(junction.second);
2959 }
2960 // insert all edges from grid again
2961 WRITE_GLDEBUG("Add edges during recomputing after calling myNetBuilder->compute(...)");
2962 for (const auto& edge : myAttributeCarriers->getEdges()) {
2963 // update centeting boundary
2964 edge.second->updateCenteringBoundary(false);
2965 // add edge in grid again
2966 addGLObjectIntoGrid(edge.second);
2967 }
2968 // remake connections
2969 for (const auto& edge : myAttributeCarriers->getEdges()) {
2970 edge.second->remakeGNEConnections(true);
2971 }
2972 // iterate over junctions of net
2973 for (const auto& junction : myAttributeCarriers->getJunctions()) {
2974 // undolist may not yet exist but is also not needed when just marking junctions as valid
2975 junction.second->setLogicValid(true, nullptr);
2976 // updated geometry
2977 junction.second->updateGeometryAfterNetbuild();
2978 // rebuild walking areas
2979 junction.second->rebuildGNEWalkingAreas();
2980 }
2981 // iterate over all edges of net
2982 for (const auto& edge : myAttributeCarriers->getEdges()) {
2983 // update geometry
2984 edge.second->updateGeometry();
2985 }
2986 }
2987 // net recomputed, then return false;
2988 myNeedRecompute = false;
2989}
2990
2991
2992void
2993GNENet::replaceInListAttribute(GNEAttributeCarrier* ac, SumoXMLAttr key, const std::string& which, const std::string& by, GNEUndoList* undoList) {
2994 assert(ac->getTagProperty().getAttributeProperties(key).isList());
2995 std::vector<std::string> values = GNEAttributeCarrier::parse<std::vector<std::string> >(ac->getAttribute(key));
2996 std::vector<std::string> newValues;
2997 bool lastBy = false;
2998 for (auto v : values) {
2999 if (v == which && !lastBy) {
3000 // avoid duplicate occurence of the 'by' edge (i.e. in routes)
3001 newValues.push_back(by);
3002 } else {
3003 newValues.push_back(v);
3004 }
3005 lastBy = v == by;
3006 }
3007 ac->setAttribute(key, toString(newValues), undoList);
3008}
3009
3010
3011/****************************************************************************/
@ 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:966
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:1798
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:1251
Dialog for edit rerouters.
Dialog for edit rerouters.
An Element which don't belong to GNENet but has influence in the simulation.
GNEDataInterval * getDataIntervalParent() const
get data interval parent
void addChildElement(T *element)
add child element
const std::vector< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
const std::vector< GNEAdditional * > & getParentAdditionals() const
get parent additionals
const std::vector< GNEAdditional * > & getChildAdditionals() const
return child additionals
const std::vector< GNEGenericData * > & getChildGenericDatas() const
return child generic data elements
void clearInspectedAC()
Clear all current inspected ACs.
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
std::string getAttribute(SumoXMLAttr key) const
void replaceIncomingConnections(GNEEdge *which, GNEEdge *by, GNEUndoList *undoList)
replace one edge by another in all tls connections
void markAsModified(GNEUndoList *undoList)
prevent re-guessing connections at this junction
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
void invalidateTLS(GNEUndoList *undoList, const NBConnection &deletedConnection=NBConnection::InvalidConnection, const NBConnection &addedConnection=NBConnection::InvalidConnection)
std::vector< GNEConnection * > getGNEConnections() const
Returns all GNEConnections vinculated with this junction.
Position getPositionInView() const
Returns position of hierarchical element in view.
void removeConnectionsFrom(GNEEdge *edge, GNEUndoList *undoList, bool updateTLS, int lane=-1)
remove all connections from the given edge
bool isValid(SumoXMLAttr key, const std::string &value)
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
void removeEdgeFromCrossings(GNEEdge *edge, GNEUndoList *undoList)
removes the given edge from all pedestrian crossings
NBNode * getNBNode() const
Return net build node.
std::vector< GNEJunction * > getJunctionNeighbours() const
return GNEJunction neighbours
void setLogicValid(bool valid, GNEUndoList *undoList, const std::string &status=FEATURE_GUESSED)
void removeConnectionsTo(GNEEdge *edge, GNEUndoList *undoList, bool updateTLS, int lane=-1)
remove all connections to the given edge
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition GNELane.h:46
int getIndex() const
returns the index of the lane
Definition GNELane.cpp:620
std::vector< GNEConnection * > getGNEOutcomingConnections()
returns a vector with the outgoing GNEConnections of this lane
Definition GNELane.cpp:1952
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition GNELane.cpp:751
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
const std::map< const std::string, GNEEdge * > & getEdges() const
map with the ID and pointer to edges of net
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
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
const std::map< const std::string, GNEJunction * > & getJunctions() const
get 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
void clearJunctions()
clear junctions
const std::map< const std::string, GNEEdgeType * > & getEdgeTypes() const
map with the ID and pointer to edgeTypes of net
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:2096
void removeSolitaryJunctions(GNEUndoList *undoList)
removes junctions that have no edges
Definition GNENet.cpp:1745
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:2560
bool joinSelectedJunctions(GNEUndoList *undoList)
join selected junctions
Definition GNENet.cpp:1565
void writeVTypeDistributions(OutputDevice &device, const bool additionalFile) const
write vTypeDistributions sorted by ID
Definition GNENet.cpp:2525
double getDataSetIntervalMaximumEnd() const
get maximum interval
Definition GNENet.cpp:2306
bool writeJuPedSimComment(OutputDevice &device) const
write JuPedSim comment
Definition GNENet.cpp:2689
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:2612
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
void disableUpdateGeometry()
disable update geometry of elements after inserting or removing an element in net
Definition GNENet.cpp:2796
void saveDemandElementsConfirmed()
save demand elements after confirming invalid objects
Definition GNENet.cpp:2391
void saveTLSPrograms(const std::string &filename)
save TLS Programs elements of the network
Definition GNENet.cpp:2741
void computeAndUpdate(OptionsCont &neteditOptions, bool volatileOptions)
recompute the network and update lane geometries
Definition GNENet.cpp:2888
NBNetBuilder * getNetBuilder() const
get net builder
Definition GNENet.cpp:1559
void saveAdditionalsConfirmed()
save additionals after confirming invalid objects
Definition GNENet.cpp:2331
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1386
GNEPathManager * getDataPathManager()
get data path manager
Definition GNENet.cpp:151
bool writeMeanDataLaneComment(OutputDevice &device) const
write Wire comment
Definition GNENet.cpp:2731
void reverseEdge(GNEEdge *edge, GNEUndoList *undoList)
reverse edge
Definition GNENet.cpp:1065
bool writeTAZComment(OutputDevice &device) const
write TAZ comment
Definition GNENet.cpp:2701
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1396
void saveJoined(const std::string &filename)
save log of joined junctions (and nothing else)
Definition GNENet.cpp:1360
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition GNENet.cpp:2161
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:2808
void setViewNet(GNEViewNet *viewNet)
Set the net to be notified of network changes.
Definition GNENet.cpp:1368
bool writeCalibratorComment(OutputDevice &device) const
write calibrator comment
Definition GNENet.cpp:2622
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:2762
void deleteNetworkElement(GNENetworkElement *networkElement, GNEUndoList *undoList)
delete network element
Definition GNENet.cpp:345
void saveAdditionals()
save additional elements
Definition GNENet.cpp:2185
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:2543
void clearDataElements(GNEUndoList *undoList)
clear data elements
Definition GNENet.cpp:2122
void deleteDataInterval(GNEDataInterval *dataInterval, GNEUndoList *undoList)
remove data interval
Definition GNENet.cpp:736
void deleteConnection(GNEConnection *connection, GNEUndoList *undoList)
remove connection
Definition GNENet.cpp:643
void clearDemandElements(GNEUndoList *undoList)
clear demand elements
Definition GNENet.cpp:2109
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:145
bool writeMeanDataEdgeComment(OutputDevice &device) const
write meanDataEdge comment
Definition GNENet.cpp:2721
void adjustPersonPlans(GNEUndoList *undoList)
adjust person plans
Definition GNENet.cpp:1851
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:1406
void writeRoutes(OutputDevice &device, const bool additionalFile) const
write route sorted by ID
Definition GNENet.cpp:2510
void cleanInvalidDemandElements(GNEUndoList *undoList)
clean invalid demand elements
Definition GNENet.cpp:1896
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:1761
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:2179
void computeJunction(GNEJunction *junction)
trigger recomputation of junction shape and logic param[in] window The window to inform about delay
Definition GNENet.cpp:1523
void resetJunctionConnections(GNEJunction *junction, GNEUndoList *undoList)
reset junction's connections
Definition GNENet.cpp:2085
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:2146
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:2834
bool writeWireComment(OutputDevice &device) const
write Wire comment
Definition GNENet.cpp:2711
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 saveDemandElements()
save demand element elements of the network
Definition GNENet.cpp:2238
void clearMeanDataElements(GNEUndoList *undoList)
clear meanDatas
Definition GNENet.cpp:2133
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:2819
bool removeRestrictedLane(SUMOVehicleClass vclass, GNEEdge *edge, GNEUndoList *undoList)
remove restricted lane
Definition GNENet.cpp:910
void saveDataElements()
save data set elements of the network
Definition GNENet.cpp:2278
~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
void saveJuPedSimElements(const std::string &file)
save JuPedSim elements
Definition GNENet.cpp:2224
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:2634
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:2492
bool isUpdateGeometryEnabled() const
check if update geometry after inserting or removing has to be updated
Definition GNENet.cpp:2802
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:1547
void writeAdditionalByType(OutputDevice &device, const std::vector< SumoXMLTag > tags) const
write additional element by type and sorted by ID
Definition GNENet.cpp:2462
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:2825
bool writeShapesComment(OutputDevice &device) const
write shape comment
Definition GNENet.cpp:2675
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:2993
bool cleanInvalidCrossings(GNEUndoList *undoList)
clear invalid crossings
Definition GNENet.cpp:1692
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:1989
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:1787
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:2597
bool writeVTypeComment(OutputDevice &device, const bool additionalFile) const
write vType comment
Definition GNENet.cpp:2575
void replaceJunctionByGeometry(GNEJunction *junction, GNEUndoList *undoList)
replace the selected junction by geometry node(s) and merge the edges
Definition GNENet.cpp:1935
bool writeDetectorComment(OutputDevice &device) const
write detector comment
Definition GNENet.cpp:2646
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:2480
void requireRecompute()
inform the net about the need for recomputation
Definition GNENet.cpp:1541
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:2658
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:2444
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition GNENet.cpp:2173
void initGNEConnections()
initialize GNEConnections
Definition GNENet.cpp:2875
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:2167
void savePlain(const std::string &prefix)
save plain xml representation of the network (and nothing else)
Definition GNENet.cpp:1351
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:1510
FXApp * getApp()
get pointer to the main App
Definition GNENet.cpp:1553
int getNumberOfTLSPrograms() const
get number of TLS Programs
Definition GNENet.cpp:2756
GNEViewNet * getViewNet() const
get view net
Definition GNENet.cpp:2155
void saveDataElementsConfirmed()
save data elements after confirming invalid objects
Definition GNENet.cpp:2429
void enableUpdateGeometry()
Definition GNENet.cpp:2790
void clearJunctionConnections(GNEJunction *junction, GNEUndoList *undoList)
clear junction's connections
Definition GNENet.cpp:2073
void saveMeanDatas()
save meanData elements of the network
Definition GNENet.cpp:2323
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:2289
void computeDemandElements(GNEApplicationWindow *window)
compute demand elements param[in] window The window to inform about delay
Definition GNENet.cpp:1490
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 (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:4378
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:4216
std::string getLaneID(int lane) const
get lane ID
Definition NBEdge.cpp:4016
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:4714
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:2358
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:4122
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
Definition NBNode.cpp:2580
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:2497
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