SUMO - Simulation of Urban MObility
GNEJunction.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // A class for visualizing and editing junctions in netedit (adapted from
8 // GUIJunctionWrapper)
9 /****************************************************************************/
10 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
11 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
12 /****************************************************************************/
13 //
14 // This file is part of SUMO.
15 // SUMO is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #include <string>
33 #include <utility>
36 #include <utils/geom/Position.h>
43 #include <utils/gui/div/GLHelper.h>
48 #include <netbuild/NBOwnTLDef.h>
50 #include <netbuild/NBAlgorithms.h>
51 #include "GNENet.h"
52 #include "GNEEdge.h"
53 #include "GNECrossing.h"
54 #include "GNEUndoList.h"
55 #include "GNEViewNet.h"
56 #include "GNEChange_Attribute.h"
57 #include "GNEChange_Connection.h"
58 #include "GNEChange_TLS.h"
59 #include "GNEConnection.h"
60 #include "GNEJunction.h"
61 
62 #ifdef CHECK_MEMORY_LEAKS
63 #include <foreign/nvwa/debug_new.h>
64 #endif // CHECK_MEMORY_LEAKS
65 
66 // ===========================================================================
67 // method definitions
68 // ===========================================================================
69 GNEJunction::GNEJunction(NBNode& nbn, GNENet* net, bool loaded) :
70  GNENetElement(net, nbn.getID(), GLO_JUNCTION, SUMO_TAG_JUNCTION),
71  myNBNode(nbn),
72  myOrigPos(nbn.getPosition()),
73  myAmCreateEdgeSource(false),
74  myLogicStatus(loaded ? LOADED : GUESSED),
75  myAmResponsible(false),
76  myHasValidLogic(loaded),
77  myAmTLSSelected(false) {
79  rebuildCrossings(false);
80 }
81 
82 
84  if (myAmResponsible) {
85  delete &myNBNode;
86  }
87  rebuildCrossings(true);
88 }
89 
90 
91 void
93  const double EXTENT = 2;
95  myOrigPos.x() - EXTENT, myOrigPos.y() - EXTENT,
96  myOrigPos.x() + EXTENT, myOrigPos.y() + EXTENT);
97  if (myNBNode.getShape().size() > 0) {
99  }
101 }
102 
103 
104 void
106  for (std::vector<GNECrossing*>::const_iterator it = myCrossings.begin(); it != myCrossings.end(); it++) {
107  (*it)->decRef();
108  if ((*it)->unreferenced()) {
109  delete *it;
110  }
111  }
112  myCrossings.clear();
113  if (!deleteOnly) {
114  const std::vector<NBNode::Crossing>& crossings = myNBNode.getCrossings();
115  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
116  myCrossings.push_back(new GNECrossing(*this, (*it).id));
117  myCrossings.back()->incRef();
118  }
119  }
120 }
121 
122 
125  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
126  buildPopupHeader(ret, app);
130  buildPositionCopyEntry(ret, false);
131  //if (parent.getVisualisationSettings()->editMode != GNE_MODE_CONNECT) {
132  // // XXX if joinable
133  // new FXMenuCommand(ret, "Join adjacent edges", 0, &parent, MID_GNE_JOIN_EDGES);
134  //}
135  FXMenuCommand* mcCustomShape = new FXMenuCommand(ret, "Set custom shape", 0, &parent, MID_GNE_NODE_SHAPE);
136  FXMenuCommand* mcReplace = new FXMenuCommand(ret, "Replace by geometry node", 0, &parent, MID_GNE_NODE_REPLACE);
137  const int editMode = parent.getVisualisationSettings()->editMode;
138  const bool wrongMode = (editMode == GNE_MODE_CONNECT || editMode == GNE_MODE_TLS || editMode == GNE_MODE_CREATE_EDGE);
139  if (wrongMode) {
140  mcCustomShape->handle(&parent, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), 0);
141  }
142  // checkIsRemovable requiers turnarounds to be computed. This is ugly
143  if (myNBNode.getIncomingEdges().size() == 2 && myNBNode.getOutgoingEdges().size() == 2) {
145  }
146  if (wrongMode || !myNBNode.checkIsRemovable()) {
147  mcReplace->handle(&parent, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), 0);
148  }
149  // let the GNEViewNet store the popup position
150  (dynamic_cast<GNEViewNet&>(parent)).markPopupPosition();
151  return ret;
152 }
153 
154 
157  return 0;
158 }
159 
160 
161 Boundary
163  Boundary b = myBoundary;
164  b.grow(20);
165  return b;
166 }
167 
168 
169 void
171  glPushName(getGlID());
172  SUMOReal exaggeration = gSelected.isSelected(getType(), getGlID()) ? s.selectionScale : 1;
173  exaggeration *= s.junctionSize.getExaggeration(s);
174  if (s.scale * exaggeration * myMaxSize < 1.) {
175  // draw something simple so that selection still works
177  } else {
178  // node shape has been computed and is valid for drawing
179  const bool drawShape = myNBNode.getShape().size() > 0 && s.drawJunctionShape;
180  const bool drawBubble = (!drawShape || myNBNode.getShape().area() < 4) && s.drawJunctionShape; // magic threshold
181 
182  if (drawShape) {
183  setColor(s, false);
184  // recognize full transparency and simply don't draw
185  GLfloat color[4];
186  glGetFloatv(GL_CURRENT_COLOR, color);
187  if (color[3] != 0) {
188  glPushMatrix();
189  glTranslated(0, 0, getType());
190  PositionVector shape = myNBNode.getShape();
191  shape.closePolygon();
192  if (exaggeration > 1) {
193  shape.scaleRelative(exaggeration);
194  }
195  if (s.scale * exaggeration * myMaxSize < 40.) {
196  GLHelper::drawFilledPoly(shape, true);
197  } else {
199  }
200  glPopMatrix();
201  }
202  }
203  if (drawBubble) {
204  setColor(s, true);
205  // recognize full transparency and simply don't draw
206  GLfloat color[4];
207  glGetFloatv(GL_CURRENT_COLOR, color);
208  if (color[3] != 0) {
209  glPushMatrix();
210  Position pos = myNBNode.getPosition();
211  glTranslated(pos.x(), pos.y(), getType() - 0.05);
212  GLHelper::drawFilledCircle(4 * exaggeration, 32);
213  glPopMatrix();
214  }
215  }
216 
218  glPushMatrix();
219  Position pos = myNBNode.getPosition();
220  glTranslated(pos.x(), pos.y(), getType() + 0.1);
221  glColor3d(1, 1, 1);
222  const SUMOReal halfWidth = 32 / s.scale;
223  const SUMOReal halfHeight = 64 / s.scale;
224  GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getGif(GNETEXTURE_TLS), -halfWidth, -halfHeight, halfWidth, halfHeight);
225  glPopMatrix();
226  }
227  // draw crossings
228  if (s.editMode != GNE_MODE_TLS) {
229  for (std::vector<GNECrossing*>::const_iterator it = myCrossings.begin(); it != myCrossings.end(); it++) {
230  (*it)->drawGL(s);
231  }
232  }
233  // (optional) draw name @todo expose this setting
235  }
236  glPopName();
237 }
238 
239 Boundary
241  return myBoundary;
242 }
243 
244 
245 NBNode*
247  return &myNBNode;
248 }
249 
250 
251 std::vector<GNEEdge*>
253  std::vector<GNEEdge*> edges;
254  // iterate over incoming edges
255  for (std::vector<NBEdge*>::const_iterator i = myNBNode.getIncomingEdges().begin(); i != myNBNode.getIncomingEdges().end(); i++) {
256  edges.push_back(myNet->retrieveEdge((*i)->getID()));
257  }
258  // iterate over outgoing edges
259  for (std::vector<NBEdge*>::const_iterator i = myNBNode.getOutgoingEdges().begin(); i != myNBNode.getOutgoingEdges().end(); i++) {
260  edges.push_back(myNet->retrieveEdge((*i)->getID()));
261  }
262  return edges;
263 }
264 
265 
266 std::vector<GNEEdge*>
268  std::vector<GNEEdge*> incomingEdges;
269  // iterate over incoming edges
270  for (std::vector<NBEdge*>::const_iterator i = myNBNode.getIncomingEdges().begin(); i != myNBNode.getIncomingEdges().end(); i++) {
271  incomingEdges.push_back(myNet->retrieveEdge((*i)->getID()));
272  }
273  return incomingEdges;
274 }
275 
276 
277 std::vector<GNEEdge*>
279  std::vector<GNEEdge*> outgoingEdges;
280  // iterate over outgoing edges
281  for (std::vector<NBEdge*>::const_iterator i = myNBNode.getOutgoingEdges().begin(); i != myNBNode.getOutgoingEdges().end(); i++) {
282  outgoingEdges.push_back(myNet->retrieveEdge((*i)->getID()));
283  }
284  return outgoingEdges;
285 }
286 
287 
288 void
290  myAmCreateEdgeSource = true;
291 }
292 
293 
294 void
296  myAmCreateEdgeSource = false;
297 }
298 
299 
300 void
301 GNEJunction::selectTLS(bool selected) {
302  myAmTLSSelected = selected;
303 }
304 
305 
306 void
308  const Position orig = myNBNode.getPosition();
309  setPosition(pos);
310  const EdgeVector& incident = getNBNode()->getEdges();
311  for (EdgeVector::const_iterator it = incident.begin(); it != incident.end(); it++) {
312  GNEEdge* edge = myNet->retrieveEdge((*it)->getID());
313  edge->updateJunctionPosition(this, orig);
314  }
315  // Update shapes without include connections, because the aren't showed in Move mode
317 }
318 
319 
320 void
322  Position newPos = myNBNode.getPosition();
323  std::string newPosValue = getAttribute(SUMO_ATTR_POSITION);
324  // actually the geometry is already up to date
325  // set the restore point to the end of the last change-set
327  // do not execute the command to avoid changing the edge geometry twice
328  undoList->add(new GNEChange_Attribute(this, SUMO_ATTR_POSITION, newPosValue), false);
329  setPosition(newPos);
330  // Refresh element to avoid grabbing problems
331  myNet->refreshElement(this);
332 }
333 
334 
335 void
337  // First declare three sets with all affected GNEJunctions, GNEEdges and GNEConnections
338  std::set<GNEJunction*> affectedJunctions;
339  std::set<GNEEdge*> affectedEdges;
340  // Fill sets
341  std::vector<GNEEdge*> GNEEdges = getGNEEdges(); // @Improve efficiency
342  std::vector<GNEEdge*> edgesNeighbor;
343  // Iterate over GNEEdges
344  for (std::vector<GNEEdge*>::const_iterator i = GNEEdges.begin(); i != GNEEdges.end(); i++) {
345  // Add source and destiny junctions
346  affectedJunctions.insert((*i)->getGNEJunctionSource()); // @Improve efficiency
347  affectedJunctions.insert((*i)->getGNEJunctionDest()); // @Improve efficiency
348  // Obtain neighbors of Junction source
349  edgesNeighbor = (*i)->getGNEJunctionSource()->getGNEEdges(); // @Improve efficiency
350  for (std::vector<GNEEdge*>::const_iterator j = edgesNeighbor.begin(); j != edgesNeighbor.end(); j++) {
351  affectedEdges.insert(*j);
352  }
353  // Obtain neighbors of Junction destiny
354  edgesNeighbor = (*i)->getGNEJunctionDest()->getGNEEdges(); // @Improve efficiency
355  for (std::vector<GNEEdge*>::const_iterator j = edgesNeighbor.begin(); j != edgesNeighbor.end(); j++) {
356  affectedEdges.insert(*j);
357  }
358  }
359  // Iterate over affected Junctions
360  for (std::set<GNEJunction*>::iterator i = affectedJunctions.begin(); i != affectedJunctions.end(); i++) {
361  // Check that Node doesn't have a custom shape
362  if ((*i)->getNBNode()->hasCustomShape() == false) {
363  // Set new shape depending of the representation
364  if (myNet->getViewNet()->showJunctionAsBubbles() == true) {
365  // Only save Position to draw bubble
366  (*i)->getNBNode()->myPoly.clear();
367  (*i)->getNBNode()->myPoly.push_back((*i)->getNBNode()->getPosition());
368  } else {
369  // Compute polygon
370  (*i)->getNBNode()->computeNodeShape(-1);
371  }
372  // Update geometry of Junction
373  (*i)->updateGeometry();
374  }
375  }
376  // Iterate over affected Edges
377  for (std::set<GNEEdge*>::iterator i = affectedEdges.begin(); i != affectedEdges.end(); i++) {
378  if (myNet->getViewNet()->showJunctionAsBubbles() == true) {
379  // Only compute lane shapes
380  (*i)->getNBEdge()->computeLaneShapes();
381  } else {
382  // Compute full edge shape because this funcion is related to computeNodeShape
383  (*i)->getNBEdge()->computeEdgeShape();
384  }
385  // Update edge geometry
386  (*i)->updateGeometry();
387  }
388  // Update view to show the new shapes
389  myNet->getViewNet()->update();
390 }
391 
392 
393 void
395  if (!myNBNode.hasCustomShape()) {
396  myNBNode.myPoly.clear();
398  }
399 }
400 
401 
402 void
403 GNEJunction::setLogicValid(bool valid, GNEUndoList* undoList, const std::string& status) {
404  myHasValidLogic = valid;
405  if (!valid) {
406  assert(undoList != 0);
407  assert(undoList->hasCommandGroup());
409  EdgeVector incoming = myNBNode.getIncomingEdges();
410  for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
411  NBEdge* srcNBE = *it;
412  NBEdge* turnEdge = srcNBE->getTurnDestination();
413  GNEEdge* srcEdge = myNet->retrieveEdge(srcNBE->getID());
414  // Make a copy of connections
415  std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
416  // delete in reverse so that undoing will add connections in the original order
417  for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
418  bool hasTurn = con_it->toEdge == turnEdge;
419  undoList->add(new GNEChange_Connection(srcEdge, *con_it, false), true);
420  // needs to come after GNEChange_Connection
421  // XXX bug: this code path will not be used on a redo!
422  if (hasTurn) {
423  myNet->addExplicitTurnaround(srcNBE->getID());
424  }
425  }
426  undoList->add(new GNEChange_Attribute(srcEdge, GNE_ATTR_MODIFICATION_STATUS, status), true);
427  }
428  undoList->add(new GNEChange_Attribute(this, GNE_ATTR_MODIFICATION_STATUS, status), true);
429  invalidateTLS(undoList);
430  } else {
431  rebuildCrossings(false);
432  }
433 }
434 
435 
436 void
438  EdgeVector incoming = myNBNode.getIncomingEdges();
439  for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
440  NBEdge* srcNBE = *it;
441  GNEEdge* srcEdge = myNet->retrieveEdge(srcNBE->getID());
442  undoList->add(new GNEChange_Attribute(srcEdge, GNE_ATTR_MODIFICATION_STATUS, MODIFIED), true);
443  }
444 }
445 
446 
447 void
448 GNEJunction::invalidateTLS(GNEUndoList* undoList, const NBConnection& deletedConnection) {
449  assert(undoList->hasCommandGroup());
450  // NBLoadedSUMOTLDef becomes invalid, replace with NBOwnTLDef which will be dynamically recomputed
451  const std::set<NBTrafficLightDefinition*> tls = myNBNode.getControllingTLS(); // make a copy!
452  for (std::set<NBTrafficLightDefinition*>::iterator it = tls.begin(); it != tls.end(); it++) {
453  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(*it);
454  if (tlDef != 0) {
455  NBTrafficLightDefinition* replacementDef = 0;
456  std::string newID = tlDef->getID(); // + "_reguessed"; // changes due to reguessing will be visible in diff
457  if (deletedConnection != NBConnection::InvalidConnection) {
458  // create replacement before deleting the original because deletion will mess up saving original nodes
459  NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(tlDef, tlDef->getLogic());
460  repl->removeConnection(deletedConnection);
461  replacementDef = repl;
462  } else {
463  replacementDef = new NBOwnTLDef(newID, tlDef->getOffset(), tlDef->getType());
464  replacementDef->setProgramID(tlDef->getProgramID());
465  }
466  undoList->add(new GNEChange_TLS(this, tlDef, false), true);
467  undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
468  // the removed traffic light may have controlled more than one junction. These too have become invalid now
469  const std::vector<NBNode*> coNodes = tlDef->getNodes(); // make a copy!
470  for (std::vector<NBNode*>::const_iterator it_node = coNodes.begin(); it_node != coNodes.end(); it_node++) {
471  GNEJunction* sharing = myNet->retrieveJunction((*it_node)->getID());
472  undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
473  undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
474  }
475  }
476  }
477 }
478 
479 void
481  // @todo implement GNEChange_Crossing
482  UNUSED_PARAMETER(undoList);
483  // make a copy because the original will be modified
484  const std::vector<NBNode::Crossing> crossings = myNBNode.getCrossings();
485  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
486  EdgeSet edgeSet((*it).edges.begin(), (*it).edges.end());
487  if (edgeSet.count(edge->getNBEdge()) == 1) {
488  myNBNode.removeCrossing((*it).edges);
489  }
490  }
491 }
492 
493 
494 bool
496  return myHasValidLogic;
497 }
498 
499 
500 std::string
502  switch (key) {
503  case SUMO_ATTR_ID:
504  return getMicrosimID();
505  break;
506  case SUMO_ATTR_POSITION:
507  return toString(myNBNode.getPosition());
508  break;
509  case SUMO_ATTR_TYPE:
510  return toString(myNBNode.getType());
511  break;
513  return myLogicStatus;
514  break;
515  case SUMO_ATTR_SHAPE:
516  return toString(myNBNode.getShape());
517  case SUMO_ATTR_RADIUS:
518  return toString(myNBNode.getRadius());
519  case SUMO_ATTR_TLTYPE:
520  // @todo this causes problems if the node were to have multiple programs of different type (plausible)
521  return myNBNode.isTLControlled() ? toString((*myNBNode.getControllingTLS().begin())->getType()) : "";
522  case SUMO_ATTR_TLID:
523  return myNBNode.isTLControlled() ? toString((*myNBNode.getControllingTLS().begin())->getID()) : "";
525  return myNBNode.getKeepClear() ? "true" : "false";
526  default:
527  throw InvalidArgument("junction attribute '" + toString(key) + "' not allowed");
528  }
529 }
530 
531 
532 void
533 GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
534  if (value == getAttribute(key)) {
535  return; //avoid needless changes, later logic relies on the fact that attributes have changed
536  }
537  switch (key) {
538  case SUMO_ATTR_ID:
539  case SUMO_ATTR_POSITION:
541  case SUMO_ATTR_SHAPE:
542  case SUMO_ATTR_RADIUS:
543  case SUMO_ATTR_TLTYPE:
545  undoList->add(new GNEChange_Attribute(this, key, value), true);
546  break;
547  case SUMO_ATTR_TYPE: {
548  undoList->p_begin("change junction type");
550  if (!getNBNode()->isTLControlled()) {
551  // create new traffic light
552  undoList->add(new GNEChange_TLS(this, 0, true), true);
553  }
554  } else if (getNBNode()->isTLControlled()) {
555  // delete old traffic light
556  // make a copy because we will modify the original
557  const std::set<NBTrafficLightDefinition*> tls = myNBNode.getControllingTLS();
558  for (std::set<NBTrafficLightDefinition*>::iterator it = tls.begin(); it != tls.end(); it++) {
559  undoList->add(new GNEChange_TLS(this, *it, false), true);
560  }
561  }
562  // must be the final step, otherwise we do not know which traffic lights to remove via GNEChange_TLS
563  undoList->add(new GNEChange_Attribute(this, key, value), true);
564  undoList->p_end();
565  break;
566  }
567  case SUMO_ATTR_TLID: {
568  undoList->p_begin("change tls id");
569  // junction is already controlled, remove from previous tls
570  const std::set<NBTrafficLightDefinition*> tls = myNBNode.getControllingTLS();
571  for (std::set<NBTrafficLightDefinition*>::iterator it = tls.begin(); it != tls.end(); it++) {
572  undoList->add(new GNEChange_TLS(this, *it, false), true);
573  }
575  const std::map<std::string, NBTrafficLightDefinition*>& programs = tlCont.getPrograms(value);
576  if (programs.size() > 0) {
577  // add to existing tls definitions
578  for (std::map<std::string, NBTrafficLightDefinition*>::const_iterator it = programs.begin(); it != programs.end(); it++) {
579  NBTrafficLightDefinition* oldTLS = it->second;
580  if (dynamic_cast<NBOwnTLDef*>(oldTLS) != 0) {
581  undoList->add(new GNEChange_TLS(this, oldTLS, true), true);
582  } else {
583  // delete and re-create the definition because the loaded phases are now invalid
584  const std::vector<NBNode*> nodes = oldTLS->getNodes();
585  for (std::vector<NBNode*>::const_iterator it_node = nodes.begin(); it_node != nodes.end(); ++it_node) {
586  GNEJunction* oldJunction = myNet->retrieveJunction((*it_node)->getID());
587  undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
588  }
589  undoList->add(new GNEChange_TLS(this, 0, true, false, value), true);
591  // re-add existing nodes
592  for (std::vector<NBNode*>::const_iterator it_node = nodes.begin(); it_node != nodes.end(); ++it_node) {
593  GNEJunction* oldJunction = myNet->retrieveJunction((*it_node)->getID());
594  undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
595  }
596  }
597  }
598  } else {
599  // create new traffic light
600  undoList->add(new GNEChange_TLS(this, 0, true, false, value), true);
601  }
602  undoList->p_end();
603  break;
604  }
605  default:
606  throw InvalidArgument("junction attribute '" + toString(key) + "' not allowed");
607  }
608 }
609 
610 
611 bool
612 GNEJunction::isValid(SumoXMLAttr key, const std::string& value) {
613  switch (key) {
614  case SUMO_ATTR_ID:
615  return isValidID(value) && myNet->retrieveJunction(value, false) == 0;
616  break;
617  case SUMO_ATTR_TYPE:
619  break;
620  case SUMO_ATTR_POSITION:
621  bool ok;
622  return GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, false).size() == 1;
623  break;
624  case SUMO_ATTR_SHAPE: {
625  bool ok = true;
627  value, "user-supplied position", 0, ok, true);
628  return ok;
629  break;
630  }
631  case SUMO_ATTR_RADIUS:
632  return canParse<SUMOReal>(value);
633  break;
634  case SUMO_ATTR_TLTYPE:
636  case SUMO_ATTR_TLID:
637  return myNBNode.isTLControlled() && value != "";
639  return value == "true" || value == "false";
640  break;
641  default:
642  throw InvalidArgument("junction attribute '" + toString(key) + "' not allowed");
643  }
644 }
645 
646 
647 void
649  myAmResponsible = newVal;
650 }
651 
652 // ===========================================================================
653 // private
654 // ===========================================================================
655 
656 void
657 GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value) {
658  switch (key) {
659  case SUMO_ATTR_ID:
660  myNet->renameJunction(this, value);
661  break;
662  case SUMO_ATTR_TYPE: {
664  break;
665  }
666  case SUMO_ATTR_POSITION:
667  bool ok;
668  myOrigPos = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, false)[0];
669  move(myOrigPos);
670  // Refresh element to avoid grabbing problems
671  myNet->refreshElement(this);
672  break;
674  if (myLogicStatus == GUESSED && value != GUESSED) {
675  // clear guessed connections. previous connections will be restored
677  std::vector<GNEEdge*> incomingEdges = getGNEIncomingEdges();
678  for (std::vector<GNEEdge*>::iterator i = incomingEdges.begin(); i != incomingEdges.end(); i++) {
679  (*i)->clearGNEConnections();
680  }
681  }
682  myLogicStatus = value;
683  break;
684  case SUMO_ATTR_SHAPE: {
685  bool ok;
686  const PositionVector shape = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, true);
687  myNBNode.setCustomShape(shape);
688  break;
689  }
690  case SUMO_ATTR_RADIUS:
691  myNBNode.setRadius(parse<SUMOReal>(value));
692  break;
693  case SUMO_ATTR_TLTYPE: {
694  const std::set<NBTrafficLightDefinition*> tls = myNBNode.getControllingTLS();
695  for (std::set<NBTrafficLightDefinition*>::iterator it = tls.begin(); it != tls.end(); it++) {
696  (*it)->setType(SUMOXMLDefinitions::TrafficLightTypes.get(value));
697  }
698  break;
699  }
701  myNBNode.setKeepClear(value == "true");
702  break;
703  default:
704  throw InvalidArgument("junction attribute '" + toString(key) + "' not allowed");
705  }
706 }
707 
708 
709 void
711  const Position& orig = myNBNode.getPosition();
712  myBoundary.moveby(pos.x() - orig.x(), pos.y() - orig.y());
714  /* //reshift also shifts the junction shape. this is not needed because shape is not yet computed
715  * const Position& orig = myNBNode.getPosition();
716  * myNBNode.reshiftPosition(pos.x() - orig.x(), pos.y() - orig.y());
717  */
718 }
719 
720 
721 SUMOReal
723  switch (s.junctionColorer.getActive()) {
724  case 0:
725  if (bubble) {
726  return 1;
727  } else {
728  return 0;
729  }
730  case 1:
731  return gSelected.isSelected(getType(), getGlID()) ? 1 : 0;
732  case 2:
733  switch (myNBNode.getType()) {
735  return 0;
737  return 1;
738  case NODETYPE_PRIORITY:
739  return 2;
741  return 3;
743  return 4;
745  return 5;
746  case NODETYPE_DISTRICT:
747  return 6;
748  case NODETYPE_NOJUNCTION:
749  return 7;
750  case NODETYPE_DEAD_END:
752  return 8;
753  case NODETYPE_UNKNOWN:
754  case NODETYPE_INTERNAL:
755  assert(false);
756  return 8;
758  return 9;
759  case NODETYPE_ZIPPER:
760  return 10;
762  return 11;
764  return 12;
765  }
766  default:
767  assert(false);
768  return 0;
769  }
770 }
771 
772 
773 void
774 GNEJunction::setColor(const GUIVisualizationSettings& s, bool bubble) const {
776  // override with special colors (unless the color scheme is based on selection)
779  }
780  if (myAmCreateEdgeSource) {
781  glColor3d(0, 1, 0);
782  }
783 }
784 
785 void
788  tlCont.insert(tlDef, forceInsert); // may return false for tlDef which controls multiple junctions
789  tlDef->addNode(&myNBNode);
790 }
791 
792 
793 void
796  if (tlDef->getNodes().size() == 1) {
797  tlCont.extract(tlDef);
798  }
800 }
801 
802 void
804  EdgeSet edgeSet(crossing.edges.begin(), crossing.edges.end());
805  for (std::vector<NBNode::Crossing>::iterator it = myNBNode.myCrossings.begin(); it != myNBNode.myCrossings.end(); ++it) {
806  EdgeSet edgeSet2((*it).edges.begin(), (*it).edges.end());
807  if (edgeSet == edgeSet2) {
808  (*it).width = crossing.width;
809  (*it).priority = crossing.priority;
810  myNet->refreshElement(this);
811  break;
812  }
813  }
814 }
815 
816 /****************************************************************************/
void drawName(const Position &pos, const SUMOReal scale, const GUIVisualizationTextSettings &settings, const SUMOReal angle=0) const
draw name of item
GUIVisualizationSizeSettings junctionSize
bool getKeepClear() const
Returns the keepClear flag.
Definition: NBNode.h:278
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition: GNEJunction.h:225
void rebuildCrossings(bool deleteOnly)
rebuilds crossing objects for this junction
GUIVisualizationTextSettings junctionName
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
void removeConnection(const NBConnection &conn, bool reconstruct=true)
removes the given connection from the traffic light if recontruct=true, reconstructs the logic and in...
bool myHasValidLogic
whether this junctions logic is valid
Definition: GNEJunction.h:228
void setResponsible(bool newVal)
set responsibility for deleting internal strctures
std::string myLogicStatus
modification status of the junction logic (all connections across this junction)
Definition: GNEJunction.h:222
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
static StringBijection< SumoXMLNodeType > NodeTypes
GNEEdge * retrieveEdge(const std::string &id, bool failHard=true)
get edge by id
Definition: GNENet.cpp:702
std::vector< Crossing > myCrossings
Vector of crossings.
Definition: NBNode.h:769
SUMOReal width
This lane&#39;s width.
Definition: NBNode.h:143
Whether vehicles must keep the junction clear.
SUMOReal getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:272
GNENet * myNet
the net to inform about updates
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
void invalidateShape()
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
PositionVector myPoly
the (outer) shape of the junction
Definition: NBNode.h:784
void refreshElement(GUIGlObject *o)
refreshes boundary information for o and update
Definition: GNENet.cpp:776
void markAsCreateEdgeSource()
marks as first junction in createEdge-mode
std::vector< GNEEdge * > getGNEEdges() const
Return all GNEEdges vinculated with this Junction.
SUMOReal getHeight() const
Returns the height of the boundary (y-axis)
Definition: Boundary.cpp:172
A loaded (complete) traffic light logic.
bool myAmCreateEdgeSource
whether this junction is the first junction for a newly creatededge
Definition: GNEJunction.h:219
static const NBConnection InvalidConnection
Definition: NBConnection.h:127
A container for traffic light definitions and built programs.
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition: NBNode.cpp:266
bool isValid(SumoXMLAttr key, const std::string &value)
void setLogicValid(bool valid, GNEUndoList *undoList=0, const std::string &status=GUESSED)
friend class GNEChange_TLS
Declare friend class.
Definition: GNEJunction.h:57
Stores the information about how to visualize structures.
GUIVisualizationSettings * getVisualisationSettings() const
get visualitation settings
bool hasCustomShape() const
return whether the shape was set by the user
Definition: NBNode.h:520
The representation of a single edge during network building.
Definition: NBEdge.h:71
TrafficLightType getType() const
get the algorithm type (static etc..)
const std::vector< Crossing > & getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.h:657
mode for editing tls
Definition: GNEViewNet.h:62
The base class for traffic light logic definitions.
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void scaleRelative(SUMOReal factor)
enlarges/shrinks the polygon by a factor based at the centroid
T MAX2(T a, T b)
Definition: StdDefs.h:75
static void drawBoxLine(const Position &beg, SUMOReal rot, SUMOReal visLength, SUMOReal width, SUMOReal offset=0)
Draws a thick line.
Definition: GLHelper.cpp:130
bool isSelected(GUIGlObjectType type, GUIGlID id)
Returns the information whether the object with the given type and id is selected.
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:87
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2490
static void drawFilledPoly(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:76
std::vector< GNEEdge * > getGNEIncomingEdges() const
Return incoming GNEEdges.
int editMode
the current NETEDIT mode (temporary)
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:86
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition: GNENet.cpp:1103
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
void selectTLS(bool selected)
notify the junction of being selected in tls-mode. (used to control drawing)
SUMOReal getWidth() const
Returns the width of the boudary (x-axis)
Definition: Boundary.cpp:166
const std::string & getID() const
Returns the id.
Definition: Named.h:66
bool myAmTLSSelected
whether this junction is selected in tls-mode
Definition: GNEJunction.h:231
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:324
void setCustomShape(const PositionVector &shape)
set the junction shape
Definition: NBNode.cpp:1728
void extract(NBTrafficLightDefinition *definition)
Extracts a traffic light definition from myDefinitions but keeps it in myExtracted for eventual * del...
void registerMove(GNEUndoList *undoList)
registers completed movement with the undoList
void updateShapesAndGeometries()
update shapes of all elements associated to the junction
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
removes a traffic light
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to copy the cursor position if geo projection is used, also builds an entry for copying the geo-position.
Boundary getBoundary() const
Returns the boundary of the junction.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
Position myOrigPos
restore point for undo
Definition: GNEJunction.h:209
SUMOReal scale
information about a lane&#39;s width (temporary, used for a single view)
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges.
Definition: NBNode.h:248
bool priority
whether the pedestrians have priority
Definition: NBNode.h:151
SUMOTime getOffset()
Returns the offset.
void renameJunction(GNEJunction *junction, const std::string &newID)
updates the map and reserves new id
Definition: GNENet.cpp:1094
static void drawFilledPolyTesselated(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:95
static void drawFilledCircle(SUMOReal width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:344
static bool isValidID(const std::string &value)
true if value is a valid sumo ID
static const std::string MODIFIED
feature has been manually modified (implies approval)
std::string getAttribute(SumoXMLAttr key) const
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:304
void invalidateIncomingConnections()
Definition: NBNode.cpp:1355
void removeCrossing(const EdgeVector &edges)
remove a pedestrian crossing from this node (identified by its edges)
Definition: NBNode.cpp:2540
The turning radius at an intersection in m.
std::set< NBEdge * > EdgeSet
Definition: NBCont.h:51
SUMOReal selectionScale
the current selection scaling in NETEDIT (temporary)
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
bool hasCommandGroup() const
Check if undoList has command group.
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:443
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
Definition: GNECrossing.h:51
void updateCrossingAttributes(NBNode::Crossing crossing)
modify the specified crossing (using friend privileges)
void setRadius(SUMOReal radius)
set the turning radius
Definition: NBNode.h:510
static StringBijection< TrafficLightType > TrafficLightTypes
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise, the sub-group will be added as a new command into parent group. A matching begin() must have been called previously.
Definition: GNEUndoList.cpp:93
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true)
get junction by id
Definition: GNENet.cpp:689
A list of positions.
bool isLogicValid()
whether this junction has a valid logic
friend class GNEChange_Attribute
declare friend class
T get(const std::string &str) const
void removeFromCrossings(GNEEdge *edge, GNEUndoList *undoList)
removes the given edge from all pedestrian crossings
const EdgeVector & getEdges() const
Returns all edges which participate in this node.
Definition: NBNode.h:256
bool showJunctionAsBubbles() const
return true if junction must be showed as bubbles
Definition: GNEViewNet.cpp:358
SUMOReal myMaxSize
The maximum size (in either x-, or y-dimension) for determining whether to draw or not...
Definition: GNEJunction.h:212
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
NBTrafficLightLogic * getLogic()
Returns the internal logic.
GUIColorer junctionColorer
The junction colorer.
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
const std::string getID() const
function to support debugging
void unMarkAsCreateEdgeSource()
removes mark as first junction in createEdge-mode
void setProgramID(const std::string &programID)
Sets the programID.
const T getColor(const SUMOReal value) const
const std::string & getProgramID() const
Returns the ProgramID.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
NBNode & myNBNode
A reference to the represented junction.
Definition: GNEJunction.h:206
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
std::vector< GNEEdge * > getGNEOutgoingEdges() const
Return incoming GNEEdges.
void setKeepClear(bool keepClear)
set the keepClear flag
Definition: NBNode.h:515
void invalidateTLS(GNEUndoList *undoList, const NBConnection &deletedConnection=NBConnection::InvalidConnection)
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any) ...
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:1722
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:55
Boundary & grow(SUMOReal by)
extends the boundary by the given amount
Definition: Boundary.cpp:232
virtual ~GNEJunction()
Destructor.
Definition: GNEJunction.cpp:83
void updateGeometry()
Update the boundary of the junction.
Definition: GNEJunction.cpp:92
SUMOReal area() const
Returns the area (0 for non-closed)
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges.
Definition: NBNode.h:240
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:803
void add(SUMOReal x, SUMOReal y, SUMOReal z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:90
Boundary myBoundary
The represented junction&#39;s boundary.
Definition: GNEJunction.h:215
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node.
Definition: NBNode.h:318
void setColor(const GUIVisualizationSettings &s, bool bubble) const
sets junction color depending on circumstances
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
void move(Position pos)
reposition the node at pos and informs the edges
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition: GNEEdge.cpp:248
The popup menu of a globject.
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:265
void buildSelectionPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to (de)select the object.
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:228
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:139
Represents a single node (junction) during network building.
Definition: NBNode.h:74
GUIGlID getGlID() const
Returns the numerical id of the object.
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
A definition of a pedestrian crossing.
Definition: NBNode.h:132
GNEJunction(NBNode &nbn, GNENet *net, bool loaded=false)
Constructor.
Definition: GNEJunction.cpp:69
SUMOReal getColorValue(const GUIVisualizationSettings &s, bool bubble) const
determines color value
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
#define SUMOReal
Definition: config.h:213
std::vector< GNECrossing * > myCrossings
the built crossing objects
Definition: GNEJunction.h:234
static const std::string GUESSED
feature has been reguessed (may still be unchanged be we can&#39;t tell (yet)
SUMOReal getExaggeration(const GUIVisualizationSettings &s, SUMOReal factor=20) const
return the drawing size including exaggeration and constantSize values
bool drawJunctionShape
whether the shape of the junction should be drawn
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
static const RGBColor selectionColor
color of selection
Definition: GNENet.h:96
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
mode for connecting lanes
Definition: GNEViewNet.h:60
mode for creating new edges
Definition: GNEViewNet.h:50
bool hasString(const std::string &str) const
void setPosition(Position pos)
reposition the NBNnode and nothing else
NBEdge * getNBEdge()
returns the internal NBEdge
Definition: GNEEdge.cpp:261
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:54
static GUIGlID getGif(GUITexture which)
returns a texture Gif previously defined in the enum GUITexture
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
void closePolygon()
ensures that the last position equals the first
bool checkIsRemovable() const
Definition: NBNode.cpp:1648
NBNode * getNBNode() const
Return net build node.
GUISelectedStorage gSelected
A global holder of selected objects.
void moveby(SUMOReal x, SUMOReal y, SUMOReal z=0)
Moves the boundary by the given amount.
Definition: Boundary.cpp:281
A window containing a gl-object&#39;s parameter.
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:1088
static void drawTexturedBox(int which, SUMOReal size)
Draws a named texture as a box with the given size.
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
Definition: NBNode.cpp:2654
static PositionVector parseShapeReporting(const std::string &shpdef, const std::string &objecttype, const char *objectid, bool &ok, bool allowEmpty, bool report=true)
Builds a PositionVector from a string representation, reporting occured errors.
void requireRecompute()
inform the net about the need for recomputation
Definition: GNENet.cpp:963
void addTrafficLight(NBTrafficLightDefinition *tlDef, bool forceInsert)
adds a traffic light
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
void markAsModified(GNEUndoList *undoList)
prevent re-guessing connections at this junction
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1082
a junction