Eclipse SUMO - Simulation of Urban MObility
GNEJunction.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // A class for visualizing and editing junctions in netedit (adapted from
19 // GUIJunctionWrapper)
20 /****************************************************************************/
21 #include <config.h>
22 
23 #include <netbuild/NBAlgorithms.h>
25 #include <netbuild/NBNetBuilder.h>
26 #include <netbuild/NBOwnTLDef.h>
27 #include <netedit/GNENet.h>
28 #include <netedit/GNEUndoList.h>
29 #include <netedit/GNEViewNet.h>
33 #include <utils/gui/div/GLHelper.h>
40 
41 #include "GNEConnection.h"
42 #include "GNEJunction.h"
43 #include "GNECrossing.h"
44 
45 
46 // ===========================================================================
47 // method definitions
48 // ===========================================================================
49 
50 GNEJunction::GNEJunction(GNENet* net, NBNode* nbn, bool loaded) :
52 {}, {}, {}, {}, {}, {}, {}, {}),
53 myNBNode(nbn),
54 myMaxDrawingSize(1),
55 myAmCreateEdgeSource(false),
56 myLogicStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED),
57 myAmResponsible(false),
58 myHasValidLogic(loaded),
59 myAmTLSSelected(false),
60 myColorForMissingConnections(false) {
61  // update centering boundary without updating grid
62  updateCenteringBoundary(false);
63 }
64 
65 
67  // delete all GNECrossing
68  for (const auto& crossing : myGNECrossings) {
69  crossing->decRef();
70  if (crossing->unreferenced()) {
71  // show extra information for tests
72  WRITE_DEBUG("Deleting unreferenced " + crossing->getTagStr() + " '" + crossing->getID() + "' in GNEJunction destructor");
73  delete crossing;
74  }
75  }
76 
77  if (myAmResponsible) {
78  // show extra information for tests
79  WRITE_DEBUG("Deleting NBNode of '" + getID() + "' in GNEJunction destructor");
80  delete myNBNode;
81  }
82 }
83 
84 
85 const PositionVector&
87  return myNBNode->getShape();
88 }
89 
90 
91 void
94 }
95 
96 
97 void
98 GNEJunction::updateGeometryAfterNetbuild(bool rebuildNBNodeCrossings) {
99  // recalc max drawing size
100  myMaxDrawingSize = MAX2(getCenteringBoundary().getWidth(), getCenteringBoundary().getHeight());
101  rebuildGNECrossings(rebuildNBNodeCrossings);
103 }
104 
105 
106 Position
108  return myNBNode->getPosition();
109 }
110 
111 
113 GNEJunction::getMoveOperation(const double shapeOffset) {
114  // edit depending if shape is being edited
115  if (isShapeEdited()) {
116  // declare shape to move
117  PositionVector shapeToMove = myNBNode->getShape();
118  // first check if in the given shapeOffset there is a geometry point
119  const Position positionAtOffset = shapeToMove.positionAtOffset2D(shapeOffset);
120  // check if position is valid
121  if (positionAtOffset == Position::INVALID) {
122  return nullptr;
123  } else {
124  // obtain index
125  const int index = myNBNode->getShape().indexOfClosest(positionAtOffset);
126  // declare new index
127  int newIndex = index;
128  // get snap radius
130  // check if we have to create a new index
131  if (positionAtOffset.distanceSquaredTo2D(shapeToMove[index]) > (snap_radius * snap_radius)) {
132  newIndex = shapeToMove.insertAtClosest(positionAtOffset, true);
133  }
134  // return move operation for edit shape
135  return new GNEMoveOperation(this, myNBNode->getShape(), {index}, shapeToMove, {newIndex});
136  }
137  } else {
138  // return junction position
139  return new GNEMoveOperation(this, myNBNode->getPosition());
140  }
141 }
142 
143 
144 void
145 GNEJunction::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
146  // edit depending if shape is being edited
147  if (isShapeEdited()) {
148  // get original shape
149  PositionVector shape = myNBNode->getShape();
150  // check shape size
151  if (shape.size() > 2) {
152  // obtain index
153  int index = shape.indexOfClosest(clickedPosition);
154  // get snap radius
156  // check if we have to create a new index
157  if ((index != -1) && shape[index].distanceSquaredTo2D(clickedPosition) < (snap_radius * snap_radius)) {
158  // remove geometry point
159  shape.erase(shape.begin() + index);
160  // commit new shape
161  undoList->p_begin("remove geometry point of " + getTagStr());
162  undoList->p_add(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(shape)));
163  undoList->p_end();
164  }
165  }
166  }
167 }
168 
169 
170 void
171 GNEJunction::rebuildGNECrossings(bool rebuildNBNodeCrossings) {
172  // rebuild GNECrossings only if create crossings and walkingAreas in net is enabled
174  if (rebuildNBNodeCrossings) {
175  // build new NBNode::Crossings and walking areas
176  mirrorXLeftHand();
178  mirrorXLeftHand();
179  }
180  // create a vector to keep retrieved and created crossings
181  std::vector<GNECrossing*> retrievedCrossings;
182  // iterate over NBNode::Crossings of GNEJunction
183  for (const auto& crossing : myNBNode->getCrossingsIncludingInvalid()) {
184  // retrieve existent GNECrossing, or create it
185  GNECrossing* retrievedGNECrossing = retrieveGNECrossing(crossing.get());
186  retrievedCrossings.push_back(retrievedGNECrossing);
187  // check if previously this GNECrossings exists, and if true, remove it from myGNECrossings and insert in tree again
188  std::vector<GNECrossing*>::iterator retrievedExists = std::find(myGNECrossings.begin(), myGNECrossings.end(), retrievedGNECrossing);
189  if (retrievedExists != myGNECrossings.end()) {
190  myGNECrossings.erase(retrievedExists);
191  // update geometry of retrieved crossing
192  retrievedGNECrossing->updateGeometry();
193  // update boundary
194  retrievedGNECrossing->updateCenteringBoundary(false);
195  } else {
196  // include reference to created GNECrossing
197  retrievedGNECrossing->incRef();
198  }
199  }
200  // delete non retrieved GNECrossings (we don't need to extract if from Tree two times)
201  for (const auto& crossing : myGNECrossings) {
202  crossing->decRef();
203  // check if crossing is selected
204  if (crossing->isAttributeCarrierSelected()) {
205  crossing->unselectAttributeCarrier();
206  }
207  if (crossing->unreferenced()) {
208  // remove it from net
209  myNet->removeGLObjectFromGrid(crossing);
210  // show extra information for tests
211  WRITE_DEBUG("Deleting unreferenced " + crossing->getTagStr() + " in rebuildGNECrossings()");
212  delete crossing;
213  }
214  }
215  // copy retrieved (existent and created) GNECrossigns to myGNECrossings
216  myGNECrossings = retrievedCrossings;
217  }
218 }
219 
220 void
222  if (OptionsCont::getOptions().getBool("lefthand")) {
223  myNBNode->mirrorX();
224  for (NBEdge* e : myNBNode->getEdges()) {
225  e->mirrorX();
226 
227  }
228  }
229 }
230 
231 
234  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
235  buildPopupHeader(ret, app);
238  // build selection and show parameters menu
241  buildPositionCopyEntry(ret, false);
242  // check if we're in supermode network
244  //if (parent.getVisualisationSettings()->editMode != GNE_MODE_CONNECT) {
245  // // XXX if joinable
246  // GUIDesigns::buildFXMenuCommand(ret, "Join adjacent edges", 0, &parent, MID_GNE_JOIN_EDGES);
247  //}
248  const int numEndpoints = (int)myNBNode->getEndPoints().size();
249  // check if we're handling a selection
250  bool handlingSelection = isAttributeCarrierSelected() && (myNet->retrieveJunctions(true).size() > 1);
251  // check if menu commands has to be disabled
255  // create menu commands
256  FXMenuCommand* mcCustomShape = GUIDesigns::buildFXMenuCommand(ret, "Set custom junction shape", nullptr, &parent, MID_GNE_JUNCTION_EDIT_SHAPE);
257  FXMenuCommand* mcResetCustomShape = GUIDesigns::buildFXMenuCommand(ret, "Reset junction shape", nullptr, &parent, MID_GNE_JUNCTION_RESET_SHAPE);
258  FXMenuCommand* mcReplace = GUIDesigns::buildFXMenuCommand(ret, "Replace junction by geometry point", nullptr, &parent, MID_GNE_JUNCTION_REPLACE);
259  FXMenuCommand* mcSplit = GUIDesigns::buildFXMenuCommand(ret, "Split junction (" + toString(numEndpoints) + " end points)", nullptr, &parent, MID_GNE_JUNCTION_SPLIT);
260  FXMenuCommand* mcSplitReconnect = GUIDesigns::buildFXMenuCommand(ret, "Split junction and reconnect", nullptr, &parent, MID_GNE_JUNCTION_SPLIT_RECONNECT);
261  if (myNBNode->isRoundabout()) {
262  GUIDesigns::buildFXMenuCommand(ret, "Select roundabout", nullptr, &parent, MID_GNE_JUNCTION_SELECT_ROUNDABOUT);
263  } else {
264  double radius = myNBNode->getRadius();
265  if (radius == NBNode::UNSPECIFIED_RADIUS) {
266  radius = OptionsCont::getOptions().getFloat("default.junctions.radius");
267  }
268  const std::string menuEntry = "Convert to roundabout (using junction radius " + toString(radius) + ")";
269  FXMenuCommand* mcRoundabout = GUIDesigns::buildFXMenuCommand(ret, menuEntry.c_str(), nullptr, &parent, MID_GNE_JUNCTION_CONVERT_ROUNDABOUT);
270  if (getChildEdges().size() < 2 ||
271  (myGNEIncomingEdges.size() == 1
272  && myGNEOutgoingEdges.size() == 1
273  && myGNEIncomingEdges[0]->getParentJunctions().front() == myGNEOutgoingEdges[0]->getParentJunctions().back())) {
274  mcRoundabout->disable();
275  }
276  }
277  FXMenuCommand* mcClearConnections = GUIDesigns::buildFXMenuCommand(ret, "Clear connections", nullptr, &parent, MID_GNE_JUNCTION_CLEAR_CONNECTIONS);
278  FXMenuCommand* mcResetConnections = GUIDesigns::buildFXMenuCommand(ret, "Reset connections", nullptr, &parent, MID_GNE_JUNCTION_RESET_CONNECTIONS);
279  // check if current mode is correct
280  if (wrongMode) {
281  mcCustomShape->disable();
282  mcClearConnections->disable();
283  mcResetConnections->disable();
284  }
285  // check if we're handling a selection
286  if (handlingSelection) {
287  mcResetCustomShape->setText("Reset junction shapes");
288  }
289  // disable mcClearConnections if juction hasn't connections
290  if (getGNEConnections().empty()) {
291  mcClearConnections->disable();
292  }
293  // disable mcResetCustomShape if junction doesn't have a custom shape
294  if (myNBNode->getShape().size() == 0) {
295  mcResetCustomShape->disable();
296  }
297  // checkIsRemovable requiers turnarounds to be computed. This is ugly
298  if ((myNBNode->getIncomingEdges().size() == 2) && (myNBNode->getOutgoingEdges().size() == 2)) {
300  }
301  std::string reason = "wrong edit mode";
302  if (wrongMode || !myNBNode->checkIsRemovableReporting(reason)) {
303  mcReplace->setText(mcReplace->getText() + " (" + reason.c_str() + ")");
304  mcReplace->disable();
305  }
306  if (numEndpoints == 1) {
307  mcSplit->disable();
308  mcSplitReconnect->disable();
309  }
310  }
311  return ret;
312 }
313 
314 
315 void
316 GNEJunction::updateCenteringBoundary(const bool updateGrid) {
317  // Remove object from net
318  if (updateGrid) {
320  }
321  // update boundary
322  if (myNBNode->getShape().size() > 0) {
324  } else {
325  // calculate boundary using EXTENT as size
326  const double EXTENT = 2;
327  Boundary b(myNBNode->getPosition().x() - EXTENT, myNBNode->getPosition().y() - EXTENT,
328  myNBNode->getPosition().x() + EXTENT, myNBNode->getPosition().y() + EXTENT);
329  myBoundary = b;
330  }
331  myBoundary.grow(10);
332  // add object into net
333  if (updateGrid) {
334  myNet->addGLObjectIntoGrid(this);
335  }
336 }
337 
338 
339 void
341  // check if boundary has to be drawn
342  if (s.drawBoundaries) {
344  }
345  // declare variables
346  const Position mousePosition = myNet->getViewNet()->getPositionInformation();
347  const double junctionExaggeration = s.junctionSize.getExaggeration(s, this, 4);
348  const double bubbleRadius = s.neteditSizeSettings.junctionBubbleRadius * junctionExaggeration;
349  // declare draw shape flag
350  const bool drawShape = (myNBNode->getShape().size() > 0) && s.drawJunctionShape;
351  // declare draw bubble flag
352  bool drawBubble = true;
353  if (!s.drawJunctionShape) {
354  // don't draw bubble if it was disabled in GUIVisualizationSettings
355  drawBubble = false;
356  }
357  if (myNBNode->getShape().area() > 4) {
358  // don't draw if shape area is greather than 4
359  drawBubble = false;
360  }
362  // only draw bubbles in network mode
363  drawBubble = false;
364  }
366  // force draw bubbles if we enabled option in checkbox of viewNet
367  drawBubble = true;
368  }
369  // only continue if exaggeration is greather than 0
370  if (junctionExaggeration > 0) {
371  // push junction name
372  glPushName(getGlID());
373  // push layer matrix
374  glPushMatrix();
375  // translate to front
376  if (myAmCreateEdgeSource) {
377  glTranslated(0, 0, GLO_TEMPORALSHAPE);
378  } else {
380  }
381  // push name
382  if (s.scale * junctionExaggeration * myMaxDrawingSize < 1.) {
383  // draw something simple so that selection still works
385  } else {
386  // check if shape has to be drawn
387  if (drawShape) {
388  // set shape color
389  const RGBColor junctionShapeColor = setColor(s, false);
390  // recognize full transparency and simply don't draw
391  if (junctionShapeColor.alpha() != 0) {
392  // set color
393  GLHelper::setColor(junctionShapeColor);
394  // obtain junction Shape
395  PositionVector junctionClosedShape = myNBNode->getShape();
396  // close junction shape
397  junctionClosedShape.closePolygon();
398  // adjust shape to exaggeration
399  if (junctionExaggeration > 1) {
400  junctionClosedShape.scaleRelative(junctionExaggeration);
401  }
402  // first check if inner junction polygon can be drawn
403  if (s.drawForPositionSelection) {
404  // only draw a point if mouse is around shape
405  if (junctionClosedShape.around(mousePosition)) {
406  // push matrix
407  glPushMatrix();
408  // move to mouse position
409  glTranslated(mousePosition.x(), mousePosition.y(), 0.1);
410  // draw a simple circle
412  // pop matrix
413  glPopMatrix();
414  }
415  } else if ((s.scale * junctionExaggeration * myMaxDrawingSize) < 40.) {
416  // draw shape
417  GLHelper::drawFilledPoly(junctionClosedShape, true);
418  } else {
419  // draw shape with high detail
420  GLHelper::drawFilledPolyTesselated(junctionClosedShape, true);
421  }
422  // draw shape points only in Network supemode
424  // set color
425  const RGBColor darkerColor = junctionShapeColor.changedBrightness(-32);
426  // calculate geometry
427  GNEGeometry::Geometry junctionGeometry;
428  // obtain junction Shape
429  PositionVector junctionOpenShape = myNBNode->getShape();
430  // adjust shape to exaggeration
431  if (junctionExaggeration > 1) {
432  junctionOpenShape.scaleRelative(junctionExaggeration);
433  }
434  // update geometry
435  junctionGeometry.updateGeometry(junctionOpenShape);
436  // set color
437  GLHelper::setColor(darkerColor);
438  // draw shape
440  // draw geometry points
441  GNEGeometry::drawGeometryPoints(s, myNet->getViewNet(), junctionOpenShape, darkerColor, darkerColor, s.neteditSizeSettings.junctionGeometryPointRadius, junctionExaggeration);
442  // draw moving hint
443  GNEGeometry::drawMovingHint(s, myNet->getViewNet(), junctionOpenShape, darkerColor, s.neteditSizeSettings.junctionGeometryPointRadius, junctionExaggeration);
444  }
445  }
446  }
447  // check if bubble has to be drawn
448  if (drawBubble) {
449  // set bubble color
450  const RGBColor bubbleColor = setColor(s, true);
451  // recognize full transparency and simply don't draw
452  if (bubbleColor.alpha() != 0) {
453  // check if mouse is in bubble
454  const bool mouseInBubble = (mousePosition.distanceSquaredTo2D(myNBNode->getPosition()) <= (bubbleRadius * bubbleRadius));
455  // only draw filled circle if we aren't in draw for selecting mode, or if distance to center is enough)
456  if (!s.drawForPositionSelection || mouseInBubble) {
457  // push matrix
458  glPushMatrix();
459  // set color
460  GLHelper::setColor(bubbleColor);
461  // move matrix junction center
462  glTranslated(myNBNode->getPosition().x(), myNBNode->getPosition().y(), 0.1);
463  // draw filled circle
465  // pop matrix
466  glPopMatrix();
467  }
468  }
469  }
470  // draw TLS
471  drawTLSIcon(s);
472  // draw elevation
474  glPushMatrix();
475  // Translate to center of junction
476  glTranslated(myNBNode->getPosition().x(), myNBNode->getPosition().y(), 0.1);
477  // draw Z value
479  glPopMatrix();
480  }
481  // pop layer Matrix
482  glPopMatrix();
483  // pop junction name
484  glPopName();
485  // draw name and ID
486  if (!s.drawForRectangleSelection) {
488  if (s.junctionName.show && myNBNode->getName() != "") {
490  }
491  }
492  // draw Junction childs
494  // check if dotted contour has to be drawn
496  if (drawShape) {
498  }
499  if (drawBubble) {
501  }
502  }
503  // check if dotted contour has to be drawn
504  if (s.drawDottedContour() || (myNet->getViewNet()->getFrontAttributeCarrier() == this)) {
505  if (drawShape) {
507  }
508  if (drawBubble) {
510  }
511  }
512  }
513  }
514 }
515 
516 
517 NBNode*
519  return myNBNode;
520 }
521 
522 
523 std::vector<GNEJunction*>
525  // use set to avoid duplicates junctions
526  std::set<GNEJunction*> junctions;
527  for (const auto& i : myGNEIncomingEdges) {
528  junctions.insert(i->getParentJunctions().front());
529  }
530  for (const auto& i : myGNEOutgoingEdges) {
531  junctions.insert(i->getParentJunctions().back());
532  }
533  return std::vector<GNEJunction*>(junctions.begin(), junctions.end());
534 }
535 
536 
537 void
539  // Check if incoming edge was already inserted
540  std::vector<GNEEdge*>::iterator i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
541  if (i != myGNEIncomingEdges.end()) {
542  throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + getTagStr() + " with ID " + getID() + "'");
543  } else {
544  // Add edge into containers
545  myGNEIncomingEdges.push_back(edge);
546  }
547 }
548 
549 
550 
551 void
553  // Check if outgoing edge was already inserted
554  std::vector<GNEEdge*>::iterator i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
555  if (i != myGNEOutgoingEdges.end()) {
556  throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + getTagStr() + " with ID " + getID() + "'");
557  } else {
558  // Add edge into containers
559  myGNEOutgoingEdges.push_back(edge);
560  }
561 }
562 
563 
564 void
566  // Check if incoming edge was already inserted
567  std::vector<GNEEdge*>::iterator i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
568  if (i == myGNEIncomingEdges.end()) {
569  throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + getTagStr() + " with ID " + getID() + "'");
570  } else {
571  // remove edge from containers
572  myGNEIncomingEdges.erase(i);
573  }
574 }
575 
576 
577 void
579  // Check if outgoing edge was already inserted
580  std::vector<GNEEdge*>::iterator i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
581  if (i == myGNEOutgoingEdges.end()) {
582  throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + getTagStr() + " with ID " + getID() + "'");
583  } else {
584  // remove edge from containers
585  myGNEOutgoingEdges.erase(i);
586  }
587 }
588 
589 
590 const std::vector<GNEEdge*>&
592  return myGNEIncomingEdges;
593 }
594 
595 
596 const std::vector<GNEEdge*>&
598  return myGNEOutgoingEdges;
599 }
600 
601 
602 const std::vector<GNECrossing*>&
604  return myGNECrossings;
605 }
606 
607 
608 std::vector<GNEConnection*>
610  std::vector<GNEConnection*> connections;
611  for (const auto& i : myGNEIncomingEdges) {
612  for (const auto& j : i->getGNEConnections()) {
613  connections.push_back(j);
614  }
615  }
616  return connections;
617 }
618 
619 
620 void
622  myAmCreateEdgeSource = true;
623 }
624 
625 
626 void
628  myAmCreateEdgeSource = false;
629 }
630 
631 
632 void
633 GNEJunction::selectTLS(bool selected) {
634  myAmTLSSelected = selected;
635 }
636 
637 
638 void
640  if (!myNBNode->hasCustomShape()) {
641  if (myNBNode->myPoly.size() > 0) {
642  // write GL Debug
643  WRITE_GLDEBUG("<-- Invalidating shape of junction '" + getID() + "' -->");
644  // clear poly
645  myNBNode->myPoly.clear();
646  // update centering boundary
648  }
650  }
651 }
652 
653 
654 void
655 GNEJunction::setLogicValid(bool valid, GNEUndoList* undoList, const std::string& status) {
656  myHasValidLogic = valid;
657  if (!valid) {
658  assert(undoList != 0);
659  assert(undoList->hasCommandGroup());
661  EdgeVector incoming = myNBNode->getIncomingEdges();
662  for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
663  GNEEdge* srcEdge = myNet->retrieveEdge((*it)->getID());
664  removeConnectionsFrom(srcEdge, undoList, false); // false, because the whole tls will be invalidated at the end
665  undoList->add(new GNEChange_Attribute(srcEdge, GNE_ATTR_MODIFICATION_STATUS, status), true);
666  }
667  undoList->add(new GNEChange_Attribute(this, GNE_ATTR_MODIFICATION_STATUS, status), true);
668  invalidateTLS(undoList);
669  } else {
670  // logic valed, then rebuild GNECrossings to adapt it to the new logic
671  // (but don't rebuild the crossings in NBNode because they are already finished)
672  rebuildGNECrossings(false);
673  }
674 }
675 
676 
677 void
678 GNEJunction::removeConnectionsFrom(GNEEdge* edge, GNEUndoList* undoList, bool updateTLS, int lane) {
679  NBEdge* srcNBE = edge->getNBEdge();
680  NBEdge* turnEdge = srcNBE->getTurnDestination();
681  // Make a copy of connections
682  std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
683  // delete in reverse so that undoing will add connections in the original order
684  for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
685  if (lane >= 0 && (*con_it).fromLane != lane) {
686  continue;
687  }
688  bool hasTurn = con_it->toEdge == turnEdge;
689  undoList->add(new GNEChange_Connection(edge, *con_it, false, false), true);
690  // needs to come after GNEChange_Connection
691  // XXX bug: this code path will not be used on a redo!
692  if (hasTurn) {
693  myNet->addExplicitTurnaround(srcNBE->getID());
694  }
695  }
696  if (updateTLS) {
697  std::vector<NBConnection> removeConnections;
698  for (NBEdge::Connection con : connections) {
699  removeConnections.push_back(NBConnection(srcNBE, con.fromLane, con.toEdge, con.toLane));
700  }
701  removeTLSConnections(removeConnections, undoList);
702  }
703 }
704 
705 
706 void
707 GNEJunction::removeConnectionsTo(GNEEdge* edge, GNEUndoList* undoList, bool updateTLS, int lane) {
708  NBEdge* destNBE = edge->getNBEdge();
709  std::vector<NBConnection> removeConnections;
710  for (NBEdge* srcNBE : myNBNode->getIncomingEdges()) {
711  GNEEdge* srcEdge = myNet->retrieveEdge(srcNBE->getID());
712  std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
713  for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
714  if ((*con_it).toEdge == destNBE) {
715  if (lane >= 0 && (*con_it).toLane != lane) {
716  continue;
717  }
718  bool hasTurn = srcNBE->getTurnDestination() == destNBE;
719  undoList->add(new GNEChange_Connection(srcEdge, *con_it, false, false), true);
720  // needs to come after GNEChange_Connection
721  // XXX bug: this code path will not be used on a redo!
722  if (hasTurn) {
723  myNet->addExplicitTurnaround(srcNBE->getID());
724  }
725  removeConnections.push_back(NBConnection(srcNBE, (*con_it).fromLane, destNBE, (*con_it).toLane));
726  }
727  }
728  }
729  if (updateTLS) {
730  removeTLSConnections(removeConnections, undoList);
731  }
732 }
733 
734 
735 void
736 GNEJunction::removeTLSConnections(std::vector<NBConnection>& connections, GNEUndoList* undoList) {
737  if (connections.size() > 0) {
738  const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
739  for (const auto& TLS : coypOfTls) {
740  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
741  // guessed TLS (NBOwnTLDef) do not need to be updated
742  if (tlDef != nullptr) {
743  std::string newID = tlDef->getID();
744  // create replacement before deleting the original because deletion will mess up saving original nodes
745  NBLoadedSUMOTLDef* replacementDef = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
746  for (NBConnection& con : connections) {
747  replacementDef->removeConnection(con);
748  }
749  undoList->add(new GNEChange_TLS(this, tlDef, false), true);
750  undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
751  // the removed traffic light may have controlled more than one junction. These too have become invalid now
752  const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
753  for (const auto& node : copyOfNodes) {
754  GNEJunction* sharing = myNet->retrieveJunction(node->getID());
755  undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
756  undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
757  }
758  }
759  }
760  }
761 }
762 
763 
764 void
766  // remap connections of the edge
767  assert(which->getLanes().size() == by->getLanes().size());
768  std::vector<NBEdge::Connection> connections = which->getNBEdge()->getConnections();
769  for (NBEdge::Connection& c : connections) {
770  undoList->add(new GNEChange_Connection(which, c, false, false), true);
771  undoList->add(new GNEChange_Connection(by, c, false, true), true);
772  }
773  // also remap tls connections
774  const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
775  for (const auto& TLS : coypOfTls) {
776  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
777  // guessed TLS (NBOwnTLDef) do not need to be updated
778  if (tlDef != nullptr) {
779  std::string newID = tlDef->getID();
780  // create replacement before deleting the original because deletion will mess up saving original nodes
781  NBLoadedSUMOTLDef* replacementDef = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
782  for (int i = 0; i < (int)which->getLanes().size(); ++i) {
783  replacementDef->replaceRemoved(which->getNBEdge(), i, by->getNBEdge(), i, true);
784  }
785  undoList->add(new GNEChange_TLS(this, tlDef, false), true);
786  undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
787  // the removed traffic light may have controlled more than one junction. These too have become invalid now
788  const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
789  for (const auto& node : copyOfNodes) {
790  GNEJunction* sharing = myNet->retrieveJunction(node->getID());
791  undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
792  undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
793  }
794  }
795  }
796 }
797 
798 
799 void
801  EdgeVector incoming = myNBNode->getIncomingEdges();
802  for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
803  NBEdge* srcNBE = *it;
804  GNEEdge* srcEdge = myNet->retrieveEdge(srcNBE->getID());
805  undoList->add(new GNEChange_Attribute(srcEdge, GNE_ATTR_MODIFICATION_STATUS, FEATURE_MODIFIED), true);
806  }
807 }
808 
809 
810 void
811 GNEJunction::invalidateTLS(GNEUndoList* undoList, const NBConnection& deletedConnection, const NBConnection& addedConnection) {
812  assert(undoList->hasCommandGroup());
813  // NBLoadedSUMOTLDef becomes invalid, replace with NBOwnTLDef which will be dynamically recomputed
814  const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
815  for (const auto& TLS : coypOfTls) {
816  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
817  if (tlDef != nullptr) {
818  NBTrafficLightDefinition* replacementDef = nullptr;
819  std::string newID = tlDef->getID(); // + "_reguessed"; // changes due to reguessing will be visible in diff
820  if (deletedConnection != NBConnection::InvalidConnection) {
821  // create replacement before deleting the original because deletion will mess up saving original nodes
822  NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
823  repl->removeConnection(deletedConnection);
824  replacementDef = repl;
825  } else if (addedConnection != NBConnection::InvalidConnection) {
826  if (addedConnection.getTLIndex() == NBConnection::InvalidTlIndex) {
827  // custom tl indices of crossings might become invalid upon recomputation so we must save them
828  // however, the could remain valud so we register a change but keep them at their old value
829  for (GNECrossing* c : myGNECrossings) {
830  const std::string oldValue = c->getAttribute(SUMO_ATTR_TLLINKINDEX);
832  undoList->add(new GNEChange_Attribute(c, SUMO_ATTR_TLLINKINDEX, oldValue), true);
833  const std::string oldValue2 = c->getAttribute(SUMO_ATTR_TLLINKINDEX);
835  undoList->add(new GNEChange_Attribute(c, SUMO_ATTR_TLLINKINDEX2, oldValue2), true);
836  }
837  }
838  NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
839  repl->addConnection(addedConnection.getFrom(), addedConnection.getTo(),
840  addedConnection.getFromLane(), addedConnection.getToLane(), addedConnection.getTLIndex(), addedConnection.getTLIndex2());
841  replacementDef = repl;
842  } else {
843  replacementDef = new NBOwnTLDef(newID, tlDef->getOffset(), tlDef->getType());
844  replacementDef->setProgramID(tlDef->getProgramID());
845  }
846  undoList->add(new GNEChange_TLS(this, tlDef, false), true);
847  undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
848  // the removed traffic light may have controlled more than one junction. These too have become invalid now
849  const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
850  for (const auto& node : copyOfNodes) {
851  GNEJunction* sharing = myNet->retrieveJunction(node->getID());
852  undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
853  undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
854  }
855  }
856  }
857 }
858 
859 void
861  // obtain a copy of GNECrossing of junctions
862  auto copyOfGNECrossings = myGNECrossings;
863  // iterate over copy of GNECrossings
864  for (int i = 0; i < (int)myGNECrossings.size(); i++) {
865  auto c = myGNECrossings.at(i);
866  // obtain the set of edges vinculated with the crossing (due it works as ID)
867  EdgeSet edgeSet(c->getCrossingEdges().begin(), c->getCrossingEdges().end());
868  // If this edge is part of the set of edges of crossing
869  if (edgeSet.count(edge->getNBEdge()) == 1) {
870  // delete crossing if this is their last edge
871  if ((c->getCrossingEdges().size() == 1) && (c->getCrossingEdges().front() == edge->getNBEdge())) {
872  myNet->deleteCrossing(c, undoList);
873  i = 0;
874  } else {
875  // remove this edge of the edge's attribute of crossing (note: This can invalidate the crossing)
876  std::vector<std::string> edges = GNEAttributeCarrier::parse<std::vector<std::string>>(c->getAttribute(SUMO_ATTR_EDGES));
877  edges.erase(std::find(edges.begin(), edges.end(), edge->getID()));
878  c->setAttribute(SUMO_ATTR_EDGES, joinToString(edges, " "), undoList);
879  }
880  }
881  }
882 }
883 
884 
885 bool
887  return myHasValidLogic;
888 }
889 
890 
892 GNEJunction::retrieveGNECrossing(NBNode::Crossing* NBNodeCrossing, bool createIfNoExist) {
893  // iterate over all crossing
894  for (const auto& crossing : myGNECrossings) {
895  // if found, return it
896  if (crossing->getCrossingEdges() == NBNodeCrossing->edges) {
897  return crossing;
898  }
899  }
900  if (createIfNoExist) {
901  // create new GNECrossing
902  GNECrossing* createdGNECrossing = new GNECrossing(this, NBNodeCrossing->edges);
903  // show extra information for tests
904  WRITE_DEBUG("Created " + createdGNECrossing->getTagStr() + " '" + createdGNECrossing->getID() + "' in retrieveGNECrossing()");
905  // update geometry after creating
906  createdGNECrossing->updateGeometry();
907  // add it in Network
908  myNet->addGLObjectIntoGrid(createdGNECrossing);
909  return createdGNECrossing;
910  } else {
911  return nullptr;
912  }
913 }
914 
915 
916 void
917 GNEJunction::markConnectionsDeprecated(bool includingNeighbours) {
918  // only it's needed to mark the connections of incoming edges
919  for (const auto& i : myGNEIncomingEdges) {
920  for (const auto& j : i->getGNEConnections()) {
921  j->markConnectionGeometryDeprecated();
922  }
923  if (includingNeighbours) {
924  i->getParentJunctions().front()->markConnectionsDeprecated(false);
925  }
926  }
927 }
928 
929 
930 void
932  // get tag
933  SumoXMLTag tag = additionalElement->getTagProperty().getTag();
934  // avoid insert duplicated path element childs
935  if (std::find(myPathAdditionalElements[tag].begin(), myPathAdditionalElements[tag].end(), additionalElement) == myPathAdditionalElements[tag].end()) {
936  myPathAdditionalElements[tag].push_back(additionalElement);
937  }
938 }
939 
940 
941 void
943  // get tag
944  SumoXMLTag tag = additionalElement->getTagProperty().getTag();
945  // search and remove pathElementChild
946  auto it = std::find(myPathAdditionalElements[tag].begin(), myPathAdditionalElements[tag].end(), additionalElement);
947  if (it != myPathAdditionalElements[tag].end()) {
948  myPathAdditionalElements[tag].erase(it);
949  }
950 }
951 
952 
953 void
955  // get tag
956  SumoXMLTag tag = demandElement->getTagProperty().getTag();
957  // avoid insert duplicated path element childs
958  if (std::find(myPathDemandElements[tag].begin(), myPathDemandElements[tag].end(), demandElement) == myPathDemandElements[tag].end()) {
959  myPathDemandElements[tag].push_back(demandElement);
960  }
961 }
962 
963 
964 void
966  // get tag
967  SumoXMLTag tag = demandElement->getTagProperty().getTag();
968  // search and remove pathElementChild
969  auto it = std::find(myPathDemandElements[tag].begin(), myPathDemandElements[tag].end(), demandElement);
970  if (it != myPathDemandElements[tag].end()) {
971  myPathDemandElements[tag].erase(it);
972  }
973 }
974 
975 
976 void
978  // get tag
979  SumoXMLTag tag = genericData->getTagProperty().getTag();
980  // avoid insert duplicated path element childs
981  if (std::find(myPathGenericDatas[tag].begin(), myPathGenericDatas[tag].end(), genericData) == myPathGenericDatas[tag].end()) {
982  myPathGenericDatas[tag].push_back(genericData);
983  }
984 }
985 
986 
987 void
989  // get tag
990  SumoXMLTag tag = genericData->getTagProperty().getTag();
991  // search and remove pathElementChild
992  auto it = std::find(myPathGenericDatas[tag].begin(), myPathGenericDatas[tag].end(), genericData);
993  if (it != myPathGenericDatas[tag].end()) {
994  myPathGenericDatas[tag].erase(it);
995  }
996 }
997 
998 
999 void
1001  // make a copy of myPathAdditionalElements
1002  auto copyOfPathAdditionalElements = myPathAdditionalElements;
1003  for (const auto& tag : copyOfPathAdditionalElements) {
1004  for (const auto& additionalElement : tag.second) {
1005  // note: currently additional elements don't use compute/invalidate paths
1006  additionalElement->updateGeometry();
1007  }
1008  }
1009  // make a copy of myPathDemandElements
1010  auto copyOfPathDemandElements = myPathDemandElements;
1011  for (const auto& tag : copyOfPathDemandElements) {
1012  for (const auto& demandElement : tag.second) {
1013  demandElement->invalidatePath();
1014  }
1015  }
1016  // make a copy of myPathGenericDatas
1017  auto copyOfPathGenericDatas = myPathGenericDatas;
1018  for (const auto& tag : copyOfPathGenericDatas) {
1019  for (const auto& genericData : tag.second) {
1020  // note: currently generic datas don't use compute/invalidate paths
1021  genericData->updateGeometry();
1022  }
1023  }
1024 }
1025 
1026 
1027 std::string
1029  switch (key) {
1030  case SUMO_ATTR_ID:
1031  return getID();
1032  case SUMO_ATTR_POSITION:
1033  return toString(myNBNode->getPosition());
1034  case SUMO_ATTR_TYPE:
1035  return toString(myNBNode->getType());
1037  return myLogicStatus;
1038  case SUMO_ATTR_SHAPE:
1039  return toString(myNBNode->getShape());
1040  case SUMO_ATTR_RADIUS:
1041  return toString(myNBNode->getRadius());
1042  case SUMO_ATTR_TLTYPE:
1044  // @todo this causes problems if the node were to have multiple programs of different type (plausible)
1045  return toString((*myNBNode->getControllingTLS().begin())->getType());
1046  } else {
1047  return "No TLS";
1048  }
1049  case SUMO_ATTR_TLLAYOUT:
1051  return toString((*myNBNode->getControllingTLS().begin())->getLayout());
1052  } else {
1053  return "No TLS";
1054  }
1055  case SUMO_ATTR_TLID:
1057  return toString((*myNBNode->getControllingTLS().begin())->getID());
1058  } else {
1059  return "No TLS";
1060  }
1061  case SUMO_ATTR_KEEP_CLEAR:
1062  // keep clear is only used as a convenience feature in plain xml
1063  // input. When saving to .net.xml the status is saved only for the connections
1064  // to show the correct state we must check all connections
1065  for (const auto& i : myGNEIncomingEdges) {
1066  for (const auto& j : i->getGNEConnections()) {
1067  if (j->getNBEdgeConnection().keepClear) {
1068  return toString(true);
1069  }
1070  }
1071  }
1072  return toString(false);
1075  case SUMO_ATTR_FRINGE:
1077  case SUMO_ATTR_NAME:
1078  return myNBNode->getName();
1079  case GNE_ATTR_SELECTED:
1081  case GNE_ATTR_PARAMETERS:
1082  return myNBNode->getParametersStr();
1083  default:
1084  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1085  }
1086 }
1087 
1088 
1089 void
1090 GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1091  if (value == getAttribute(key)) {
1092  return; //avoid needless changes, later logic relies on the fact that attributes have changed
1093  }
1094  switch (key) {
1095  case SUMO_ATTR_ID:
1096  case SUMO_ATTR_POSITION:
1098  case SUMO_ATTR_SHAPE:
1099  case SUMO_ATTR_RADIUS:
1101  case SUMO_ATTR_FRINGE:
1102  case SUMO_ATTR_NAME:
1103  case GNE_ATTR_SELECTED:
1104  case GNE_ATTR_PARAMETERS:
1105  undoList->add(new GNEChange_Attribute(this, key, value), true);
1106  break;
1107  case SUMO_ATTR_KEEP_CLEAR:
1108  // change Keep Clear attribute in all connections
1109  undoList->p_begin("change keepClear for whole junction");
1110  for (const auto& i : myGNEIncomingEdges) {
1111  for (const auto& j : i->getGNEConnections()) {
1112  undoList->add(new GNEChange_Attribute(j, key, value), true);
1113  }
1114  }
1115  undoList->p_end();
1116  break;
1117  case SUMO_ATTR_TYPE: {
1118  undoList->p_begin("change " + getTagStr() + " type");
1120  if (getNBNode()->isTLControlled() &&
1121  // if switching changing from or to traffic_light_right_on_red we need to remove the old plan
1124  ) {
1125  // make a copy because we will modify the original
1126  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1127  for (const auto& TLS : copyOfTls) {
1128  undoList->add(new GNEChange_TLS(this, TLS, false), true);
1129  }
1130  }
1131  if (!getNBNode()->isTLControlled()) {
1132  // create new traffic light
1133  undoList->add(new GNEChange_TLS(this, nullptr, true), true);
1134  }
1135  } else if (getNBNode()->isTLControlled()) {
1136  // delete old traffic light
1137  // make a copy because we will modify the original
1138  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1139  for (const auto& TLS : copyOfTls) {
1140  undoList->add(new GNEChange_TLS(this, TLS, false, false), true);
1141  }
1142  }
1143  // must be the final step, otherwise we do not know which traffic lights to remove via GNEChange_TLS
1144  undoList->add(new GNEChange_Attribute(this, key, value), true);
1145  for (const auto& crossing : myGNECrossings) {
1146  undoList->add(new GNEChange_Attribute(crossing, SUMO_ATTR_TLLINKINDEX, "-1"), true);
1147  undoList->add(new GNEChange_Attribute(crossing, SUMO_ATTR_TLLINKINDEX2, "-1"), true);
1148  }
1149  undoList->p_end();
1150  break;
1151  }
1152  case SUMO_ATTR_TLTYPE: {
1153  undoList->p_begin("change " + getTagStr() + " tl-type");
1154  // make a copy because we will modify the original
1155  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1156  for (const auto& TLS : copyOfTls) {
1157  NBLoadedSUMOTLDef* oldLoaded = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
1158  if (oldLoaded != nullptr) {
1159  NBLoadedSUMOTLDef* newDef = new NBLoadedSUMOTLDef(*oldLoaded, *oldLoaded->getLogic());
1160  newDef->guessMinMaxDuration();
1161  std::vector<NBNode*> nodes = TLS->getNodes();
1162  for (const auto& node : nodes) {
1163  GNEJunction* junction = myNet->retrieveJunction(node->getID());
1164  undoList->add(new GNEChange_TLS(junction, TLS, false), true);
1165  undoList->add(new GNEChange_TLS(junction, newDef, true), true);
1166  }
1167  }
1168  }
1169  undoList->add(new GNEChange_Attribute(this, key, value), true);
1170  undoList->p_end();
1171  break;
1172  }
1173  case SUMO_ATTR_TLLAYOUT: {
1174  undoList->p_begin("change " + getTagStr() + " tlLayout");
1175  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1176  for (const auto& oldTLS : copyOfTls) {
1177  std::vector<NBNode*> copyOfNodes = oldTLS->getNodes();
1178  NBOwnTLDef* newTLS = new NBOwnTLDef(oldTLS->getID(), oldTLS->getOffset(), oldTLS->getType());
1180  newTLS->setProgramID(oldTLS->getProgramID());
1181  for (const auto& node : copyOfNodes) {
1182  GNEJunction* oldJunction = myNet->retrieveJunction(node->getID());
1183  undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
1184  }
1185  for (const auto& node : copyOfNodes) {
1186  GNEJunction* oldJunction = myNet->retrieveJunction(node->getID());
1187  undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
1188  }
1189  }
1190  undoList->p_end();
1191  break;
1192  }
1193  case SUMO_ATTR_TLID: {
1194  undoList->p_begin("change " + toString(SUMO_TAG_TRAFFIC_LIGHT) + " id");
1195  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1196  assert(copyOfTls.size() > 0);
1197  NBTrafficLightDefinition* currentTLS = *copyOfTls.begin();
1198  NBTrafficLightDefinition* currentTLSCopy = nullptr;
1199  const bool currentIsSingle = currentTLS->getNodes().size() == 1;
1200  const bool currentIsLoaded = dynamic_cast<NBLoadedSUMOTLDef*>(currentTLS) != nullptr;
1201  if (currentIsLoaded) {
1202  currentTLSCopy = new NBLoadedSUMOTLDef(*currentTLS,
1203  *dynamic_cast<NBLoadedSUMOTLDef*>(currentTLS)->getLogic());
1204  }
1205  // remove from previous tls
1206  for (const auto& TLS : copyOfTls) {
1207  undoList->add(new GNEChange_TLS(this, TLS, false), true);
1208  }
1210  // programs to which the current node shall be added
1211  const std::map<std::string, NBTrafficLightDefinition*> programs = tlCont.getPrograms(value);
1212  if (programs.size() > 0) {
1213  for (const auto& TLSProgram : programs) {
1214  NBTrafficLightDefinition* oldTLS = TLSProgram.second;
1215  if (dynamic_cast<NBOwnTLDef*>(oldTLS) != nullptr) {
1216  undoList->add(new GNEChange_TLS(this, oldTLS, true), true);
1217  } else {
1218  // delete and re-create the definition because the loaded phases are now invalid
1219  if (dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS) != nullptr &&
1220  dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS)->usingSignalGroups()) {
1221  // keep the old program and add all-red state for the added links
1222  NBLoadedSUMOTLDef* newTLSJoined = new NBLoadedSUMOTLDef(*oldTLS, *dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS)->getLogic());
1223  newTLSJoined->joinLogic(currentTLSCopy);
1224  undoList->add(new GNEChange_TLS(this, newTLSJoined, true, true), true);
1225  } else {
1226  undoList->add(new GNEChange_TLS(this, nullptr, true, false, value), true);
1227  }
1228  NBTrafficLightDefinition* newTLS = *myNBNode->getControllingTLS().begin();
1229  // switch from old to new definition
1230  std::vector<NBNode*> copyOfNodes = oldTLS->getNodes();
1231  for (const auto& node : copyOfNodes) {
1232  GNEJunction* oldJunction = myNet->retrieveJunction(node->getID());
1233  undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
1234  undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
1235  }
1236  }
1237  }
1238  } else {
1239  if (currentIsSingle && currentIsLoaded) {
1240  // rename the traffic light but keep everything else
1241  NBTrafficLightLogic* renamedLogic = dynamic_cast<NBLoadedSUMOTLDef*>(currentTLSCopy)->getLogic();
1242  renamedLogic->setID(value);
1243  NBLoadedSUMOTLDef* renamedTLS = new NBLoadedSUMOTLDef(*currentTLSCopy, *renamedLogic);
1244  renamedTLS->setID(value);
1245  undoList->add(new GNEChange_TLS(this, renamedTLS, true, true), true);
1246  } else {
1247  // create new traffic light
1248  undoList->add(new GNEChange_TLS(this, nullptr, true, false, value), true);
1249  }
1250  }
1251  delete currentTLSCopy;
1252  undoList->p_end();
1253  break;
1254  }
1255  default:
1256  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1257  }
1258 }
1259 
1260 
1261 bool
1262 GNEJunction::isValid(SumoXMLAttr key, const std::string& value) {
1263  switch (key) {
1264  case SUMO_ATTR_ID:
1265  return SUMOXMLDefinitions::isValidNetID(value) && (myNet->retrieveJunction(value, false) == nullptr);
1266  case SUMO_ATTR_TYPE:
1268  case SUMO_ATTR_POSITION:
1269  return canParse<Position>(value);
1270  case SUMO_ATTR_SHAPE:
1271  // empty shapes are allowed
1272  return canParse<PositionVector>(value);
1273  case SUMO_ATTR_RADIUS:
1274  return canParse<double>(value) && (parse<double>(value) >= -1);
1275  case SUMO_ATTR_TLTYPE:
1277  case SUMO_ATTR_TLLAYOUT:
1279  case SUMO_ATTR_TLID:
1280  return myNBNode->isTLControlled() && (value != "");
1281  case SUMO_ATTR_KEEP_CLEAR:
1282  return canParse<bool>(value);
1285  case SUMO_ATTR_FRINGE:
1287  case SUMO_ATTR_NAME:
1288  return true;
1289  case GNE_ATTR_SELECTED:
1290  return canParse<bool>(value);
1291  case GNE_ATTR_PARAMETERS:
1292  return Parameterised::areParametersValid(value);
1293  default:
1294  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1295  }
1296 }
1297 
1298 
1299 bool
1301  switch (key) {
1302  case SUMO_ATTR_TLTYPE:
1303  case SUMO_ATTR_TLLAYOUT:
1304  case SUMO_ATTR_TLID:
1305  return myNBNode->isTLControlled();
1306  case SUMO_ATTR_KEEP_CLEAR: {
1307  // check if at least there is an incoming connection
1308  for (const auto& i : myGNEIncomingEdges) {
1309  if (i->getGNEConnections().size() > 0) {
1310  return true;
1311  }
1312  }
1313  return false;
1314  }
1315  default:
1316  return true;
1317  }
1318 }
1319 
1320 
1321 const std::map<std::string, std::string>&
1323  return myNBNode->getParametersMap();
1324 }
1325 
1326 
1327 void
1329  myAmResponsible = newVal;
1330 }
1331 
1332 // ===========================================================================
1333 // private
1334 // ===========================================================================
1335 
1336 void
1338  // draw TLS icon if isn't being drawn for selecting
1341  glPushMatrix();
1342  Position pos = myNBNode->getPosition();
1343  glTranslated(pos.x(), pos.y(), 0.2);
1344  glColor3d(1, 1, 1);
1345  const double halfWidth = 32 / s.scale;
1346  const double halfHeight = 64 / s.scale;
1347  GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GNETEXTURE_TLS), -halfWidth, -halfHeight, halfWidth, halfHeight);
1348  glPopMatrix();
1349  }
1350 }
1351 
1352 
1353 void
1355  // draw crossings
1356  for (const auto& crossing : myGNECrossings) {
1357  crossing->drawGL(s);
1358  }
1359  // draw connections and route elements connections (Only for incoming edges)
1360  for (const auto& incomingEdge : myGNEIncomingEdges) {
1361  for (const auto& connection : incomingEdge->getGNEConnections()) {
1362  connection->drawGL(s);
1363  }
1364  }
1365  // draw child demand elements
1366  for (const auto& demandElement : getChildDemandElements()) {
1367  if (!demandElement->getTagProperty().isPlacedInRTree()) {
1368  demandElement->drawGL(s);
1369  }
1370  }
1371  // draw child path additionals
1372  for (const auto& tag : myPathAdditionalElements) {
1373  for (const auto& element : tag.second) {
1374  element->drawJunctionPathChildren(s, this, 0);
1375  }
1376  }
1377  // draw child path demand elements
1378  for (const auto& tag : myPathDemandElements) {
1379  for (const GNEDemandElement* const element : tag.second) {
1380  element->drawJunctionPathChildren(s, this, 0);
1381  }
1382  }
1383  // draw child path generic datas
1384  for (const auto& tag : myPathGenericDatas) {
1385  for (const GNEGenericData* const element : tag.second) {
1386  element->drawJunctionPathChildren(s, this, 0);
1387  }
1388  }
1389 }
1390 
1391 
1392 void
1393 GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value) {
1394  switch (key) {
1395  case SUMO_ATTR_KEEP_CLEAR: {
1396  throw InvalidArgument(toString(key) + " cannot be edited");
1397  }
1398  case SUMO_ATTR_ID: {
1399  myNet->getAttributeCarriers()->updateID(this, value);
1400  break;
1401  }
1402  case SUMO_ATTR_TYPE: {
1406  }
1407  myNBNode->reinit(myNBNode->getPosition(), type);
1408  break;
1409  }
1410  case SUMO_ATTR_POSITION: {
1411  // set new position in NBNode updating edge boundaries
1412  moveJunctionGeometry(parse<Position>(value), true);
1413  // mark this connections and all of the junction's Neighbours as deprecated
1415  // update centering boundary and grid
1417  break;
1418  }
1420  if (myLogicStatus == FEATURE_GUESSED && value != FEATURE_GUESSED) {
1421  // clear guessed connections. previous connections will be restored
1423  // Clear GNEConnections of incoming edges
1424  for (const auto& i : myGNEIncomingEdges) {
1425  i->clearGNEConnections();
1426  }
1427  }
1428  myLogicStatus = value;
1429  break;
1430  case SUMO_ATTR_SHAPE: {
1431  // set new shape (without updating grid)
1432  myNBNode->setCustomShape(parse<PositionVector>(value));
1433  // mark this connections and all of the junction's Neighbours as deprecated
1435  // update centering boundary and grid
1437  break;
1438  }
1439  case SUMO_ATTR_RADIUS: {
1440  myNBNode->setRadius(parse<double>(value));
1441  break;
1442  }
1443  case SUMO_ATTR_TLTYPE: {
1444  // we need to make a copy of controlling TLS (because original will be updated)
1445  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1446  for (const auto& TLS : copyOfTls) {
1447  TLS->setType(SUMOXMLDefinitions::TrafficLightTypes.get(value));
1448  }
1449  break;
1450  }
1451  case SUMO_ATTR_TLLAYOUT:
1452  // should not be triggered (handled via GNEChange_TLS)
1453  break;
1456  break;
1457  case SUMO_ATTR_FRINGE:
1459  break;
1460  case SUMO_ATTR_NAME:
1461  myNBNode->setName(value);
1462  break;
1463  case GNE_ATTR_SELECTED:
1464  if (parse<bool>(value)) {
1466  } else {
1468  }
1469  break;
1470  case GNE_ATTR_PARAMETERS:
1471  myNBNode->setParametersStr(value);
1472  break;
1473  default:
1474  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1475  }
1476 }
1477 
1478 
1479 void
1481  // set new position in NBNode without updating grid
1482  if (isShapeEdited()) {
1483  // set new shape
1484  myNBNode->setCustomShape(moveResult.shapeToUpdate);
1485  } else if (moveResult.shapeToUpdate.size() > 0) {
1486  moveJunctionGeometry(moveResult.shapeToUpdate.front(), false);
1487  }
1488  updateGeometry();
1489 }
1490 
1491 
1492 void
1494  // make sure that newShape isn't empty
1495  if (moveResult.shapeToUpdate.size() > 0) {
1496  // check if we're editing a shape
1497  if (isShapeEdited()) {
1498  // commit new shape
1499  undoList->p_begin("moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
1500  undoList->p_add(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(moveResult.shapeToUpdate)));
1501  undoList->p_end();
1503  undoList->p_begin("position of " + getTagStr());
1504  undoList->p_add(new GNEChange_Attribute(this, SUMO_ATTR_POSITION, toString(moveResult.shapeToUpdate.front())));
1505  undoList->p_end();
1506  }
1507  }
1508 }
1509 
1510 
1511 double
1512 GNEJunction::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
1513  switch (activeScheme) {
1514  case 0:
1516  return 3;
1517  } else {
1518  return 0;
1519  }
1520  case 1:
1521  return isAttributeCarrierSelected();
1522  case 2:
1523  switch (myNBNode->getType()) {
1525  return 0;
1527  return 1;
1529  return 2;
1531  return 3;
1533  return 4;
1535  return 5;
1537  return 6;
1539  return 7;
1542  return 8;
1544  return 8; // may happen before first network computation
1546  assert(false);
1547  return 8;
1549  return 9;
1551  return 10;
1553  return 11;
1555  return 12;
1556  default:
1557  assert(false);
1558  return 0;
1559  }
1560  case 3:
1561  return myNBNode->getPosition().z();
1562  default:
1563  assert(false);
1564  return 0;
1565  }
1566 }
1567 
1568 void
1570  for (auto edge : myGNEIncomingEdges) {
1571  if (edge->getGNEConnections().size() > 0) {
1573  return;
1574  }
1575  }
1576  // no connections. Use normal color for border edges and cul-de-sac
1577  if (myGNEIncomingEdges.size() == 0 || myGNEOutgoingEdges.size() == 0) {
1579  return;
1580  } else if (myGNEIncomingEdges.size() == 1 && myGNEOutgoingEdges.size() == 1) {
1581  NBEdge* in = myGNEIncomingEdges[0]->getNBEdge();
1582  NBEdge* out = myGNEOutgoingEdges[0]->getNBEdge();
1583  if (in->isTurningDirectionAt(out)) {
1585  return;
1586  }
1587  }
1589 }
1590 
1591 
1592 void
1593 GNEJunction::moveJunctionGeometry(const Position& pos, const bool updateEdgeBoundaries) {
1594  // obtain NBNode position
1595  const Position orig = myNBNode->getPosition();
1596  // reinit NBNode
1597  myNBNode->reinit(pos, myNBNode->getType());
1598  // set new position of adjacent edges
1599  for (const auto& edge : getNBNode()->getEdges()) {
1600  myNet->retrieveEdge(edge->getID())->updateJunctionPosition(this, orig);
1601  }
1602  // declare three sets with all affected GNEJunctions, GNEEdges and GNEConnections
1603  std::set<GNEJunction*> affectedJunctions;
1604  std::set<GNEEdge*> affectedEdges;
1605  // Iterate over GNEEdges
1606  for (const auto& edge : getChildEdges()) {
1607  // Add source and destiny junctions
1608  affectedJunctions.insert(edge->getParentJunctions().front());
1609  affectedJunctions.insert(edge->getParentJunctions().back());
1610  // Obtain neighbors of Junction source
1611  for (const auto& junctionSourceEdge : edge->getParentJunctions().front()->getChildEdges()) {
1612  affectedEdges.insert(junctionSourceEdge);
1613  }
1614  // Obtain neighbors of Junction destiny
1615  for (const auto& junctionDestinyEdge : edge->getParentJunctions().back()->getChildEdges()) {
1616  affectedEdges.insert(junctionDestinyEdge);
1617  }
1618  }
1619  // Iterate over affected Edges
1620  for (const auto& affectedEdge : affectedEdges) {
1621  // update edge boundaries
1622  if (updateEdgeBoundaries) {
1623  affectedEdge->updateCenteringBoundary(true);
1624  }
1625  // Update edge geometry
1626  affectedEdge->updateGeometry();
1627  }
1628 }
1629 
1630 
1631 RGBColor
1632 GNEJunction::setColor(const GUIVisualizationSettings& s, bool bubble) const {
1633  // get active scheme
1634  const int scheme = s.junctionColorer.getActive();
1635  // first check if we're editing shape
1636  if (myShapeEdited) {
1637  return s.colorSettings.editShape;
1638  }
1639  // set default color
1640  RGBColor color = s.junctionColorer.getScheme().getColor(getColorValue(s, scheme));
1641  // set special bubble color
1642  if (bubble && (scheme == 0) && !myColorForMissingConnections) {
1643  color = s.junctionColorer.getScheme().getColor(1);
1644  }
1645  // override with special colors (unless the color scheme is based on selection)
1646  if (drawUsingSelectColor() && scheme != 1) {
1647  color = s.colorSettings.selectionColor;
1648  }
1649  // set special color if we're creating a new edge
1650  if (myAmCreateEdgeSource) {
1651  color = RGBColor::GREEN;
1652  }
1653  // overwritte color if we're in data mode
1655  color = s.junctionColorer.getScheme().getColor(6);
1656  }
1657  // return color
1658  return color;
1659 }
1660 
1661 
1662 void
1665  tlCont.insert(tlDef, forceInsert); // may return false for tlDef which controls multiple junctions
1666  tlDef->addNode(myNBNode);
1667 }
1668 
1669 
1670 void
1673  if (tlDef->getNodes().size() == 1) {
1674  tlCont.extract(tlDef);
1675  }
1676  myNBNode->removeTrafficLight(tlDef);
1677 }
1678 
1679 
1680 /****************************************************************************/
@ NETWORK_CREATE_EDGE
mode for creating new edges
@ NETWORK_TLS
mode for editing tls
@ NETWORK_CONNECT
mode for connecting lanes
@ MID_GNE_JUNCTION_CLEAR_CONNECTIONS
clear junction's connections
Definition: GUIAppEnum.h:981
@ MID_GNE_JUNCTION_SELECT_ROUNDABOUT
select all roundabout nodes and edges of the current roundabout
Definition: GUIAppEnum.h:995
@ MID_GNE_JUNCTION_RESET_SHAPE
reset junction shape
Definition: GUIAppEnum.h:993
@ MID_GNE_JUNCTION_RESET_CONNECTIONS
reset junction's connections
Definition: GUIAppEnum.h:983
@ MID_GNE_JUNCTION_SPLIT
turn junction into multiple junctions
Definition: GUIAppEnum.h:987
@ MID_GNE_JUNCTION_REPLACE
turn junction into geometry node
Definition: GUIAppEnum.h:985
@ MID_GNE_JUNCTION_CONVERT_ROUNDABOUT
convert junction to roundabout
Definition: GUIAppEnum.h:997
@ MID_GNE_JUNCTION_SPLIT_RECONNECT
turn junction into multiple junctions and reconnect them heuristically
Definition: GUIAppEnum.h:989
@ MID_GNE_JUNCTION_EDIT_SHAPE
edit junction shape
Definition: GUIAppEnum.h:991
@ GLO_TEMPORALSHAPE
temporal shape (used in NETEDIT)
@ GLO_MAX
empty max
@ GLO_JUNCTION
a junction
@ GNETEXTURE_TLS
Definition: GUITextures.h:44
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:286
#define WRITE_GLDEBUG(msg)
Definition: MsgHandler.h:287
std::set< NBEdge * > EdgeSet
container for unique edges
Definition: NBCont.h:49
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:34
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ SUMO_TAG_TRAFFIC_LIGHT
a traffic light
@ SUMO_TAG_EDGE
begin/end of the description of an edge
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_TLLINKINDEX2
link: the index of the opposite direction link of a pedestrian crossing
@ SUMO_ATTR_RADIUS
The turning radius at an intersection in m.
@ SUMO_ATTR_TLLAYOUT
node: the layout of the traffic light program
@ GNE_ATTR_SELECTED
element is selected
@ SUMO_ATTR_EDGES
the edges of a route
@ GNE_ATTR_PARAMETERS
parameters "key1=value1|key2=value2|...|keyN=valueN"
@ SUMO_ATTR_FRINGE
Fringe type of node.
@ GNE_ATTR_MODIFICATION_STATUS
whether a feature has been loaded,guessed,modified or approved
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_TLTYPE
node: the type of traffic light
@ SUMO_ATTR_NAME
@ SUMO_ATTR_TLID
link,node: the traffic light id responsible for this link
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_RIGHT_OF_WAY
How to compute right of way.
@ SUMO_ATTR_TLLINKINDEX
link: the index of the link within the traffic light
@ SUMO_ATTR_KEEP_CLEAR
Whether vehicles must keep the junction clear.
@ SUMO_ATTR_POSITION
T MAX2(T a, T b)
Definition: StdDefs.h:79
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:250
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:299
static void drawFilledPoly(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:81
static void drawBoundary(const Boundary &b)
Draw a boundary (used for debugging)
Definition: GLHelper.cpp:647
static void drawFilledPolyTesselated(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:100
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:446
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:347
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition: GLHelper.cpp:135
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition: GLHelper.cpp:498
static void drawTextSettings(const GUIVisualizationTextSettings &settings, const std::string &text, const Position &pos, const double scale, const double angle=0, const double layer=2048, const int align=0)
Definition: GLHelper.cpp:529
An Element which don't belongs to GNENet but has influency in the simulation.
Definition: GNEAdditional.h:47
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
friend class GNEChange_Attribute
declare friend class
const std::string & getTagStr() const
get tag assigned to this object in string format
static const std::string FEATURE_GUESSED
feature has been reguessed (may still be unchanged be we can't tell (yet)
const GNETagProperties & getTagProperty() const
get Tag Property assigned to this object
void unselectAttributeCarrier(const bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
GNENet * myNet
pointer to net
void selectAttributeCarrier(const bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
static const std::string FEATURE_MODIFIED
feature has been manually modified (implies approval)
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
Definition: GNECrossing.h:41
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
void updateGeometry()
update pre-computed geometry information
Definition: GNECrossing.cpp:64
An Element which don't belongs to GNENet but has influency in the simulation.
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:49
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition: GNEEdge.cpp:399
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:723
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition: GNEEdge.cpp:290
An Element which don't belongs to GNENet but has influency in the simulation.
class for NETEDIT geometries over lanes
Definition: GNEGeometry.h:76
void updateGeometry(const PositionVector &shape, double startPos=-1, double endPos=-1, const Position &extraFirstPosition=Position::INVALID, const Position &extraLastPosition=Position::INVALID)
update geometry shape
Definition: GNEGeometry.cpp:81
const std::vector< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
const std::vector< GNEEdge * > & getChildEdges() const
get child edges
void removeTLSConnections(std::vector< NBConnection > &connections, GNEUndoList *undoList)
remove the given connections from all traffic light definitions of this junction
void markAsCreateEdgeSource()
marks as first junction in createEdge-mode
void addTrafficLight(NBTrafficLightDefinition *tlDef, bool forceInsert)
adds a traffic light
std::map< SumoXMLTag, std::vector< GNEAdditional * > > myPathAdditionalElements
map with references to path additional elements
Definition: GNEJunction.h:262
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
void updateGeometryAfterNetbuild(bool rebuildNBNodeCrossings=false)
update pre-computed geometry information without modifying netbuild structures
Definition: GNEJunction.cpp:98
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition: GNEJunction.h:281
void addPathGenericData(GNEGenericData *genericData)
add path demand element (used by GNEPathElement)
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList)
remove geometry point in the clicked position
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
friend class GNEChange_TLS
Declare friend class.
Definition: GNEJunction.h:48
std::string getAttribute(SumoXMLAttr key) const
void setResponsible(bool newVal)
set responsibility for deleting internal strctures
bool myColorForMissingConnections
whether this junction probably should have some connections but doesn't
Definition: GNEJunction.h:290
GNEJunction(GNENet *net, NBNode *nbn, bool loaded=false)
Constructor.
Definition: GNEJunction.cpp:50
void unMarkAsCreateEdgeSource()
removes mark as first junction in createEdge-mode
const std::map< std::string, std::string > & getACParametersMap() const
get parameters map
std::map< SumoXMLTag, std::vector< GNEDemandElement * > > myPathDemandElements
map with references to path demand elements
Definition: GNEJunction.h:265
void moveJunctionGeometry(const Position &pos, const bool updateEdgeBoundaries)
reposition the node at pos without updating GRID and informs the edges
void invalidateShape()
void updateGeometry()
update pre-computed geometry information (including crossings)
Definition: GNEJunction.cpp:92
void removePathDemandElement(GNEDemandElement *demandElement)
remove path demand element (used by GNEPathElement)
bool isLogicValid()
whether this junction has a valid logic
void drawTLSIcon(const GUIVisualizationSettings &s) const
draw TLS icon
std::vector< GNEEdge * > myGNEOutgoingEdges
vector with the (child) outgoings GNEEdges vinculated with this junction
Definition: GNEJunction.h:256
std::map< SumoXMLTag, std::vector< GNEGenericData * > > myPathGenericDatas
map with references to path generic data elements
Definition: GNEJunction.h:268
void removePathAdditionalElement(GNEAdditional *additionalElement)
remove path additional element (used by GNEPathElement)
double getColorValue(const GUIVisualizationSettings &s, int activeScheme) const
determines color value
void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)
commit move shape
void drawJunctionChildren(const GUIVisualizationSettings &s) const
draw junction childs
void selectTLS(bool selected)
notify the junction of being selected in tls-mode. (used to control drawing)
void addPathAdditionalElement(GNEAdditional *additionalElement)
add path additional element (used by GNEPathElement)
void replaceIncomingConnections(GNEEdge *which, GNEEdge *by, GNEUndoList *undoList)
replace one edge by another in all tls connections
void removeOutgoingGNEEdge(GNEEdge *edge)
remove outgoing GNEEdge
void markAsModified(GNEUndoList *undoList)
prevent re-guessing connections at this junction
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
std::vector< GNECrossing * > myGNECrossings
the built crossing objects
Definition: GNEJunction.h:259
void invalidateTLS(GNEUndoList *undoList, const NBConnection &deletedConnection=NBConnection::InvalidConnection, const NBConnection &addedConnection=NBConnection::InvalidConnection)
void removeIncomingGNEEdge(GNEEdge *edge)
remove incoming GNEEdge
std::vector< GNEConnection * > getGNEConnections() const
Returns all GNEConnections vinculated with this junction.
void invalidatePathElements()
invalidate path element childs
GNECrossing * retrieveGNECrossing(NBNode::Crossing *NBNodeCrossing, bool createIfNoExist=true)
get GNECrossing if exist, and if not create it if create is enabled
std::vector< GNEEdge * > myGNEIncomingEdges
vector with the (child) incomings GNEEdges vinculated with this junction
Definition: GNEJunction.h:253
const PositionVector & getJunctionShape() const
Definition: GNEJunction.cpp:86
void setMoveShape(const GNEMoveResult &moveResult)
set move shape
void markConnectionsDeprecated(bool includingNeighbours)
mark connections as deprecated
void mirrorXLeftHand()
temporarily mirror coordinates in lefthand network to compute correct crossing geometries
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
double myMaxDrawingSize
The maximum size (in either x-, or y-dimension) for determining whether to draw or not.
Definition: GNEJunction.h:271
Position getPositionInView() const
Returns position of hierarchical element in view.
void removePathGenericData(GNEGenericData *genericData)
remove path demand element (used by GNEPathElement)
bool myAmTLSSelected
whether this junction is selected in tls-mode
Definition: GNEJunction.h:287
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)
void addIncomingGNEEdge(GNEEdge *edge)
add incoming GNEEdge
RGBColor setColor(const GUIVisualizationSettings &s, bool bubble) const
sets junction color depending on circumstances
bool myHasValidLogic
whether this junctions logic is valid
Definition: GNEJunction.h:284
std::string myLogicStatus
modification status of the junction logic (all connections across this junction)
Definition: GNEJunction.h:278
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
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.
void addPathDemandElement(GNEDemandElement *demandElement)
add path demand element (used by GNEPathElement)
NBNode * myNBNode
A reference to the represented junction.
Definition: GNEJunction.h:250
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
void checkMissingConnections()
compute whether this junction probably should have some connections but doesn't
std::vector< GNEJunction * > getJunctionNeighbours() const
return GNEJunction neighbours
GNEMoveOperation * getMoveOperation(const double shapeOffset)
get move operation for the given shapeOffset
~GNEJunction()
Destructor.
Definition: GNEJunction.cpp:66
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
bool myAmCreateEdgeSource
whether this junction is the first junction for a newly creatededge
Definition: GNEJunction.h:275
void addOutgoingGNEEdge(GNEEdge *edge)
add outgoing GNEEdge
void rebuildGNECrossings(bool rebuildNBNodeCrossings=true)
rebuilds crossing objects for this junction
bool isAttributeEnabled(SumoXMLAttr key) const
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
removes a traffic light
move operation
move result
PositionVector shapeToUpdate
shape to update (edited in moveElement)
void updateID(GNEAttributeCarrier *AC, const std::string newID)
update ID
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:40
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:509
NBNetBuilder * getNetBuilder() const
get net builder
Definition: GNENet.cpp:1738
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1411
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1423
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:2282
GNEEdge * retrieveEdge(const std::string &id, bool failHard=true) const
get edge by id
Definition: GNENet.cpp:1141
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
retrieve all attribute carriers of Net
Definition: GNENet.cpp:130
std::vector< GNEJunction * > retrieveJunctions(bool onlySelected=false)
return all junctions
Definition: GNENet.cpp:1370
void requireRecompute()
inform the net about the need for recomputation
Definition: GNENet.cpp:1709
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition: GNENet.cpp:2294
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:2245
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true) const
get junction by id
Definition: GNENet.cpp:1113
bool myShapeEdited
flag to check if element shape is being edited
bool isShapeEdited() const
check if shape is being edited
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
const std::string & getID() const
get ID
Boundary myBoundary
object boundary
void drawJunctionPathChildren(const GUIVisualizationSettings &s, const GNEJunction *junction, const double offset) const
draw junction path child
void incRef(const std::string &debugMsg="")
Increarse reference.
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
bool hasCommandGroup() const
Check if undoList has command group.
void p_add(GNEChange_Attribute *cmd)
special method, avoid empty changes, always execute
void p_begin(const std::string &description)
Begin undo command sub-group. This begins a new group of commands that are treated as a single comman...
Definition: GNEUndoList.cpp:71
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
Definition: GNEUndoList.cpp:78
GNEJunction * getJunctionFront() const
get front junction or a pointer to nullptr
const GNEAttributeCarrier * getFrontAttributeCarrier() const
get front attributeCarrier
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:467
bool showJunctionAsBubbles() const
return true if junction must be showed as bubbles
Definition: GNEViewNet.cpp:599
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
Definition: GNEViewNet.cpp:479
bool mergeJunctions(GNEJunction *movedJunction, GNEJunction *targetJunction)
try to merge moved junction with another junction in that spot return true if merging did take place
Definition: GNEViewNet.cpp:605
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:368
bool isAttributeCarrierInspected(const GNEAttributeCarrier *AC) const
check if attribute carrier is being inspected
void drawTranslateFrontAttributeCarrier(const GNEAttributeCarrier *AC, GUIGlObjectType objectType, const double extraOffset=0)
draw front attributeCarrier
const GNEViewNetHelper::ObjectsUnderCursor & getObjectsUnderCursor() const
get objects under cursor
Definition: GNEViewNet.cpp:362
static FXMenuCommand * buildFXMenuCommand(FXComposite *p, const std::string &text, FXIcon *icon, FXObject *tgt, FXSelector sel)
build menu command
Definition: GUIDesigns.cpp:40
The popup menu of a globject.
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to copy the cursor position if geo projection is used,...
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
GUIGlID getGlID() const
Returns the numerical id of the object.
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0) const
draw name of item
const T getColor(const double value) const
GUIVisualizationSettings & getVisualisationSettings() const
get visualization settings
Position getPositionInformation() const
Returns the cursor's x/y position within the network.
static GUIGlID getTexture(GUITexture which)
returns a texture previously defined in the enum GUITexture
static void drawTexturedBox(int which, double size)
Draws a named texture as a box with the given size.
Stores the information about how to visualize structures.
GUIVisualizationTextSettings junctionName
GUIVisualizationSizeSettings junctionSize
bool drawBoundaries
enable or disable draw boundaries
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
bool drawJunctionShape
whether the shape of the junction should be drawn
bool drawForPositionSelection
whether drawing is performed for the purpose of selecting objects with a single click
GUIVisualizationTextSettings junctionID
bool drawDottedContour() const
check if dotted contour can be drawn
bool drawMovingGeometryPoint(const double exaggeration, const double radius) const
check if moving geometry point can be draw
GUIVisualizationColorSettings colorSettings
color settings
double scale
information about a lane's width (temporary, used for a single view)
int getCircleResolution() const
function to calculate circle resolution for all circles drawn in drawGL(...) functions
GUIColorer junctionColorer
The junction colorer.
GUIVisualizationNeteditSizeSettings neteditSizeSettings
netedit size settings
double angle
The current view rotation angle.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
int getFromLane() const
returns the from-lane
int getTLIndex2() const
Definition: NBConnection.h:94
int getTLIndex() const
returns the index within the controlling tls or InvalidTLIndex if this link is unontrolled
Definition: NBConnection.h:91
static const int InvalidTlIndex
Definition: NBConnection.h:123
int getToLane() const
returns the to-lane
NBEdge * getTo() const
returns the to-edge (end of the connection)
static const NBConnection InvalidConnection
Definition: NBConnection.h:124
void removeRoundabout(const NBNode *node)
remove roundabout that contains the given node
The representation of a single edge during network building.
Definition: NBEdge.h:91
const std::string & getID() const
Definition: NBEdge.h:1423
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:3006
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3336
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:964
A loaded (complete) traffic light logic.
void removeConnection(const NBConnection &conn, bool reconstruct=true)
removes the given connection from the traffic light if recontruct=true, reconstructs the logic and in...
void joinLogic(NBTrafficLightDefinition *def)
join nodes and states from the given logic (append red state)
void addConnection(NBEdge *from, NBEdge *to, int fromLane, int toLane, int linkIndex, int linkIndex2, bool reconstruct=true)
Adds a connection and immediately informs the edges.
void guessMinMaxDuration()
heuristically add minDur and maxDur when switching from tlType fixed to actuated
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane, bool incoming)
Replaces a removed edge/lane.
NBTrafficLightLogic * getLogic()
Returns the internal logic.
bool haveNetworkCrossings()
notify about style of loaded network (Without Crossings)
Definition: NBNetBuilder.h:193
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:148
A definition of a pedestrian crossing.
Definition: NBNode.h:129
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:136
Represents a single node (junction) during network building.
Definition: NBNode.h:66
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
Definition: NBNode.h:286
Position getCenter() const
Returns a position that is guaranteed to lie within the node shape.
Definition: NBNode.cpp:3348
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition: NBNode.cpp:306
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition: NBNode.h:207
void invalidateIncomingConnections()
invalidate incoming connections
Definition: NBNode.cpp:1783
FringeType getFringeType() const
Returns fringe type.
Definition: NBNode.h:291
void buildCrossingsAndWalkingAreas()
build crossings, and walkingareas. Also removes invalid loaded crossings if wished
Definition: NBNode.cpp:2560
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:271
const std::string & getName() const
Returns intersection name.
Definition: NBNode.h:296
void setRightOfWay(RightOfWay rightOfWay)
set method for computing right-of-way
Definition: NBNode.h:538
void setCustomShape(const PositionVector &shape)
set the junction shape
Definition: NBNode.cpp:2291
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
Definition: NBNode.cpp:3424
void mirrorX()
mirror coordinates along the x-axis
Definition: NBNode.cpp:345
std::vector< std::pair< Position, std::string > > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
Definition: NBNode.cpp:3527
const std::vector< std::unique_ptr< Crossing > > & getCrossingsIncludingInvalid() const
Definition: NBNode.h:702
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:259
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
Definition: NBNode.h:264
bool hasCustomShape() const
return whether the shape was set by the user
Definition: NBNode.h:553
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:254
void setRadius(double radius)
set the turning radius
Definition: NBNode.h:528
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
Definition: NBNode.h:322
void setName(const std::string &name)
set intersection name
Definition: NBNode.h:548
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:374
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:2285
const Position & getPosition() const
Definition: NBNode.h:246
double getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:276
bool isRoundabout() const
return whether this node is part of a roundabout
Definition: NBNode.cpp:3234
bool checkIsRemovableReporting(std::string &reason) const
check if node is removable and return reason if not
Definition: NBNode.cpp:2195
PositionVector myPoly
the (outer) shape of the junction
Definition: NBNode.h:879
void setFringeType(FringeType fringeType)
set method for computing right-of-way
Definition: NBNode.h:543
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:317
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:44
void setLayout(TrafficLightLayout layout)
sets the layout for the generated signal plan
Definition: NBOwnTLDef.h:137
The base class for traffic light logic definitions.
const std::string & getProgramID() const
Returns the ProgramID.
TrafficLightType getType() const
get the algorithm type (static etc..)
virtual void setProgramID(const std::string &programID)
Sets the programID.
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
SUMOTime getOffset()
Returns the offset.
A container for traffic light definitions and built programs.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
void extract(NBTrafficLightDefinition *definition)
Extracts a traffic light definition from myDefinitions but keeps it in myExtracted for eventual * del...
A SUMO-compliant built logic for a traffic light.
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any)
virtual void setID(const std::string &newID)
resets the id
Definition: Named.h:81
const std::string & getID() const
Returns the id.
Definition: Named.h:73
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
static bool areParametersValid(const std::string &value, bool report=false, ParameterisedAttrType attrType=ParameterisedAttrType::STRING, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to a parameters map "key1=value1|key2=value2|....
void setParametersStr(const std::string &paramsString, const std::string kvsep="=", const std::string sep="|")
set the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN"
std::string getParametersStr(const std::string kvsep="=", const std::string sep="|") const
Returns the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN".
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value map.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition: Position.h:246
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:282
double x() const
Returns the x-position.
Definition: Position.h:54
double z() const
Returns the z-position.
Definition: Position.h:64
double y() const
Returns the y-position.
Definition: Position.h:59
A list of positions.
void closePolygon()
ensures that the last position equals the first
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
int insertAtClosest(const Position &p, bool interpolateZ)
inserts p between the two closest positions
int indexOfClosest(const Position &p) const
index of the closest position to p
void scaleRelative(double factor)
enlarges/shrinks the polygon by a factor based at the centroid
double area() const
Returns the area (0 for non-closed)
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point.
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition: RGBColor.h:73
static const RGBColor GREEN
Definition: RGBColor.h:181
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:145
static StringBijection< SumoXMLNodeType > NodeTypes
node types
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
static StringBijection< TrafficLightLayout > TrafficLightLayouts
traffic light layouts
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
static StringBijection< RightOfWay > RightOfWayValues
righ of way algorithms
static StringBijection< FringeType > FringeTypeValues
fringe types
bool hasString(const std::string &str) const
const std::string & getString(const T key) const
T get(const std::string &str) const
static void drawDottedContourClosedShape(const DottedContourType type, const GUIVisualizationSettings &s, const PositionVector &shape, const double exaggeration)
draw dotted contour for the given closed shape (used by Juctions, shapes and TAZs)
static void drawGeometryPoints(const GUIVisualizationSettings &s, const GNEViewNet *viewNet, const PositionVector &shape, const RGBColor &geometryPointColor, const RGBColor &textColor, const double radius, const double exaggeration)
draw geometry points
static void drawGeometry(const GNEViewNet *viewNet, const Geometry &geometry, const double width)
draw geometry
static void drawMovingHint(const GUIVisualizationSettings &s, const GNEViewNet *viewNet, const PositionVector &shape, const RGBColor &hintColor, const double radius, const double exaggeration)
draw moving hint
static void drawDottedContourCircle(const DottedContourType type, const GUIVisualizationSettings &s, const Position &pos, const double radius, const double exaggeration)
draw dotted contour for the given Position and radius (used by Juctions and POIs)
NetworkEditMode networkEditMode
the current Network edit mode
bool isCurrentSupermodeData() const
@check if current supermode is Data
bool isCurrentSupermodeNetwork() const
@check if current supermode is Network
bool editingElevation() const
check if we're editing elevation
RGBColor selectionColor
basic selection color
static const RGBColor editShape
color for edited shapes (Junctions, crossings and connections)
static const double junctionGeometryPointRadius
moving junction geometry point radius
static const double junctionBubbleRadius
junction buuble radius
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
double scaledSize(double scale, double constFactor=0.1) const
get scale size
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:188