SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 /****************************************************************************/
GUIVisualizationSizeSettings junctionSize
SUMOReal getExaggeration(const GUIVisualizationSettings &s, SUMOReal factor=20) const
return the drawing size including exaggeration and constantSize values
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
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
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges.
Definition: NBNode.h:240
std::string myLogicStatus
modification status of the junction logic (all connections across this junction)
Definition: GNEJunction.h:222
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
bool getKeepClear() const
Returns the keepClear flag.
Definition: NBNode.h:278
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
SUMOReal getHeight() const
Returns the height of the boundary (y-axis)
Definition: Boundary.cpp:172
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's width.
Definition: NBNode.h:143
Whether vehicles must keep the junction clear.
GNENet * myNet
the net to inform about updates
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
SUMOReal getWidth() const
Returns the width of the boudary (x-axis)
Definition: Boundary.cpp:166
void invalidateShape()
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
SUMOReal getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:272
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
bool hasString(const std::string &str) const
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 isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:304
bool isValid(SumoXMLAttr key, const std::string &value)
TrafficLightType getType() const
get the algorithm type (static etc..)
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.
const std::string & getProgramID() const
Returns the ProgramID.
The representation of a single edge during network building.
Definition: NBEdge.h:71
mode for editing tls
Definition: GNEViewNet.h:62
NBNode * getNBNode() const
Return net build node.
const std::vector< Crossing > & getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.h:657
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
static void drawFilledPoly(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition: GLHelper.cpp:76
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
bool hasCustomShape() const
return whether the shape was set by the user
Definition: NBNode.h:520
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)
bool checkIsRemovable() const
Definition: NBNode.cpp:1648
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
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
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.
GUIGlID getGlID() const
Returns the numerical id of the object.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
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's width (temporary, used for a single view)
void setColor(const GUIVisualizationSettings &s, bool bubble) const
sets junction color depending on circumstances
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
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges.
Definition: NBNode.h:248
static void drawFilledCircle(SUMOReal width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:344
const std::string & getID() const
Returns the id.
Definition: Named.h:66
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)
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
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
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:228
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)
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node.
Definition: NBNode.h:318
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
SUMOReal getColorValue(const GUIVisualizationSettings &s, bool bubble) const
determines color value
friend class GNEChange_Attribute
declare friend class
std::vector< GNEEdge * > getGNEEdges() const
Return all GNEEdges vinculated with this Junction.
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:265
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
void removeFromCrossings(GNEEdge *edge, GNEUndoList *undoList)
removes the given edge from all pedestrian crossings
SUMOReal myMaxSize
The maximum size (in either x-, or y-dimension) for determining whether to draw or not...
Definition: GNEJunction.h:212
const EdgeVector & getEdges() const
Returns all edges which participate in this node.
Definition: NBNode.h:256
const T getColor(const SUMOReal value) const
NBTrafficLightLogic * getLogic()
Returns the internal logic.
GUIColorer junctionColorer
The junction colorer.
void unMarkAsCreateEdgeSource()
removes mark as first junction in createEdge-mode
void setProgramID(const std::string &programID)
Sets the programID.
const std::string getID() const
function to support debugging
void drawName(const Position &pos, const SUMOReal scale, const GUIVisualizationTextSettings &settings, const SUMOReal angle=0) const
draw name of item
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:1722
NBNode & myNBNode
A reference to the represented junction.
Definition: GNEJunction.h:206
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
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) ...
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
bool hasCommandGroup() const
Check if undoList has command group.
virtual ~GNEJunction()
Destructor.
Definition: GNEJunction.cpp:83
void updateGeometry()
Update the boundary of the junction.
Definition: GNEJunction.cpp:92
void add(SUMOReal x, SUMOReal y, SUMOReal z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:90
Boundary getBoundary() const
Returns the boundary of the junction.
Boundary myBoundary
The represented junction's boundary.
Definition: GNEJunction.h:215
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
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.
std::vector< GNEEdge * > getGNEOutgoingEdges() const
Return incoming GNEEdges.
void buildSelectionPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to (de)select the object.
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:139
Represents a single node (junction) during network building.
Definition: NBNode.h:74
T get(const std::string &str) const
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
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
GUIVisualizationSettings * getVisualisationSettings() const
get visualitation settings
#define SUMOReal
Definition: config.h:214
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't tell (yet)
bool drawJunctionShape
whether the shape of the junction should be drawn
static const RGBColor selectionColor
color of selection
Definition: GNENet.h:96
mode for connecting lanes
Definition: GNEViewNet.h:60
std::vector< GNEEdge * > getGNEIncomingEdges() const
Return incoming GNEEdges.
mode for creating new edges
Definition: GNEViewNet.h:50
std::string getAttribute(SumoXMLAttr key) const
void setPosition(Position pos)
reposition the NBNnode and nothing else
NBEdge * getNBEdge()
returns the internal NBEdge
Definition: GNEEdge.cpp:261
SUMOReal area() const
Returns the area (0 for non-closed)
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:54
bool showJunctionAsBubbles() const
return true if junction must be showed as bubbles
Definition: GNEViewNet.cpp:358
static GUIGlID getGif(GUITexture which)
returns a texture Gif previously defined in the enum GUITexture
void closePolygon()
ensures that the last position equals the first
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
GUISelectedStorage gSelected
A global holder of selected objects.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:803
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's parameter.
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2490
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:1088
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1082
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
a junction