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