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