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