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