Eclipse SUMO - Simulation of Urban MObility
GNENet.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
15 // A visual container for GNE-network-components such as GNEEdge and GNEJunction.
16 // GNE components wrap netbuild-components and supply visualisation and editing
17 // capabilities (adapted from GUINet)
18 //
19 // WorkrouteFlow (rough draft)
20 // use NILoader to fill
21 // do netedit stuff
22 // call compute to save results
23 //
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #include <netbuild/NBAlgorithms.h>
31 #include <netbuild/NBNetBuilder.h>
55 #include <netwrite/NWFrame.h>
56 #include <netwrite/NWWriter_SUMO.h>
57 #include <netwrite/NWWriter_XML.h>
63 #include <utils/xml/XMLSubSys.h>
64 
65 #include "GNEApplicationWindow.h"
66 #include "GNENet.h"
67 #include "GNEViewNet.h"
68 #include "GNEUndoList.h"
69 #include "GNEViewParent.h"
70 
71 
72 // ===========================================================================
73 // FOX callback mapping
74 // ===========================================================================
75 
76 FXIMPLEMENT_ABSTRACT(GNENet::GNEChange_ReplaceEdgeInTLS, GNEChange, nullptr, 0)
77 
78 // ===========================================================================
79 // static members
80 // ===========================================================================
81 
82 const double GNENet::Z_INITIALIZED = 1;
83 
84 // ===========================================================================
85 // member method definitions
86 // ===========================================================================
87 
88 GNENet::GNENet(NBNetBuilder* netBuilder) :
91  myViewNet(nullptr),
92  myNetBuilder(netBuilder),
93  myEdgeIDSupplier("gneE", netBuilder->getEdgeCont().getAllNames()),
94  myJunctionIDSupplier("gneJ", netBuilder->getNodeCont().getAllNames()),
95  myNeedRecompute(true),
96  myNetSaved(true),
97  myAdditionalsSaved(true),
98  myTLSProgramsSaved(true),
99  myDemandElementsSaved(true),
100  myUpdateGeometryEnabled(true),
101  myAllowUndoShapes(true) {
102  // set net in gIDStorage
104  // Write GL debug information
105  WRITE_GLDEBUG("initJunctionsAndEdges function called in GNENet constructor");
106  // init junction and edges
107  initJunctionsAndEdges();
108  // check Z boundary
109  if (myZBoundary.ymin() != Z_INITIALIZED) {
110  myZBoundary.add(0, 0);
111  }
112  // fill additionals with tags (note: this include the TAZS)
113  auto listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_ADDITIONAL, false);
114  for (auto i : listOfTags) {
115  myAttributeCarriers.additionals.insert(std::make_pair(i, std::map<std::string, GNEAdditional*>()));
116  }
117  listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_TAZ, false);
118  for (auto i : listOfTags) {
119  myAttributeCarriers.additionals.insert(std::make_pair(i, std::map<std::string, GNEAdditional*>()));
120  }
121 
122  // fill demand elements with tags
123  listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_DEMANDELEMENT, false);
124  for (auto i : listOfTags) {
125  myAttributeCarriers.demandElements.insert(std::make_pair(i, std::map<std::string, GNEDemandElement*>()));
126  }
127  listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_STOP, false);
128  for (auto i : listOfTags) {
129  myAttributeCarriers.demandElements.insert(std::make_pair(i, std::map<std::string, GNEDemandElement*>()));
130  }
131 }
132 
133 
135  // Decrease reference of Polys (needed after volatile recomputing)
136  for (auto i : myPolygons) {
137  dynamic_cast<GNEAttributeCarrier*>(i.second)->decRef("GNENet::~GNENet");
138  }
139  // Decrease reference of POIs (needed after volatile recomputing)
140  for (auto i : myPOIs) {
141  dynamic_cast<GNEAttributeCarrier*>(i.second)->decRef("GNENet::~GNENet");
142  }
143  // Drop Edges
144  for (auto it : myAttributeCarriers.edges) {
145  it.second->decRef("GNENet::~GNENet");
146  // show extra information for tests
147  WRITE_DEBUG("Deleting unreferenced " + it.second->getTagStr() + " '" + it.second->getID() + "' in GNENet destructor");
148  delete it.second;
149  }
150  // Drop junctions
151  for (auto it : myAttributeCarriers.junctions) {
152  it.second->decRef("GNENet::~GNENet");
153  // show extra information for tests
154  WRITE_DEBUG("Deleting unreferenced " + it.second->getTagStr() + " '" + it.second->getID() + "' in GNENet destructor");
155  delete it.second;
156  }
157  // Drop Additionals (Only used for additionals that were inserted without using GNEChange_Additional)
158  for (auto it : myAttributeCarriers.additionals) {
159  for (auto j : it.second) {
160  // decrease reference manually (because it was increased manually in GNEAdditionalHandler)
161  j.second->decRef();
162  // show extra information for tests
163  WRITE_DEBUG("Deleting unreferenced " + j.second->getTagStr() + " '" + j.second->getID() + "' in GNENet destructor");
164  delete j.second;
165  }
166  }
167  // Drop demand elements (Only used for demand elements that were inserted without using GNEChange_DemandElement, for example the default VType")
168  for (auto it : myAttributeCarriers.demandElements) {
169  for (auto j : it.second) {
170  // decrease reference manually (because it was increased manually in GNERouteHandler)
171  j.second->decRef();
172  // show extra information for tests
173  WRITE_DEBUG("Deleting unreferenced " + j.second->getTagStr() + " '" + j.second->getID() + "' in GNENet destructor");
174  delete j.second;
175  }
176  }
177  // delete RouteCalculator instance of GNEDemandElement
179  // show extra information for tests
180  WRITE_DEBUG("Deleting net builder in GNENet destructor");
181  delete myNetBuilder;
182 }
183 
184 
185 const Boundary&
187  // SUMORTree is also a Boundary
188  return myGrid;
189 }
190 
191 
194  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
195  buildPopupHeader(ret, app);
197  buildPositionCopyEntry(ret, false);
198  return ret;
199 }
200 
201 
204  // Nets lanes don't have attributes
205  GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this, 2);
206  // close building
207  ret->closeBuilding();
208  return ret;
209 }
210 
211 
212 void
214 }
215 
216 
217 bool
218 GNENet::addPolygon(const std::string& id, const std::string& type, const RGBColor& color, double layer, double angle,
219  const std::string& imgFile, bool relativePath, const PositionVector& shape, bool geo, bool fill, double lineWidth, bool /*ignorePruning*/) {
220  // check if ID is duplicated
221  if (myPolygons.get(id) == nullptr) {
222  // create poly
223  GNEPoly* poly = new GNEPoly(this, id, type, shape, geo, fill, lineWidth, color, layer, angle, imgFile, relativePath, false, false);
224  if (myAllowUndoShapes) {
226  myViewNet->getUndoList()->add(new GNEChange_Shape(poly, true), true);
228  } else {
229  // insert shape without allowing undo/redo
230  insertShape(poly, true);
231  poly->incRef("addPolygon");
232  }
233  return true;
234  } else {
235  return false;
236  }
237 }
238 
239 
240 bool
241 GNENet::addPOI(const std::string& id, const std::string& type, const RGBColor& color, const Position& pos, bool geo,
242  const std::string& lane, double posOverLane, double posLat, double layer, double angle,
243  const std::string& imgFile, bool relativePath, double width, double height, bool /*ignorePruning*/) {
244  // check if ID is duplicated
245  if (myPOIs.get(id) == nullptr) {
246  // create POI or POILane depending of parameter lane
247  if (lane == "") {
248  // create POI
249  GNEPOI* poi = new GNEPOI(this, id, type, color, pos, geo, layer, angle, imgFile, relativePath, width, height, false);
250  if (myPOIs.add(poi->getID(), poi)) {
251  if (myAllowUndoShapes) {
252  myViewNet->getUndoList()->p_begin("add " + poi->getTagStr());
253  myViewNet->getUndoList()->add(new GNEChange_Shape(poi, true), true);
255  } else {
256  // insert shape without allowing undo/redo
257  insertShape(poi, true);
258  poi->incRef("addPOI");
259  }
260  return true;
261  } else {
262  throw ProcessError("Error adding GNEPOI into shapeContainer");
263  }
264  } else {
265  // create POI over lane
266  GNELane* retrievedLane = retrieveLane(lane);
267  GNEPOI* poi = new GNEPOI(this, id, type, color, layer, angle, imgFile, relativePath, retrievedLane, posOverLane, posLat, width, height, false);
268  if (myPOIs.add(poi->getID(), poi)) {
269  if (myAllowUndoShapes) {
270  myViewNet->getUndoList()->p_begin("add " + poi->getTagStr());
271  myViewNet->getUndoList()->add(new GNEChange_Shape(poi, true), true);
273  } else {
274  // insert shape without allowing undo/redo
275  insertShape(poi, true);
276  poi->incRef("addPOI");
277  }
278  return true;
279  } else {
280  throw ProcessError("Error adding GNEPOI over lane into shapeContainer");
281  }
282  }
283  } else {
284  return false;
285  }
286 }
287 
288 
289 Boundary
291  return getBoundary();
292 }
293 
294 
295 const Boundary&
297  return myZBoundary;
298 }
299 
300 
301 SUMORTree&
303  return myGrid;
304 }
305 
306 
307 const SUMORTree&
309  return myGrid;
310 }
311 
312 
315  std::string id = myJunctionIDSupplier.getNext();
316  NBNode* nbn = new NBNode(id, pos);
317  GNEJunction* junction = new GNEJunction(*nbn, this);
318  undoList->add(new GNEChange_Junction(junction, true), true);
319  assert(myAttributeCarriers.junctions[id]);
320  return junction;
321 }
322 
323 
324 GNEEdge*
326  GNEJunction* src, GNEJunction* dest, GNEEdge* tpl, GNEUndoList* undoList,
327  const std::string& suggestedName,
328  bool wasSplit,
329  bool allowDuplicateGeom,
330  bool recomputeConnections) {
331  // prevent duplicate edge (same geometry)
332  const EdgeVector& outgoing = src->getNBNode()->getOutgoingEdges();
333  for (EdgeVector::const_iterator it = outgoing.begin(); it != outgoing.end(); it++) {
334  if ((*it)->getToNode() == dest->getNBNode() && (*it)->getGeometry().size() == 2) {
335  if (!allowDuplicateGeom) {
336  return nullptr;
337  }
338  }
339  }
340 
341  std::string id;
342  if (suggestedName != "" && !retrieveEdge(suggestedName, false)) {
343  id = suggestedName;
344  reserveEdgeID(id);
345  } else {
346  id = myEdgeIDSupplier.getNext();
347  }
348 
349  GNEEdge* edge;
350  if (tpl) {
351  NBEdge* nbeTpl = tpl->getNBEdge();
352  NBEdge* nbe = new NBEdge(id, src->getNBNode(), dest->getNBNode(), nbeTpl);
353  edge = new GNEEdge(*nbe, this, wasSplit);
354  } else {
355  // default if no template is given
356  const OptionsCont& oc = OptionsCont::getOptions();
357  double defaultSpeed = oc.getFloat("default.speed");
358  std::string defaultType = "";
359  int defaultNrLanes = oc.getInt("default.lanenumber");
360  int defaultPriority = oc.getInt("default.priority");
361  double defaultWidth = NBEdge::UNSPECIFIED_WIDTH;
362  double defaultOffset = NBEdge::UNSPECIFIED_OFFSET;
363  NBEdge* nbe = new NBEdge(id, src->getNBNode(), dest->getNBNode(),
364  defaultType, defaultSpeed,
365  defaultNrLanes, defaultPriority,
366  defaultWidth,
367  defaultOffset);
368  edge = new GNEEdge(*nbe, this, wasSplit);
369  }
370  undoList->p_begin("create " + toString(SUMO_TAG_EDGE));
371  undoList->add(new GNEChange_Edge(edge, true), true);
372  if (recomputeConnections) {
373  src->setLogicValid(false, undoList);
374  dest->setLogicValid(false, undoList);
375  }
377  undoList->p_end();
378  assert(myAttributeCarriers.edges[id]);
379  return edge;
380 }
381 
382 
383 void
385  // we have to delete all incident edges because they cannot exist without that junction
386  // all deletions must be undone/redone together so we start a new command group
387  // @todo if any of those edges are dead-ends should we remove their orphan junctions as well?
388  undoList->p_begin("delete " + toString(SUMO_TAG_JUNCTION));
389 
390  // delete all crossings vinculated with junction
391  while (junction->getGNECrossings().size() > 0) {
392  deleteCrossing(junction->getGNECrossings().front(), undoList);
393  }
394 
395  // find all crossings of neightbour junctions that shares an edge of this junction
396  std::vector<GNECrossing*> crossingsToRemove;
397  std::vector<GNEJunction*> junctionNeighbours = junction->getJunctionNeighbours();
398  for (auto i : junctionNeighbours) {
399  // iterate over crossing of neighbour juntion
400  for (auto j : i->getGNECrossings()) {
401  // if at least one of the edges of junction to remove belongs to a crossing of the neighbour junction, delete it
402  if (j->checkEdgeBelong(junction->getGNEEdges())) {
403  crossingsToRemove.push_back(j);
404  }
405  }
406  }
407 
408  // delete crossings top remove
409  for (auto i : crossingsToRemove) {
410  deleteCrossing(i, undoList);
411  }
412 
413  // deleting edges changes in the underlying EdgeVector so we have to make a copy
414  const EdgeVector incident = junction->getNBNode()->getEdges();
415  for (auto it : incident) {
416  deleteEdge(myAttributeCarriers.edges[it->getID()], undoList, true);
417  }
418 
419  // remove any traffic lights from the traffic light container (avoids lots of warnings)
420  junction->setAttribute(SUMO_ATTR_TYPE, toString(NODETYPE_PRIORITY), undoList);
421 
422  // delete edge
423  undoList->add(new GNEChange_Junction(junction, false), true);
424  undoList->p_end();
425 }
426 
427 
428 void
429 GNENet::deleteEdge(GNEEdge* edge, GNEUndoList* undoList, bool recomputeConnections) {
430  undoList->p_begin("delete " + toString(SUMO_TAG_EDGE));
431  // delete all shapes children of edge
432  while (edge->getShapeChildren().size() > 0) {
433  deleteShape(edge->getShapeChildren().front(), undoList);
434  }
435  // delete all shapes children of lane
436  for (auto i : edge->getLanes()) {
437  while (i->getShapeChildren().size() > 0) {
438  deleteShape(i->getShapeChildren().front(), undoList);
439  }
440  }
441  // delete all additionals children of edge
442  while (edge->getAdditionalChildren().size() > 0) {
443  deleteAdditional(edge->getAdditionalChildren().front(), undoList);
444  }
445  // delete all additionals children of lane
446  for (auto i : edge->getLanes()) {
447  while (i->getAdditionalChildren().size() > 0) {
448  deleteAdditional(i->getAdditionalChildren().front(), undoList);
449  }
450  }
451  // delete all demand element children of edge
452  while (edge->getDemandElementChildren().size() > 0) {
453  deleteDemandElement(edge->getDemandElementChildren().front(), undoList);
454  }
455  // delete all demand element children of lane
456  for (auto i : edge->getLanes()) {
457  while (i->getDemandElementChildren().size() > 0) {
458  deleteDemandElement(i->getDemandElementChildren().front(), undoList);
459  }
460  }
461  // remove edge from crossings related with this edge
462  edge->getGNEJunctionSource()->removeEdgeFromCrossings(edge, undoList);
463  edge->getGNEJunctionDestiny()->removeEdgeFromCrossings(edge, undoList);
464  // update affected connections
465  if (recomputeConnections) {
466  edge->getGNEJunctionSource()->setLogicValid(false, undoList);
467  edge->getGNEJunctionDestiny()->setLogicValid(false, undoList);
468  } else {
469  edge->getGNEJunctionSource()->removeConnectionsTo(edge, undoList, true);
470  edge->getGNEJunctionSource()->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->getGNEJunctionSource()->getNBNode()->isTLControlled() && (edge->getGNEJunctionSource()->getGNEOutgoingEdges().size() <= 1)) {
475  }
476  // if junction destiny is a TLS and after deletion will have only an edge, remove TLS
477  if (edge->getGNEJunctionDestiny()->getNBNode()->isTLControlled() && (edge->getGNEJunctionDestiny()->getGNEIncomingEdges().size() <= 1)) {
479  }
480  // Delete edge
481  undoList->add(new GNEChange_Edge(edge, false), true);
482  // remove edge requieres always a recompute (due geometry and connections)
484  // finish delete edge
485  undoList->p_end();
486 }
487 
488 
489 void
491  undoList->p_begin("replace " + toString(SUMO_TAG_EDGE));
492  undoList->p_add(new GNEChange_Attribute(by, this, SUMO_ATTR_TO, which->getAttribute(SUMO_ATTR_TO)));
493  // replace in additionals children of edge
494  while (which->getAdditionalChildren().size() > 0) {
495  undoList->p_add(new GNEChange_Attribute(which->getAdditionalChildren().front(), this, SUMO_ATTR_EDGE, by->getID()));
496  }
497  // replace in additionals children of lane
498  for (auto i : which->getLanes()) {
499  std::vector<GNEAdditional*> copyOfLaneAdditionals = i->getAdditionalChildren();
500  for (auto j : copyOfLaneAdditionals) {
501  undoList->p_add(new GNEChange_Attribute(j, this, SUMO_ATTR_LANE, by->getNBEdge()->getLaneID(i->getIndex())));
502  }
503  }
504  // replace in demand elements children of edge
505  while (which->getDemandElementChildren().size() > 0) {
506  undoList->p_add(new GNEChange_Attribute(which->getDemandElementChildren().front(), this, SUMO_ATTR_EDGE, by->getID()));
507  }
508  // replace in demand elements children of lane
509  for (auto i : which->getLanes()) {
510  std::vector<GNEDemandElement*> copyOfLaneDemandElements = i->getDemandElementChildren();
511  for (auto j : copyOfLaneDemandElements) {
512  undoList->p_add(new GNEChange_Attribute(j, this, SUMO_ATTR_LANE, by->getNBEdge()->getLaneID(i->getIndex())));
513  }
514  }
515  // replace in shapes children of lane
516  for (auto i : which->getLanes()) {
517  std::vector<GNEShape*> copyOfLaneShapes = i->getShapeChildren();
518  for (auto j : copyOfLaneShapes) {
519  undoList->p_add(new GNEChange_Attribute(j, this, SUMO_ATTR_LANE, by->getNBEdge()->getLaneID(i->getIndex())));
520  }
521  }
522  // replace in rerouters
523  for (auto rerouter : which->getAdditionalParents()) {
524  replaceInListAttribute(rerouter, SUMO_ATTR_EDGES, which->getID(), by->getID(), undoList);
525  }
526  // replace in crossings
527  for (auto crossing : which->getGNEJunctionDestiny()->getGNECrossings()) {
528  // if at least one of the edges of junction to remove belongs to a crossing of the source junction, delete it
529  replaceInListAttribute(crossing, SUMO_ATTR_EDGES, which->getID(), by->getID(), undoList);
530  }
531  // fix connections (make a copy because they will be modified
532  std::vector<NBEdge::Connection> connections = which->getNBEdge()->getConnections();
533  for (auto con : connections) {
534  undoList->add(new GNEChange_Connection(which, con, false, false), true);
535  undoList->add(new GNEChange_Connection(by, con, false, true), true);
536  }
537  undoList->add(new GNEChange_ReplaceEdgeInTLS(getTLLogicCont(), which->getNBEdge(), by->getNBEdge()), true);
538  // Delete edge
539  undoList->add(new GNEChange_Edge(which, false), true);
540  // finish replace edge
541  undoList->p_end();
542 }
543 
544 
545 void
546 GNENet::deleteLane(GNELane* lane, GNEUndoList* undoList, bool recomputeConnections) {
547  GNEEdge* edge = &lane->getParentEdge();
548  if (edge->getNBEdge()->getNumLanes() == 1) {
549  // remove the whole edge instead
550  deleteEdge(edge, undoList, recomputeConnections);
551  } else {
552  undoList->p_begin("delete " + toString(SUMO_TAG_LANE));
553  // delete additionals children of lane
554  while (lane->getAdditionalChildren().size() > 0) {
555  deleteAdditional(lane->getAdditionalChildren().front(), undoList);
556  }
557  // delete demand element children of lane
558  while (lane->getDemandElementChildren().size() > 0) {
559  deleteDemandElement(lane->getDemandElementChildren().front(), undoList);
560  }
561  // delete POIShapes of Lane
562  while (lane->getShapeChildren().size() > 0) {
563  undoList->add(new GNEChange_Shape(lane->getShapeChildren().front(), false), true);
564  }
565  // update affected connections
566  if (recomputeConnections) {
567  edge->getGNEJunctionSource()->setLogicValid(false, undoList);
568  edge->getGNEJunctionDestiny()->setLogicValid(false, undoList);
569  } else {
570  edge->getGNEJunctionSource()->removeConnectionsTo(edge, undoList, true, lane->getIndex());
571  edge->getGNEJunctionSource()->removeConnectionsFrom(edge, undoList, true, lane->getIndex());
572  }
573  // delete lane
574  const NBEdge::Lane& laneAttrs = edge->getNBEdge()->getLaneStruct(lane->getIndex());
575  undoList->add(new GNEChange_Lane(edge, lane, laneAttrs, false, recomputeConnections), true);
576  // remove lane requieres always a recompute (due geometry and connections)
578  undoList->p_end();
579  }
580 }
581 
582 
583 void
585  undoList->p_begin("delete " + toString(SUMO_TAG_CONNECTION));
586  // obtain NBConnection to remove
587  NBConnection deleted = connection->getNBConnection();
588  GNEJunction* junctionDestiny = connection->getEdgeFrom()->getGNEJunctionDestiny();
589  junctionDestiny->markAsModified(undoList);
590  undoList->add(new GNEChange_Connection(connection->getEdgeFrom(), connection->getNBEdgeConnection(), connection->isAttributeCarrierSelected(), false), true);
591  junctionDestiny->invalidateTLS(undoList, deleted);
592  // remove connection requieres always a recompute (due geometry and connections)
594  undoList->p_end();
595 }
596 
597 
598 void
600  undoList->p_begin("delete crossing");
601  // remove it using GNEChange_Crossing
602  undoList->add(new GNEChange_Crossing(crossing->getParentJunction(), crossing->getNBCrossing()->edges,
603  crossing->getNBCrossing()->width, crossing->getNBCrossing()->priority,
604  crossing->getNBCrossing()->customTLIndex,
605  crossing->getNBCrossing()->customTLIndex2,
606  crossing->getNBCrossing()->customShape,
607  crossing->isAttributeCarrierSelected(),
608  false), true);
609  // remove crossing requieres always a recompute (due geometry and connections)
611  undoList->p_end();
612 }
613 
614 
615 void
617  undoList->p_begin("delete " + shape->getTagStr());
618  // delete shape
619  undoList->add(new GNEChange_Shape(shape, false), true);
620  undoList->p_end();
621 }
622 
623 
624 void
626  undoList->p_begin("delete " + additional->getTagStr());
627  // first remove all additional children of this additional calling this function recursively
628  while (additional->getAdditionalChildren().size() > 0) {
629  deleteAdditional(additional->getAdditionalChildren().front(), undoList);
630  }
631  // remove additional
632  undoList->add(new GNEChange_Additional(additional, false), true);
633  undoList->p_end();
634 }
635 
636 
637 void
639  // check that default VTypes aren't removed
640  if ((demandElement->getTagProperty().getTag() == SUMO_TAG_VTYPE) && (GNEAttributeCarrier::parse<bool>(demandElement->getAttribute(GNE_ATTR_DEFAULT_VTYPE)))) {
641  throw ProcessError("Trying to delete a default Vehicle Type");
642  } else {
643  undoList->p_begin("delete " + demandElement->getTagStr());
644  // first remove all demand element children of this demandElement calling this function recursively
645  while (demandElement->getDemandElementChildren().size() > 0) {
646  deleteDemandElement(demandElement->getDemandElementChildren().front(), undoList);
647  }
648  // remove demandElement
649  undoList->add(new GNEChange_DemandElement(demandElement, false), true);
650  undoList->p_end();
651  }
652 }
653 
654 
655 void
656 GNENet::duplicateLane(GNELane* lane, GNEUndoList* undoList, bool recomputeConnections) {
657  undoList->p_begin("duplicate " + toString(SUMO_TAG_LANE));
658  GNEEdge* edge = &lane->getParentEdge();
659  const NBEdge::Lane& laneAttrs = edge->getNBEdge()->getLaneStruct(lane->getIndex());
660  if (recomputeConnections) {
661  edge->getGNEJunctionSource()->setLogicValid(false, undoList);
662  edge->getGNEJunctionSource()->setLogicValid(false, undoList);
663  }
664  GNELane* newLane = new GNELane(*edge, lane->getIndex());
665  undoList->add(new GNEChange_Lane(edge, newLane, laneAttrs, true, recomputeConnections), true);
667  undoList->p_end();
668 }
669 
670 
671 bool
673  bool addRestriction = true;
674  if (vclass == SVC_PEDESTRIAN) {
675  GNEEdge& edge = lane->getParentEdge();
676  for (auto i : edge.getLanes()) {
677  if (i->isRestricted(SVC_PEDESTRIAN)) {
678  // prevent adding a 2nd sidewalk
679  addRestriction = false;
680  } else {
681  // ensure that the sidewalk is used exclusively
682  const SVCPermissions allOldWithoutPeds = edge.getNBEdge()->getPermissions(i->getIndex()) & ~SVC_PEDESTRIAN;
683  i->setAttribute(SUMO_ATTR_ALLOW, getVehicleClassNames(allOldWithoutPeds), undoList);
684  }
685  }
686  }
687  // restrict the lane
688  if (addRestriction) {
689  const double width = (vclass == SVC_PEDESTRIAN || vclass == SVC_BICYCLE
690  ? OptionsCont::getOptions().getFloat("default.sidewalk-width")
691  : OptionsCont::getOptions().getFloat("default.lanewidth"));
692  lane->setAttribute(SUMO_ATTR_ALLOW, toString(vclass), undoList);
693  lane->setAttribute(SUMO_ATTR_WIDTH, toString(width), undoList);
694  return true;
695  } else {
696  return false;
697  }
698 }
699 
700 
701 bool
702 GNENet::addRestrictedLane(SUMOVehicleClass vclass, GNEEdge& edge, int index, GNEUndoList* undoList) {
703  // First check that edge don't have a restricted lane of the given vclass
704  for (auto i : edge.getLanes()) {
705  if (i->isRestricted(vclass)) {
706  return false;
707  }
708  }
709  // check that index is correct (index == size adds to the left of the leftmost lane)
710  const int numLanes = (int)edge.getLanes().size();
711  if (index > numLanes) {
712  return false;
713  }
714  if (index < 0) {
715  // guess index from vclass
716  if (vclass == SVC_PEDESTRIAN) {
717  index = 0;
718  } else if (vclass == SVC_BICYCLE) {
719  // add bikelanes to the left of an existing sidewalk
720  index = edge.getLanes()[0]->isRestricted(SVC_PEDESTRIAN) ? 1 : 0;
721  } else if (vclass == SVC_IGNORING || vclass == SVC_BUS) {
722  // add greenVerge to the left of an existing sidewalk or bikeLane
723  // add busLane to the left of an existing sidewalk, bikeLane or greenVerge
724  index = 0;
725  while (index < numLanes && (edge.getNBEdge()->getPermissions(index) & ~(SVC_PEDESTRIAN | SVC_BICYCLE)) == 0) {
726  index++;
727  }
728  }
729  }
730  // duplicate selected lane
731  duplicateLane(edge.getLanes().at(MIN2(index, numLanes - 1)), undoList, true);
732  // transform the created lane
733  return restrictLane(vclass, edge.getLanes().at(index), undoList);
734 }
735 
736 
737 bool
739  // iterate over lanes of edge
740  for (auto i : edge.getLanes()) {
741  if (i->isRestricted(vclass)) {
742  // Delete lane
743  deleteLane(i, undoList, true);
744  return true;
745  }
746  }
747  return false;
748 }
749 
750 
752 GNENet::splitEdge(GNEEdge* edge, const Position& pos, GNEUndoList* undoList, GNEJunction* newJunction) {
753  undoList->p_begin("split " + toString(SUMO_TAG_EDGE));
754  if (newJunction == nullptr) {
755  newJunction = createJunction(pos, undoList);
756  }
757  // compute geometry
758  const PositionVector& oldGeom = edge->getNBEdge()->getGeometry();
759  const double linePos = oldGeom.nearest_offset_to_point2D(pos, false);
760  std::pair<PositionVector, PositionVector> newGeoms = oldGeom.splitAt(linePos);
761  const std::string shapeEnd = edge->getAttribute(GNE_ATTR_SHAPE_END);
762  // figure out the new name
763  int posBase = 0;
764  std::string baseName = edge->getMicrosimID();
765  if (edge->wasSplit()) {
766  const std::string::size_type sep_index = baseName.rfind('.');
767  if (sep_index != std::string::npos) { // edge may have been renamed in between
768  std::string posString = baseName.substr(sep_index + 1);
769  try {
770  posBase = GNEAttributeCarrier::parse<int>(posString.c_str());
771  baseName = baseName.substr(0, sep_index); // includes the .
772  } catch (NumberFormatException&) {
773  }
774  }
775  }
776  baseName += '.';
777  // create a new edge from the new junction to the previous destination
778  GNEEdge* secondPart = createEdge(newJunction, edge->getGNEJunctionDestiny(), edge,
779  undoList, baseName + toString(posBase + (int)linePos), true, false, false);
780  // fix connections from the split edge (must happen before changing SUMO_ATTR_TO)
781  edge->getGNEJunctionDestiny()->replaceIncomingConnections(edge, secondPart, undoList);
782  // remove affected crossings from junction (must happen before changing SUMO_ATTR_TO)
783  std::vector<NBNode::Crossing> affectedCrossings;
784  for (GNECrossing* crossing : edge->getGNEJunctionDestiny()->getGNECrossings()) {
785  if (crossing->checkEdgeBelong(edge)) {
786  NBNode::Crossing nbC = *crossing->getNBCrossing();
787  undoList->add(new GNEChange_Crossing(edge->getGNEJunctionDestiny(), nbC, false), true);
788  EdgeVector newEdges;
789  for (NBEdge* nbEdge : nbC.edges) {
790  if (nbEdge == edge->getNBEdge()) {
791  newEdges.push_back(secondPart->getNBEdge());
792  } else {
793  newEdges.push_back(nbEdge);
794  }
795  }
796  nbC.edges = newEdges;
797  affectedCrossings.push_back(nbC);
798  }
799  }
800  // modify the edge so that it ends at the new junction (and all incoming connections are preserved
801  undoList->p_add(new GNEChange_Attribute(edge, this, SUMO_ATTR_TO, newJunction->getID()));
802  // fix first part of geometry
803  newGeoms.first.pop_back();
804  newGeoms.first.erase(newGeoms.first.begin());
805  edge->setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
806  edge->setAttribute(SUMO_ATTR_SHAPE, toString(newGeoms.first), undoList);
807  // fix second part of geometry
808  secondPart->setAttribute(GNE_ATTR_SHAPE_END, shapeEnd, undoList);
809  newGeoms.second.pop_back();
810  newGeoms.second.erase(newGeoms.second.begin());
811  secondPart->setAttribute(SUMO_ATTR_SHAPE, toString(newGeoms.second), undoList);
812  // reconnect across the split
813  for (int i = 0; i < (int)edge->getLanes().size(); ++i) {
814  undoList->add(new GNEChange_Connection(edge, NBEdge::Connection(i, secondPart->getNBEdge(), i), false, true), true);
815  }
816  // re-add modified crossings
817  for (const auto& nbC : affectedCrossings) {
818  undoList->add(new GNEChange_Crossing(secondPart->getGNEJunctionDestiny(), nbC, true), true);
819  }
820  undoList->p_end();
821  return newJunction;
822 }
823 
824 
825 void
826 GNENet::splitEdgesBidi(GNEEdge* edge, GNEEdge* oppositeEdge, const Position& pos, GNEUndoList* undoList) {
827  GNEJunction* newJunction = nullptr;
828  undoList->p_begin("split " + toString(SUMO_TAG_EDGE) + "s");
829  // split edge and save created junction
830  newJunction = splitEdge(edge, pos, undoList, newJunction);
831  // split second edge
832  splitEdge(oppositeEdge, pos, undoList, newJunction);
833  undoList->p_end();
834 }
835 
836 
837 void
839  undoList->p_begin("reverse " + toString(SUMO_TAG_EDGE));
840  deleteEdge(edge, undoList, false); // still exists. we delete it so we can reuse the name in case of resplit
841  GNEEdge* reversed = createEdge(edge->getGNEJunctionDestiny(), edge->getGNEJunctionSource(), edge, undoList, edge->getID(), false, true);
842  assert(reversed != 0);
843  reversed->setAttribute(SUMO_ATTR_SHAPE, toString(edge->getNBEdge()->getInnerGeometry().reverse()), undoList);
846  undoList->p_end();
847 }
848 
849 
850 GNEEdge*
852  undoList->p_begin("add reversed " + toString(SUMO_TAG_EDGE));
853  GNEEdge* reversed = nullptr;
855  // for rail edges, we assume bi-directional tracks are wanted
856  reversed = createEdge(edge->getGNEJunctionDestiny(), edge->getGNEJunctionSource(), edge, undoList, "-" + edge->getID(), false, true);
857  assert(reversed != 0);
858  reversed->setAttribute(SUMO_ATTR_SHAPE, toString(edge->getNBEdge()->getInnerGeometry().reverse()), undoList);
861  } else {
862  // if the edge is centered it should probably connect somewhere else
863  // make it easy to move and reconnect it
864  PositionVector orig = edge->getNBEdge()->getGeometry();
865  PositionVector origInner = edge->getNBEdge()->getInnerGeometry();
866  const double tentativeShift = edge->getNBEdge()->getTotalWidth() + 2;
867  orig.move2side(-tentativeShift);
868  origInner.move2side(-tentativeShift);
869  GNEJunction* src = createJunction(orig.back(), undoList);
870  GNEJunction* dest = createJunction(orig.front(), undoList);
871  reversed = createEdge(src, dest, edge, undoList, "-" + edge->getID(), false, true);
872  assert(reversed != 0);
873  reversed->setAttribute(SUMO_ATTR_SHAPE, toString(origInner.reverse()), undoList);
874  reversed->setAttribute(SUMO_ATTR_SHAPE, toString(origInner.reverse()), undoList);
875  // select the new edge and its nodes
876  reversed->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
877  src->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
878  dest->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
879  }
880  undoList->p_end();
881  return reversed;
882 }
883 
884 
885 void
887  undoList->p_begin("merge " + toString(SUMO_TAG_JUNCTION) + "s");
888  // place moved junction in the same position of target junction
890  // deleting edges changes in the underlying EdgeVector so we have to make a copy
891  const EdgeVector incoming = moved->getNBNode()->getIncomingEdges();
892  for (NBEdge* edge : incoming) {
893  // delete edges between the merged junctions
894  GNEEdge* e = myAttributeCarriers.edges[edge->getID()];
895  assert(e != 0);
896  if (e->getGNEJunctionSource() == target) {
897  deleteEdge(e, undoList, false);
898  } else {
899  undoList->p_add(new GNEChange_Attribute(e, this, SUMO_ATTR_TO, target->getID()));
900  }
901  }
902  // deleting edges changes in the underlying EdgeVector so we have to make a copy
903  const EdgeVector outgoing = moved->getNBNode()->getOutgoingEdges();
904  for (NBEdge* edge : outgoing) {
905  // delete edges between the merged junctions
906  GNEEdge* e = myAttributeCarriers.edges[edge->getID()];
907  assert(e != 0);
908  if (e->getGNEJunctionDestiny() == target) {
909  deleteEdge(e, undoList, false);
910  } else {
911  undoList->p_add(new GNEChange_Attribute(e, this, SUMO_ATTR_FROM, target->getID()));
912  }
913  }
914  // deleted moved junction
915  deleteJunction(moved, undoList);
916  undoList->p_end();
917 }
918 
919 
920 bool
922  // Check that there isn't another junction in the same position as Pos
923  for (auto i : myAttributeCarriers.junctions) {
924  if (i.second->getPositionInView() == pos) {
925  return false;
926  }
927  }
928  return true;
929 }
930 
931 
932 void
934  if (myNetSaved == true) {
935  WRITE_DEBUG("net has to be saved");
936  std::string additionalsSaved = (myAdditionalsSaved ? "saved" : "unsaved");
937  std::string demandElementsSaved = (myDemandElementsSaved ? "saved" : "unsaved");
938  WRITE_DEBUG("Current saving Status: net unsaved, additionals " + additionalsSaved + ", demand elements " + demandElementsSaved);
939  }
940  myNetSaved = !value;
941 }
942 
943 
944 bool
946  return myNetSaved;
947 }
948 
949 
950 void
952  // compute without volatile options and update network
953  computeAndUpdate(oc, false);
954  // write network
956  myNetSaved = true;
957 }
958 
959 
960 void
962  // compute without volatile options
963  computeAndUpdate(oc, false);
965 }
966 
967 
968 void
970  // compute without volatile options
971  computeAndUpdate(oc, false);
973 }
974 
975 
976 void
978  myViewNet = viewNet;
979 
980  // Create default vehicle Type (it has to be created here due myViewNet was previously nullptr)
982  myAttributeCarriers.demandElements.at(defaultVehicleType->getTagProperty().getTag()).insert(std::make_pair(defaultVehicleType->getID(), defaultVehicleType));
983  defaultVehicleType->incRef("GNENet::DEFAULT_VEHTYPE");
984 
985  // Create default Bike Type (it has to be created here due myViewNet was previously nullptr)
987  myAttributeCarriers.demandElements.at(defaultBikeType->getTagProperty().getTag()).insert(std::make_pair(defaultBikeType->getID(), defaultBikeType));
988  defaultBikeType->incRef("GNENet::DEFAULT_BIKETYPE_ID");
989 
990  // Create default person Type (it has to be created here due myViewNet was previously nullptr)
992  myAttributeCarriers.demandElements.at(defaultPersonType->getTagProperty().getTag()).insert(std::make_pair(defaultPersonType->getID(), defaultPersonType));
993  defaultPersonType->incRef("GNENet::DEFAULT_PEDTYPE_ID");
994 
995  // create instance of RouteCalculator
997 }
998 
999 
1000 GNEJunction*
1001 GNENet::retrieveJunction(const std::string& id, bool failHard) {
1002  if (myAttributeCarriers.junctions.count(id)) {
1003  return myAttributeCarriers.junctions[id];
1004  } else if (failHard) {
1005  // If junction wasn't found, throw exception
1006  throw UnknownElement("Junction " + id);
1007  } else {
1008  return nullptr;
1009  }
1010 }
1011 
1012 
1015  return myAttributeCarriers;
1016 }
1017 
1018 
1019 GNEEdge*
1020 GNENet::retrieveEdge(const std::string& id, bool failHard) {
1021  auto i = myAttributeCarriers.edges.find(id);
1022  // If edge was found
1023  if (i != myAttributeCarriers.edges.end()) {
1024  return i->second;
1025  } else if (failHard) {
1026  // If edge wasn't found, throw exception
1027  throw UnknownElement("Edge " + id);
1028  } else {
1029  return nullptr;
1030  }
1031 }
1032 
1033 
1034 GNEEdge*
1035 GNENet::retrieveEdge(GNEJunction* from, GNEJunction* to, bool failHard) {
1036  assert((from != nullptr) && (to != nullptr));
1037  // iterate over Junctions of net
1038  for (auto i : myAttributeCarriers.edges) {
1039  if ((i.second->getGNEJunctionSource() == from) && (i.second->getGNEJunctionDestiny() == to)) {
1040  return i.second;
1041  }
1042  }
1043  // if edge wasn' found, throw exception or return nullptr
1044  if (failHard) {
1045  throw UnknownElement("Edge with from='" + from->getID() + "' and to='" + to->getID() + "'");
1046  } else {
1047  return nullptr;
1048  }
1049 }
1050 
1051 
1052 GNEPoly*
1053 GNENet::retrievePolygon(const std::string& id, bool failHard) const {
1054  if (myPolygons.get(id) != 0) {
1055  return reinterpret_cast<GNEPoly*>(myPolygons.get(id));
1056  } else if (failHard) {
1057  // If Polygon wasn't found, throw exception
1058  throw UnknownElement("Polygon " + id);
1059  } else {
1060  return nullptr;
1061  }
1062 }
1063 
1064 
1065 GNEPOI*
1066 GNENet::retrievePOI(const std::string& id, bool failHard) const {
1067  if (myPOIs.get(id) != 0) {
1068  return reinterpret_cast<GNEPOI*>(myPOIs.get(id));
1069  } else if (failHard) {
1070  // If POI wasn't found, throw exception
1071  throw UnknownElement("POI " + id);
1072  } else {
1073  return nullptr;
1074  }
1075 }
1076 
1077 
1079 GNENet::retrieveConnection(const std::string& id, bool failHard) const {
1080  // iterate over junctions
1081  for (auto i : myAttributeCarriers.junctions) {
1082  // iterate over connections
1083  for (auto j : i.second->getGNEConnections()) {
1084  if (j->getID() == id) {
1085  return j;
1086  }
1087  }
1088  }
1089  if (failHard) {
1090  // If POI wasn't found, throw exception
1091  throw UnknownElement("Connection " + id);
1092  } else {
1093  return nullptr;
1094  }
1095 }
1096 
1097 
1098 std::vector<GNEConnection*>
1099 GNENet::retrieveConnections(bool onlySelected) const {
1100  std::vector<GNEConnection*> result;
1101  // iterate over junctions
1102  for (auto i : myAttributeCarriers.junctions) {
1103  // iterate over connections
1104  for (auto j : i.second->getGNEConnections()) {
1105  if (!onlySelected || j->isAttributeCarrierSelected()) {
1106  result.push_back(j);
1107  }
1108  }
1109  }
1110  return result;
1111 }
1112 
1113 
1114 GNECrossing*
1115 GNENet::retrieveCrossing(const std::string& id, bool failHard) const {
1116  // iterate over junctions
1117  for (auto i : myAttributeCarriers.junctions) {
1118  // iterate over crossings
1119  for (auto j : i.second->getGNECrossings()) {
1120  if (j->getID() == id) {
1121  return j;
1122  }
1123  }
1124  }
1125  if (failHard) {
1126  // If POI wasn't found, throw exception
1127  throw UnknownElement("Crossing " + id);
1128  } else {
1129  return nullptr;
1130  }
1131 }
1132 
1133 
1134 std::vector<GNECrossing*>
1135 GNENet::retrieveCrossings(bool onlySelected) const {
1136  std::vector<GNECrossing*> result;
1137  // iterate over junctions
1138  for (auto i : myAttributeCarriers.junctions) {
1139  // iterate over crossings
1140  for (auto j : i.second->getGNECrossings()) {
1141  if (!onlySelected || j->isAttributeCarrierSelected()) {
1142  result.push_back(j);
1143  }
1144  }
1145  }
1146  return result;
1147 }
1148 
1149 
1150 std::vector<GNEEdge*>
1151 GNENet::retrieveEdges(bool onlySelected) {
1152  std::vector<GNEEdge*> result;
1153  // returns edges depending of selection
1154  for (auto i : myAttributeCarriers.edges) {
1155  if (!onlySelected || i.second->isAttributeCarrierSelected()) {
1156  result.push_back(i.second);
1157  }
1158  }
1159  return result;
1160 }
1161 
1162 
1163 std::vector<GNELane*>
1164 GNENet::retrieveLanes(bool onlySelected) {
1165  std::vector<GNELane*> result;
1166  // returns lanes depending of selection
1167  for (auto i : myAttributeCarriers.edges) {
1168  for (auto j : i.second->getLanes()) {
1169  if (!onlySelected || j->isAttributeCarrierSelected()) {
1170  result.push_back(j);
1171  }
1172  }
1173  }
1174  return result;
1175 }
1176 
1177 
1178 GNELane*
1179 GNENet::retrieveLane(const std::string& id, bool failHard, bool checkVolatileChange) {
1180  const std::string edge_id = SUMOXMLDefinitions::getEdgeIDFromLane(id);
1181  GNEEdge* edge = retrieveEdge(edge_id, failHard);
1182  if (edge != nullptr) {
1183  GNELane* lane = nullptr;
1184  // search lane in lane's edges
1185  for (auto it : edge->getLanes()) {
1186  if (it->getID() == id) {
1187  lane = it;
1188  }
1189  }
1190  // throw exception or return nullptr if lane wasn't found
1191  if (lane == nullptr) {
1192  if (failHard) {
1193  // Throw exception if failHard is enabled
1194  throw UnknownElement(toString(SUMO_TAG_LANE) + " " + id);
1195  }
1196  } else {
1197  // check if the recomputing with volatile option has changed the number of lanes (needed for additionals and demand elements)
1198  if (checkVolatileChange && (myEdgesAndNumberOfLanes.count(edge_id) == 1) && myEdgesAndNumberOfLanes[edge_id] != (int)edge->getLanes().size()) {
1199  return edge->getLanes().at(lane->getIndex() + 1);
1200  }
1201  return lane;
1202  }
1203  } else if (failHard) {
1204  // Throw exception if failHard is enabled
1205  throw UnknownElement(toString(SUMO_TAG_EDGE) + " " + edge_id);
1206  }
1207  return nullptr;
1208 }
1209 
1210 
1211 std::vector<GNEJunction*>
1212 GNENet::retrieveJunctions(bool onlySelected) {
1213  std::vector<GNEJunction*> result;
1214  // returns junctions depending of selection
1215  for (auto i : myAttributeCarriers.junctions) {
1216  if (!onlySelected || i.second->isAttributeCarrierSelected()) {
1217  result.push_back(i.second);
1218  }
1219  }
1220  return result;
1221 }
1222 
1223 
1224 std::vector<GNEShape*>
1225 GNENet::retrieveShapes(SumoXMLTag shapeTag, bool onlySelected) {
1226  std::vector<GNEShape*> result;
1227  // return dependingn of shape type
1228  if (shapeTag == SUMO_TAG_POLY) {
1229  // return all polys depending of onlySelected
1230  for (auto it : getPolygons()) {
1231  GNEShape* shape = dynamic_cast<GNEShape*>(it.second);
1232  if (!onlySelected || shape->isAttributeCarrierSelected()) {
1233  result.push_back(shape);
1234  }
1235  }
1236  } else {
1237  // check if we need to return a POI or POILane
1238  for (auto it : getPOIs()) {
1239  GNEPOI* poi = dynamic_cast<GNEPOI*>(it.second);
1240  if (poi && (poi->getTagProperty().getTag() == shapeTag)) {
1241  // return all POIs or POILanes depending of onlySelected
1242  if (!onlySelected || poi->isAttributeCarrierSelected()) {
1243  result.push_back(poi);
1244  }
1245  }
1246  }
1247  }
1248  return result;
1249 }
1250 
1251 
1252 std::vector<GNEShape*>
1253 GNENet::retrieveShapes(bool onlySelected) {
1254  std::vector<GNEShape*> result;
1255  // return all polygons and POIs
1256  for (const auto& it : getPolygons()) {
1257  GNEPoly* poly = dynamic_cast<GNEPoly*>(it.second);
1258  if (!onlySelected || poly->isAttributeCarrierSelected()) {
1259  result.push_back(poly);
1260  }
1261  }
1262  for (const auto& it : getPOIs()) {
1263  GNEPOI* poi = dynamic_cast<GNEPOI*>(it.second);
1264  if (!onlySelected || poi->isAttributeCarrierSelected()) {
1265  result.push_back(poi);
1266  }
1267  }
1268  return result;
1269 }
1270 
1271 
1272 void
1275 }
1276 
1277 
1278 void
1281 }
1282 
1283 
1286  // obtain blocked GUIGlObject
1288  // Make sure that object exists
1289  if (object != nullptr) {
1290  // unblock and try to parse to AtributeCarrier
1292  GNEAttributeCarrier* ac = dynamic_cast<GNEAttributeCarrier*>(object);
1293  // If was sucesfully parsed, return it
1294  if (ac == nullptr) {
1295  throw ProcessError("GUIGlObject does not match the declared type");
1296  } else {
1297  return ac;
1298  }
1299  } else if (failHard) {
1300  throw ProcessError("Attempted to retrieve non-existant GUIGlObject");
1301  } else {
1302  return nullptr;
1303  }
1304 }
1305 
1306 
1307 std::vector<GNEAttributeCarrier*>
1309  std::vector<GNEAttributeCarrier*> result;
1310  if (type == SUMO_TAG_NOTHING) {
1311  // return all elements
1312  for (auto i : myAttributeCarriers.junctions) {
1313  result.push_back(i.second);
1314  for (auto j : i.second->getGNECrossings()) {
1315  result.push_back(j);
1316  }
1317  }
1318  for (auto i : myAttributeCarriers.edges) {
1319  result.push_back(i.second);
1320  for (auto j : i.second->getLanes()) {
1321  result.push_back(j);
1322  }
1323  for (auto j : i.second->getGNEConnections()) {
1324  result.push_back(j);
1325  }
1326  }
1327  for (auto i : myAttributeCarriers.additionals) {
1328  for (auto j : i.second) {
1329  result.push_back(j.second);
1330  }
1331  }
1332  for (auto i : myPolygons) {
1333  result.push_back(dynamic_cast<GNEPoly*>(i.second));
1334  }
1335  for (auto i : myPOIs) {
1336  result.push_back(dynamic_cast<GNEPOI*>(i.second));
1337  }
1338  for (auto i : myAttributeCarriers.demandElements) {
1339  for (auto j : i.second) {
1340  result.push_back(j.second);
1341  }
1342  }
1343  } else if (GNEAttributeCarrier::getTagProperties(type).isAdditional() || GNEAttributeCarrier::getTagProperties(type).isTAZ()) {
1344  // only returns additionals of a certain type.
1345  for (auto i : myAttributeCarriers.additionals.at(type)) {
1346  result.push_back(i.second);
1347  }
1348  } else if (GNEAttributeCarrier::getTagProperties(type).isDemandElement() || GNEAttributeCarrier::getTagProperties(type).isStop()) {
1349  // only returns demand elements of a certain type.
1350  for (auto i : myAttributeCarriers.demandElements.at(type)) {
1351  result.push_back(i.second);
1352  }
1353  } else {
1354  // return only a part of elements, depending of type
1355  switch (type) {
1356  case SUMO_TAG_JUNCTION:
1357  for (auto i : myAttributeCarriers.junctions) {
1358  result.push_back(i.second);
1359  }
1360  break;
1361  case SUMO_TAG_EDGE:
1362  for (auto i : myAttributeCarriers.edges) {
1363  result.push_back(i.second);
1364  }
1365  break;
1366  case SUMO_TAG_LANE:
1367  for (auto i : myAttributeCarriers.edges) {
1368  for (auto j : i.second->getLanes()) {
1369  result.push_back(j);
1370  }
1371  }
1372  break;
1373  case SUMO_TAG_CONNECTION:
1374  for (auto i : myAttributeCarriers.edges) {
1375  for (auto j : i.second->getGNEConnections()) {
1376  result.push_back(j);
1377  }
1378  }
1379  break;
1380  case SUMO_TAG_CROSSING:
1381  for (auto i : myAttributeCarriers.junctions) {
1382  for (auto j : i.second->getGNECrossings()) {
1383  result.push_back(j);
1384  }
1385  }
1386  break;
1387  case SUMO_TAG_POLY:
1388  for (auto i : myPolygons) {
1389  result.push_back(dynamic_cast<GNEPoly*>(i.second));
1390  }
1391  break;
1392  case SUMO_TAG_POI:
1393  case SUMO_TAG_POILANE:
1394  for (auto i : myPOIs) {
1395  result.push_back(dynamic_cast<GNEPOI*>(i.second));
1396  }
1397  break;
1398  default:
1399  // return nothing
1400  break;
1401  }
1402  }
1403  return result;
1404 }
1405 
1406 
1407 void
1408 GNENet::computeNetwork(GNEApplicationWindow* window, bool force, bool volatileOptions, std::string additionalPath, std::string demandPath) {
1409  if (!myNeedRecompute) {
1410  if (force) {
1411  if (volatileOptions) {
1412  window->setStatusBarText("Forced computing junctions with volatile options ...");
1413  } else {
1414  window->setStatusBarText("Forced computing junctions ...");
1415  }
1416  } else {
1417  return;
1418  }
1419  } else {
1420  if (volatileOptions) {
1421  window->setStatusBarText("Computing junctions with volatile options ...");
1422  } else {
1423  window->setStatusBarText("Computing junctions ...");
1424  }
1425  }
1426  // save current number of lanes for every edge if recomputing is with volatile options
1427  if (volatileOptions) {
1428  for (auto it : myAttributeCarriers.edges) {
1429  myEdgesAndNumberOfLanes[it.second->getID()] = (int)it.second->getLanes().size();
1430  }
1431  }
1432 
1433  // compute and update
1435  computeAndUpdate(oc, volatileOptions);
1436 
1437  // load additionals if was recomputed with volatile options
1438  if (additionalPath != "") {
1439  // fill additionals with tags
1440  auto listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_ADDITIONAL, false);
1441  for (auto i : listOfTags) {
1442  myAttributeCarriers.additionals.insert(std::make_pair(i, std::map<std::string, GNEAdditional*>()));
1443  }
1444  listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_TAZ, false);
1445  for (auto i : listOfTags) {
1446  myAttributeCarriers.additionals.insert(std::make_pair(i, std::map<std::string, GNEAdditional*>()));
1447  }
1448  // Create additional handler
1449  GNEAdditionalHandler additionalHandler(additionalPath, myViewNet);
1450  // Run parser
1451  if (!XMLSubSys::runParser(additionalHandler, additionalPath, false)) {
1452  WRITE_MESSAGE("Loading of " + additionalPath + " failed.");
1453  } else {
1454  // update view
1455  update();
1456  }
1457  // clear myEdgesAndNumberOfLanes after reload additionals
1458  myEdgesAndNumberOfLanes.clear();
1459  }
1460  // load demand elements if was recomputed with volatile options
1461  if (demandPath != "") {
1462  // fill demandElements with tags
1463  auto listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_DEMANDELEMENT, false);
1464  for (auto i : listOfTags) {
1465  myAttributeCarriers.demandElements.insert(std::make_pair(i, std::map<std::string, GNEDemandElement*>()));
1466  }
1467  listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_STOP, false);
1468  for (auto i : listOfTags) {
1469  myAttributeCarriers.demandElements.insert(std::make_pair(i, std::map<std::string, GNEDemandElement*>()));
1470  }
1471  // Create demandElement handler
1472  GNERouteHandler demandElementHandler(demandPath, myViewNet, false);
1473  // Run parser
1474  if (!XMLSubSys::runParser(demandElementHandler, demandPath, false)) {
1475  WRITE_MESSAGE("Loading of " + demandPath + " failed.");
1476  } else {
1477  // update view
1478  update();
1479  }
1480  // clear myEdgesAndNumberOfLanes after reload demandElements
1481  myEdgesAndNumberOfLanes.clear();
1482  }
1483  window->getApp()->endWaitCursor();
1484  window->setStatusBarText("Finished computing junctions.");
1485 }
1486 
1487 
1488 void
1490  window->setStatusBarText("Computing demand elements ...");
1491  // iterate over all demand elements and compute
1492  for (const auto& i : myAttributeCarriers.demandElements) {
1493  for (const auto& j : i.second) {
1494  j.second->compute();
1495  }
1496  }
1497  window->setStatusBarText("Finished computing demand elements.");
1498 }
1499 
1500 
1501 void
1503  // recompute tl-logics
1506  // iterate over traffic lights definitions. Make a copy because invalid
1507  // definitions will be removed (and would otherwise destroy the iterator)
1508  const std::set<NBTrafficLightDefinition*> tlsDefs = junction->getNBNode()->getControllingTLS();
1509  for (auto it : tlsDefs) {
1510  it->setParticipantsInformation();
1511  it->setTLControllingInformation();
1512  tllCont.computeSingleLogic(oc, it);
1513  }
1514 
1515  // @todo compute connections etc...
1516 }
1517 
1518 
1519 void
1521  myNeedRecompute = true;
1522 }
1523 
1524 
1525 bool
1527  for (auto n : myAttributeCarriers.junctions) {
1528  if (n.second->getGNECrossings().size() > 0) {
1529  return true;
1530  }
1531  }
1532  return false;
1533 }
1534 
1535 
1536 FXApp*
1538  return myViewNet->getApp();
1539 }
1540 
1541 
1542 NBNetBuilder*
1544  return myNetBuilder;
1545 }
1546 
1547 
1548 bool
1550  std::vector<GNEJunction*> selectedJunctions = retrieveJunctions(true);
1551  if (selectedJunctions.size() < 2) {
1552  return false;
1553  }
1554  EdgeVector allIncoming;
1555  EdgeVector allOutgoing;
1556  std::set<NBNode*, ComparatorIdLess> cluster;
1557  for (auto it : selectedJunctions) {
1558  cluster.insert(it->getNBNode());
1559  const EdgeVector& incoming = it->getNBNode()->getIncomingEdges();
1560  allIncoming.insert(allIncoming.end(), incoming.begin(), incoming.end());
1561  const EdgeVector& outgoing = it->getNBNode()->getOutgoingEdges();
1562  allOutgoing.insert(allOutgoing.end(), outgoing.begin(), outgoing.end());
1563  }
1564  // create new junction
1565  Position pos;
1566  Position oldPos;
1567  bool setTL;
1568  std::string id = "cluster";
1569  TrafficLightType type;
1570  SumoXMLNodeType nodeType = NODETYPE_UNKNOWN;
1571  myNetBuilder->getNodeCont().analyzeCluster(cluster, id, pos, setTL, type, nodeType);
1572  // save position
1573  oldPos = pos;
1574 
1575  // Check that there isn't another junction in the same position as Pos but doesn't belong to cluster
1576  for (auto i : myAttributeCarriers.junctions) {
1577  if ((i.second->getPositionInView() == pos) && (cluster.find(i.second->getNBNode()) == cluster.end())) {
1578  // show warning in gui testing debug mode
1579  WRITE_DEBUG("Opening FXMessageBox 'Join non-selected junction'");
1580  // Ask confirmation to user
1581  FXuint answer = FXMessageBox::question(getApp(), MBOX_YES_NO,
1582  ("Position of joined " + toString(SUMO_TAG_JUNCTION)).c_str(), "%s",
1583  ("There is another unselected " + toString(SUMO_TAG_JUNCTION) + " in the same position of joined " + toString(SUMO_TAG_JUNCTION) +
1584  + ".\nIt will be joined with the other selected " + toString(SUMO_TAG_JUNCTION) + "s. Continue?").c_str());
1585  if (answer != 1) { // 1:yes, 2:no, 4:esc
1586  // write warning if netedit is running in testing mode
1587  if (answer == 2) {
1588  WRITE_DEBUG("Closed FXMessageBox 'Join non-selected junction' with 'No'");
1589  } else if (answer == 4) {
1590  WRITE_DEBUG("Closed FXMessageBox 'Join non-selected junction' with 'ESC'");
1591  }
1592  return false;
1593  } else {
1594  // write warning if netedit is running in testing mode
1595  WRITE_DEBUG("Closed FXMessageBox 'Join non-selected junction' with 'Yes'");
1596  // select conflicted junction an join all again
1597  i.second->setAttribute(GNE_ATTR_SELECTED, "true", undoList);
1598  return joinSelectedJunctions(undoList);
1599  }
1600  }
1601  }
1602 
1603  // use checkJunctionPosition to avoid conflicts with junction in the same position as others
1604  while (checkJunctionPosition(pos) == false) {
1605  pos.setx(pos.x() + 0.1);
1606  pos.sety(pos.y() + 0.1);
1607  }
1608 
1609  // start with the join selected junctions
1610  undoList->p_begin("Join selected " + toString(SUMO_TAG_JUNCTION) + "s");
1611  GNEJunction* joined = createJunction(pos, undoList);
1612  joined->setAttribute(SUMO_ATTR_TYPE, toString(nodeType), undoList); // i.e. rail crossing
1613  if (setTL) {
1614  joined->setAttribute(SUMO_ATTR_TLTYPE, toString(type), undoList);
1615  }
1616 
1617  // #3128 this is not undone when calling 'undo'
1619 
1620  // first remove all crossing of the involved junctions and edges
1621  // (otherwise edge removal will trigger discarding)
1622  std::vector<NBNode::Crossing> oldCrossings;
1623  for (auto i : selectedJunctions) {
1624  while (i->getGNECrossings().size() > 0) {
1625  GNECrossing* crossing = i->getGNECrossings().front();
1626  oldCrossings.push_back(*crossing->getNBCrossing());
1627  deleteCrossing(crossing, undoList);
1628  }
1629  }
1630 
1631  // preserve old connections
1632  for (auto it : selectedJunctions) {
1633  it->setLogicValid(false, undoList);
1634  }
1635  // remap edges
1636  for (auto it : allIncoming) {
1637  undoList->p_add(new GNEChange_Attribute(myAttributeCarriers.edges[it->getID()], this, SUMO_ATTR_TO, joined->getID()));
1638  }
1639 
1640  EdgeSet edgesWithin;
1641  for (auto it : allOutgoing) {
1642  // delete edges within the cluster
1643  GNEEdge* e = myAttributeCarriers.edges[it->getID()];
1644  assert(e != 0);
1645  if (e->getGNEJunctionDestiny() == joined) {
1646  edgesWithin.insert(it);
1647  deleteEdge(e, undoList, false);
1648  } else {
1649  undoList->p_add(new GNEChange_Attribute(myAttributeCarriers.edges[it->getID()], this, SUMO_ATTR_FROM, joined->getID()));
1650  }
1651  }
1652 
1653  // remap all crossing of the involved junctions and edges
1654  for (auto nbc : oldCrossings) {
1655  bool keep = true;
1656  for (NBEdge* e : nbc.edges) {
1657  if (edgesWithin.count(e) != 0) {
1658  keep = false;
1659  break;
1660  }
1661  };
1662  if (keep) {
1663  undoList->add(new GNEChange_Crossing(joined, nbc.edges, nbc.width,
1664  nbc.priority || joined->getNBNode()->isTLControlled(),
1665  nbc.customTLIndex, nbc.customTLIndex2, nbc.customShape,
1666  false, true), true);
1667  }
1668  }
1669 
1670  // delete original junctions
1671  for (auto it : selectedJunctions) {
1672  deleteJunction(it, undoList);
1673  }
1674  joined->setAttribute(SUMO_ATTR_ID, id, undoList);
1675 
1676 
1677  // check if joined junction had to change their original position to avoid errors
1678  if (pos != oldPos) {
1679  joined->setAttribute(SUMO_ATTR_POSITION, toString(oldPos), undoList);
1680  }
1681  undoList->p_end();
1682  return true;
1683 }
1684 
1685 
1686 bool
1688  // obtain current net's crossings
1689  std::vector<GNECrossing*> myNetCrossings;
1690  for (auto it : myAttributeCarriers.junctions) {
1691  myNetCrossings.reserve(myNetCrossings.size() + it.second->getGNECrossings().size());
1692  myNetCrossings.insert(myNetCrossings.end(), it.second->getGNECrossings().begin(), it.second->getGNECrossings().end());
1693  }
1694  // obtain invalid crossigns
1695  std::vector<GNECrossing*> myInvalidCrossings;
1696  for (auto i = myNetCrossings.begin(); i != myNetCrossings.end(); i++) {
1697  if ((*i)->getNBCrossing()->valid == false) {
1698  myInvalidCrossings.push_back(*i);
1699  }
1700  }
1701 
1702  if (myInvalidCrossings.empty()) {
1703  // show warning in gui testing debug mode
1704  WRITE_DEBUG("Opening FXMessageBox 'No crossing to remove'");
1705  // open a dialog informing that there isn't crossing to remove
1706  FXMessageBox::warning(getApp(), MBOX_OK,
1707  ("Clear " + toString(SUMO_TAG_CROSSING) + "s").c_str(), "%s",
1708  ("There is no invalid " + toString(SUMO_TAG_CROSSING) + "s to remove").c_str());
1709  // show warning in gui testing debug mode
1710  WRITE_DEBUG("Closed FXMessageBox 'No crossing to remove' with 'OK'");
1711  } else {
1712  std::string plural = myInvalidCrossings.size() == 1 ? ("") : ("s");
1713  // show warning in gui testing debug mode
1714  WRITE_DEBUG("Opening FXMessageBox 'clear crossings'");
1715  // Ask confirmation to user
1716  FXuint answer = FXMessageBox::question(getApp(), MBOX_YES_NO,
1717  ("Clear " + toString(SUMO_TAG_CROSSING) + "s").c_str(), "%s",
1718  ("Clear " + toString(SUMO_TAG_CROSSING) + plural + " will be removed. Continue?").c_str());
1719  if (answer != 1) { // 1:yes, 2:no, 4:esc
1720  // write warning if netedit is running in testing mode
1721  if (answer == 2) {
1722  WRITE_DEBUG("Closed FXMessageBox 'clear crossings' with 'No'");
1723  } else if (answer == 4) {
1724  WRITE_DEBUG("Closed FXMessageBox 'clear crossings' with 'ESC'");
1725  }
1726  } else {
1727  undoList->p_begin("Clean " + toString(SUMO_TAG_CROSSING) + "s");
1728  for (auto i = myInvalidCrossings.begin(); i != myInvalidCrossings.end(); i++) {
1729  deleteCrossing((*i), undoList);
1730  }
1731  undoList->p_end();
1732  }
1733  }
1734  return 1;
1735 }
1736 
1737 
1738 void
1740  undoList->p_begin("Clean " + toString(SUMO_TAG_JUNCTION) + "s");
1741  std::vector<GNEJunction*> toRemove;
1742  for (auto it : myAttributeCarriers.junctions) {
1743  GNEJunction* junction = it.second;
1744  if (junction->getNBNode()->getEdges().size() == 0) {
1745  toRemove.push_back(junction);
1746  }
1747  }
1748  for (auto it : toRemove) {
1749  deleteJunction(it, undoList);
1750  }
1751  undoList->p_end();
1752 }
1753 
1754 
1755 void
1757  // first declare a vector to save all routes without children
1758  std::vector<GNEDemandElement*> routesWithoutChildren;
1759  routesWithoutChildren.reserve(myAttributeCarriers.demandElements.at(SUMO_TAG_ROUTE).size());
1760  // iterate over routes
1761  for (const auto& i : myAttributeCarriers.demandElements.at(SUMO_TAG_ROUTE)) {
1762  if (i.second->getDemandElementChildren().empty()) {
1763  routesWithoutChildren.push_back(i.second);
1764  }
1765  }
1766  // finally remove all routesWithoutChildren
1767  if (routesWithoutChildren.size() > 0) {
1768  // begin undo list
1769  undoList->p_begin("clean unused routes");
1770  // iterate over routesWithoutChildren
1771  for (const auto& i : routesWithoutChildren) {
1772  // due route doesn't have children, simply call GNEChange_DemandElement
1773  undoList->add(new GNEChange_DemandElement(i, false), true);
1774  }
1775  // update view
1776  myViewNet->update();
1777  // end undo list
1778  undoList->p_end();
1779  }
1780 }
1781 
1782 
1783 void
1785  // first declare a sorted set of sorted route's edges in string format
1786  std::set<std::pair<std::string, GNEDemandElement*> > mySortedRoutes;
1787  // iterate over routes and save it in mySortedRoutes (only if it doesn't have Stop Children)
1788  for (const auto& i : myAttributeCarriers.demandElements.at(SUMO_TAG_ROUTE)) {
1789  // first check route has stops
1790  bool hasStops = false;
1791  for (const auto& j : i.second->getDemandElementChildren()) {
1792  if (j->getTagProperty().isStop()) {
1793  hasStops = true;
1794  }
1795  }
1796  if (!hasStops) {
1797  mySortedRoutes.insert(std::make_pair(GNEAttributeCarrier::parseIDs(i.second->getEdgeParents()), i.second));
1798  }
1799  }
1800  // now declare a matrix in which organice routes to be merged
1801  std::vector<std::vector<GNEDemandElement*> > routesToMerge;
1802  auto index = mySortedRoutes.begin();
1803  // iterate over mySortedRoutes
1804  for (auto i = mySortedRoutes.begin(); i != mySortedRoutes.end(); i++) {
1805  if (routesToMerge.empty()) {
1806  routesToMerge.push_back({i->second});
1807  } else {
1808  if (index->first == i->first) {
1809  routesToMerge.back().push_back(i->second);
1810  } else {
1811  routesToMerge.push_back({i->second});
1812  index = i;
1813  }
1814  }
1815  }
1816  // now check if there is routes to merge
1817  bool thereIsRoutesToMerge = false;
1818  for (const auto& i : routesToMerge) {
1819  if (i.size() > 1) {
1820  thereIsRoutesToMerge = true;
1821  }
1822  }
1823  // if exist
1824  if (thereIsRoutesToMerge) {
1825  // begin undo list
1826  undoList->p_begin("merge routes");
1827  // iterate over route to edges
1828  for (const auto& i : routesToMerge) {
1829  if (i.size() > 1) {
1830  // iterate over duplicated routes
1831  for (int j = 1; j < (int)i.size(); j++) {
1832  // move all vehicles of every duplicated route
1833  while (i.at(j)->getDemandElementChildren().size() > 0) {
1834  i.at(j)->getDemandElementChildren().front()->setAttribute(SUMO_ATTR_ROUTE, i.at(0)->getID(), undoList);
1835  }
1836  // finally remove route
1837  undoList->add(new GNEChange_DemandElement(i.at(j), false), true);
1838  }
1839  }
1840  }
1841  // update view
1842  myViewNet->update();
1843  // end undo list
1844  undoList->p_end();
1845  }
1846 }
1847 
1848 
1849 void
1851  // first declare a vector to save all invalid demand elements
1852  std::vector<GNEDemandElement*> invalidDemandElements;
1853  invalidDemandElements.reserve(myAttributeCarriers.demandElements.at(SUMO_TAG_ROUTE).size() +
1856  // iterate over routes
1857  for (const auto& i : myAttributeCarriers.demandElements.at(SUMO_TAG_ROUTE)) {
1858  if (!i.second->isDemandElementValid()) {
1859  invalidDemandElements.push_back(i.second);
1860  }
1861  }
1862  // iterate over flows
1863  for (const auto& i : myAttributeCarriers.demandElements.at(SUMO_TAG_FLOW)) {
1864  if (!i.second->isDemandElementValid()) {
1865  invalidDemandElements.push_back(i.second);
1866  }
1867  }
1868  // iterate over trip
1869  for (const auto& i : myAttributeCarriers.demandElements.at(SUMO_TAG_TRIP)) {
1870  if (!i.second->isDemandElementValid()) {
1871  invalidDemandElements.push_back(i.second);
1872  }
1873  }
1874  // continue if there is invalidDemandElements to remove
1875  if (invalidDemandElements.size() > 0) {
1876  // begin undo list
1877  undoList->p_begin("remove invalid demand elements");
1878  // iterate over invalidDemandElements
1879  for (const auto& i : invalidDemandElements) {
1880  // simply call GNEChange_DemandElement
1881  undoList->add(new GNEChange_DemandElement(i, false), true);
1882  }
1883  // update view
1884  myViewNet->update();
1885  // end undo list
1886  undoList->p_end();
1887  }
1888 }
1889 
1890 void
1892  assert(junction->getNBNode()->checkIsRemovable());
1893  // start operation
1894  undoList->p_begin("Replace junction by geometry");
1895  // obtain Edges to join
1896  std::vector<std::pair<NBEdge*, NBEdge*> > toJoin = junction->getNBNode()->getEdgesToJoin();
1897  // clear connections of junction to replace
1898  clearJunctionConnections(junction, undoList);
1899  // iterate over NBEdges to join
1900  for (auto j : toJoin) {
1901  // obtain GNEEdges
1902  GNEEdge* begin = myAttributeCarriers.edges[j.first->getID()];
1903  GNEEdge* continuation = myAttributeCarriers.edges[j.second->getID()];
1904  // remove connections between the edges
1905  std::vector<NBEdge::Connection> connections = begin->getNBEdge()->getConnections();
1906  for (auto con : connections) {
1907  undoList->add(new GNEChange_Connection(begin, con, false, false), true);
1908  }
1909  // fix shape of replaced edge
1910  PositionVector newShape = begin->getNBEdge()->getInnerGeometry();
1911  if (begin->getNBEdge()->hasDefaultGeometryEndpointAtNode(begin->getNBEdge()->getToNode())) {
1912  newShape.push_back(junction->getNBNode()->getPosition());
1913  } else {
1914  newShape.push_back(begin->getNBEdge()->getGeometry()[-1]);
1915  }
1916  if (continuation->getNBEdge()->hasDefaultGeometryEndpointAtNode(begin->getNBEdge()->getToNode())) {
1917  newShape.push_back_noDoublePos(junction->getNBNode()->getPosition());
1918  } else {
1919  newShape.push_back_noDoublePos(continuation->getNBEdge()->getGeometry()[0]);
1920  }
1921  // replace incoming edge
1922  replaceIncomingEdge(continuation, begin, undoList);
1923 
1924  newShape.append(continuation->getNBEdge()->getInnerGeometry());
1925  begin->setAttribute(GNE_ATTR_SHAPE_END, continuation->getAttribute(GNE_ATTR_SHAPE_END), undoList);
1926  begin->setAttribute(SUMO_ATTR_ENDOFFSET, continuation->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
1927  begin->setAttribute(SUMO_ATTR_SHAPE, toString(newShape), undoList);
1928  }
1929  //delete replaced junction
1930  deleteJunction(junction, undoList);
1931  // finish operation
1932  undoList->p_end();
1933 }
1934 
1935 
1936 void
1937 GNENet::splitJunction(GNEJunction* junction, bool reconnect, GNEUndoList* undoList) {
1938  std::vector<std::pair<Position, std::string> > endpoints = junction->getNBNode()->getEndPoints();
1939  if (endpoints.size() < 2) {
1940  return;
1941  }
1942  // start operation
1943  undoList->p_begin("Split junction");
1944  // record connections
1945  std::map<GNEEdge*, std::vector<NBEdge::Connection>> straightConnections;
1946  for (GNEEdge* e : junction->getGNEIncomingEdges()) {
1947  for (const auto& c : e->getNBEdge()->getConnections()) {
1948  if (c.fromLane >= 0 && junction->getNBNode()->getDirection(e->getNBEdge(), c.toEdge) == LINKDIR_STRAIGHT) {
1949  straightConnections[e].push_back(c);
1950  }
1951  };
1952  }
1953  //std::cout << "split junction at endpoints:\n";
1954 
1955  junction->setLogicValid(false, undoList);
1956  for (const auto& pair : endpoints) {
1957  const Position& pos = pair.first;
1958  const std::string& origID = pair.second;
1959  GNEJunction* newJunction = createJunction(pos, undoList);
1960  std::string newID = origID != "" ? origID : newJunction->getID();
1961  // make a copy because the original vectors are modified during iteration
1962  const std::vector<GNEEdge*> incoming = junction->getGNEIncomingEdges();
1963  const std::vector<GNEEdge*> outgoing = junction->getGNEOutgoingEdges();
1964  //std::cout << " checkEndpoint " << pair.first << " " << pair.second << " newID=" << newID << "\n";
1965  for (GNEEdge* e : incoming) {
1966  //std::cout << " incoming " << e->getID() << " pos=" << pos << " origTo=" << e->getNBEdge()->getParameter("origTo") << " newID=" << newID << "\n";
1967  if (e->getNBEdge()->getGeometry().back().almostSame(pos) || e->getNBEdge()->getParameter("origTo") == newID) {
1968  //std::cout << " match\n";
1969  undoList->p_add(new GNEChange_Attribute(e, this, SUMO_ATTR_TO, newJunction->getID()));
1970  }
1971  }
1972  for (GNEEdge* e : outgoing) {
1973  //std::cout << " outgoing " << e->getID() << " pos=" << pos << " origFrom=" << e->getNBEdge()->getParameter("origFrom") << " newID=" << newID << "\n";
1974  if (e->getNBEdge()->getGeometry().front().almostSame(pos) || e->getNBEdge()->getParameter("origFrom") == newID) {
1975  //std::cout << " match\n";
1976  undoList->p_add(new GNEChange_Attribute(e, this, SUMO_ATTR_FROM, newJunction->getID()));
1977  }
1978  }
1979  if (newID != newJunction->getID()) {
1980  if (newJunction->isValid(SUMO_ATTR_ID, newID)) {
1981  undoList->p_add(new GNEChange_Attribute(newJunction, this, SUMO_ATTR_ID, newID));
1982  } else {
1983  WRITE_WARNING("Could not rename split node to '" + newID + "'");
1984  }
1985  }
1986  }
1987  // recreate edges from straightConnections
1988  if (reconnect) {
1989  for (const auto& item : straightConnections) {
1990  GNEEdge* in = item.first;
1991  std::map<NBEdge*, GNEEdge*> newEdges;
1992  for (auto& c : item.second) {
1993  GNEEdge* out = retrieveEdge(c.toEdge->getID());
1994  GNEEdge* newEdge = nullptr;
1995  if (in->getGNEJunctionDestiny() == out->getGNEJunctionSource()) {
1996  continue;
1997  }
1998  if (newEdges.count(c.toEdge) == 0) {
1999  newEdge = createEdge(in->getGNEJunctionDestiny(), out->getGNEJunctionSource(), in, undoList);
2000  newEdges[c.toEdge] = newEdge;
2001  newEdge->setAttribute(SUMO_ATTR_NUMLANES, "1", undoList);
2002  } else {
2003  newEdge = newEdges[c.toEdge];
2004  duplicateLane(newEdge->getLanes().back(), undoList, true);
2005  }
2006  // copy permissions
2007  newEdge->getLanes().back()->setAttribute(SUMO_ATTR_ALLOW,
2008  in->getLanes()[c.fromLane]-> getAttribute(SUMO_ATTR_ALLOW), undoList);
2009  }
2010  }
2011  }
2012 
2013  deleteJunction(junction, undoList);
2014  // finish operation
2015  undoList->p_end();
2016 }
2017 
2018 
2019 
2020 void
2022  undoList->p_begin("clear junction connections");
2023  std::vector<GNEConnection*> connections = junction->getGNEConnections();
2024  // Iterate over all connections and clear it
2025  for (auto i : connections) {
2026  deleteConnection(i, undoList);
2027  }
2028  undoList->p_end();
2029 }
2030 
2031 
2032 void
2034  undoList->p_begin("reset junction connections");
2035  // first clear connections
2036  clearJunctionConnections(junction, undoList);
2037  // invalidate logic to create new connections in the next recomputing
2038  junction->setLogicValid(false, undoList);
2039  undoList->p_end();
2040 }
2041 
2042 
2043 void
2044 GNENet::renameEdge(GNEEdge* edge, const std::string& newID) {
2045  myAttributeCarriers.edges.erase(edge->getNBEdge()->getID());
2046  myNetBuilder->getEdgeCont().rename(edge->getNBEdge(), newID);
2047  edge->setMicrosimID(newID);
2048  myAttributeCarriers.edges[newID] = edge;
2049  // rename all connections related to this edge
2050  for (auto i : edge->getLanes()) {
2051  i->updateConnectionIDs();
2052  }
2053 }
2054 
2055 
2056 void
2057 GNENet::changeEdgeEndpoints(GNEEdge* edge, const std::string& newSource, const std::string& newDest) {
2058  NBNode* from = retrieveJunction(newSource)->getNBNode();
2059  NBNode* to = retrieveJunction(newDest)->getNBNode();
2060  edge->getNBEdge()->reinitNodes(from, to);
2061  requireRecompute();
2062  update();
2063 }
2064 
2065 
2066 GNEViewNet*
2068  return myViewNet;
2069 }
2070 
2071 
2072 std::vector<GNEAttributeCarrier*>
2073 GNENet::getSelectedAttributeCarriers(bool ignoreCurrentSupermode) {
2074  // declare vector to save result
2075  std::vector<GNEAttributeCarrier*> result;
2076  result.reserve(gSelected.getSelected().size());
2077  // iterate over all elements of global selection
2078  for (auto i : gSelected.getSelected()) {
2079  // obtain AC
2081  // check if attribute carrier exist and is selected
2082  if (AC && AC->isAttributeCarrierSelected()) {
2083  // now check if selected supermode is correct
2084  if (ignoreCurrentSupermode ||
2087  // add it into result vector
2088  result.push_back(AC);
2089  }
2090  }
2091  }
2092  return result;
2093 }
2094 
2095 
2098  return myNetBuilder->getTLLogicCont();
2099 }
2100 
2101 
2102 NBEdgeCont&
2104  return myNetBuilder->getEdgeCont();
2105 }
2106 
2107 
2108 void
2109 GNENet::renameJunction(GNEJunction* junction, const std::string& newID) {
2110  std::string oldID = junction->getID();
2111  myAttributeCarriers.junctions.erase(junction->getNBNode()->getID());
2112  myNetBuilder->getNodeCont().rename(junction->getNBNode(), newID);
2113  junction->setMicrosimID(newID);
2114  myAttributeCarriers.junctions[newID] = junction;
2115  // build crossings
2116  junction->getNBNode()->buildCrossings();
2117 }
2118 
2119 
2120 void
2122  myExplicitTurnarounds.insert(id);
2123 }
2124 
2125 
2126 void
2128  myExplicitTurnarounds.erase(id);
2129 }
2130 
2131 
2133 GNENet::retrieveAdditional(SumoXMLTag type, const std::string& id, bool hardFail) const {
2134  if ((myAttributeCarriers.additionals.count(type) > 0) && (myAttributeCarriers.additionals.at(type).count(id) != 0)) {
2135  return myAttributeCarriers.additionals.at(type).at(id);
2136  } else if (hardFail) {
2137  throw ProcessError("Attempted to retrieve non-existant additional");
2138  } else {
2139  return nullptr;
2140  }
2141 }
2142 
2143 
2144 std::vector<GNEAdditional*>
2145 GNENet::retrieveAdditionals(bool onlySelected) const {
2146  std::vector<GNEAdditional*> result;
2147  // returns additionals depending of selection
2148  for (auto i : myAttributeCarriers.additionals) {
2149  for (auto j : i.second) {
2150  if (!onlySelected || j.second->isAttributeCarrierSelected()) {
2151  result.push_back(j.second);
2152  }
2153  }
2154  }
2155  return result;
2156 }
2157 
2158 
2159 int
2161  int counter = 0;
2162  for (auto i : myAttributeCarriers.additionals) {
2163  if ((type == SUMO_TAG_NOTHING) || (type == i.first)) {
2164  counter += (int)i.second.size();
2165  }
2166  }
2167  return counter;
2168 }
2169 
2170 
2171 void
2172 GNENet::updateAdditionalID(const std::string& oldID, GNEAdditional* additional) {
2173  if (myAttributeCarriers.additionals.at(additional->getTagProperty().getTag()).count(oldID) == 0) {
2174  throw ProcessError(additional->getTagStr() + " with old ID='" + oldID + "' doesn't exist");
2175  } else {
2176  // remove an insert additional again into container
2177  myAttributeCarriers.additionals.at(additional->getTagProperty().getTag()).erase(oldID);
2178  myAttributeCarriers.additionals.at(additional->getTagProperty().getTag()).insert(std::make_pair(additional->getID(), additional));
2179  // additionals has to be saved
2181  }
2182 }
2183 
2184 
2185 void
2187  if (myAdditionalsSaved == true) {
2188  WRITE_DEBUG("Additionals has to be saved");
2189  std::string netSaved = (myNetSaved ? "saved" : "unsaved");
2190  std::string demandElementsSaved = (myDemandElementsSaved ? "saved" : "unsaved");
2191  WRITE_DEBUG("Current saving Status: net " + netSaved + ", additionals unsaved, demand elements " + demandElementsSaved);
2192  }
2193  myAdditionalsSaved = !value;
2194  if (myViewNet != nullptr) {
2195  if (myAdditionalsSaved) {
2197  } else {
2199  }
2200  }
2201 }
2202 
2203 
2204 void
2205 GNENet::saveAdditionals(const std::string& filename) {
2206  // obtain invalid additionals depending of number of their lane parents
2207  std::vector<GNEAdditional*> invalidSingleLaneAdditionals;
2208  std::vector<GNEAdditional*> invalidMultiLaneAdditionals;
2209  // iterate over additionals and obtain invalids
2210  for (auto i : myAttributeCarriers.additionals) {
2211  for (auto j : i.second) {
2212  // check if has to be fixed
2213  if (j.second->getTagProperty().hasAttribute(SUMO_ATTR_LANE) && !j.second->isAdditionalValid()) {
2214  invalidSingleLaneAdditionals.push_back(j.second);
2215  } else if (j.second->getTagProperty().hasAttribute(SUMO_ATTR_LANES) && !j.second->isAdditionalValid()) {
2216  invalidMultiLaneAdditionals.push_back(j.second);
2217  }
2218  }
2219  }
2220  // if there are invalid StoppingPlaces or detectors, open GNEDialog_FixAdditionalElements
2221  if (invalidSingleLaneAdditionals.size() > 0 || invalidMultiLaneAdditionals.size() > 0) {
2222  // 0 -> Canceled Saving, with or whithout selecting invalid stopping places and E2
2223  // 1 -> Invalid stoppingPlaces and E2 fixed, friendlyPos enabled, or saved with invalid positions
2224  GNEDialog_FixAdditionalElements fixAdditionalElementsDialog(myViewNet, invalidSingleLaneAdditionals, invalidMultiLaneAdditionals);
2225  if (fixAdditionalElementsDialog.execute() == 0) {
2226  // show debug information
2227  WRITE_DEBUG("Additionals saving aborted");
2228  } else {
2229  saveAdditionalsConfirmed(filename);
2230  // change value of flag
2231  myAdditionalsSaved = true;
2232  // show debug information
2233  WRITE_DEBUG("Additionals saved after dialog");
2234  }
2235  // update view
2236  myViewNet->update();
2237  // set focus again in viewNet
2238  myViewNet->setFocus();
2239  } else {
2240  saveAdditionalsConfirmed(filename);
2241  // change value of flag
2242  myAdditionalsSaved = true;
2243  // show debug information
2244  WRITE_DEBUG("Additionals saved");
2245  }
2246 }
2247 
2248 
2249 bool
2251  return myAdditionalsSaved;
2252 }
2253 
2254 
2255 std::string
2257  int counter = 0;
2258  while (myAttributeCarriers.additionals.at(type).count(toString(type) + "_" + toString(counter)) != 0) {
2259  counter++;
2260  }
2261  return (toString(type) + "_" + toString(counter));
2262 }
2263 
2264 
2266 GNENet::retrieveDemandElement(SumoXMLTag type, const std::string& id, bool hardFail) const {
2267  if ((myAttributeCarriers.demandElements.count(type) > 0) && (myAttributeCarriers.demandElements.at(type).count(id) != 0)) {
2268  return myAttributeCarriers.demandElements.at(type).at(id);
2269  } else if (hardFail) {
2270  throw ProcessError("Attempted to retrieve non-existant demand element");
2271  } else {
2272  return nullptr;
2273  }
2274 }
2275 
2276 
2277 std::vector<GNEDemandElement*>
2278 GNENet::retrieveDemandElements(bool onlySelected) const {
2279  std::vector<GNEDemandElement*> result;
2280  // returns demand elements depending of selection
2281  for (auto i : myAttributeCarriers.demandElements) {
2282  for (auto j : i.second) {
2283  if (!onlySelected || j.second->isAttributeCarrierSelected()) {
2284  result.push_back(j.second);
2285  }
2286  }
2287  }
2288  return result;
2289 }
2290 
2291 
2292 int
2294  int counter = 0;
2295  for (auto i : myAttributeCarriers.demandElements) {
2296  if ((type == SUMO_TAG_NOTHING) || (type == i.first)) {
2297  counter += (int)i.second.size();
2298  }
2299  }
2300  return counter;
2301 }
2302 
2303 
2304 void
2305 GNENet::updateDemandElementID(const std::string& oldID, GNEDemandElement* demandElement) {
2306  if (myAttributeCarriers.demandElements.at(demandElement->getTagProperty().getTag()).count(oldID) == 0) {
2307  throw ProcessError(demandElement->getTagStr() + " with old ID='" + oldID + "' doesn't exist");
2308  } else {
2309  // remove an insert demand element again into container
2310  myAttributeCarriers.demandElements.at(demandElement->getTagProperty().getTag()).erase(oldID);
2311  myAttributeCarriers.demandElements.at(demandElement->getTagProperty().getTag()).insert(std::make_pair(demandElement->getID(), demandElement));
2312  // remove an insert demand element again into vehicleDepartures container
2313  if (demandElement->getTagProperty().isVehicle()) {
2314  if (myAttributeCarriers.vehicleDepartures.count(demandElement->getBegin() + "_" + oldID) == 0) {
2315  throw ProcessError(demandElement->getTagStr() + " with old ID='" + oldID + "' doesn't exist");
2316  } else {
2317  myAttributeCarriers.vehicleDepartures.erase(demandElement->getBegin() + "_" + oldID);
2318  myAttributeCarriers.vehicleDepartures.insert(std::make_pair(demandElement->getBegin() + "_" + demandElement->getID(), demandElement));
2319  }
2320  }
2321  // demand elements has to be saved
2323  }
2324 }
2325 
2326 
2327 void
2328 GNENet::updateDemandElementBegin(const std::string& oldBegin, GNEDemandElement* demandElement) {
2329  if (myAttributeCarriers.vehicleDepartures.count(oldBegin + "_" + demandElement->getID()) == 0) {
2330  throw ProcessError(demandElement->getTagStr() + " with old begin='" + oldBegin + "' doesn't exist");
2331  } else {
2332  // remove an insert demand element again into vehicleDepartures container
2333  if (demandElement->getTagProperty().isVehicle()) {
2334  myAttributeCarriers.vehicleDepartures.erase(oldBegin + "_" + demandElement->getID());
2335  myAttributeCarriers.vehicleDepartures.insert(std::make_pair(demandElement->getBegin() + "_" + demandElement->getID(), demandElement));
2336  }
2337  }
2338 }
2339 
2340 
2341 void
2343  if (myDemandElementsSaved == true) {
2344  WRITE_DEBUG("DemandElements has to be saved");
2345  std::string netSaved = (myNetSaved ? "saved" : "unsaved");
2346  std::string additionalsSaved = (myAdditionalsSaved ? "saved" : "unsaved");
2347  WRITE_DEBUG("Current saving Status: net " + netSaved + ", additionals " + additionalsSaved + ", demand elements unsaved");
2348  }
2349  myDemandElementsSaved = !value;
2350  if (myViewNet != nullptr) {
2351  if (myDemandElementsSaved) {
2353  } else {
2355  }
2356  }
2357 }
2358 
2359 
2360 void
2361 GNENet::saveDemandElements(const std::string& filename) {
2362  // first recompute demand elements
2364  // obtain invalid demandElements depending of number of their lane parents
2365  std::vector<GNEDemandElement*> invalidSingleLaneDemandElements;
2366  // iterate over demandElements and obtain invalids
2367  for (auto i : myAttributeCarriers.demandElements) {
2368  for (auto j : i.second) {
2369  // check if has to be fixed
2370  if (!j.second->isDemandElementValid()) {
2371  invalidSingleLaneDemandElements.push_back(j.second);
2372  }
2373  }
2374  }
2375  // if there are invalid demand elements, open GNEDialog_FixDemandElements
2376  if (invalidSingleLaneDemandElements.size() > 0) {
2377  // 0 -> Canceled Saving, with or whithout selecting invalid demand elements
2378  // 1 -> Invalid demand elements fixed, friendlyPos enabled, or saved with invalid positions
2379  GNEDialog_FixDemandElements fixDemandElementsDialog(myViewNet, invalidSingleLaneDemandElements);
2380  if (fixDemandElementsDialog.execute() == 0) {
2381  // show debug information
2382  WRITE_DEBUG("demand elements saving aborted");
2383  } else {
2384  saveDemandElementsConfirmed(filename);
2385  // change value of flag
2386  myDemandElementsSaved = true;
2387  // show debug information
2388  WRITE_DEBUG("demand elements saved after dialog");
2389  }
2390  // update view
2391  myViewNet->update();
2392  // set focus again in viewNet
2393  myViewNet->setFocus();
2394  } else {
2395  saveDemandElementsConfirmed(filename);
2396  // change value of flag
2397  myDemandElementsSaved = true;
2398  // show debug information
2399  WRITE_DEBUG("demand elements saved");
2400  }
2401 }
2402 
2403 
2404 bool
2406  return myDemandElementsSaved;
2407 }
2408 
2409 
2410 std::string
2411 GNENet::generateDemandElementID(const std::string& prefix, SumoXMLTag type) const {
2412  int counter = 0;
2413  if ((type == SUMO_TAG_VEHICLE) || (type == SUMO_TAG_TRIP) || (type == SUMO_TAG_ROUTEFLOW) || (type == SUMO_TAG_FLOW)) {
2414  // special case for vehicles (Vehicles, Flows, Trips and routeFlows share nameSpaces)
2415  while ((myAttributeCarriers.demandElements.at(SUMO_TAG_VEHICLE).count(prefix + toString(type) + "_" + toString(counter)) != 0) ||
2416  (myAttributeCarriers.demandElements.at(SUMO_TAG_TRIP).count(prefix + toString(type) + "_" + toString(counter)) != 0) ||
2417  (myAttributeCarriers.demandElements.at(SUMO_TAG_ROUTEFLOW).count(prefix + toString(type) + "_" + toString(counter)) != 0) ||
2418  (myAttributeCarriers.demandElements.at(SUMO_TAG_FLOW).count(prefix + toString(type) + "_" + toString(counter)) != 0)) {
2419  counter++;
2420  }
2421  } else if ((type == SUMO_TAG_PERSON) || (type == SUMO_TAG_PERSONFLOW)) {
2422  // special case for persons (person and personFlows share nameSpaces)
2423  while ((myAttributeCarriers.demandElements.at(SUMO_TAG_PERSON).count(prefix + toString(type) + "_" + toString(counter)) != 0) ||
2424  (myAttributeCarriers.demandElements.at(SUMO_TAG_PERSONFLOW).count(prefix + toString(type) + "_" + toString(counter)) != 0)) {
2425  counter++;
2426  }
2427  } else {
2428  while (myAttributeCarriers.demandElements.at(type).count(prefix + toString(type) + "_" + toString(counter)) != 0) {
2429  counter++;
2430  }
2431  }
2432  return (prefix + toString(type) + "_" + toString(counter));
2433 }
2434 
2435 
2436 void
2437 GNENet::saveAdditionalsConfirmed(const std::string& filename) {
2438  OutputDevice& device = OutputDevice::getDevice(filename);
2439  device.writeXMLHeader("additional", "additional_file.xsd");
2440  // now write all route probes (see Ticket #4058)
2441  for (auto i : myAttributeCarriers.additionals) {
2442  if (i.first == SUMO_TAG_ROUTEPROBE) {
2443  for (auto j : i.second) {
2444  j.second->writeAdditional(device);
2445  }
2446  }
2447  }
2448  // now write all stoppingPlaces
2449  for (auto i : myAttributeCarriers.additionals) {
2451  for (auto j : i.second) {
2452  // only save stoppingPlaces that doesn't have Additional parents, because they are automatically writed by writeAdditional(...) parent's function
2453  if (j.second->getAdditionalParents().empty()) {
2454  j.second->writeAdditional(device);
2455  }
2456  }
2457  }
2458  }
2459  // now write all detectors
2460  for (auto i : myAttributeCarriers.additionals) {
2462  for (auto j : i.second) {
2463  // only save Detectors that doesn't have Additional parents, because they are automatically writed by writeAdditional(...) parent's function
2464  if (j.second->getAdditionalParents().empty()) {
2465  j.second->writeAdditional(device);
2466  }
2467  }
2468  }
2469  }
2470  // now write rest of additionals
2471  for (auto i : myAttributeCarriers.additionals) {
2472  const auto& tagValue = GNEAttributeCarrier::getTagProperties(i.first);
2473  if (!tagValue.isStoppingPlace() && !tagValue.isDetector() && (i.first != SUMO_TAG_ROUTEPROBE) && (i.first != SUMO_TAG_VTYPE) && (i.first != SUMO_TAG_ROUTE)) {
2474  for (auto j : i.second) {
2475  // only save additionals that doesn't have Additional parents, because they are automatically writed by writeAdditional(...) parent's function
2476  if (j.second->getAdditionalParents().empty()) {
2477  j.second->writeAdditional(device);
2478  }
2479  }
2480  }
2481  }
2482  // now write shapes and POIs
2483  for (const auto& i : myPolygons) {
2484  dynamic_cast<GNEShape*>(i.second)->writeShape(device);
2485  }
2486  for (const auto& i : myPOIs) {
2487  dynamic_cast<GNEShape*>(i.second)->writeShape(device);
2488  }
2489  device.close();
2490 }
2491 
2492 
2493 void
2494 GNENet::saveDemandElementsConfirmed(const std::string& filename) {
2495  OutputDevice& device = OutputDevice::getDevice(filename);
2496  device.writeXMLHeader("routes", "routes_file.xsd");
2497  // first write all vehicle types
2499  i.second->writeDemandElement(device);
2500  }
2501  // first write all person types
2503  i.second->writeDemandElement(device);
2504  }
2505  // now write all routes (and their associated stops)
2507  i.second->writeDemandElement(device);
2508  }
2509  // finally write all vehicles and persons sorted by depart time (and their associated stops, personPlans, etc.)
2510  for (auto i : myAttributeCarriers.vehicleDepartures) {
2511  i.second->writeDemandElement(device);
2512  }
2513  device.close();
2514 }
2515 
2516 
2517 GNEPoly*
2518 GNENet::addPolygonForEditShapes(GNENetElement* netElement, const PositionVector& shape, bool fill, RGBColor col) {
2519  if (shape.size() > 0) {
2520  // create poly for edit shapes
2521  GNEPoly* shapePoly = new GNEPoly(this, "edit_shape", "edit_shape", shape, false, fill, 0.3, col, GLO_POLYGON, 0, "", false, false, false);
2522  shapePoly->setShapeEditedElement(netElement);
2523  myGrid.addAdditionalGLObject(shapePoly);
2524  myViewNet->update();
2525  return shapePoly;
2526  } else {
2527  throw ProcessError("shape cannot be empty");
2528  }
2529 }
2530 
2531 
2532 void
2534  if (polygon) {
2535  // remove it from Inspector Frame
2537  // Remove from grid
2539  myViewNet->update();
2540  } else {
2541  throw ProcessError("Polygon for edit shapes has to be inicializated");
2542  }
2543 }
2544 
2545 
2546 std::string
2548  // generate tag depending of type of shape
2549  if (shapeTag == SUMO_TAG_POLY) {
2550  int counter = 0;
2551  std::string newID = "poly_" + toString(counter);
2552  // generate new IDs to find a non-assigned ID
2553  while (myPolygons.get(newID) != nullptr) {
2554  counter++;
2555  newID = "poly_" + toString(counter);
2556  }
2557  return newID;
2558  } else {
2559  int counter = 0;
2560  std::string newID = "POI_" + toString(counter);
2561  // generate new IDs to find a non-assigned ID
2562  while (myPOIs.get(newID) != nullptr) {
2563  counter++;
2564  newID = "POI_" + toString(counter);
2565  }
2566  return newID;
2567  }
2568 }
2569 
2570 
2571 void
2572 GNENet::changeShapeID(GNEShape* s, const std::string& OldID) {
2573  if (s->getTagProperty().getTag() == SUMO_TAG_POLY) {
2574  if (myPolygons.get(OldID) == 0) {
2575  throw UnknownElement("Polygon " + OldID);
2576  } else {
2577  myPolygons.changeID(OldID, s->getID());
2578  }
2579  } else {
2580  if (myPOIs.get(OldID) == 0) {
2581  throw UnknownElement("POI " + OldID);
2582  } else {
2583  myPOIs.changeID(OldID, s->getID());
2584  }
2585  }
2586 }
2587 
2588 
2589 int
2591  return (int)(myPolygons.size() + myPOIs.size());
2592 }
2593 
2594 
2595 void
2597  if (myTLSProgramsSaved == true) {
2598  WRITE_DEBUG("TLSPrograms has to be saved");
2599  }
2600  myTLSProgramsSaved = false;
2602 }
2603 
2604 
2605 void
2606 GNENet::saveTLSPrograms(const std::string& filename) {
2607  // open output device
2608  OutputDevice& device = OutputDevice::getDevice(filename);
2609  device.openTag("additionals");
2610  // write traffic lights using NWWriter
2612  device.close();
2613  // change flag to true
2614  myTLSProgramsSaved = true;
2615  // show debug information
2616  WRITE_DEBUG("TLSPrograms saved");
2617 }
2618 
2619 
2620 int
2622  return -1;
2623 }
2624 
2625 void
2627  myUpdateGeometryEnabled = true;
2628 }
2629 
2630 
2631 void
2633  myUpdateGeometryEnabled = false;
2634 }
2635 
2636 
2637 bool
2639  return myUpdateGeometryEnabled;
2640 }
2641 
2642 // ---------------------------------------------------------------------------
2643 // GNENet - protected methods
2644 // ---------------------------------------------------------------------------
2645 
2646 bool
2648  // first check that additional pointer is valid
2649  if (additional) {
2650  return myAttributeCarriers.additionals.at(additional->getTagProperty().getTag()).find(additional->getID()) !=
2651  myAttributeCarriers.additionals.at(additional->getTagProperty().getTag()).end();
2652  } else {
2653  throw ProcessError("Invalid additional pointer");
2654  }
2655 }
2656 
2657 
2658 void
2660  // Check if additional element exists before insertion
2661  if (!additionalExist(additional)) {
2662  myAttributeCarriers.additionals.at(additional->getTagProperty().getTag()).insert(std::make_pair(additional->getID(), additional));
2663  // only add drawable elements in grid
2664  if (additional->getTagProperty().isDrawable() && additional->getTagProperty().isPlacedInRTree()) {
2665  myGrid.addAdditionalGLObject(additional);
2666  }
2667  // check if additional is selected
2668  if (additional->isAttributeCarrierSelected()) {
2669  additional->selectAttributeCarrier(false);
2670  }
2671  // update geometry after insertion of additionals if myUpdateGeometryEnabled is enabled
2673  additional->updateGeometry();
2674  }
2675  // additionals has to be saved
2677  } else {
2678  throw ProcessError(additional->getTagStr() + " with ID='" + additional->getID() + "' already exist");
2679  }
2680 }
2681 
2682 
2683 bool
2684 GNENet::deleteAdditional(GNEAdditional* additional, bool updateViewAfterDeleting) {
2685  // first check that additional pointer is valid
2686  if (additionalExist(additional)) {
2687  // obtain demand element and erase it from container
2688  auto it = myAttributeCarriers.additionals.at(additional->getTagProperty().getTag()).find(additional->getID());
2689  myAttributeCarriers.additionals.at(additional->getTagProperty().getTag()).erase(it);
2690  // remove it from Inspector Frame
2692  // only remove drawable elements of grid
2693  if (additional->getTagProperty().isDrawable() && additional->getTagProperty().isPlacedInRTree()) {
2694  myGrid.removeAdditionalGLObject(additional);
2695  }
2696  // check if additional is selected
2697  if (additional->isAttributeCarrierSelected()) {
2698  additional->unselectAttributeCarrier(false);
2699  }
2700  // check if view has to be updated
2701  if (updateViewAfterDeleting) {
2702  myViewNet->update();
2703  }
2704  // additionals has to be saved
2706  // additional removed, then return true
2707  return true;
2708  } else {
2709  throw ProcessError("Invalid additional pointer");
2710  }
2711 }
2712 
2713 
2714 bool
2716  // first check that demandElement pointer is valid
2717  if (demandElement) {
2718  return myAttributeCarriers.demandElements.at(demandElement->getTagProperty().getTag()).find(demandElement->getID()) !=
2719  myAttributeCarriers.demandElements.at(demandElement->getTagProperty().getTag()).end();
2720  } else {
2721  throw ProcessError("Invalid demandElement pointer");
2722  }
2723 }
2724 
2725 
2726 void
2728  // Check if demandElement element exists before insertion
2729  if (!demandElementExist(demandElement)) {
2730  // insert in demandElements container
2731  myAttributeCarriers.demandElements.at(demandElement->getTagProperty().getTag()).insert(std::make_pair(demandElement->getID(), demandElement));
2732  // also insert in vehicleDepartures container if it's either a vehicle or a person
2733  if (demandElement->getTagProperty().isVehicle() || demandElement->getTagProperty().isPerson()) {
2734  if (myAttributeCarriers.vehicleDepartures.count(demandElement->getBegin() + "_" + demandElement->getID()) != 0) {
2735  throw ProcessError(demandElement->getTagStr() + " with departure ='" + demandElement->getBegin() + "_" + demandElement->getID() + "' already inserted");
2736  } else {
2737  myAttributeCarriers.vehicleDepartures.insert(std::make_pair(demandElement->getBegin() + "_" + demandElement->getID(), demandElement));
2738  }
2739  }
2740  // only add drawable elements in grid
2741  if (demandElement->getTagProperty().isDrawable() && demandElement->getTagProperty().isPlacedInRTree()) {
2742  myGrid.addAdditionalGLObject(demandElement);
2743  }
2744  // check if demandElement is selected
2745  if (demandElement->isAttributeCarrierSelected()) {
2746  demandElement->selectAttributeCarrier(false);
2747  }
2748  // update geometry after insertion of demandElements if myUpdateGeometryEnabled is enabled
2750  demandElement->updateGeometry();
2751  }
2752  // demandElements has to be saved
2754  } else {
2755  throw ProcessError(demandElement->getTagStr() + " with ID='" + demandElement->getID() + "' already exist");
2756  }
2757 }
2758 
2759 
2760 bool
2761 GNENet::deleteDemandElement(GNEDemandElement* demandElement, bool updateViewAfterDeleting) {
2762  // first check that demandElement pointer is valid
2763  if (demandElementExist(demandElement)) {
2764  // obtain demand element and erase it from container
2765  auto it = myAttributeCarriers.demandElements.at(demandElement->getTagProperty().getTag()).find(demandElement->getID());
2766  myAttributeCarriers.demandElements.at(demandElement->getTagProperty().getTag()).erase(it);
2767  // remove it from Inspector Frame
2769  // also remove fromvehicleDepartures container if it's either a vehicle or a person
2770  if (demandElement->getTagProperty().isVehicle() || demandElement->getTagProperty().isPerson()) {
2771  if (myAttributeCarriers.vehicleDepartures.count(demandElement->getBegin() + "_" + demandElement->getID()) == 0) {
2772  throw ProcessError(demandElement->getTagStr() + " with departure ='" + demandElement->getBegin() + "_" + demandElement->getID() + "' doesn't exist");
2773  } else {
2774  myAttributeCarriers.vehicleDepartures.erase(demandElement->getBegin() + "_" + demandElement->getID());
2775  }
2776  }
2777  // only remove drawable elements of grid
2778  if (demandElement->getTagProperty().isDrawable() && demandElement->getTagProperty().isPlacedInRTree()) {
2779  myGrid.removeAdditionalGLObject(demandElement);
2780  }
2781  // check if demandElement is selected
2782  if (demandElement->isAttributeCarrierSelected()) {
2783  demandElement->unselectAttributeCarrier(false);
2784  }
2785  // check if view has to be updated
2786  if (updateViewAfterDeleting) {
2787  myViewNet->update();
2788  }
2789  // demandElements has to be saved
2791  // demandElement removed, then return true
2792  return true;
2793  } else {
2794  throw ProcessError("Invalid demandElement pointer");
2795  }
2796 }
2797 
2798 // ===========================================================================
2799 // private
2800 // ===========================================================================
2801 
2802 void
2804  // init junctions (by default Crossing and walking areas aren't created)
2805  NBNodeCont& nodeContainer = myNetBuilder->getNodeCont();
2806  for (auto name_it : nodeContainer.getAllNames()) {
2807  NBNode* nbn = nodeContainer.retrieve(name_it);
2808  registerJunction(new GNEJunction(*nbn, this, true));
2809  }
2810 
2811  // init edges
2813  for (auto name_it : ec.getAllNames()) {
2814  NBEdge* nbe = ec.retrieve(name_it);
2815  registerEdge(new GNEEdge(*nbe, this, false, true));
2816  if (myGrid.getWidth() > 10e16 || myGrid.getHeight() > 10e16) {
2817  throw ProcessError("Network size exceeds 1 Lightyear. Please reconsider your inputs.\n");
2818  }
2819  }
2820 
2821  // make sure myGrid is initialized even for an empty net
2822  if (myAttributeCarriers.edges.size() == 0) {
2823  myGrid.add(Boundary(0, 0, 100, 100));
2824  }
2825 
2826  // sort nodes edges so that arrows can be drawn correctly
2827  NBNodesEdgesSorter::sortNodesEdges(nodeContainer);
2828 }
2829 
2830 
2831 void
2833  myNetBuilder->getNodeCont().insert(junction->getNBNode());
2834  registerJunction(junction);
2835 }
2836 
2837 
2838 void
2840  NBEdge* nbe = edge->getNBEdge();
2841  myNetBuilder->getEdgeCont().insert(nbe); // should we ignore pruning double edges?
2842  // if this edge was previouls extracted from the edgeContainer we have to rewire the nodes
2843  nbe->getFromNode()->addOutgoingEdge(nbe);
2844  nbe->getToNode()->addIncomingEdge(nbe);
2845  registerEdge(edge);
2846 }
2847 
2848 
2849 GNEJunction*
2851  // increase reference
2852  junction->incRef("GNENet::registerJunction");
2853  junction->setResponsible(false);
2854  myAttributeCarriers.junctions[junction->getMicrosimID()] = junction;
2855  // add it into grid
2856  myGrid.add(junction->getCenteringBoundary());
2857  myGrid.addAdditionalGLObject(junction);
2858  // update geometry
2859  junction->updateGeometry();
2860  // check if junction is selected
2861  if (junction->isAttributeCarrierSelected()) {
2862  junction->selectAttributeCarrier(false);
2863  }
2864  // @todo let Boundary class track z-coordinate natively
2865  const double z = junction->getNBNode()->getPosition().z();
2866  if (z != 0) {
2868  }
2869  update();
2870  return junction;
2871 }
2872 
2873 
2874 GNEEdge*
2876  edge->incRef("GNENet::registerEdge");
2877  edge->setResponsible(false);
2878  // add edge to internal container of GNENet
2879  myAttributeCarriers.edges[edge->getMicrosimID()] = edge;
2880  // add edge to grid
2881  myGrid.add(edge->getCenteringBoundary());
2883  // check if edge is selected
2884  if (edge->isAttributeCarrierSelected()) {
2885  edge->selectAttributeCarrier(false);
2886  }
2887  // Add references into GNEJunctions
2890  // update view
2891  update();
2892  return edge;
2893 }
2894 
2895 
2896 void
2897 GNENet::deleteSingleJunction(GNEJunction* junction, bool updateViewAfterDeleting) {
2898  // remove it from Inspector Frame
2900  // Remove from grid and container
2901  myGrid.removeAdditionalGLObject(junction);
2902  // check if junction is selected
2903  if (junction->isAttributeCarrierSelected()) {
2904  junction->unselectAttributeCarrier(false);
2905  }
2906  myAttributeCarriers.junctions.erase(junction->getMicrosimID());
2907  myNetBuilder->getNodeCont().extract(junction->getNBNode());
2908  junction->decRef("GNENet::deleteSingleJunction");
2909  junction->setResponsible(true);
2910  // check if view has to be updated
2911  if (updateViewAfterDeleting) {
2912  myViewNet->update();
2913  }
2914 }
2915 
2916 
2917 void
2918 GNENet::deleteSingleEdge(GNEEdge* edge, bool updateViewAfterDeleting) {
2919  // remove it from Inspector Frame
2921  // remove edge from visual grid and container
2923  // check if junction is selected
2924  if (edge->isAttributeCarrierSelected()) {
2925  edge->unselectAttributeCarrier(false);
2926  }
2927  myAttributeCarriers.edges.erase(edge->getMicrosimID());
2928  // extract edge of district container
2930  edge->decRef("GNENet::deleteSingleEdge");
2931  edge->setResponsible(true);
2932  // Remove refrences from GNEJunctions
2935  // check if view has to be updated
2936  if (updateViewAfterDeleting) {
2937  myViewNet->update();
2938  }
2939 }
2940 
2941 
2942 void
2943 GNENet::insertShape(GNEShape* shape, bool updateViewAfterDeleting) {
2944  // add shape depending of their type and if is selected
2945  if (shape->getTagProperty().getTag() == SUMO_TAG_POLY) {
2946  GUIPolygon* poly = dynamic_cast<GUIPolygon*>(shape);
2947  // all polys are placed over RTree
2949  myPolygons.add(shape->getID(), poly);
2950  } else {
2951  GUIPointOfInterest* poi = dynamic_cast<GUIPointOfInterest*>(shape);
2952  // Only certain POIs are placed in RTrees
2953  if (shape->getTagProperty().isPlacedInRTree()) {
2955  }
2956  myPOIs.add(shape->getID(), poi);
2957 
2958  }
2959  // check if shape has to be selected
2960  if (shape->isAttributeCarrierSelected()) {
2961  shape->selectAttributeCarrier(false);
2962  }
2963  // insert shape requieres always save additionals
2965  // after inserting, update geometry (needed for POILanes
2966  shape->updateGeometry();
2967  // check if view has to be updated
2968  if (updateViewAfterDeleting) {
2969  myViewNet->update();
2970  }
2971 }
2972 
2973 
2974 void
2975 GNENet::removeShape(GNEShape* shape, bool updateViewAfterDeleting) {
2976  // remove it from Inspector Frame
2978  if (shape->getTagProperty().getTag() == SUMO_TAG_POLY) {
2979  GUIPolygon* poly = dynamic_cast<GUIPolygon*>(shape);
2981  myPolygons.remove(shape->getID(), false);
2982  } else {
2983  GUIPointOfInterest* poi = dynamic_cast<GUIPointOfInterest*>(shape);
2984  // only certain POIS are placed in RTREE
2985  if (shape->getTagProperty().isPlacedInRTree()) {
2987  }
2988  myPOIs.remove(shape->getID(), false);
2989  }
2990  // check if shape has to be unselected
2991  if (shape->isAttributeCarrierSelected()) {
2992  shape->unselectAttributeCarrier(false);
2993  }
2994  // remove shape requires always save additionals
2996  // check if view has to be updated
2997  if (updateViewAfterDeleting) {
2998  myViewNet->update();
2999  }
3000 }
3001 
3002 
3003 void
3005  if (myViewNet) {
3006  myViewNet->update();
3007  }
3008 }
3009 
3010 
3011 void
3012 GNENet::reserveEdgeID(const std::string& id) {
3013  myEdgeIDSupplier.avoid(id);
3014 }
3015 
3016 
3017 void
3018 GNENet::reserveJunctionID(const std::string& id) {
3020 }
3021 
3022 
3023 void
3025  for (const auto& i : myAttributeCarriers.edges) {
3026  // remake connections
3027  i.second->remakeGNEConnections();
3028  // update geometry of connections
3029  for (const auto& j : i.second->getGNEConnections()) {
3030  j->updateGeometry();
3031  }
3032  }
3033 }
3034 
3035 
3036 void
3037 GNENet::computeAndUpdate(OptionsCont& oc, bool volatileOptions) {
3038  // make sure we only add turn arounds to edges which currently exist within the network
3039  std::set<std::string> liveExplicitTurnarounds;
3040  for (auto it : myExplicitTurnarounds) {
3041  if (myAttributeCarriers.edges.count(it) > 0) {
3042  liveExplicitTurnarounds.insert(it);
3043  }
3044  }
3045  // removes all junctions of grid
3046  WRITE_GLDEBUG("Removing junctions during recomputing");
3047  for (const auto& it : myAttributeCarriers.junctions) {
3048  myGrid.removeAdditionalGLObject(it.second);
3049  }
3050  // remove all edges from grid
3051  WRITE_GLDEBUG("Removing edges during recomputing");
3052  for (const auto& it : myAttributeCarriers.edges) {
3053  myGrid.removeAdditionalGLObject(it.second);
3054  }
3055  // compute using NetBuilder
3056  myNetBuilder->compute(oc, liveExplicitTurnarounds, volatileOptions);
3057  // update ids if necessary
3058  if (oc.getBool("numerical-ids") || oc.isSet("reserved-ids")) {
3059  std::map<std::string, GNEEdge*> newEdgeMap;
3060  std::map<std::string, GNEJunction*> newJunctionMap;
3061  // fill newEdgeMap
3062  for (auto it : myAttributeCarriers.edges) {
3063  it.second->setMicrosimID(it.second->getNBEdge()->getID());
3064  newEdgeMap[it.second->getNBEdge()->getID()] = it.second;
3065  }
3066  for (auto it : myAttributeCarriers.junctions) {
3067  newJunctionMap[it.second->getNBNode()->getID()] = it.second;
3068  it.second->setMicrosimID(it.second->getNBNode()->getID());
3069  }
3070  myAttributeCarriers.edges = newEdgeMap;
3071  myAttributeCarriers.junctions = newJunctionMap;
3072  }
3073  // update rtree if necessary
3074  if (!oc.getBool("offset.disable-normalization")) {
3075  for (auto it : myAttributeCarriers.edges) {
3076  // refresh edge geometry
3077  it.second->updateGeometry();
3078  }
3079  }
3080  // Clear current inspected ACs in inspectorFrame if a previous net was loaded
3081  if (myViewNet != nullptr) {
3083  }
3084  // Reset Grid
3085  myGrid.reset();
3086  myGrid.add(GeoConvHelper::getFinal().getConvBoundary());
3087  // if volatile options are true
3088  if (volatileOptions) {
3089  // check that viewNet exist
3090  if (myViewNet == nullptr) {
3091  throw ProcessError("ViewNet doesn't exist");
3092  }
3093  // disable update geometry before clear undo list
3094  myUpdateGeometryEnabled = false;
3095  // clear undo list (This will be remove additionals and shapes)
3097  // remove all edges of net (It was already removed from grid)
3098  auto copyOfEdges = myAttributeCarriers.edges;
3099  for (auto it : copyOfEdges) {
3100  myAttributeCarriers.edges.erase(it.second->getMicrosimID());
3101  }
3102  // removes all junctions of net (It was already removed from grid)
3103  auto copyOfJunctions = myAttributeCarriers.junctions;
3104  for (auto it : copyOfJunctions) {
3105  myAttributeCarriers.junctions.erase(it.second->getMicrosimID());
3106  }
3107  // clear rest of additional that weren't removed during cleaning of undo list
3108  for (const auto& it : myAttributeCarriers.additionals) {
3109  for (const auto& j : it.second) {
3110  // only remove drawable additionals
3111  if (j.second->getTagProperty().isDrawable()) {
3112  myGrid.removeAdditionalGLObject(j.second);
3113  }
3114  }
3115  }
3117  // fill additionals with tags (note: this include the TAZS)
3118  auto listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_ADDITIONAL, false);
3119  for (auto i : listOfTags) {
3120  myAttributeCarriers.additionals.insert(std::make_pair(i, std::map<std::string, GNEAdditional*>()));
3121  }
3122  listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_TAZ, false);
3123  for (auto i : listOfTags) {
3124  myAttributeCarriers.additionals.insert(std::make_pair(i, std::map<std::string, GNEAdditional*>()));
3125  }
3126  // clear rest of polygons that weren't removed during cleaning of undo list
3127  for (const auto& it : myPolygons) {
3128  myGrid.removeAdditionalGLObject(dynamic_cast<GUIGlObject*>(it.second));
3129  }
3130  myPolygons.clear();
3131  // clear rest of POIs that weren't removed during cleaning of undo list
3132  for (const auto& it : myPOIs) {
3133  myGrid.removeAdditionalGLObject(dynamic_cast<GUIGlObject*>(it.second));
3134  }
3135  myPOIs.clear();
3136  // clear rest of demand elements that weren't removed during cleaning of undo list
3137  for (const auto& it : myAttributeCarriers.demandElements) {
3138  for (const auto& j : it.second) {
3139  // only remove drawable additionals
3140  if (j.second->getTagProperty().isDrawable()) {
3141  myGrid.removeAdditionalGLObject(j.second);
3142  }
3143  }
3144  }
3146  // fill demand elements with tags
3147  listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_DEMANDELEMENT, false);
3148  for (auto i : listOfTags) {
3149  myAttributeCarriers.demandElements.insert(std::make_pair(i, std::map<std::string, GNEDemandElement*>()));
3150  }
3151  listOfTags = GNEAttributeCarrier::allowedTagsByCategory(GNEAttributeCarrier::TagType::TAGTYPE_STOP, false);
3152  for (auto i : listOfTags) {
3153  myAttributeCarriers.demandElements.insert(std::make_pair(i, std::map<std::string, GNEDemandElement*>()));
3154  }
3155  // enable update geometry again
3156  myUpdateGeometryEnabled = true;
3157  // Write GL debug information
3158  WRITE_GLDEBUG("initJunctionsAndEdges function called in computeAndUpdate(...) due recomputing with volatile options");
3159  // init again junction an edges (Additionals and shapes will be loaded after the end of this function)
3161  } else {
3162  // insert all junctions of grid again
3163  WRITE_GLDEBUG("Add junctions during recomputing after calling myNetBuilder->compute(...)");
3164  for (const auto& it : myAttributeCarriers.junctions) {
3165  myGrid.addAdditionalGLObject(it.second);
3166  }
3167  // insert all edges from grid again
3168  WRITE_GLDEBUG("Add egdges during recomputing after calling myNetBuilder->compute(...)");
3169  for (const auto& it : myAttributeCarriers.edges) {
3170  myGrid.addAdditionalGLObject(it.second);
3171  }
3172  // remake connections
3173  for (auto it : myAttributeCarriers.edges) {
3174  it.second->remakeGNEConnections();
3175  }
3176  // iterate over junctions of net
3177  for (const auto& it : myAttributeCarriers.junctions) {
3178  // undolist may not yet exist but is also not needed when just marking junctions as valid
3179  it.second->setLogicValid(true, nullptr);
3180  // updated geometry
3181  it.second->updateGeometryAfterNetbuild();
3182  }
3183  // iterate over all edges of net
3184  for (const auto& it : myAttributeCarriers.edges) {
3185  // update geometry
3186  it.second->updateGeometry();
3187  }
3188  }
3189  // net recomputed, then return false;
3190  myNeedRecompute = false;
3191 }
3192 
3193 
3194 void
3195 GNENet::replaceInListAttribute(GNEAttributeCarrier* ac, SumoXMLAttr key, const std::string& which, const std::string& by, GNEUndoList* undoList) {
3196  assert(ac->getTagProperty().getAttributeProperties(key).isList());
3197  std::vector<std::string> values = GNEAttributeCarrier::parse<std::vector<std::string> >(ac->getAttribute(key));
3198  std::vector<std::string> newValues;
3199  for (auto v : values) {
3200  newValues.push_back(v == which ? by : v);
3201  }
3202  ac->setAttribute(key, toString(newValues), undoList);
3203 }
3204 
3205 /****************************************************************************/
void setViewNet(GNEViewNet *viewNet)
Set the viewNet to be notified of network changes.
Definition: GNENet.cpp:977
const AttributeCarriers & getAttributeCarriers() const
retrieve all attribute carriers of Net
Definition: GNENet.cpp:1014
GNEJunction * splitEdge(GNEEdge *edge, const Position &pos, GNEUndoList *undoList, GNEJunction *newJunction=0)
split edge at position by inserting a new junction
Definition: GNENet.cpp:752
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge&#39;s lanes&#39; lateral offset is computed.
Definition: NBEdge.h:762
void enableSaveTLSProgramsMenu()
enable save TLS Programs
bool addRestrictedLane(SUMOVehicleClass vclass, GNEEdge &edge, int index, GNEUndoList *undoList)
add restricted lane to edge
Definition: GNENet.cpp:702
std::vector< GNEJunction * > retrieveJunctions(bool onlySelected=false)
return all junctions
Definition: GNENet.cpp:1212
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:108
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNENet.cpp:193
void setResponsible(bool newVal)
set responsibility for deleting internal strctures
std::vector< GNEConnection * > getGNEConnections() const
Returns all GNEConnections vinculated with this junction.
void initJunctionsAndEdges()
Init Junctions and edges.
Definition: GNENet.cpp:2803
void insertAdditional(GNEAdditional *additional)
Insert a additional element int GNENet container.
Definition: GNENet.cpp:2659
static const TagProperties & getTagProperties(SumoXMLTag tag)
get Tag Properties
std::vector< GNELane * > retrieveLanes(bool onlySelected=false)
return all lanes
Definition: GNENet.cpp:1164
void close()
Closes the device and removes it from the dictionary.
GNEViewNet * myViewNet
The viewNet to be notofied of about changes.
Definition: GNENet.h:735
SumoXMLTag
Numbers representing SUMO-XML - element names.
const std::set< GUIGlID > & getSelected() const
Returns the set of ids of all selected objects.
GNEInspectorFrame * getInspectorFrame() const
get frame for GNE_NMODE_INSPECT
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
the function-object for an editing operation (abstract base)
Definition: GNEChange.h:43
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:184
void addIncomingGNEEdge(GNEEdge *edge)
add incoming GNEEdge
void enableSaveAdditionalsMenu()
enable save additionals
a routeprobe detector
GNEEdge * retrieveEdge(const std::string &id, bool failHard=true)
get edge by id
Definition: GNENet.cpp:1020
IDSupplier myEdgeIDSupplier
Definition: GNENet.h:745
description of a vehicle type
void closeBuilding(const Parameterised *p=0)
Closes the building of the table.
bool isVehicle() const
return true if tag correspond to a vehicle element
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
virtual void selectAttributeCarrier(bool changeFlag=true)=0
void setStatusBarText(const std::string &statusBarText)
set text of the statusBar
a polygon
int buildCrossings()
build pedestrian crossings
Definition: NBNode.cpp:2515
bool isDrawable() const
return true if tag correspond to a drawable element
void append(const PositionVector &v, double sameThreshold=2.0)
void removeIncomingGNEEdge(GNEEdge *edge)
remove incoming GNEEdge
SUMORTree myGrid
the rtree which contains all GUIGlObjects (so named for historical reasons)
Definition: GNENet.h:732
double z() const
Returns the z-position.
Definition: Position.h:67
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GNEEdge.cpp:460
begin/end of the description of a junction
begin/end of the description of a single lane
std::map< std::string, GNEEdge * > edges
map with the name and pointer to edges of net
Definition: GNENet.h:99
FXApp * getApp()
get pointer to the main App
Definition: GNENet.cpp:1537
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types...
void enableSaveDemandElementsMenu()
enable save demand elements
void update() const
Mark the entire GNEViewNet to be repainted later.
Definition: GNEViewNet.cpp:292
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:1937
The main window of the Netedit.
bool changeID(const std::string &oldId, const std::string &newId)
change ID of a stored object
a flow definitio nusing a from-to edges instead of a route (used by router)
void removeEdgeFromCrossings(GNEEdge *edge, GNEUndoList *undoList)
removes the given edge from all pedestrian crossings
NBNetBuilder * getNetBuilder() const
get net builder
Definition: GNENet.cpp:1543
const AttributeProperties & getAttributeProperties(SumoXMLAttr attr) const
get attribute (throw error if doesn&#39;t exist)
void setMicrosimID(const std::string &newID)
override to also set lane ids
Definition: GNEEdge.cpp:1863
const Polygons & getPolygons() const
Returns all polygons.
bool isDemandElement() const
return true if tag correspond to a demand element
A container for traffic light definitions and built programs.
int size() const
Returns the number of stored items within the container.
bool isValid(SumoXMLAttr key, const std::string &value)
void deleteDemandElement(GNEDemandElement *demandElement, GNEUndoList *undoList)
remove demand element
Definition: GNENet.cpp:638
a flow definition nusing a route instead of a from-to edges route (used in NETEDIT) ...
void deleteSingleEdge(GNEEdge *edge, bool updateViewAfterDeleting)
deletes a single edge
Definition: GNENet.cpp:2918
std::map< SumoXMLTag, std::map< std::string, GNEAdditional * > > additionals
map with the name and pointer to additional elements of net
Definition: GNENet.h:102
Definition: GNEPOI.h:45
GNEAttributeCarrier * retrieveAttributeCarrier(const GUIGlID id, bool failHard=true)
get a single attribute carrier based on a GLID
Definition: GNENet.cpp:1285
connectio between two lanes
Stores the information about how to visualize structures.
std::vector< GNEAttributeCarrier * > getSelectedAttributeCarriers(bool ignoreCurrentSupermode)
get all selected attribute carriers (or only relative to current supermode
Definition: GNENet.cpp:2073
vehicle is a bicycle
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.
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
Definition: GNEShape.cpp:139
GNEViewParent * getViewParent() const
get the net object
Definition: GNEViewNet.cpp:921
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
Definition: NBNode.cpp:449
double y() const
Returns the y-position.
Definition: Position.h:62
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
GNEConnection * retrieveConnection(const std::string &id, bool failHard=true) const
get Connection by id
Definition: GNENet.cpp:1079
T get(const std::string &id) const
Retrieves an item.
friend class GNEChange_Lane
Definition: GNENet.h:85
The representation of a single edge during network building.
Definition: NBEdge.h:86
void reinitNodes(NBNode *from, NBNode *to)
Resets nodes but keeps all other values the same (used when joining)
Definition: NBEdge.cpp:414
POIs myPOIs
stored POIs
virtual void updateGeometry()=0
update pre-computed geometry information
Polygons myPolygons
stored Polygons
friend class GNEChange_Additional
Definition: GNENet.h:89
static void writeJoinedJunctions(const OptionsCont &oc, NBNodeCont &nc)
Writes the joined-juncionts to file.
GNEPOI * retrievePOI(const std::string &id, bool failHard=true) const
get POI by id
Definition: GNENet.cpp:1066
static std::string parseIDs(const std::vector< T > &ACs)
parses a list of specific Attribute Carriers into a string of IDs
std::vector< std::pair< Position, std::string > > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
Definition: NBNode.cpp:3375
void removeAdditionalGLObject(GUIGlObject *o)
Removes an additional object (detector/shape/trigger) from being visualised.
Definition: SUMORTree.h:157
double x() const
Returns the x-position.
Definition: Position.h:57
void avoid(const std::string &id)
make sure that the given id is never supplied
Definition: IDSupplier.cpp:60
void saveDemandElementsConfirmed(const std::string &filename)
save demand elements after confirming invalid objects
Definition: GNENet.cpp:2494
void reverseEdge(GNEEdge *edge, GNEUndoList *undoList)
reverse edge
Definition: GNENet.cpp:838
void update()
notify myViewNet
Definition: GNENet.cpp:3004
void insertJunction(GNEJunction *junction)
inserts a single junction into the net and into the underlying netbuild-container ...
Definition: GNENet.cpp:2832
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:306
void deleteShape(GNEShape *shape, GNEUndoList *undoList)
remove shape
Definition: GNENet.cpp:616
#define WRITE_GLDEBUG(msg)
Definition: MsgHandler.h:247
GNEPoly * retrievePolygon(const std::string &id, bool failHard=true) const
get Polygon by id
Definition: GNENet.cpp:1053
static std::vector< SumoXMLTag > allowedTagsByCategory(int tagPropertyCategory, bool onlyDrawables)
get tags of all editable element types using TagProperty Type (TAGTYPE_NETELEMENT, TAGTYPE_ADDITIONAL, etc.)
void unselectAttributeCarrier(bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
void deleteConnection(GNEConnection *connection, GNEUndoList *undoList)
remove connection
Definition: GNENet.cpp:584
double getWidth() const
Returns the width of the boudary (x-axis)
Definition: Boundary.cpp:155
void resetJunctionConnections(GNEJunction *junction, GNEUndoList *undoList)
reset junction&#39;s connections
Definition: GNENet.cpp:2033
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:78
GNEEdge * createEdge(GNEJunction *src, GNEJunction *dest, GNEEdge *tpl, 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:325
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:46
std::vector< GNEConnection * > retrieveConnections(bool onlySelected=false) const
return all connections
Definition: GNENet.cpp:1099
void p_begin(const std::string &description)
Begin undo command sub-group. This begins a new group of commands that are treated as a single comman...
Definition: GNEUndoList.cpp:73
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition: GNENet.cpp:2121
void rename(NBEdge *edge, const std::string &newID)
Renames the edge. Throws exception if newID already exists.
Definition: NBEdgeCont.cpp:398
PositionVector reverse() const
reverse position vector
bool myAllowUndoShapes
flag used to indicate if shaped created can be undo
Definition: GNENet.h:864
const std::string DEFAULT_BIKETYPE_ID
bool cleanInvalidCrossings(GNEUndoList *undoList)
clear invalid crossings
Definition: GNENet.cpp:1687
bool isDetector() const
return true if tag correspond to a shape (Only used to group all detectors in the XML) ...
friend class GNEChange_Shape
Definition: GNENet.h:87
int getNumberOfAdditionals(SumoXMLTag type=SUMO_TAG_NOTHING) const
Returns the number of additionals of the net.
Definition: GNENet.cpp:2160
Storage for geometrical objects.
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
begin/end of the description of a Point of interest
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNENet.cpp:213
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
void insertEdge(GNEEdge *edge)
inserts a single edge into the net and into the underlying netbuild-container
Definition: GNENet.cpp:2839
const std::string & getID() const
Returns the id.
Definition: Named.h:77
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
std::map< std::string, GNEDemandElement * > vehicleDepartures
special map used for saving Demand Elements of type "Vehicle" (Vehicles, routeFlows, etc.) sorted by depart time
Definition: GNENet.h:108
static void writeTrafficLights(OutputDevice &into, const NBTrafficLightLogicCont &tllCont)
writes the traffic light logics to the given device
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1271
const Boundary & getBoundary() const
returns the bounder of the network
Definition: GNENet.cpp:186
virtual void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)=0
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything&#39;s ok.
Definition: XMLSubSys.cpp:113
static void sortNodesEdges(NBNodeCont &nc, bool useNodeShape=false)
Sorts a node&#39;s edges clockwise regarding driving direction.
const std::string DEFAULT_VTYPE_ID
A RT-tree for efficient storing of SUMO&#39;s GL-objects.
Definition: SUMORTree.h:69
const std::vector< GNEEdge * > & getGNEEdges() const
Returns all GNEEdges vinculated with this Junction.
virtual std::string getAttribute(SumoXMLAttr key) const =0
first coordinate of edge shape
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to copy the cursor position if geo projection is used, also builds an entry for copying the geo-position.
void addOutgoingEdge(NBEdge *edge)
adds an outgoing edge
Definition: NBNode.cpp:459
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
const std::vector< GNEAdditional * > & getAdditionalChildren() const
return vector of additionals that have as Parent this edge (For example, Calibrators) ...
void cleanInvalidDemandElements(GNEUndoList *undoList)
clean invalid demand elements
Definition: GNENet.cpp:1850
GNEJunction * registerJunction(GNEJunction *junction)
registers a junction with GNENet containers
Definition: GNENet.cpp:2850
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:303
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
bool myNeedRecompute
whether the net needs recomputation
Definition: GNENet.h:753
void selectAttributeCarrier(bool changeFlag=true)
Definition: GNEShape.cpp:109
Builds additional objects for GNENet (busStops, chargingStations, detectors, etc..)
begin/end of the description of a route
NBNetBuilder * myNetBuilder
The internal netbuilder.
Definition: GNENet.h:738
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
bool netHasGNECrossings() const
check if net has GNECrossings
Definition: GNENet.cpp:1526
void setNetObject(GUIGlObject *object)
Sets the given object as the "network" object.
bool isDemandElementsSaved() const
check if demand elements are saved
Definition: GNENet.cpp:2405
void saveTLSPrograms(const std::string &filename)
save TLS Programs elements of the network
Definition: GNENet.cpp:2606
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
void p_clear()
clears the undo list (implies abort)
Definition: GNEUndoList.cpp:87
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:264
bool priority
whether the pedestrians have priority
Definition: NBNode.h:152
const std::vector< GNEDemandElement * > & getDemandElementChildren() const
return vector of demand elements that have as Parent this edge (For example, Calibrators) ...
const std::vector< GNEShape * > & getShapeChildren() const
get shapes of VSS
bool add(const std::string &id, T item)
Adds an item.
void disableSaveAdditionalsMenu()
disable save additionals
bool restrictLane(SUMOVehicleClass vclass, GNELane *lane, GNEUndoList *undoList)
transform lane to restricted lane
Definition: GNENet.cpp:672
std::string generateShapeID(SumoXMLTag shapeTag) const
generate Shape ID
Definition: GNENet.cpp:2547
void joinRoutes(GNEUndoList *undoList)
join routes
Definition: GNENet.cpp:1784
The link is a straight direction.
bool isList() const
return true if atribute is a list
bool myAdditionalsSaved
Flag to check if additionals has to be saved.
Definition: GNENet.h:759
void renameJunction(GNEJunction *junction, const std::string &newID)
updates the map and reserves new id
Definition: GNENet.cpp:2109
GNEAdditional * retrieveAdditional(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named additional.
Definition: GNENet.cpp:2133
void removeOutgoingGNEEdge(GNEEdge *edge)
remove outgoing GNEEdge
void p_add(GNEChange_Attribute *cmd)
special method, avoid empty changes, always execute
IDSupplier myJunctionIDSupplier
Definition: GNENet.h:746
std::map< std::string, int > myEdgesAndNumberOfLanes
map with the Edges and their number of lanes
Definition: GNENet.h:861
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition: GNEEdge.cpp:625
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
NBEdge::Connection & getNBEdgeConnection() const
get Edge::Connection
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:137
the function-object for an editing operation (abstract base)
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
void registerJoinedCluster(const NodeSet &cluster)
gets all joined clusters (see doc for myClusters2Join)
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEEdge.cpp:858
static const double Z_INITIALIZED
marker for whether the z-boundary is initialized
Definition: GNENet.h:858
std::string getAttribute(SumoXMLAttr key) const
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:317
GNEUndoList * getUndoList() const
get the undoList object
Definition: GNEViewNet.cpp:933
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:733
friend class GNEChange_Connection
Definition: GNENet.h:86
void removeShape(GNEShape *shape, bool updateViewAfterDeleting)
remove created shape (but NOT delete)
Definition: GNENet.cpp:2975
static void createRouteCalculatorInstance(GNENet *net)
create instance of RouteCalculator
void updateAdditionalID(const std::string &oldID, GNEAdditional *additional)
update additional ID in container
Definition: GNENet.cpp:2172
std::set< NBEdge * > EdgeSet
container for unique edges
Definition: NBCont.h:50
void removeConnectionsFrom(GNEEdge *edge, GNEUndoList *undoList, bool updateTLS, int lane=-1)
remove all connections from the given edge
std::string getNext()
Returns the next id.
Definition: IDSupplier.cpp:52
bool removeRestrictedLane(SUMOVehicleClass vclass, GNEEdge &edge, GNEUndoList *undoList)
remove restricted lane
Definition: GNENet.cpp:738
the edges of a route
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:152
std::vector< GNEDemandElement * > retrieveDemandElements(bool onlySelected=false) const
return all demand elements
Definition: GNENet.cpp:2278
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
void deleteAdditional(GNEAdditional *additional, GNEUndoList *undoList)
remove additional
Definition: GNENet.cpp:625
GNEPoly * addPolygonForEditShapes(GNENetElement *netElement, const PositionVector &shape, bool fill, RGBColor col)
Builds a special polygon used for edit Junctions&#39;s shapes.
Definition: GNENet.cpp:2518
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
Definition: GNECrossing.h:45
GNEEdge & getParentEdge()
Returns underlying parent edge.
Definition: GNELane.cpp:1292
void saveAdditionalsConfirmed(const std::string &filename)
save additionals after confirming invalid objects
Definition: GNENet.cpp:2437
void enableUpdateGeometry()
Definition: GNENet.cpp:2626
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNELane.cpp:815
void deleteLane(GNELane *lane, GNEUndoList *undoList, bool recomputeConnections)
removes lane
Definition: GNENet.cpp:546
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:563
NBEdgeCont & getEdgeCont()
returns the NBEdgeCont of the underlying netbuilder
Definition: GNENet.cpp:2103
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
Definition: GNENet.cpp:203
GNEDemandElement * retrieveDemandElement(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named demand element.
Definition: GNENet.cpp:2266
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
std::string getLaneID(int lane) const
get lane ID
Definition: NBEdge.cpp:3125
void extract(NBDistrictCont &dc, NBEdge *edge, bool remember=false)
Removes the given edge from the container like erase but does not delete it.
Definition: NBEdgeCont.cpp:386
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:465
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise, the sub-group will be added as a new command into parent group. A matching begin() must have been called previously.
Definition: GNEUndoList.cpp:80
bool isUpdateGeometryEnabled() const
check if update geometry after inserting or removing has to be updated
Definition: GNENet.cpp:2638
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true)
get junction by id
Definition: GNENet.cpp:1001
void setx(double x)
set position x
Definition: Position.h:72
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:151
A list of positions.
Supermode currentSupermode
the current supermode
GNEEdge * getEdgeFrom() const
get the name of the edge the vehicles leave
bool joinSelectedJunctions(GNEUndoList *undoList)
join selected junctions
Definition: GNENet.cpp:1549
Boundary myZBoundary
the z boundary (stored in the x-coordinate), values of 0 are ignored
Definition: GNENet.h:855
void removeGLObjectFromGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1279
GNEFrameAttributesModuls::AttributesEditor * getAttributesEditor() const
get AttributesEditor
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:544
void replaceIncomingEdge(GNEEdge *which, GNEEdge *by, GNEUndoList *undoList)
replaces edge
Definition: GNENet.cpp:490
void selectAttributeCarrier(bool changeFlag=true)
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
bool isPerson() const
return true if tag correspond to a person element
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
int getNumberOfDemandElements(SumoXMLTag type=SUMO_TAG_NOTHING) const
Returns the number of demand elements of the net.
Definition: GNENet.cpp:2293
virtual bool isAttributeCarrierSelected() const =0
check if attribute carrier is selected
bool additionalExist(GNEAdditional *additional) const
return true if additional exist (use pointer instead ID)
Definition: GNENet.cpp:2647
void requiereSaveDemandElements(bool value)
inform that demand elements has to be saved
Definition: GNENet.cpp:2342
bool addPOI(const std::string &id, const std::string &type, const RGBColor &color, const Position &pos, bool geo, const std::string &lane, double posOverLane, double posLat, double layer, double angle, const std::string &imgFile, bool relativePath, double width, double height, bool ignorePruning=false)
Builds a POI using the given values and adds it to the container.
Definition: GNENet.cpp:241
GNEApplicationWindow * getGNEAppWindows() const
get GNE Application Windows
GNEJunction * getGNEJunctionDestiny() const
returns the destination-junction
Definition: GNEEdge.cpp:505
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node) ...
Definition: NBNode.h:269
void computeJunction(GNEJunction *junction)
trigger recomputation of junction shape and logic param[in] window The window to inform about delay ...
Definition: GNENet.cpp:1502
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:840
void requiereSaveAdditionals(bool value)
inform that additionals has to be saved
Definition: GNENet.cpp:2186
const std::string & getID() const
Definition: NBEdge.h:1364
virtual void updateGeometry()=0
update pre-computed geometry information
virtual void unselectAttributeCarrier(bool changeFlag=true)=0
unselect attribute carrier using GUIGlobalSelection
const std::vector< GNEAdditional * > & getAdditionalParents() const
return vector of additionals that have as Parent this edge (For example, Calibrators) ...
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:61
T MIN2(T a, T b)
Definition: StdDefs.h:74
void initGNEConnections()
initialize GNEConnections
Definition: GNENet.cpp:3024
bool isAdditionalsSaved() const
check if additionals are saved
Definition: GNENet.cpp:2250
void updateDemandElementID(const std::string &oldID, GNEDemandElement *demandElement)
update demand element ID in container
Definition: GNENet.cpp:2305
std::map< SumoXMLTag, std::map< std::string, GNEDemandElement * > > demandElements
map with the name and pointer to demand elements of net
Definition: GNENet.h:105
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network into XML-files (nodes, edges, connections, traffic lights)
void save(OptionsCont &oc)
save the network
Definition: GNENet.cpp:951
node: the type of traffic light
edge: the shape in xml-definition
void cleanUnusedRoutes(GNEUndoList *undoList)
clean unused routes
Definition: GNENet.cpp:1756
void removeConnectionsTo(GNEEdge *edge, GNEUndoList *undoList, bool updateTLS, int lane=-1)
remove all connections to the given edge
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:599
bool isPlacedInRTree() const
return true if Tag correspond to an element that has has to be placed in RTREE
void addOutgoingGNEEdge(GNEEdge *edge)
add outgoing GNEEdge
const std::string getID() const
function to support debugging
friend class GNEChange_Edge
Definition: GNENet.h:84
void clearInspectedAC()
Clear all current inspected ACs.
void changeShapeID(GNEShape *s, const std::string &OldID)
change Shape ID
Definition: GNENet.cpp:2572
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:246
friend class GNEChange_DemandElement
Definition: GNENet.h:90
GNEJunction * createJunction(const Position &pos, GNEUndoList *undoList)
creates a new junction
Definition: GNENet.cpp:314
std::vector< GNEShape * > retrieveShapes(SumoXMLTag shapeTag, bool onlySelected=false)
return shape by type shapes
Definition: GNENet.cpp:1225
bool isStoppingPlace() const
return true if tag correspond to a detector (Only used to group all stoppingPlaces in the output XML)...
GNEJunction * getGNEJunctionSource() const
returns the source-junction
Definition: GNEEdge.cpp:499
void incRef(const std::string &debugMsg="")
Increarse reference.
std::string generateDemandElementID(const std::string &prefix, SumoXMLTag type) const
generate demand element id
Definition: GNENet.cpp:2411
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
void insertShape(GNEShape *shape, bool updateViewAfterDeleting)
insert shape
Definition: GNENet.cpp:2943
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3441
vehicle is a passenger car (a "normal" car)
SUMORTree & getVisualisationSpeedUp()
Returns the RTree used for visualisation speed-up.
Definition: GNENet.cpp:302
std::vector< GNEAttributeCarrier * > retrieveAttributeCarriers(SumoXMLTag type=SUMO_TAG_NOTHING)
get the attribute carriers based on Type
Definition: GNENet.cpp:1308
void selectAttributeCarrier(bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
std::set< std::string > myExplicitTurnarounds
list of edge ids for which turn-arounds must be added explicitly
Definition: GNENet.h:750
void decRef(const std::string &debugMsg="")
Decrease reference.
void rename(NBNode *node, const std::string &newID)
Renames the node. Throws exception if newID already exists.
int customTLIndex2
Definition: NBNode.h:160
begin/end of the description of an edge
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream&#39;s direction.
Definition: NBNode.cpp:1936
void unselectAttributeCarrier(bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
bool checkJunctionPosition(const Position &pos)
return true if there are already a Junction in the given position, false in other case ...
Definition: GNENet.cpp:921
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network stored in the given net builder.
Definition: NWFrame.cpp:175
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:680
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GNENet.cpp:290
void replaceJunctionByGeometry(GNEJunction *junction, GNEUndoList *undoList)
replace the selected junction by geometry node(s) and merge the edges
Definition: GNENet.cpp:1891
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:50
unsigned int GUIGlID
Definition: GUIGlObject.h:43
void reserveJunctionID(const std::string &id)
reserve junction ID (To avoid duplicates)
Definition: GNENet.cpp:3018
void duplicateLane(GNELane *lane, GNEUndoList *undoList, bool recomputeConnections)
duplicates lane
Definition: GNENet.cpp:656
vehicle is a bus
void reset()
Resets the boundary.
Definition: Boundary.cpp:67
void updateDemandElementBegin(const std::string &oldBegin, GNEDemandElement *demandElement)
update demand element begin in container
Definition: GNENet.cpp:2328
void setResponsible(bool newVal)
set responsibility for deleting internal strctures
Definition: GNEEdge.cpp:1183
GNECrossing * retrieveCrossing(const std::string &id, bool failHard=true) const
get Crossing by id
Definition: GNENet.cpp:1115
std::vector< std::string > getAllNames() const
get all node names
Builds trigger objects for GNENet (busStops, chargingStations, detectors, etc..)
bool myDemandElementsSaved
Flag to check if demand elements has to be saved.
Definition: GNENet.h:765
double width
This crossing&#39;s width.
Definition: NBNode.h:144
~GNENet()
Destructor.
Definition: GNENet.cpp:134
const Boundary & getZBoundary() const
Returns the Z boundary (stored in the x() coordinate) values of 0 do not affect the boundary...
Definition: GNENet.cpp:296
std::string generateAdditionalID(SumoXMLTag type) const
generate additional id
Definition: GNENet.cpp:2256
int customTLIndex
the custom traffic light index of this crossing (if controlled)
Definition: NBNode.h:159
void deleteEdge(GNEEdge *edge, GNEUndoList *undoList, bool recomputeConnections)
removes edge
Definition: GNENet.cpp:429
Flag to check if VType is a default VType.
void setShapeEditedElement(GNENetElement *element)
retrieve the netElement of which the shape is being edited
Definition: GNEPoly.cpp:455
void updateGeometry()
update pre-computed geometry information
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:259
void removeEditedAC(GNEAttributeCarrier *AC)
remove edited ACs
std::vector< GNEEdge * > retrieveEdges(bool onlySelected=false)
return all edges
Definition: GNENet.cpp:1151
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:924
NBConnection getNBConnection() const
get NBConnection
GNEEdge * registerEdge(GNEEdge *edge)
registers an edge with GNENet containers
Definition: GNENet.cpp:2875
PositionVector customShape
optional customShape for this crossing
Definition: NBNode.h:154
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a &#39; &#39;.
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:156
double getHeight() const
Returns the height of the boundary (y-axis)
Definition: Boundary.cpp:161
void addAdditionalGLObject(GUIGlObject *o)
Adds an additional object (detector/shape/trigger) for visualisation.
Definition: SUMORTree.h:127
bool computeSingleLogic(OptionsCont &oc, NBTrafficLightDefinition *def)
Computes a specific traffic light logic (using by NETEDIT)
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
An Element which don&#39;t belongs to GNENet but has influency in the simulation.
Definition: GNEAdditional.h:47
std::vector< GNEAdditional * > retrieveAdditionals(bool onlySelected=false) const
return all additionals
Definition: GNENet.cpp:2145
Instance responsible for building networks.
Definition: NBNetBuilder.h:110
const std::string DEFAULT_PEDTYPE_ID
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
friend class GNEChange_Junction
Definition: GNENet.h:83
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:322
void computeNetwork(GNEApplicationWindow *window, bool force=false, bool volatileOptions=false, std::string additionalPath="", std::string demandPath="")
trigger full netbuild computation param[in] window The window to inform about delay param[in] force W...
Definition: GNENet.cpp:1408
void removeSolitaryJunctions(GNEUndoList *undoList)
removes junctions that have no edges
Definition: GNENet.cpp:1739
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition: NBEdge.cpp:3308
const std::string & getTagStr() const
get tag assigned to this object in string format
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:245
bool myUpdateGeometryEnabled
Flag to enable or disable update geometry of elements after inserting or removing element in net...
Definition: GNENet.h:768
void requiereSaveNet(bool value)
inform that net has to be saved
Definition: GNENet.cpp:933
Demanding mode (Routes, Vehicles etc..)
struct used for saving all attribute carriers of net, in different formats
Definition: GNENet.h:94
AttributeCarriers myAttributeCarriers
AttributeCarriers of net.
Definition: GNENet.h:741
void sety(double y)
set position y
Definition: Position.h:77
element is selected
A storage for options typed value containers)
Definition: OptionsCont.h:90
void disableSaveDemandElementsMenu()
disable save demand elements
void deleteSingleJunction(GNEJunction *junction, bool updateViewAfterDeleting)
deletes a single junction
Definition: GNENet.cpp:2897
The popup menu of a globject.
void computeDemandElements(GNEApplicationWindow *window)
compute demand elements param[in] window The window to inform about delay
Definition: GNENet.cpp:1489
class for GNEChange_ReplaceEdgeInTLS
Definition: GNENet.h:867
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:79
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:166
void clearJunctionConnections(GNEJunction *junction, GNEUndoList *undoList)
clear junction&#39;s connections
Definition: GNENet.cpp:2021
void computeAndUpdate(OptionsCont &oc, bool volatileOptions)
recompute the network and update lane geometries
Definition: GNENet.cpp:3037
int getNumberOfShapes() const
get number of shapes
Definition: GNENet.cpp:2590
crossing between edges for pedestrians
void renameEdge(GNEEdge *edge, const std::string &newID)
updates the map and reserves new id
Definition: GNENet.cpp:2044
static void replaceInListAttribute(GNEAttributeCarrier *ac, SumoXMLAttr key, const std::string &which, const std::string &by, GNEUndoList *undoList)
Definition: GNENet.cpp:3195
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
void replaceIncomingConnections(GNEEdge *which, GNEEdge *by, GNEUndoList *undoList)
replace one edge by another in all tls connections
void deleteJunction(GNEJunction *junction, GNEUndoList *undoList)
removes junction and all incident edges
Definition: GNENet.cpp:384
void unselectAttributeCarrier(bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
Definition: GNEShape.cpp:124
bool myTLSProgramsSaved
Flag to check if shapes has to be saved.
Definition: GNENet.h:762
std::map< std::string, GNEJunction * > junctions
map with the name and pointer to junctions of net
Definition: GNENet.h:96
The network - empty.
std::vector< GNECrossing * > retrieveCrossings(bool onlySelected=false) const
return all crossings
Definition: GNENet.cpp:1135
const Position & getPosition() const
Definition: NBNode.h:251
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition: GNENet.cpp:2127
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:138
Represents a single node (junction) during network building.
Definition: NBNode.h:68
void saveJoined(OptionsCont &oc)
save log of joined junctions (and nothing else)
Definition: GNENet.cpp:969
description of a vehicle
A definition of a pedestrian crossing.
Definition: NBNode.h:132
GNEEdge * addReversedEdge(GNEEdge *edge, GNEUndoList *undoList)
add reversed edge
Definition: GNENet.cpp:851
void saveDemandElements(const std::string &filename)
save demand element elements of the network
Definition: GNENet.cpp:2361
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
const TagProperties & getTagProperty() const
get Tag Property assigned to this object
last coordinate of edge shape
virtual std::string getBegin() const
get begin time of demand element
NBNode::Crossing * getNBCrossing() const
get referente to NBode::Crossing
Definition: GNECrossing.cpp:94
description of a person type (used in NETEDIT)
void push_back_noDoublePos(const Position &p)
insert in back a non double position
virtual void updateGeometry()=0
update pre-computed geometry information
a single trip definition (used by router)
void unblockObject(GUIGlID id)
Marks an object as unblocked.
void reserveEdgeID(const std::string &id)
reserve edge ID (To avoid duplicates)
Definition: GNENet.cpp:3012
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
static void deleteRouteCalculatorInstance()
delete instance of RouteCalculator
void disableUpdateGeometry()
disable update geometry of elements after inserting or removing an element in net ...
Definition: GNENet.cpp:2632
void compute(OptionsCont &oc, const std::set< std::string > &explicitTurnarounds=std::set< std::string >(), bool mayAddOrRemove=true)
Performs the network building steps.
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:479
void analyzeCluster(NodeSet cluster, std::string &id, Position &pos, bool &hasTLS, TrafficLightType &type, SumoXMLNodeType &nodeType)
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:60
bool demandElementExist(GNEDemandElement *demandElement) const
return true if demand element exist (use pointer instead ID)
Definition: GNENet.cpp:2715
void removePolygonForEditShapes(GNEPoly *polygon)
remove Polygon for edit shapes
Definition: GNENet.cpp:2533
std::vector< GNEJunction * > getJunctionNeighbours() const
return GNEJunction neighbours
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:79
void mergeJunctions(GNEJunction *moved, GNEJunction *target, GNEUndoList *undoList)
merge the given junctions edges between the given junctions will be deleted
Definition: GNENet.cpp:886
void requiereSaveTLSPrograms()
Definition: GNENet.cpp:2596
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:399
bool remove(const std::string &id, const bool del=true)
Removes an item.
begin/end of the description of a Point of interest over Lane (used by Netedit)
bool extract(NBNode *node, bool remember=false)
Removes the given node but does not delete it.
Definition: NBNodeCont.cpp:149
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:240
GUIGlObject * getObjectBlocking(GUIGlID id)
Returns the object from the container locking it.
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
Network mode (Edges, junctions, etc..)
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Definition: NBNetBuilder.h:171
bool checkIsRemovable() const
check if node is removable
Definition: NBNode.cpp:2047
NBNode * getNBNode() const
Return net build node.
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:688
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
Definition: NBNode.cpp:2120
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNEEdge.cpp:940
void addGLObjectIntoGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1273
GUISelectedStorage gSelected
A global holder of selected objects.
GNELane * retrieveLane(const std::string &id, bool failHard=true, bool checkVolatileChange=false)
get lane by id
Definition: GNENet.cpp:1179
void setLogicValid(bool valid, GNEUndoList *undoList, const std::string &status=FEATURE_GUESSED)
A window containing a gl-object&#39;s parameter.
void insertDemandElement(GNEDemandElement *demandElement)
Insert a demand element element int GNENet container.
Definition: GNENet.cpp:2727
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition: GNENet.cpp:2057
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:2097
bool wasSplit()
whether this edge was created from a split
Definition: GNEEdge.cpp:852
int getNumberOfTLSPrograms() const
get number of TLS Programs
Definition: GNENet.cpp:2621
virtual std::string getAttribute(SumoXMLAttr key) const =0
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:486
void saveAdditionals(const std::string &filename)
save additional elements of the network
Definition: GNENet.cpp:2205
bool myNetSaved
Flag to check if net has to be saved.
Definition: GNENet.h:756
void savePlain(OptionsCont &oc)
save plain xml representation of the network (and nothing else)
Definition: GNENet.cpp:961
vehicles ignoring classes
void splitEdgesBidi(GNEEdge *edge, GNEEdge *oppositeEdge, const Position &pos, GNEUndoList *undoList)
split all edges at position by inserting one new junction
Definition: GNENet.cpp:826
void requireRecompute()
inform the net about the need for recomputation
Definition: GNENet.cpp:1520
bool isNetSaved() const
return if net has to be saved
Definition: GNENet.cpp:945
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool addPolygon(const std::string &id, const std::string &type, const RGBColor &color, double layer, double angle, const std::string &imgFile, bool relativePath, const PositionVector &shape, bool geo, bool fill, double lineWidth, bool ignorePruning=false)
Builds a polygon using the given values and adds it to the container.
Definition: GNENet.cpp:218
void invalidateTLS(GNEUndoList *undoList, const NBConnection &deletedConnection=NBConnection::InvalidConnection, const NBConnection &addedConnection=NBConnection::InvalidConnection)
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
TrafficLightType
An Element which don&#39;t belongs to GNENet but has influency in the simulation.
begin/end of the description of a polygon
void markAsModified(GNEUndoList *undoList)
prevent re-guessing connections at this junction
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:2067
GNEJunction * getParentJunction() const
get parent Junction
Definition: GNECrossing.cpp:82
const POIs & getPOIs() const
Returns all pois.