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-2022 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  // check if remove it from Attribute Carriers
72  if (myNet->getAttributeCarriers()->getCrossings().count(crossing) > 0) {
74  }
75  // show extra information for tests
76  WRITE_DEBUG("Deleting unreferenced " + crossing->getTagStr() + " '" + crossing->getID() + "' in GNEJunction destructor");
77  delete crossing;
78  }
79  }
80  if (myAmResponsible) {
81  // show extra information for tests
82  WRITE_DEBUG("Deleting NBNode of '" + getID() + "' in GNEJunction destructor");
83  delete myNBNode;
84  }
85 }
86 
87 
88 const PositionVector&
90  return myNBNode->getShape();
91 }
92 
93 
94 void
97 }
98 
99 
100 void
101 GNEJunction::updateGeometryAfterNetbuild(bool rebuildNBNodeCrossings) {
102  // recalc max drawing size
103  myMaxDrawingSize = MAX2(getCenteringBoundary().getWidth(), getCenteringBoundary().getHeight());
104  rebuildGNECrossings(rebuildNBNodeCrossings);
106 }
107 
108 
109 Position
111  return myNBNode->getPosition();
112 }
113 
114 
117  // edit depending if shape is being edited
118  if (isShapeEdited()) {
119  // calculate move shape operation
122  } else {
123  // return move junction position
124  return new GNEMoveOperation(this, myNBNode->getPosition());
125  }
126 }
127 
128 
129 void
130 GNEJunction::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
131  // edit depending if shape is being edited
132  if (isShapeEdited()) {
133  // get original shape
134  PositionVector shape = myNBNode->getShape();
135  // check shape size
136  if (shape.size() > 2) {
137  // obtain index
138  int index = shape.indexOfClosest(clickedPosition);
139  // get snap radius
141  // check if we have to create a new index
142  if ((index != -1) && shape[index].distanceSquaredTo2D(clickedPosition) < (snap_radius * snap_radius)) {
143  // remove geometry point
144  shape.erase(shape.begin() + index);
145  // commit new shape
146  undoList->begin(GUIIcon::JUNCTION, "remove geometry point of " + getTagStr());
147  undoList->changeAttribute(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(shape)));
148  undoList->end();
149  }
150  }
151  }
152 }
153 
154 
155 void
156 GNEJunction::rebuildGNECrossings(bool rebuildNBNodeCrossings) {
157  // rebuild GNECrossings only if create crossings and walkingAreas in net is enabled
159  if (rebuildNBNodeCrossings) {
160  // build new NBNode::Crossings and walking areas
161  mirrorXLeftHand();
163  mirrorXLeftHand();
164  }
165  // create a vector to keep retrieved and created crossings
166  std::vector<GNECrossing*> retrievedCrossings;
167  // iterate over NBNode::Crossings of GNEJunction
168  for (const auto& crossing : myNBNode->getCrossingsIncludingInvalid()) {
169  // retrieve existent GNECrossing, or create it
170  GNECrossing* retrievedGNECrossing = retrieveGNECrossing(crossing.get());
171  retrievedCrossings.push_back(retrievedGNECrossing);
172  // check if previously this GNECrossings exists, and if true, remove it from myGNECrossings and insert in tree again
173  std::vector<GNECrossing*>::iterator retrievedExists = std::find(myGNECrossings.begin(), myGNECrossings.end(), retrievedGNECrossing);
174  if (retrievedExists != myGNECrossings.end()) {
175  myGNECrossings.erase(retrievedExists);
176  // update geometry of retrieved crossing
177  retrievedGNECrossing->updateGeometry();
178  // update boundary
179  retrievedGNECrossing->updateCenteringBoundary(false);
180  } else {
181  // include reference to created GNECrossing
182  retrievedGNECrossing->incRef();
183  }
184  }
185  // delete non retrieved GNECrossings (we don't need to extract if from Tree two times)
186  for (const auto& crossing : myGNECrossings) {
187  crossing->decRef();
188  // check if crossing is selected
189  if (crossing->isAttributeCarrierSelected()) {
190  crossing->unselectAttributeCarrier();
191  }
192  // remove it from inspected ACS
194  // remove it from net
195  myNet->removeGLObjectFromGrid(crossing);
196  // remove it from attributeCarriers
198  if (crossing->unreferenced()) {
199  // show extra information for tests
200  WRITE_DEBUG("Deleting unreferenced " + crossing->getTagStr() + " in rebuildGNECrossings()");
201  delete crossing;
202  }
203  }
204  // copy retrieved (existent and created) GNECrossigns to myGNECrossings
205  myGNECrossings = retrievedCrossings;
206  }
207 }
208 
209 void
211  if (OptionsCont::getOptions().getBool("lefthand")) {
212  myNBNode->mirrorX();
213  for (NBEdge* e : myNBNode->getEdges()) {
214  e->mirrorX();
215 
216  }
217  }
218 }
219 
220 
223  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
224  buildPopupHeader(ret, app);
227  // build selection and show parameters menu
230  buildPositionCopyEntry(ret, false);
231  // check if we're in supermode network
233  //if (parent.getVisualisationSettings()->editMode != GNE_MODE_CONNECT) {
234  // // XXX if joinable
235  // GUIDesigns::buildFXMenuCommand(ret, "Join adjacent edges", 0, &parent, MID_GNE_JOIN_EDGES);
236  //}
237  const int numSelectedJunctions = myNet->getAttributeCarriers()->getNumberOfSelectedJunctions();
238  const int numEndpoints = (int)myNBNode->getEndPoints().size();
239  // check if we're handling a selection
240  bool handlingSelection = isAttributeCarrierSelected() && (numSelectedJunctions > 1);
241  // check if menu commands has to be disabled
245  // create menu commands
246  FXMenuCommand* mcCustomShape = GUIDesigns::buildFXMenuCommand(ret, "Set custom junction shape", nullptr, &parent, MID_GNE_JUNCTION_EDIT_SHAPE);
247  FXMenuCommand* mcResetCustomShape = GUIDesigns::buildFXMenuCommand(ret, "Reset junction shape", nullptr, &parent, MID_GNE_JUNCTION_RESET_SHAPE);
248  FXMenuCommand* mcReplace = GUIDesigns::buildFXMenuCommand(ret, "Replace junction by geometry point", nullptr, &parent, MID_GNE_JUNCTION_REPLACE);
249  FXMenuCommand* mcSplit = GUIDesigns::buildFXMenuCommand(ret, "Split junction (" + toString(numEndpoints) + " end points)", nullptr, &parent, MID_GNE_JUNCTION_SPLIT);
250  FXMenuCommand* mcSplitReconnect = GUIDesigns::buildFXMenuCommand(ret, "Split junction and reconnect", nullptr, &parent, MID_GNE_JUNCTION_SPLIT_RECONNECT);
251  if (myNBNode->isRoundabout()) {
252  GUIDesigns::buildFXMenuCommand(ret, "Select roundabout", nullptr, &parent, MID_GNE_JUNCTION_SELECT_ROUNDABOUT);
253  } else {
254  double radius = myNBNode->getRadius();
255  if (radius == NBNode::UNSPECIFIED_RADIUS) {
256  radius = OptionsCont::getOptions().getFloat("default.junctions.radius");
257  }
258  const std::string menuEntry = "Convert to roundabout (using junction radius " + toString(radius) + ")";
259  FXMenuCommand* mcRoundabout = GUIDesigns::buildFXMenuCommand(ret, menuEntry.c_str(), nullptr, &parent, MID_GNE_JUNCTION_CONVERT_ROUNDABOUT);
260  if (getChildEdges().size() < 2 ||
261  (myGNEIncomingEdges.size() == 1
262  && myGNEOutgoingEdges.size() == 1
263  && myGNEIncomingEdges[0]->getFromJunction() == myGNEOutgoingEdges[0]->getToJunction())) {
264  mcRoundabout->disable();
265  }
266  }
267  std::string multi;
268  if ((numSelectedJunctions > 1) && isAttributeCarrierSelected()) {
269  multi = " of " + toString(numSelectedJunctions) + " junctions";
270  }
271  FXMenuCommand* mcClearConnections = GUIDesigns::buildFXMenuCommand(ret, "Clear connections" + multi, nullptr, &parent, MID_GNE_JUNCTION_CLEAR_CONNECTIONS);
272  FXMenuCommand* mcResetConnections = GUIDesigns::buildFXMenuCommand(ret, "Reset connections" + multi, nullptr, &parent, MID_GNE_JUNCTION_RESET_CONNECTIONS);
273  // check if current mode is correct
274  if (wrongMode) {
275  mcCustomShape->disable();
276  mcClearConnections->disable();
277  mcResetConnections->disable();
278  }
279  // check if we're handling a selection
280  if (handlingSelection) {
281  mcResetCustomShape->setText("Reset junction shapes");
282  }
283  // disable mcClearConnections if juction hasn't connections
284  if (getGNEConnections().empty()) {
285  mcClearConnections->disable();
286  }
287  // disable mcResetCustomShape if junction doesn't have a custom shape
288  if (myNBNode->getShape().size() == 0) {
289  mcResetCustomShape->disable();
290  }
291  // checkIsRemovable requiers turnarounds to be computed. This is ugly
292  if ((myNBNode->getIncomingEdges().size() == 2) && (myNBNode->getOutgoingEdges().size() == 2)) {
294  }
295  std::string reason = "wrong edit mode";
296  if (wrongMode || !myNBNode->checkIsRemovableReporting(reason)) {
297  mcReplace->setText(mcReplace->getText() + " (" + reason.c_str() + ")");
298  mcReplace->disable();
299  }
300  if (numEndpoints == 1) {
301  mcSplit->disable();
302  mcSplitReconnect->disable();
303  }
304  }
305  return ret;
306 }
307 
308 
309 double
311  return s.junctionSize.getExaggeration(s, this, 4);
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  // check if draw start und end
346  const bool drawExtremeSymbols = myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork() &&
348  // declare variables
349  const Position mousePosition = myNet->getViewNet()->getPositionInformation();
350  const double junctionExaggeration = getExaggeration(s);
351  const double bubbleRadius = s.neteditSizeSettings.junctionBubbleRadius * junctionExaggeration;
352  // declare draw shape flag
353  const bool drawShape = (myNBNode->getShape().size() > 0) && s.drawJunctionShape;
354  // declare draw bubble flag
355  bool drawBubble = true;
356  if (!s.drawJunctionShape) {
357  // don't draw bubble if it was disabled in GUIVisualizationSettings
358  drawBubble = false;
359  }
360  if (myNBNode->getShape().area() > 4) {
361  // don't draw if shape area is greather than 4
362  drawBubble = false;
363  }
365  // only draw bubbles in network mode
366  drawBubble = false;
367  }
369  // force draw bubbles if we enabled option in checkbox of viewNet
370  drawBubble = true;
371  }
372  if ((myNBNode->getShape().area() < 4) && (mySourceCandidate || myTargetCandidate ||
374  // force draw if this junction is a candidate
375  drawBubble = true;
376  }
377  // only continue if exaggeration is greather than 0
378  if (junctionExaggeration > 0) {
379  // push junction name
381  // push layer matrix
383  // translate to front
384  if (myAmCreateEdgeSource) {
385  glTranslated(0, 0, GLO_TEMPORALSHAPE);
386  } else {
388  }
389  // push name
390  if (s.scale * junctionExaggeration * myMaxDrawingSize < 1.) {
391  // draw something simple so that selection still works
393  } else {
394  // check if shape has to be drawn
395  if (drawShape) {
396  // set shape color
397  const RGBColor junctionShapeColor = setColor(s, false);
398  // recognize full transparency and simply don't draw
399  if (junctionShapeColor.alpha() != 0) {
400  // set color
401  GLHelper::setColor(junctionShapeColor);
402  // obtain junction Shape
403  PositionVector junctionClosedShape = myNBNode->getShape();
404  // close junction shape
405  junctionClosedShape.closePolygon();
406  // adjust shape to exaggeration
407  if (junctionExaggeration > 1) {
408  junctionClosedShape.scaleRelative(junctionExaggeration);
409  }
410  // first check if inner junction polygon can be drawn
411  if (s.drawForPositionSelection) {
412  // only draw a point if mouse is around shape
413  if (junctionClosedShape.around(mousePosition)) {
414  // push matrix
416  // move to mouse position
417  glTranslated(mousePosition.x(), mousePosition.y(), 0.1);
418  // draw a simple circle
420  // pop matrix
422  }
423  } else if ((s.scale * junctionExaggeration * myMaxDrawingSize) < 40.) {
424  // draw shape
425  GLHelper::drawFilledPoly(junctionClosedShape, true);
426  } else {
427  // draw shape with high detail
428  GLHelper::drawFilledPolyTesselated(junctionClosedShape, true);
429  }
430  // draw shape points only in Network supemode
432  // set color
433  const RGBColor darkerColor = junctionShapeColor.changedBrightness(-32);
434  // calculate geometry
435  GUIGeometry junctionGeometry;
436  // obtain junction Shape
437  PositionVector junctionOpenShape = myNBNode->getShape();
438  // adjust shape to exaggeration
439  if (junctionExaggeration > 1) {
440  junctionOpenShape.scaleRelative(junctionExaggeration);
441  }
442  // update geometry
443  junctionGeometry.updateGeometry(junctionOpenShape);
444  // set color
445  GLHelper::setColor(darkerColor);
446  // draw shape
448  // draw geometry points
450  s.neteditSizeSettings.junctionGeometryPointRadius, junctionExaggeration,
451  myNet->getViewNet()->getNetworkViewOptions().editingElevation(), drawExtremeSymbols);
452  // draw moving hint
454  GUIGeometry::drawMovingHint(s, myNet->getViewNet()->getPositionInformation(), junctionOpenShape, darkerColor,
455  s.neteditSizeSettings.junctionGeometryPointRadius, junctionExaggeration);
456  }
457  }
458  }
459  }
460  // check if bubble has to be drawn
461  if (drawBubble) {
462  // set bubble color
463  const RGBColor bubbleColor = setColor(s, true);
464  // recognize full transparency and simply don't draw
465  if (bubbleColor.alpha() != 0) {
466  // check if mouse is in bubble
467  const bool mouseInBubble = (mousePosition.distanceSquaredTo2D(myNBNode->getPosition()) <= (bubbleRadius * bubbleRadius));
468  // only draw filled circle if we aren't in draw for selecting mode, or if distance to center is enough)
469  if (!s.drawForPositionSelection || mouseInBubble) {
470  // push matrix
472  // set color
473  GLHelper::setColor(bubbleColor);
474  // move matrix junction center
475  glTranslated(myNBNode->getPosition().x(), myNBNode->getPosition().y(), 0.1);
476  // draw filled circle
478  // pop matrix
480  }
481  }
482  }
483  // draw TLS
484  drawTLSIcon(s);
485  // draw elevation
488  // Translate to center of junction
489  glTranslated(myNBNode->getPosition().x(), myNBNode->getPosition().y(), 0.1);
490  // draw Z value
493  }
494  // pop layer Matrix
496  // pop junction name
498  // draw name and ID
499  if (!s.drawForRectangleSelection) {
501  if (s.junctionName.show(this) && myNBNode->getName() != "") {
503  }
504  }
505  // draw Junction childs
507  // draw path additional elements
509  // draw lock icon
511  // check if dotted contour has to be drawn
513  if (drawShape) {
515  (junctionExaggeration >= 1) ? junctionExaggeration : 1);
516  }
517  if (drawBubble) {
519  (junctionExaggeration >= 1) ? junctionExaggeration : 1);
520  }
521  }
522  // check if dotted contour has to be drawn
523  if ((myNet->getViewNet()->getFrontAttributeCarrier() == this)) {
524  if (drawShape) {
526  (junctionExaggeration >= 1) ? junctionExaggeration : 1);
527  }
528  if (drawBubble) {
530  (junctionExaggeration >= 1) ? junctionExaggeration : 1);
531  }
532  }
533  }
534  }
535 }
536 
537 
538 NBNode*
540  return myNBNode;
541 }
542 
543 
544 std::vector<GNEJunction*>
546  // use set to avoid duplicates junctions
547  std::set<GNEJunction*> junctions;
548  for (const auto& incomingEdge : myGNEIncomingEdges) {
549  junctions.insert(incomingEdge->getFromJunction());
550  }
551  for (const auto& outgoingEdge : myGNEOutgoingEdges) {
552  junctions.insert(outgoingEdge->getToJunction());
553  }
554  return std::vector<GNEJunction*>(junctions.begin(), junctions.end());
555 }
556 
557 
558 void
560  // Check if incoming edge was already inserted
561  std::vector<GNEEdge*>::iterator i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
562  if (i != myGNEIncomingEdges.end()) {
563  throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + getTagStr() + " with ID " + getID() + "'");
564  } else {
565  // Add edge into containers
566  myGNEIncomingEdges.push_back(edge);
567  }
568 }
569 
570 
571 
572 void
574  // Check if outgoing edge was already inserted
575  std::vector<GNEEdge*>::iterator i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
576  if (i != myGNEOutgoingEdges.end()) {
577  throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + getTagStr() + " with ID " + getID() + "'");
578  } else {
579  // Add edge into containers
580  myGNEOutgoingEdges.push_back(edge);
581  }
582 }
583 
584 
585 void
587  // Check if incoming edge was already inserted
588  std::vector<GNEEdge*>::iterator i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
589  if (i == myGNEIncomingEdges.end()) {
590  throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + getTagStr() + " with ID " + getID() + "'");
591  } else {
592  // remove edge from containers
593  myGNEIncomingEdges.erase(i);
594  }
595 }
596 
597 
598 void
600  // Check if outgoing edge was already inserted
601  std::vector<GNEEdge*>::iterator i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
602  if (i == myGNEOutgoingEdges.end()) {
603  throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + getTagStr() + " with ID " + getID() + "'");
604  } else {
605  // remove edge from containers
606  myGNEOutgoingEdges.erase(i);
607  }
608 }
609 
610 
611 const std::vector<GNEEdge*>&
613  return myGNEIncomingEdges;
614 }
615 
616 
617 const std::vector<GNEEdge*>&
619  return myGNEOutgoingEdges;
620 }
621 
622 
623 const std::vector<GNECrossing*>&
625  return myGNECrossings;
626 }
627 
628 
629 std::vector<GNEConnection*>
631  std::vector<GNEConnection*> connections;
632  for (const auto& i : myGNEIncomingEdges) {
633  for (const auto& j : i->getGNEConnections()) {
634  connections.push_back(j);
635  }
636  }
637  return connections;
638 }
639 
640 
641 void
643  myAmCreateEdgeSource = true;
644 }
645 
646 
647 void
649  myAmCreateEdgeSource = false;
650 }
651 
652 
653 void
654 GNEJunction::selectTLS(bool selected) {
655  myAmTLSSelected = selected;
656 }
657 
658 
659 void
661  if (!myNBNode->hasCustomShape()) {
662  if (myNBNode->myPoly.size() > 0) {
663  // write GL Debug
664  WRITE_GLDEBUG("<-- Invalidating shape of junction '" + getID() + "' -->");
665  // clear poly
666  myNBNode->myPoly.clear();
667  // update centering boundary
669  }
671  }
672 }
673 
674 
675 void
676 GNEJunction::setLogicValid(bool valid, GNEUndoList* undoList, const std::string& status) {
677  myHasValidLogic = valid;
678  if (!valid) {
679  assert(undoList != 0);
680  assert(undoList->hasCommandGroup());
682  EdgeVector incoming = myNBNode->getIncomingEdges();
683  for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
684  GNEEdge* srcEdge = myNet->getAttributeCarriers()->retrieveEdge((*it)->getID());
685  removeConnectionsFrom(srcEdge, undoList, false); // false, because the whole tls will be invalidated at the end
686  undoList->add(new GNEChange_Attribute(srcEdge, GNE_ATTR_MODIFICATION_STATUS, status), true);
687  }
688  undoList->add(new GNEChange_Attribute(this, GNE_ATTR_MODIFICATION_STATUS, status), true);
689  invalidateTLS(undoList);
690  } else {
691  // logic valed, then rebuild GNECrossings to adapt it to the new logic
692  // (but don't rebuild the crossings in NBNode because they are already finished)
693  rebuildGNECrossings(false);
694  }
695 }
696 
697 
698 void
699 GNEJunction::removeConnectionsFrom(GNEEdge* edge, GNEUndoList* undoList, bool updateTLS, int lane) {
700  NBEdge* srcNBE = edge->getNBEdge();
701  NBEdge* turnEdge = srcNBE->getTurnDestination();
702  // Make a copy of connections
703  std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
704  // delete in reverse so that undoing will add connections in the original order
705  for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
706  if (lane >= 0 && (*con_it).fromLane != lane) {
707  continue;
708  }
709  bool hasTurn = con_it->toEdge == turnEdge;
710  undoList->add(new GNEChange_Connection(edge, *con_it, false, false), true);
711  // needs to come after GNEChange_Connection
712  // XXX bug: this code path will not be used on a redo!
713  if (hasTurn) {
714  myNet->addExplicitTurnaround(srcNBE->getID());
715  }
716  }
717  if (updateTLS) {
718  std::vector<NBConnection> removeConnections;
719  for (NBEdge::Connection con : connections) {
720  removeConnections.push_back(NBConnection(srcNBE, con.fromLane, con.toEdge, con.toLane));
721  }
722  removeTLSConnections(removeConnections, undoList);
723  }
724 }
725 
726 
727 void
728 GNEJunction::removeConnectionsTo(GNEEdge* edge, GNEUndoList* undoList, bool updateTLS, int lane) {
729  NBEdge* destNBE = edge->getNBEdge();
730  std::vector<NBConnection> removeConnections;
731  for (NBEdge* srcNBE : myNBNode->getIncomingEdges()) {
732  GNEEdge* srcEdge = myNet->getAttributeCarriers()->retrieveEdge(srcNBE->getID());
733  std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
734  for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
735  if ((*con_it).toEdge == destNBE) {
736  if (lane >= 0 && (*con_it).toLane != lane) {
737  continue;
738  }
739  bool hasTurn = srcNBE->getTurnDestination() == destNBE;
740  undoList->add(new GNEChange_Connection(srcEdge, *con_it, false, false), true);
741  // needs to come after GNEChange_Connection
742  // XXX bug: this code path will not be used on a redo!
743  if (hasTurn) {
744  myNet->addExplicitTurnaround(srcNBE->getID());
745  }
746  removeConnections.push_back(NBConnection(srcNBE, (*con_it).fromLane, destNBE, (*con_it).toLane));
747  }
748  }
749  }
750  if (updateTLS) {
751  removeTLSConnections(removeConnections, undoList);
752  }
753 }
754 
755 
756 void
757 GNEJunction::removeTLSConnections(std::vector<NBConnection>& connections, GNEUndoList* undoList) {
758  if (connections.size() > 0) {
759  const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
760  for (const auto& TLS : coypOfTls) {
761  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
762  // guessed TLS (NBOwnTLDef) do not need to be updated
763  if (tlDef != nullptr) {
764  std::string newID = tlDef->getID();
765  // create replacement before deleting the original because deletion will mess up saving original nodes
766  NBLoadedSUMOTLDef* replacementDef = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
767  for (NBConnection& con : connections) {
768  replacementDef->removeConnection(con);
769  }
770  undoList->add(new GNEChange_TLS(this, tlDef, false), true);
771  undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
772  // the removed traffic light may have controlled more than one junction. These too have become invalid now
773  const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
774  for (const auto& node : copyOfNodes) {
775  GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
776  undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
777  undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
778  }
779  }
780  }
781  }
782 }
783 
784 
785 void
787  // remap connections of the edge
788  assert(which->getLanes().size() == by->getLanes().size());
789  std::vector<NBEdge::Connection> connections = which->getNBEdge()->getConnections();
790  for (NBEdge::Connection& c : connections) {
791  undoList->add(new GNEChange_Connection(which, c, false, false), true);
792  undoList->add(new GNEChange_Connection(by, c, false, true), true);
793  }
794  // also remap tls connections
795  const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
796  for (const auto& TLS : coypOfTls) {
797  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
798  // guessed TLS (NBOwnTLDef) do not need to be updated
799  if (tlDef != nullptr) {
800  std::string newID = tlDef->getID();
801  // create replacement before deleting the original because deletion will mess up saving original nodes
802  NBLoadedSUMOTLDef* replacementDef = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
803  for (int i = 0; i < (int)which->getLanes().size(); ++i) {
804  replacementDef->replaceRemoved(which->getNBEdge(), i, by->getNBEdge(), i, true);
805  }
806  undoList->add(new GNEChange_TLS(this, tlDef, false), true);
807  undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
808  // the removed traffic light may have controlled more than one junction. These too have become invalid now
809  const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
810  for (const auto& node : copyOfNodes) {
811  GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
812  undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
813  undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
814  }
815  }
816  }
817 }
818 
819 
820 void
822  EdgeVector incoming = myNBNode->getIncomingEdges();
823  for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
824  NBEdge* srcNBE = *it;
825  GNEEdge* srcEdge = myNet->getAttributeCarriers()->retrieveEdge(srcNBE->getID());
827  }
828 }
829 
830 
831 void
832 GNEJunction::invalidateTLS(GNEUndoList* undoList, const NBConnection& deletedConnection, const NBConnection& addedConnection) {
833  assert(undoList->hasCommandGroup());
834  // NBLoadedSUMOTLDef becomes invalid, replace with NBOwnTLDef which will be dynamically recomputed
835  const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
836  for (const auto& TLS : coypOfTls) {
837  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
838  if (tlDef != nullptr) {
839  NBTrafficLightDefinition* replacementDef = nullptr;
840  std::string newID = tlDef->getID(); // + "_reguessed"; // changes due to reguessing will be visible in diff
841  if (deletedConnection != NBConnection::InvalidConnection) {
842  // create replacement before deleting the original because deletion will mess up saving original nodes
843  NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
844  repl->removeConnection(deletedConnection);
845  replacementDef = repl;
846  } else if (addedConnection != NBConnection::InvalidConnection) {
847  if (addedConnection.getTLIndex() == NBConnection::InvalidTlIndex) {
848  // custom tl indices of crossings might become invalid upon recomputation so we must save them
849  // however, they could remain valid so we register a change but keep them at their old value
850  for (GNECrossing* c : myGNECrossings) {
851  const std::string oldValue = c->getAttribute(SUMO_ATTR_TLLINKINDEX);
853  undoList->add(new GNEChange_Attribute(c, SUMO_ATTR_TLLINKINDEX, oldValue), true);
854  const std::string oldValue2 = c->getAttribute(SUMO_ATTR_TLLINKINDEX2);
856  undoList->add(new GNEChange_Attribute(c, SUMO_ATTR_TLLINKINDEX2, oldValue2), true);
857  }
858  }
859  NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
860  repl->addConnection(addedConnection.getFrom(), addedConnection.getTo(),
861  addedConnection.getFromLane(), addedConnection.getToLane(), addedConnection.getTLIndex(), addedConnection.getTLIndex2());
862  replacementDef = repl;
863  } else {
864  // recompute crossing indices along with everything else
865  for (GNECrossing* c : myGNECrossings) {
866  const std::string oldValue = c->getAttribute(SUMO_ATTR_TLLINKINDEX);
868  const std::string oldValue2 = c->getAttribute(SUMO_ATTR_TLLINKINDEX2);
870  }
871  replacementDef = new NBOwnTLDef(newID, tlDef->getOffset(), tlDef->getType());
872  replacementDef->setProgramID(tlDef->getProgramID());
873  }
874  undoList->add(new GNEChange_TLS(this, tlDef, false), true);
875  undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
876  // the removed traffic light may have controlled more than one junction. These too have become invalid now
877  const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
878  for (const auto& node : copyOfNodes) {
879  GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
880  undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
881  undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
882  }
883  }
884  }
885 }
886 
887 void
889  // obtain a copy of GNECrossing of junctions
890  const auto copyOfGNECrossings = myGNECrossings;
891  // iterate over copy of GNECrossings
892  for (const auto& crossing : copyOfGNECrossings) {
893  // obtain the set of edges vinculated with the crossing (due it works as ID)
894  EdgeSet edgeSet(crossing->getCrossingEdges().begin(), crossing->getCrossingEdges().end());
895  // If this edge is part of the set of edges of crossing
896  if (edgeSet.count(edge->getNBEdge()) == 1) {
897  // delete crossing if this is their last edge
898  if ((crossing->getCrossingEdges().size() == 1) && (crossing->getCrossingEdges().front() == edge->getNBEdge())) {
899  myNet->deleteCrossing(crossing, undoList);
900  } else {
901  // remove this edge of the edge's attribute of crossing (note: This can invalidate the crossing)
902  std::vector<std::string> edges = GNEAttributeCarrier::parse<std::vector<std::string>>(crossing->getAttribute(SUMO_ATTR_EDGES));
903  edges.erase(std::find(edges.begin(), edges.end(), edge->getID()));
904  crossing->setAttribute(SUMO_ATTR_EDGES, joinToString(edges, " "), undoList);
905  }
906  }
907  }
908 }
909 
910 
911 bool
913  return myHasValidLogic;
914 }
915 
916 
918 GNEJunction::retrieveGNECrossing(NBNode::Crossing* NBNodeCrossing, bool createIfNoExist) {
919  // iterate over all crossing
920  for (const auto& crossing : myGNECrossings) {
921  // if found, return it
922  if (crossing->getCrossingEdges() == NBNodeCrossing->edges) {
923  return crossing;
924  }
925  }
926  if (createIfNoExist) {
927  // create new GNECrossing
928  GNECrossing* createdGNECrossing = new GNECrossing(this, NBNodeCrossing->edges);
929  // show extra information for tests
930  WRITE_DEBUG("Created " + createdGNECrossing->getTagStr() + " '" + createdGNECrossing->getID() + "' in retrieveGNECrossing()");
931  // update geometry after creating
932  createdGNECrossing->updateGeometry();
933  // add it in Network
934  myNet->addGLObjectIntoGrid(createdGNECrossing);
935  // add it in attributeCarriers
936  myNet->getAttributeCarriers()->insertCrossing(createdGNECrossing);
937  return createdGNECrossing;
938  } else {
939  return nullptr;
940  }
941 }
942 
943 
944 void
945 GNEJunction::markConnectionsDeprecated(bool includingNeighbours) {
946  // only it's needed to mark the connections of incoming edges
947  for (const auto& i : myGNEIncomingEdges) {
948  for (const auto& j : i->getGNEConnections()) {
949  j->markConnectionGeometryDeprecated();
950  }
951  if (includingNeighbours) {
952  i->getFromJunction()->markConnectionsDeprecated(false);
953  }
954  }
955 }
956 
957 
958 std::string
960  switch (key) {
961  case SUMO_ATTR_ID:
962  return getID();
963  case SUMO_ATTR_POSITION:
964  return toString(myNBNode->getPosition());
965  case SUMO_ATTR_TYPE:
966  return toString(myNBNode->getType());
968  return myLogicStatus;
969  case SUMO_ATTR_SHAPE:
970  return toString(myNBNode->getShape());
971  case SUMO_ATTR_RADIUS:
972  if (myNBNode->getRadius() < 0) {
973  return "default";
974  } else {
975  return toString(myNBNode->getRadius());
976  }
977  case SUMO_ATTR_TLTYPE:
979  // @todo this causes problems if the node were to have multiple programs of different type (plausible)
980  return toString((*myNBNode->getControllingTLS().begin())->getType());
981  } else {
982  return "No TLS";
983  }
984  case SUMO_ATTR_TLLAYOUT:
986  return toString((*myNBNode->getControllingTLS().begin())->getLayout());
987  } else {
988  return "No TLS";
989  }
990  case SUMO_ATTR_TLID:
992  return toString((*myNBNode->getControllingTLS().begin())->getID());
993  } else {
994  return "No TLS";
995  }
997  // keep clear is only used as a convenience feature in plain xml
998  // input. When saving to .net.xml the status is saved only for the connections
999  // to show the correct state we must check all connections
1000  for (const auto& i : myGNEIncomingEdges) {
1001  for (const auto& j : i->getGNEConnections()) {
1002  if (j->getNBEdgeConnection().keepClear) {
1003  return toString(true);
1004  }
1005  }
1006  }
1007  return toString(false);
1010  case SUMO_ATTR_FRINGE:
1012  case SUMO_ATTR_NAME:
1013  return myNBNode->getName();
1014  case GNE_ATTR_SELECTED:
1016  case GNE_ATTR_PARAMETERS:
1017  return myNBNode->getParametersStr();
1018  default:
1019  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1020  }
1021 }
1022 
1023 
1024 void
1025 GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1026  if (value == getAttribute(key)) {
1027  return; //avoid needless changes, later logic relies on the fact that attributes have changed
1028  }
1029  switch (key) {
1030  case SUMO_ATTR_ID:
1031  case SUMO_ATTR_POSITION:
1033  case SUMO_ATTR_SHAPE:
1034  case SUMO_ATTR_RADIUS:
1036  case SUMO_ATTR_FRINGE:
1037  case SUMO_ATTR_NAME:
1038  case GNE_ATTR_SELECTED:
1039  case GNE_ATTR_PARAMETERS:
1040  undoList->add(new GNEChange_Attribute(this, key, value), true);
1041  break;
1042  case SUMO_ATTR_KEEP_CLEAR:
1043  // change Keep Clear attribute in all connections
1044  undoList->begin(GUIIcon::JUNCTION, "change keepClear for whole junction");
1045  for (const auto& i : myGNEIncomingEdges) {
1046  for (const auto& j : i->getGNEConnections()) {
1047  undoList->add(new GNEChange_Attribute(j, key, value), true);
1048  }
1049  }
1050  undoList->end();
1051  break;
1052  case SUMO_ATTR_TYPE: {
1053  undoList->begin(GUIIcon::JUNCTION, "change " + getTagStr() + " type");
1055  if (getNBNode()->isTLControlled() &&
1056  // if switching changing from or to traffic_light_right_on_red we need to remove the old plan
1059  ) {
1060  // make a copy because we will modify the original
1061  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1062  for (const auto& TLS : copyOfTls) {
1063  undoList->add(new GNEChange_TLS(this, TLS, false), true);
1064  }
1065  }
1066  if (!getNBNode()->isTLControlled()) {
1067  // create new traffic light
1068  undoList->add(new GNEChange_TLS(this, nullptr, true), true);
1069  }
1070  } else if (getNBNode()->isTLControlled()) {
1071  // delete old traffic light
1072  // make a copy because we will modify the original
1073  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1074  for (const auto& TLS : copyOfTls) {
1075  undoList->add(new GNEChange_TLS(this, TLS, false, false), true);
1076  }
1077  }
1078  // must be the final step, otherwise we do not know which traffic lights to remove via GNEChange_TLS
1079  undoList->add(new GNEChange_Attribute(this, key, value), true);
1080  for (const auto& crossing : myGNECrossings) {
1081  undoList->add(new GNEChange_Attribute(crossing, SUMO_ATTR_TLLINKINDEX, "-1"), true);
1082  undoList->add(new GNEChange_Attribute(crossing, SUMO_ATTR_TLLINKINDEX2, "-1"), true);
1083  }
1084  undoList->end();
1085  break;
1086  }
1087  case SUMO_ATTR_TLTYPE: {
1088  undoList->begin(GUIIcon::JUNCTION, "change " + getTagStr() + " tl-type");
1089  // make a copy because we will modify the original
1090  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1091  for (const auto& TLS : copyOfTls) {
1092  NBLoadedSUMOTLDef* oldLoaded = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
1093  if (oldLoaded != nullptr) {
1094  NBLoadedSUMOTLDef* newDef = new NBLoadedSUMOTLDef(*oldLoaded, *oldLoaded->getLogic());
1095  newDef->guessMinMaxDuration();
1096  std::vector<NBNode*> nodes = TLS->getNodes();
1097  for (const auto& node : nodes) {
1098  GNEJunction* junction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1099  undoList->add(new GNEChange_TLS(junction, TLS, false), true);
1100  undoList->add(new GNEChange_TLS(junction, newDef, true), true);
1101  }
1102  }
1103  }
1104  undoList->add(new GNEChange_Attribute(this, key, value), true);
1105  undoList->end();
1106  break;
1107  }
1108  case SUMO_ATTR_TLLAYOUT: {
1109  undoList->begin(GUIIcon::JUNCTION, "change " + getTagStr() + " tlLayout");
1110  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1111  for (const auto& oldTLS : copyOfTls) {
1112  std::vector<NBNode*> copyOfNodes = oldTLS->getNodes();
1113  NBOwnTLDef* newTLS = new NBOwnTLDef(oldTLS->getID(), oldTLS->getOffset(), oldTLS->getType());
1115  newTLS->setProgramID(oldTLS->getProgramID());
1116  for (const auto& node : copyOfNodes) {
1117  GNEJunction* oldJunction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1118  undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
1119  }
1120  for (const auto& node : copyOfNodes) {
1121  GNEJunction* oldJunction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1122  undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
1123  }
1124  }
1125  undoList->end();
1126  break;
1127  }
1128  case SUMO_ATTR_TLID: {
1129  undoList->begin(GUIIcon::JUNCTION, "change " + toString(SUMO_TAG_TRAFFIC_LIGHT) + " id");
1130  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1131  assert(copyOfTls.size() > 0);
1132  NBTrafficLightDefinition* currentTLS = *copyOfTls.begin();
1133  NBTrafficLightDefinition* currentTLSCopy = nullptr;
1134  const bool currentIsSingle = currentTLS->getNodes().size() == 1;
1135  const bool currentIsLoaded = dynamic_cast<NBLoadedSUMOTLDef*>(currentTLS) != nullptr;
1136  if (currentIsLoaded) {
1137  currentTLSCopy = new NBLoadedSUMOTLDef(*currentTLS,
1138  *dynamic_cast<NBLoadedSUMOTLDef*>(currentTLS)->getLogic());
1139  }
1140  // remove from previous tls
1141  for (const auto& TLS : copyOfTls) {
1142  undoList->add(new GNEChange_TLS(this, TLS, false), true);
1143  }
1145  // programs to which the current node shall be added
1146  const std::map<std::string, NBTrafficLightDefinition*> programs = tlCont.getPrograms(value);
1147  if (programs.size() > 0) {
1148  for (const auto& TLSProgram : programs) {
1149  NBTrafficLightDefinition* oldTLS = TLSProgram.second;
1150  if (dynamic_cast<NBOwnTLDef*>(oldTLS) != nullptr) {
1151  undoList->add(new GNEChange_TLS(this, oldTLS, true), true);
1152  } else {
1153  // delete and re-create the definition because the loaded phases are now invalid
1154  if (dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS) != nullptr &&
1155  dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS)->usingSignalGroups()) {
1156  // keep the old program and add all-red state for the added links
1157  NBLoadedSUMOTLDef* newTLSJoined = new NBLoadedSUMOTLDef(*oldTLS, *dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS)->getLogic());
1158  newTLSJoined->joinLogic(currentTLSCopy);
1159  undoList->add(new GNEChange_TLS(this, newTLSJoined, true, true), true);
1160  } else {
1161  undoList->add(new GNEChange_TLS(this, nullptr, true, false, value), true);
1162  }
1163  NBTrafficLightDefinition* newTLS = *myNBNode->getControllingTLS().begin();
1164  // switch from old to new definition
1165  std::vector<NBNode*> copyOfNodes = oldTLS->getNodes();
1166  for (const auto& node : copyOfNodes) {
1167  GNEJunction* oldJunction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1168  undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
1169  undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
1170  }
1171  }
1172  }
1173  } else {
1174  if (currentIsSingle && currentIsLoaded) {
1175  // rename the traffic light but keep everything else
1176  NBTrafficLightLogic* renamedLogic = dynamic_cast<NBLoadedSUMOTLDef*>(currentTLSCopy)->getLogic();
1177  renamedLogic->setID(value);
1178  NBLoadedSUMOTLDef* renamedTLS = new NBLoadedSUMOTLDef(*currentTLSCopy, *renamedLogic);
1179  renamedTLS->setID(value);
1180  undoList->add(new GNEChange_TLS(this, renamedTLS, true, true), true);
1181  } else {
1182  // create new traffic light
1183  undoList->add(new GNEChange_TLS(this, nullptr, true, false, value), true);
1184  }
1185  }
1186  delete currentTLSCopy;
1187  undoList->end();
1188  break;
1189  }
1190  default:
1191  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1192  }
1193 }
1194 
1195 
1196 bool
1197 GNEJunction::isValid(SumoXMLAttr key, const std::string& value) {
1198  switch (key) {
1199  case SUMO_ATTR_ID:
1200  return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveJunction(value, false) == nullptr);
1201  case SUMO_ATTR_TYPE:
1203  case SUMO_ATTR_POSITION:
1204  return canParse<Position>(value);
1205  case SUMO_ATTR_SHAPE:
1206  // empty shapes are allowed
1207  return canParse<PositionVector>(value);
1208  case SUMO_ATTR_RADIUS:
1209  if (value.empty() || (value == "default")) {
1210  return true;
1211  } else {
1212  return canParse<double>(value) && ((parse<double>(value) >= 0) || (parse<double>(value) == -1));
1213  }
1214  case SUMO_ATTR_TLTYPE:
1216  case SUMO_ATTR_TLLAYOUT:
1218  case SUMO_ATTR_TLID:
1219  return myNBNode->isTLControlled() && (value != "");
1220  case SUMO_ATTR_KEEP_CLEAR:
1221  return canParse<bool>(value);
1224  case SUMO_ATTR_FRINGE:
1226  case SUMO_ATTR_NAME:
1227  return true;
1228  case GNE_ATTR_SELECTED:
1229  return canParse<bool>(value);
1230  case GNE_ATTR_PARAMETERS:
1231  return Parameterised::areParametersValid(value);
1232  default:
1233  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1234  }
1235 }
1236 
1237 
1238 bool
1240  switch (key) {
1241  case SUMO_ATTR_TLTYPE:
1242  case SUMO_ATTR_TLLAYOUT:
1243  case SUMO_ATTR_TLID:
1244  return myNBNode->isTLControlled();
1245  case SUMO_ATTR_KEEP_CLEAR: {
1246  // check if at least there is an incoming connection
1247  for (const auto& incomingEdge : myGNEIncomingEdges) {
1248  if (incomingEdge->getGNEConnections().size() > 0) {
1249  return true;
1250  }
1251  }
1252  return false;
1253  }
1254  default:
1255  return true;
1256  }
1257 }
1258 
1259 
1260 bool
1262  switch (key) {
1263  case SUMO_ATTR_SHAPE:
1264  return !myNBNode->hasCustomShape();
1265  default:
1266  return false;
1267  }
1268 }
1269 
1270 
1271 const std::map<std::string, std::string>&
1273  return myNBNode->getParametersMap();
1274 }
1275 
1276 
1277 void
1279  myAmResponsible = newVal;
1280 }
1281 
1282 // ===========================================================================
1283 // private
1284 // ===========================================================================
1285 
1286 void
1288  // draw TLS icon if isn't being drawn for selecting
1292  Position pos = myNBNode->getPosition();
1293  glTranslated(pos.x(), pos.y(), 0.2);
1294  glColor3d(1, 1, 1);
1295  const double halfWidth = 32 / s.scale;
1296  const double halfHeight = 64 / s.scale;
1297  GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GUITexture::TLS), -halfWidth, -halfHeight, halfWidth, halfHeight);
1299  }
1300 }
1301 
1302 
1303 void
1305  // draw crossings
1306  for (const auto& crossing : myGNECrossings) {
1307  crossing->drawGL(s);
1308  }
1309  // draw connections and route elements connections (Only for incoming edges)
1310  for (const auto& incomingEdge : myGNEIncomingEdges) {
1311  for (const auto& connection : incomingEdge->getGNEConnections()) {
1312  connection->drawGL(s);
1313  }
1314  }
1315  // draw child demand elements
1316  for (const auto& demandElement : getChildDemandElements()) {
1317  if (!demandElement->getTagProperty().isPlacedInRTree()) {
1318  demandElement->drawGL(s);
1319  }
1320  }
1321 }
1322 
1323 
1324 void
1325 GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value) {
1326  switch (key) {
1327  case SUMO_ATTR_KEEP_CLEAR: {
1328  throw InvalidArgument(toString(key) + " cannot be edited");
1329  }
1330  case SUMO_ATTR_ID: {
1331  myNet->getAttributeCarriers()->updateJunctionID(this, value);
1332  break;
1333  }
1334  case SUMO_ATTR_TYPE: {
1338  }
1339  myNBNode->reinit(myNBNode->getPosition(), type);
1340  break;
1341  }
1342  case SUMO_ATTR_POSITION: {
1343  // set new position in NBNode updating edge boundaries
1344  moveJunctionGeometry(parse<Position>(value), true);
1345  // mark this connections and all of the junction's Neighbours as deprecated
1347  // update centering boundary and grid
1349  break;
1350  }
1352  if (myLogicStatus == FEATURE_GUESSED && value != FEATURE_GUESSED) {
1353  // clear guessed connections. previous connections will be restored
1355  // Clear GNEConnections of incoming edges
1356  for (const auto& i : myGNEIncomingEdges) {
1357  i->clearGNEConnections();
1358  }
1359  }
1360  myLogicStatus = value;
1361  break;
1362  case SUMO_ATTR_SHAPE: {
1363  // set new shape (without updating grid)
1364  myNBNode->setCustomShape(parse<PositionVector>(value));
1365  // mark this connections and all of the junction's Neighbours as deprecated
1367  // update centering boundary and grid
1369  break;
1370  }
1371  case SUMO_ATTR_RADIUS: {
1372  if (value.empty() || (value == "default")) {
1373  myNBNode->setRadius(-1);
1374  } else {
1375  myNBNode->setRadius(parse<double>(value));
1376  }
1377  break;
1378  }
1379  case SUMO_ATTR_TLTYPE: {
1380  // we need to make a copy of controlling TLS (because original will be updated)
1381  const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1382  for (const auto& TLS : copyOfTls) {
1383  TLS->setType(SUMOXMLDefinitions::TrafficLightTypes.get(value));
1384  }
1385  break;
1386  }
1387  case SUMO_ATTR_TLLAYOUT:
1388  // should not be triggered (handled via GNEChange_TLS)
1389  break;
1392  break;
1393  case SUMO_ATTR_FRINGE:
1395  break;
1396  case SUMO_ATTR_NAME:
1397  myNBNode->setName(value);
1398  break;
1399  case GNE_ATTR_SELECTED:
1400  if (parse<bool>(value)) {
1402  } else {
1404  }
1405  break;
1406  case GNE_ATTR_PARAMETERS:
1407  myNBNode->setParametersStr(value);
1408  break;
1409  default:
1410  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1411  }
1412  // invalidate path calculator
1414 }
1415 
1416 
1417 void
1419  // set new position in NBNode without updating grid
1420  if (isShapeEdited()) {
1421  // set new shape
1422  myNBNode->setCustomShape(moveResult.shapeToUpdate);
1423  } else if (moveResult.shapeToUpdate.size() > 0) {
1424  moveJunctionGeometry(moveResult.shapeToUpdate.front(), false);
1425  }
1426  updateGeometry();
1427 }
1428 
1429 
1430 void
1432  // make sure that newShape isn't empty
1433  if (moveResult.shapeToUpdate.size() > 0) {
1434  // check if we're editing a shape
1435  if (isShapeEdited()) {
1436  // commit new shape
1437  undoList->begin(GUIIcon::JUNCTION, "moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
1438  undoList->changeAttribute(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(moveResult.shapeToUpdate)));
1439  undoList->end();
1441  undoList->begin(GUIIcon::JUNCTION, "position of " + getTagStr());
1442  undoList->changeAttribute(new GNEChange_Attribute(this, SUMO_ATTR_POSITION, toString(moveResult.shapeToUpdate.front())));
1443  undoList->end();
1444  }
1445  }
1446 }
1447 
1448 
1449 double
1450 GNEJunction::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
1451  switch (activeScheme) {
1452  case 0:
1454  return 3;
1455  } else {
1456  return 0;
1457  }
1458  case 1:
1459  return isAttributeCarrierSelected();
1460  case 2:
1461  switch (myNBNode->getType()) {
1463  return 0;
1465  return 1;
1467  return 2;
1469  return 3;
1471  return 4;
1473  return 5;
1475  return 6;
1477  return 7;
1480  return 8;
1482  return 8; // may happen before first network computation
1484  assert(false);
1485  return 8;
1487  return 9;
1489  return 10;
1491  return 11;
1493  return 12;
1494  default:
1495  assert(false);
1496  return 0;
1497  }
1498  case 3:
1499  return myNBNode->getPosition().z();
1500  default:
1501  assert(false);
1502  return 0;
1503  }
1504 }
1505 
1506 void
1508  for (auto edge : myGNEIncomingEdges) {
1509  if (edge->getGNEConnections().size() > 0) {
1511  return;
1512  }
1513  }
1514  // no connections. Use normal color for border edges and cul-de-sac
1515  if (myGNEIncomingEdges.size() == 0 || myGNEOutgoingEdges.size() == 0) {
1517  return;
1518  } else if (myGNEIncomingEdges.size() == 1 && myGNEOutgoingEdges.size() == 1) {
1519  NBEdge* in = myGNEIncomingEdges[0]->getNBEdge();
1520  NBEdge* out = myGNEOutgoingEdges[0]->getNBEdge();
1521  if (in->isTurningDirectionAt(out)) {
1523  return;
1524  }
1525  }
1527 }
1528 
1529 
1530 void
1531 GNEJunction::moveJunctionGeometry(const Position& pos, const bool updateEdgeBoundaries) {
1532  // obtain NBNode position
1533  const Position orig = myNBNode->getPosition();
1534  // reinit NBNode
1535  myNBNode->reinit(pos, myNBNode->getType());
1536  // set new position of adjacent edges
1537  for (const auto& edge : getNBNode()->getEdges()) {
1538  myNet->getAttributeCarriers()->retrieveEdge(edge->getID())->updateJunctionPosition(this, orig);
1539  }
1540  // declare three sets with all affected GNEJunctions, GNEEdges and GNEConnections
1541  std::set<GNEJunction*> affectedJunctions;
1542  std::set<GNEEdge*> affectedEdges;
1543  // Iterate over GNEEdges
1544  for (const auto& edge : getChildEdges()) {
1545  // Add source and destiny junctions
1546  affectedJunctions.insert(edge->getFromJunction());
1547  affectedJunctions.insert(edge->getToJunction());
1548  // Obtain neighbors of Junction source
1549  for (const auto& junctionSourceEdge : edge->getFromJunction()->getChildEdges()) {
1550  affectedEdges.insert(junctionSourceEdge);
1551  }
1552  // Obtain neighbors of Junction destiny
1553  for (const auto& junctionDestinyEdge : edge->getToJunction()->getChildEdges()) {
1554  affectedEdges.insert(junctionDestinyEdge);
1555  }
1556  }
1557  // Iterate over affected Edges
1558  for (const auto& affectedEdge : affectedEdges) {
1559  // update edge boundaries
1560  if (updateEdgeBoundaries) {
1561  affectedEdge->updateCenteringBoundary(true);
1562  }
1563  // Update edge geometry
1564  affectedEdge->updateGeometry();
1565  }
1566 }
1567 
1568 
1569 RGBColor
1570 GNEJunction::setColor(const GUIVisualizationSettings& s, bool bubble) const {
1571  // get active scheme
1572  const int scheme = s.junctionColorer.getActive();
1573  // first check if we're editing shape
1574  if (myShapeEdited) {
1575  return s.colorSettings.editShapeColor;
1576  }
1577  // set default color
1578  RGBColor color = s.junctionColorer.getScheme().getColor(getColorValue(s, scheme));
1579  // set special bubble color
1580  if (bubble && (scheme == 0) && !myColorForMissingConnections) {
1581  color = s.junctionColorer.getScheme().getColor(1);
1582  }
1583  // override with special colors (unless the color scheme is based on selection)
1584  if (drawUsingSelectColor() && scheme != 1) {
1585  color = s.colorSettings.selectionColor;
1586  }
1587  // set special color if we're creating a new edge
1588  if (myAmCreateEdgeSource) {
1589  color = RGBColor::GREEN;
1590  }
1591  // overwritte color if we're in data mode
1593  color = s.junctionColorer.getScheme().getColor(6);
1594  }
1595  // special color for source candidate junction
1596  if (mySourceCandidate) {
1597  color = s.candidateColorSettings.source;
1598  }
1599  // special color for target candidate junction
1600  if (myTargetCandidate) {
1601  color = s.candidateColorSettings.target;
1602  }
1603  // special color for special candidate junction
1604  if (mySpecialCandidate) {
1605  color = s.candidateColorSettings.special;
1606  }
1607  // special color for possible candidate junction
1608  if (myPossibleCandidate) {
1609  color = s.candidateColorSettings.possible;
1610  }
1611  // special color for conflicted candidate junction
1612  if (myConflictedCandidate) {
1613  color = s.candidateColorSettings.conflict;
1614  }
1615  // return color
1616  return color;
1617 }
1618 
1619 
1620 void
1623  tlCont.insert(tlDef, forceInsert); // may return false for tlDef which controls multiple junctions
1624  tlDef->addNode(myNBNode);
1625 }
1626 
1627 
1628 void
1631  if (tlDef->getNodes().size() == 1) {
1632  tlCont.extract(tlDef);
1633  }
1634  myNBNode->removeTrafficLight(tlDef);
1635 }
1636 
1637 
1638 /****************************************************************************/
@ NETWORK_MOVE
mode for moving network elements
@ 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:1070
@ MID_GNE_JUNCTION_SELECT_ROUNDABOUT
select all roundabout nodes and edges of the current roundabout
Definition: GUIAppEnum.h:1084
@ MID_GNE_JUNCTION_RESET_SHAPE
reset junction shape
Definition: GUIAppEnum.h:1082
@ MID_GNE_JUNCTION_RESET_CONNECTIONS
reset junction's connections
Definition: GUIAppEnum.h:1072
@ MID_GNE_JUNCTION_SPLIT
turn junction into multiple junctions
Definition: GUIAppEnum.h:1076
@ MID_GNE_JUNCTION_REPLACE
turn junction into geometry node
Definition: GUIAppEnum.h:1074
@ MID_GNE_JUNCTION_CONVERT_ROUNDABOUT
convert junction to roundabout
Definition: GUIAppEnum.h:1086
@ MID_GNE_JUNCTION_SPLIT_RECONNECT
turn junction into multiple junctions and reconnect them heuristically
Definition: GUIAppEnum.h:1078
@ MID_GNE_JUNCTION_EDIT_SHAPE
edit junction shape
Definition: GUIAppEnum.h:1080
@ GLO_TEMPORALSHAPE
temporal shape (used in NETEDIT)
@ GLO_MAX
empty max
@ GLO_JUNCTION
a junction
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:290
#define WRITE_GLDEBUG(msg)
Definition: MsgHandler.h:291
std::set< NBEdge * > EdgeSet
container for unique edges
Definition: NBCont.h:50
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
@ 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:80
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:269
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
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:170
static void drawBoundary(const Boundary &b)
Draw a boundary (used for debugging)
Definition: GLHelper.cpp:801
static void drawFilledPolyTesselated(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:189
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:507
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:431
static void pushName(unsigned int name)
push Name
Definition: GLHelper.cpp:132
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:123
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition: GLHelper.cpp:231
static void popName()
pop Name
Definition: GLHelper.cpp:141
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:114
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:609
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:640
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)
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)
bool myPossibleCandidate
flag to mark this element as possible candidate
bool mySpecialCandidate
flag to mark this element as special candidate
bool myTargetCandidate
flag to mark this element as target candidate
bool myConflictedCandidate
flag to mark this element as conflicted candidate
bool mySourceCandidate
flag to mark this element as source candidate
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
Definition: GNECrossing.h:42
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
void updateGeometry()
update pre-computed geometry information
Definition: GNECrossing.cpp:74
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:53
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition: GNEEdge.cpp:435
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:782
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition: GNEEdge.cpp:309
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
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
void updateGeometryAfterNetbuild(bool rebuildNBNodeCrossings=false)
update pre-computed geometry information without modifying netbuild structures
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition: GNEJunction.h:262
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:51
std::string getAttribute(SumoXMLAttr key) const
void setResponsible(bool newVal)
set responsibility for deleting internal structures
bool myColorForMissingConnections
whether this junction probably should have some connections but doesn't
Definition: GNEJunction.h:271
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
void moveJunctionGeometry(const Position &pos, const bool updateEdgeBoundaries)
reposition the node at pos without updating GRID and informs the edges
double getExaggeration(const GUIVisualizationSettings &s) const
return exaggeration asociated with this GLObject
void invalidateShape()
void updateGeometry()
update pre-computed geometry information (including crossings)
Definition: GNEJunction.cpp:95
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:246
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 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:249
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.
GNEMoveOperation * getMoveOperation()
get move operation
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:243
const PositionVector & getJunctionShape() const
Definition: GNEJunction.cpp:89
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:252
Position getPositionInView() const
Returns position of hierarchical element in view.
bool isAttributeComputed(SumoXMLAttr key) const
bool myAmTLSSelected
whether this junction is selected in tls-mode
Definition: GNEJunction.h:268
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:265
std::string myLogicStatus
modification status of the junction logic (all connections across this junction)
Definition: GNEJunction.h:259
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.
NBNode * myNBNode
A reference to the represented junction.
Definition: GNEJunction.h:240
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
~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:256
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
GNEMoveOperation * calculateMoveShapeOperation(const PositionVector originalShape, const Position mousePosition, const double snapRadius, const bool onlyContour)
calculate move shape operation
move operation
move result
PositionVector shapeToUpdate
shape to update (edited in moveElement)
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
void updateJunctionID(GNEJunction *junction, const std::string &newID)
update junction ID in container
void insertCrossing(GNECrossing *crossing)
insert crossing
int getNumberOfSelectedJunctions() const
get number of selected junctions
const std::set< GNECrossing * > & getCrossings() const
get crossings
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
void deleteCrossing(GNECrossing *crossing)
delete crossing
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:42
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:561
NBNetBuilder * getNetBuilder() const
get net builder
Definition: GNENet.cpp:1359
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1210
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1222
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:1970
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:125
GNEPathManager * getPathManager()
get path manager
Definition: GNENet.cpp:131
void requireRecompute()
inform the net about the need for recomputation
Definition: GNENet.cpp:1341
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition: GNENet.cpp:1982
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1964
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 invalidatePathCalculator()
invalidate pathCalculator
PathCalculator * getPathCalculator()
obtain instance of PathCalculator
void drawJunctionPathElements(const GUIVisualizationSettings &s, const GNEJunction *junction)
draw junction path elements
void incRef(const std::string &debugMsg="")
Increarse reference.
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
bool hasCommandGroup() const
Check if undoList has command group.
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...
void changeAttribute(GNEChange_Attribute *change)
special method for change attributes, avoid empty changes, always execute
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:513
bool showJunctionAsBubbles() const
return true if junction must be showed as bubbles
Definition: GNEViewNet.cpp:653
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
Definition: GNEViewNet.cpp:525
void drawTranslateFrontAttributeCarrier(const GNEAttributeCarrier *AC, double typeOrLayer, const double extraOffset=0)
draw front attributeCarrier
void removeFromAttributeCarrierInspected(const GNEAttributeCarrier *AC)
remove given AC of list of inspected Attribute Carriers
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:659
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:432
bool isAttributeCarrierInspected(const GNEAttributeCarrier *AC) const
check if attribute carrier is being inspected
const GNEViewNetHelper::ObjectsUnderCursor & getObjectsUnderCursor() const
get objects under cursor
Definition: GNEViewNet.cpp:420
static FXMenuCommand * buildFXMenuCommand(FXComposite *p, const std::string &text, FXIcon *icon, FXObject *tgt, FXSelector sel)
build menu command
Definition: GUIDesigns.cpp:42
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)
static void drawDottedContourClosedShape(const DottedContourType type, const GUIVisualizationSettings &s, const PositionVector &shape, const double exaggeration, const double lineWidth=-1)
draw dotted contour for the given closed shape (used by Juctions, shapes and TAZs)
The popup menu of a globject.
static void drawGeometryPoints(const GUIVisualizationSettings &s, const Position &mousePos, const PositionVector &shape, const RGBColor &geometryPointColor, const RGBColor &textColor, const double radius, const double exaggeration, const bool editingElevation, const bool drawExtremeSymbols)
draw geometry points
static void drawGeometry(const GUIVisualizationSettings &s, const Position &mousePos, const GUIGeometry &geometry, const double width, double offset=0)
draw geometry
void updateGeometry(const PositionVector &shape)
update entire geometry
Definition: GUIGeometry.cpp:58
static void drawMovingHint(const GUIVisualizationSettings &s, const Position &mousePos, const PositionVector &shape, const RGBColor &hintColor, const double radius, const double exaggeration)
draw moving hint
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, bool forceShow=false) 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
GUIVisualizationCandidateColorSettings candidateColorSettings
candidate color settings
GUIVisualizationTextSettings junctionID
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:1465
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:3356
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3684
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:1006
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:288
Position getCenter() const
Returns a position that is guaranteed to lie within the node shape.
Definition: NBNode.cpp:3499
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition: NBNode.cpp:307
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition: NBNode.h:208
FringeType getFringeType() const
Returns fringe type.
Definition: NBNode.h:293
void buildCrossingsAndWalkingAreas()
build crossings, and walkingareas. Also removes invalid loaded crossings if wished
Definition: NBNode.cpp:2700
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:273
const std::string & getName() const
Returns intersection name.
Definition: NBNode.h:298
void setRightOfWay(RightOfWay rightOfWay)
set method for computing right-of-way
Definition: NBNode.h:543
void setCustomShape(const PositionVector &shape)
set the junction shape
Definition: NBNode.cpp:2424
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
Definition: NBNode.cpp:3555
void invalidateIncomingConnections(bool reallowSetting=false)
invalidate incoming connections
Definition: NBNode.cpp:1876
void mirrorX()
mirror coordinates along the x-axis
Definition: NBNode.cpp:346
std::vector< std::pair< Position, std::string > > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
Definition: NBNode.cpp:3658
const std::vector< std::unique_ptr< Crossing > > & getCrossingsIncludingInvalid() const
Definition: NBNode.h:709
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:261
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
Definition: NBNode.h:266
bool hasCustomShape() const
return whether the shape was set by the user
Definition: NBNode.h:558
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:256
void setRadius(double radius)
set the turning radius
Definition: NBNode.h:533
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:324
void setName(const std::string &name)
set intersection name
Definition: NBNode.h:553
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:375
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:2418
const Position & getPosition() const
Definition: NBNode.h:248
double getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:278
bool isRoundabout() const
return whether this node is part of a roundabout
Definition: NBNode.cpp:3385
bool checkIsRemovableReporting(std::string &reason) const
check if node is removable and return reason if not
Definition: NBNode.cpp:2325
PositionVector myPoly
the (outer) shape of the junction
Definition: NBNode.h:888
void setFringeType(FringeType fringeType)
set method for computing right-of-way
Definition: NBNode.h:548
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:319
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:82
const std::string & getID() const
Returns the id.
Definition: Named.h:74
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, 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:37
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition: Position.h:257
double x() const
Returns the x-position.
Definition: Position.h:55
double z() const
Returns the z-position.
Definition: Position.h:65
double y() const
Returns the y-position.
Definition: Position.h:60
A list of positions.
void closePolygon()
ensures that the last position equals the first
int indexOfClosest(const Position &p, bool twoD=false) const
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
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)
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.cpp:92
static const RGBColor GREEN
Definition: RGBColor.h:186
static const RGBColor BLACK
Definition: RGBColor.h:193
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:197
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
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
static void drawLockIcon(const GNEAttributeCarrier *AC, GUIGlObjectType type, const Position viewPosition, const double exaggeration, const double size=0.5, const double offsetx=0, const double offsety=0)
draw lock icon
bool editingElevation() const
check if we're editing elevation
static const RGBColor special
color for selected special candidate element (Usually selected using shift+click)
static const RGBColor conflict
color for selected conflict candidate element (Usually selected using ctrl+click)
static const RGBColor target
color for selected candidate target
static const RGBColor possible
color for possible candidate element
static const RGBColor source
color for selected candidate source
RGBColor selectionColor
basic selection color
static const RGBColor editShapeColor
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
bool show(const GUIGlObject *o) const
whether to show the text
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:197