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