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-2017 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) :
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 }
80 
81 
83  if (myAmResponsible) {
84  delete &myNBNode;
85  }
87 }
88 
89 
90 void
92  const double EXTENT = 2;
94  myOrigPos.x() - EXTENT, myOrigPos.y() - EXTENT,
95  myOrigPos.x() + EXTENT, myOrigPos.y() + EXTENT);
96  if (myNBNode.getShape().size() > 0) {
98  }
101 }
102 
103 
104 void
106  // drop existent GNECrossings
108  // rebuild GNECrossings only if create crossings and walkingAreas in net is enabled
109  if (myNet->getNetBuilder()->haveNetworkCrossings() == true) {
110  // build new NBNode::Crossings and walking areas and create GNECrossings
112  const std::vector<NBNode::Crossing>& crossings = myNBNode.getCrossings();
113  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
114  myGNECrossings.push_back(new GNECrossing(this, (*it).id));
115  myGNECrossings.back()->incRef();
116  }
117  }
118 }
119 
120 
123  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
124  buildPopupHeader(ret, app);
128  buildPositionCopyEntry(ret, false);
129  //if (parent.getVisualisationSettings()->editMode != GNE_MODE_CONNECT) {
130  // // XXX if joinable
131  // new FXMenuCommand(ret, "Join adjacent edges", 0, &parent, MID_GNE_JOIN_EDGES);
132  //}
133  FXMenuCommand* mcCustomShape = new FXMenuCommand(ret, "Set custom shape", 0, &parent, MID_GNE_NODE_SHAPE);
134  FXMenuCommand* mcReplace = new FXMenuCommand(ret, "Replace by geometry node", 0, &parent, MID_GNE_NODE_REPLACE);
135  const int editMode = parent.getVisualisationSettings()->editMode;
136  const bool wrongMode = (editMode == GNE_MODE_CONNECT || editMode == GNE_MODE_TLS || editMode == GNE_MODE_CREATE_EDGE);
137  if (wrongMode) {
138  mcCustomShape->handle(&parent, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), 0);
139  }
140  // checkIsRemovable requiers turnarounds to be computed. This is ugly
141  if (myNBNode.getIncomingEdges().size() == 2 && myNBNode.getOutgoingEdges().size() == 2) {
143  }
144  if (wrongMode || !myNBNode.checkIsRemovable()) {
145  mcReplace->handle(&parent, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), 0);
146  }
147  // let the GNEViewNet store the popup position
148  (dynamic_cast<GNEViewNet&>(parent)).markPopupPosition();
149  return ret;
150 }
151 
152 
155  return 0;
156 }
157 
158 
159 Boundary
161  Boundary b = myBoundary;
162  b.grow(20);
163  return b;
164 }
165 
166 
167 void
169  glPushName(getGlID());
170  SUMOReal exaggeration = gSelected.isSelected(getType(), getGlID()) ? s.selectionScale : 1;
171  exaggeration *= s.junctionSize.getExaggeration(s);
172  if (s.scale * exaggeration * myMaxSize < 1.) {
173  // draw something simple so that selection still works
175  } else {
176  // node shape has been computed and is valid for drawing
177  const bool drawShape = myNBNode.getShape().size() > 0 && s.drawJunctionShape;
178  const bool drawBubble = (!drawShape || myNBNode.getShape().area() < 4) && s.drawJunctionShape; // magic threshold
179 
180  if (drawShape) {
181  setColor(s, false);
182  // recognize full transparency and simply don't draw
183  GLfloat color[4];
184  glGetFloatv(GL_CURRENT_COLOR, color);
185  if (color[3] != 0) {
186  glPushMatrix();
187  glTranslated(0, 0, getType());
188  PositionVector shape = myNBNode.getShape();
189  shape.closePolygon();
190  if (exaggeration > 1) {
191  shape.scaleRelative(exaggeration);
192  }
193  if (s.scale * exaggeration * myMaxSize < 40.) {
194  GLHelper::drawFilledPoly(shape, true);
195  } else {
197  }
198  glPopMatrix();
199  }
200  // Check if a buuble must be drawed over junction
202  setColor(s, true);
203  // recognize full transparency and simply don't draw
204  GLfloat color[4];
205  glGetFloatv(GL_CURRENT_COLOR, color);
206  if (color[3] != 0) {
207  glPushMatrix();
208  Position pos = myNBNode.getPosition();
209  glTranslated(pos.x(), pos.y(), getType() + 0.05);
210  GLHelper::drawFilledCircle(4 * exaggeration, 32);
211  glPopMatrix();
212  }
213  }
214  }
215  if (drawBubble) {
216  setColor(s, true);
217  // recognize full transparency and simply don't draw
218  GLfloat color[4];
219  glGetFloatv(GL_CURRENT_COLOR, color);
220  if (color[3] != 0) {
221  glPushMatrix();
222  Position pos = myNBNode.getPosition();
223  glTranslated(pos.x(), pos.y(), getType() - 0.05);
224  GLHelper::drawFilledCircle(4 * exaggeration, 32);
225  glPopMatrix();
226  }
227  }
228 
230  glPushMatrix();
231  Position pos = myNBNode.getPosition();
232  glTranslated(pos.x(), pos.y(), getType() + 0.1);
233  glColor3d(1, 1, 1);
234  const SUMOReal halfWidth = 32 / s.scale;
235  const SUMOReal halfHeight = 64 / s.scale;
236  GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GNETEXTURE_TLS), -halfWidth, -halfHeight, halfWidth, halfHeight);
237  glPopMatrix();
238  }
239  // draw crossings
240  if (s.editMode != GNE_MODE_TLS) {
241  for (std::vector<GNECrossing*>::const_iterator it = myGNECrossings.begin(); it != myGNECrossings.end(); it++) {
242  (*it)->drawGL(s);
243  }
244  }
245  // (optional) draw name @todo expose this setting
247  }
248  glPopName();
249 }
250 
251 Boundary
253  return myBoundary;
254 }
255 
256 
257 NBNode*
259  return &myNBNode;
260 }
261 
262 
263 
264 void
266  // Check if incoming edge was already inserted
267  std::vector<GNEEdge*>::iterator i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
268  if (i != myGNEIncomingEdges.end()) {
269  throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + toString(getTag()) + " with ID " + getID() + "'");
270  } else {
271  // Add edge into containers
272  myGNEIncomingEdges.push_back(edge);
273  myGNEEdges.push_back(edge);
274  }
275 }
276 
277 
278 void
280  // Check if outgoing edge was already inserted
281  std::vector<GNEEdge*>::iterator i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
282  if (i != myGNEOutgoingEdges.end()) {
283  throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + toString(getTag()) + " with ID " + getID() + "'");
284  } else {
285  // Add edge into containers
286  myGNEOutgoingEdges.push_back(edge);
287  myGNEEdges.push_back(edge);
288  }
289 }
290 
291 
292 void
294  // Check if incoming edge was already inserted
295  std::vector<GNEEdge*>::iterator i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
296  if (i == myGNEIncomingEdges.end()) {
297  throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + toString(getTag()) + " with ID " + getID() + "'");
298  } else {
299  // remove edge from containers
300  myGNEIncomingEdges.erase(i);
301  myGNEEdges.erase(std::find(myGNEEdges.begin(), myGNEEdges.end(), edge));
302  }
303 }
304 
305 
306 void
308  // Check if outgoing edge was already inserted
309  std::vector<GNEEdge*>::iterator i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
310  if (i == myGNEOutgoingEdges.end()) {
311  throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + toString(getTag()) + " with ID " + getID() + "'");
312  } else {
313  // remove edge from containers
314  myGNEOutgoingEdges.erase(i);
315  myGNEEdges.erase(std::find(myGNEEdges.begin(), myGNEEdges.end(), edge));
316  }
317 }
318 
319 
320 const std::vector<GNEEdge*>&
322  return myGNEEdges;
323 }
324 
325 
326 const std::vector<GNEEdge*>&
328  return myGNEIncomingEdges;
329 }
330 
331 
332 const std::vector<GNEEdge*>&
334  return myGNEOutgoingEdges;
335 }
336 
337 const std::vector<GNECrossing*>&
339  return myGNECrossings;
340 }
341 
342 void
344  myAmCreateEdgeSource = true;
345 }
346 
347 
348 void
350  myAmCreateEdgeSource = false;
351 }
352 
353 
354 void
355 GNEJunction::selectTLS(bool selected) {
356  myAmTLSSelected = selected;
357 }
358 
359 
360 void
362  const Position orig = myNBNode.getPosition();
363  setPosition(pos);
364  const EdgeVector& incident = getNBNode()->getEdges();
365  for (EdgeVector::const_iterator it = incident.begin(); it != incident.end(); it++) {
366  GNEEdge* edge = myNet->retrieveEdge((*it)->getID());
367  edge->updateJunctionPosition(this, orig);
368  }
369  // Update shapes without include connections, because the aren't showed in Move mode
371 }
372 
373 
374 void
376  Position newPos = myNBNode.getPosition();
377  std::string newPosValue = getAttribute(SUMO_ATTR_POSITION);
378  // actually the geometry is already up to date
379  // set the restore point to the end of the last change-set
381  // do not execute the command to avoid changing the edge geometry twice
382  undoList->add(new GNEChange_Attribute(this, SUMO_ATTR_POSITION, newPosValue), false);
383  setPosition(newPos);
384  // Refresh element to avoid grabbing problems
385  myNet->refreshElement(this);
386 }
387 
388 
389 void
391  // First declare three sets with all affected GNEJunctions, GNEEdges and GNEConnections
392  std::set<GNEJunction*> affectedJunctions;
393  std::set<GNEEdge*> affectedEdges;
394  // Iterate over GNEEdges
395  for (std::vector<GNEEdge*>::const_iterator i = myGNEEdges.begin(); i != myGNEEdges.end(); i++) {
396  // Add source and destiny junctions
397  affectedJunctions.insert((*i)->getGNEJunctionSource());
398  affectedJunctions.insert((*i)->getGNEJunctionDestiny());
399  // Obtain neighbors of Junction source
400  for (std::vector<GNEEdge*>::const_iterator j = (*i)->getGNEJunctionSource()->getGNEEdges().begin(); j != (*i)->getGNEJunctionSource()->getGNEEdges().end(); j++) {
401  affectedEdges.insert(*j);
402  }
403  // Obtain neighbors of Junction destiny
404  for (std::vector<GNEEdge*>::const_iterator j = (*i)->getGNEJunctionDestiny()->getGNEEdges().begin(); j != (*i)->getGNEJunctionDestiny()->getGNEEdges().end(); j++) {
405  affectedEdges.insert(*j);
406  }
407  }
408  // Iterate over affected Junctions
409  for (std::set<GNEJunction*>::iterator i = affectedJunctions.begin(); i != affectedJunctions.end(); i++) {
410  // Check that Node doesn't have a custom shape
411  if ((*i)->getNBNode()->hasCustomShape() == false) {
412  // Compute polygon
413  (*i)->getNBNode()->sortEdges(false);
414  (*i)->getNBNode()->computeNodeShape(-1);
415  }
416  // Update geometry of Junction
417  (*i)->updateGeometry();
418  }
419  // Iterate over affected Edges
420  for (std::set<GNEEdge*>::iterator i = affectedEdges.begin(); i != affectedEdges.end(); i++) {
421  // Compute full edge shape because this funcion is related to computeNodeShape
422  (*i)->getNBEdge()->computeEdgeShape();
423  // Update edge geometry
424  (*i)->updateGeometry();
425  }
426  // Finally update geometry of this edge
427  updateGeometry();
428  // Update view to show the new shapes
429  if (myNet->getViewNet()) {
430  myNet->getViewNet()->update();
431  }
432 }
433 
434 
435 void
437  if (!myNBNode.hasCustomShape()) {
438  myNBNode.myPoly.clear();
440  }
441 }
442 
443 
444 void
445 GNEJunction::setLogicValid(bool valid, GNEUndoList* undoList, const std::string& status) {
446  myHasValidLogic = valid;
447  if (!valid) {
448  assert(undoList != 0);
449  assert(undoList->hasCommandGroup());
451  EdgeVector incoming = myNBNode.getIncomingEdges();
452  for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
453  NBEdge* srcNBE = *it;
454  NBEdge* turnEdge = srcNBE->getTurnDestination();
455  GNEEdge* srcEdge = myNet->retrieveEdge(srcNBE->getID());
456  // Make a copy of connections
457  std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
458  // delete in reverse so that undoing will add connections in the original order
459  for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
460  bool hasTurn = con_it->toEdge == turnEdge;
461  undoList->add(new GNEChange_Connection(srcEdge, *con_it, false), true);
462  // needs to come after GNEChange_Connection
463  // XXX bug: this code path will not be used on a redo!
464  if (hasTurn) {
465  myNet->addExplicitTurnaround(srcNBE->getID());
466  }
467  }
468  undoList->add(new GNEChange_Attribute(srcEdge, GNE_ATTR_MODIFICATION_STATUS, status), true);
469  }
470  undoList->add(new GNEChange_Attribute(this, GNE_ATTR_MODIFICATION_STATUS, status), true);
471  invalidateTLS(undoList);
472  } else {
474  }
475 }
476 
477 
478 void
480  EdgeVector incoming = myNBNode.getIncomingEdges();
481  for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
482  NBEdge* srcNBE = *it;
483  GNEEdge* srcEdge = myNet->retrieveEdge(srcNBE->getID());
484  undoList->add(new GNEChange_Attribute(srcEdge, GNE_ATTR_MODIFICATION_STATUS, MODIFIED), true);
485  }
486 }
487 
488 
489 void
490 GNEJunction::invalidateTLS(GNEUndoList* undoList, const NBConnection& deletedConnection) {
491  assert(undoList->hasCommandGroup());
492  // NBLoadedSUMOTLDef becomes invalid, replace with NBOwnTLDef which will be dynamically recomputed
493  const std::set<NBTrafficLightDefinition*> tls = myNBNode.getControllingTLS(); // make a copy!
494  for (std::set<NBTrafficLightDefinition*>::iterator it = tls.begin(); it != tls.end(); it++) {
495  NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(*it);
496  if (tlDef != 0) {
497  NBTrafficLightDefinition* replacementDef = 0;
498  std::string newID = tlDef->getID(); // + "_reguessed"; // changes due to reguessing will be visible in diff
499  if (deletedConnection != NBConnection::InvalidConnection) {
500  // create replacement before deleting the original because deletion will mess up saving original nodes
501  NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(tlDef, tlDef->getLogic());
502  repl->removeConnection(deletedConnection);
503  replacementDef = repl;
504  } else {
505  replacementDef = new NBOwnTLDef(newID, tlDef->getOffset(), tlDef->getType());
506  replacementDef->setProgramID(tlDef->getProgramID());
507  }
508  undoList->add(new GNEChange_TLS(this, tlDef, false), true);
509  undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
510  // the removed traffic light may have controlled more than one junction. These too have become invalid now
511  const std::vector<NBNode*> coNodes = tlDef->getNodes(); // make a copy!
512  for (std::vector<NBNode*>::const_iterator it_node = coNodes.begin(); it_node != coNodes.end(); it_node++) {
513  GNEJunction* sharing = myNet->retrieveJunction((*it_node)->getID());
514  undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
515  undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
516  }
517  }
518  }
519 }
520 
521 void
523  // @todo implement GNEChange_Crossing
524  UNUSED_PARAMETER(undoList);
525  // make a copy because the original will be modified
526  const std::vector<NBNode::Crossing> crossings = myNBNode.getCrossings();
527  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
528  EdgeSet edgeSet((*it).edges.begin(), (*it).edges.end());
529  if (edgeSet.count(edge->getNBEdge()) == 1) {
530  myNBNode.removeCrossing((*it).edges);
531  }
532  }
533 }
534 
535 
536 bool
538  return myHasValidLogic;
539 }
540 
541 
542 void
544  // delete all GNECrossing
545  for (std::vector<GNECrossing*>::const_iterator it = myGNECrossings.begin(); it != myGNECrossings.end(); it++) {
546  (*it)->decRef();
547  if ((*it)->unreferenced()) {
548  delete *it;
549  }
550  }
551  myGNECrossings.clear();
552 }
553 
554 
555 std::string
557  switch (key) {
558  case SUMO_ATTR_ID:
559  return getMicrosimID();
560  break;
561  case SUMO_ATTR_POSITION:
562  return toString(myNBNode.getPosition());
563  break;
564  case SUMO_ATTR_TYPE:
565  return toString(myNBNode.getType());
566  break;
568  return myLogicStatus;
569  break;
570  case SUMO_ATTR_SHAPE:
571  return toString(myNBNode.getShape());
572  case SUMO_ATTR_RADIUS:
573  return toString(myNBNode.getRadius());
574  case SUMO_ATTR_TLTYPE:
575  // @todo this causes problems if the node were to have multiple programs of different type (plausible)
576  return myNBNode.isTLControlled() ? toString((*myNBNode.getControllingTLS().begin())->getType()) : "";
577  case SUMO_ATTR_TLID:
578  return myNBNode.isTLControlled() ? toString((*myNBNode.getControllingTLS().begin())->getID()) : "";
580  return myNBNode.getKeepClear() ? "true" : "false";
581  default:
582  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
583  }
584 }
585 
586 
587 void
588 GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
589  if (value == getAttribute(key)) {
590  return; //avoid needless changes, later logic relies on the fact that attributes have changed
591  }
592  switch (key) {
593  case SUMO_ATTR_ID:
594  case SUMO_ATTR_POSITION:
596  case SUMO_ATTR_SHAPE:
597  case SUMO_ATTR_RADIUS:
598  case SUMO_ATTR_TLTYPE:
600  undoList->add(new GNEChange_Attribute(this, key, value), true);
601  break;
602  case SUMO_ATTR_TYPE: {
603  undoList->p_begin("change " + toString(getTag()) + " type");
605  if (!getNBNode()->isTLControlled()) {
606  // create new traffic light
607  undoList->add(new GNEChange_TLS(this, 0, true), true);
608  }
609  } else if (getNBNode()->isTLControlled()) {
610  // delete old traffic light
611  // make a copy because we will modify the original
612  const std::set<NBTrafficLightDefinition*> tls = myNBNode.getControllingTLS();
613  for (std::set<NBTrafficLightDefinition*>::iterator it = tls.begin(); it != tls.end(); it++) {
614  undoList->add(new GNEChange_TLS(this, *it, false), true);
615  }
616  }
617  // must be the final step, otherwise we do not know which traffic lights to remove via GNEChange_TLS
618  undoList->add(new GNEChange_Attribute(this, key, value), true);
619  undoList->p_end();
620  break;
621  }
622  case SUMO_ATTR_TLID: {
623  undoList->p_begin("change " + toString(SUMO_TAG_TRAFFIC_LIGHT) + " id");
624  // junction is already controlled, remove from previous tls
625  const std::set<NBTrafficLightDefinition*> tls = myNBNode.getControllingTLS();
626  for (std::set<NBTrafficLightDefinition*>::iterator it = tls.begin(); it != tls.end(); it++) {
627  undoList->add(new GNEChange_TLS(this, *it, false), true);
628  }
630  const std::map<std::string, NBTrafficLightDefinition*>& programs = tlCont.getPrograms(value);
631  if (programs.size() > 0) {
632  // add to existing tls definitions
633  for (std::map<std::string, NBTrafficLightDefinition*>::const_iterator it = programs.begin(); it != programs.end(); it++) {
634  NBTrafficLightDefinition* oldTLS = it->second;
635  if (dynamic_cast<NBOwnTLDef*>(oldTLS) != 0) {
636  undoList->add(new GNEChange_TLS(this, oldTLS, true), true);
637  } else {
638  // delete and re-create the definition because the loaded phases are now invalid
639  const std::vector<NBNode*> nodes = oldTLS->getNodes();
640  for (std::vector<NBNode*>::const_iterator it_node = nodes.begin(); it_node != nodes.end(); ++it_node) {
641  GNEJunction* oldJunction = myNet->retrieveJunction((*it_node)->getID());
642  undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
643  }
644  undoList->add(new GNEChange_TLS(this, 0, true, false, value), true);
646  // re-add existing nodes
647  for (std::vector<NBNode*>::const_iterator it_node = nodes.begin(); it_node != nodes.end(); ++it_node) {
648  GNEJunction* oldJunction = myNet->retrieveJunction((*it_node)->getID());
649  undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
650  }
651  }
652  }
653  } else {
654  // create new traffic light
655  undoList->add(new GNEChange_TLS(this, 0, true, false, value), true);
656  }
657  undoList->p_end();
658  break;
659  }
660  default:
661  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
662  }
663 }
664 
665 
666 bool
667 GNEJunction::isValid(SumoXMLAttr key, const std::string& value) {
668  switch (key) {
669  case SUMO_ATTR_ID:
670  return isValidID(value) && myNet->retrieveJunction(value, false) == 0;
671  break;
672  case SUMO_ATTR_TYPE:
674  break;
675  case SUMO_ATTR_POSITION:
676  bool ok;
677  return GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, false).size() == 1;
678  break;
679  case SUMO_ATTR_SHAPE: {
680  bool ok = true;
681  PositionVector shape = GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, true);
682  return ok;
683  break;
684  }
685  case SUMO_ATTR_RADIUS:
686  return canParse<SUMOReal>(value);
687  break;
688  case SUMO_ATTR_TLTYPE:
690  case SUMO_ATTR_TLID:
691  return myNBNode.isTLControlled() && value != "";
693  return value == "true" || value == "false";
694  break;
695  default:
696  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
697  }
698 }
699 
700 
701 void
703  myAmResponsible = newVal;
704 }
705 
706 // ===========================================================================
707 // private
708 // ===========================================================================
709 
710 void
711 GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value) {
712  switch (key) {
713  case SUMO_ATTR_ID:
714  myNet->renameJunction(this, value);
715  break;
716  case SUMO_ATTR_TYPE: {
718  break;
719  }
720  case SUMO_ATTR_POSITION:
721  bool ok;
722  myOrigPos = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, false)[0];
723  move(myOrigPos);
724  // Refresh element to avoid grabbing problems
725  myNet->refreshElement(this);
726  break;
728  if (myLogicStatus == GUESSED && value != GUESSED) {
729  // clear guessed connections. previous connections will be restored
731  // Clear GNEConnections of incoming edges
732  for (std::vector<GNEEdge*>::iterator i = myGNEIncomingEdges.begin(); i != myGNEIncomingEdges.end(); i++) {
733  (*i)->clearGNEConnections();
734  }
735  }
736  myLogicStatus = value;
737  break;
738  case SUMO_ATTR_SHAPE: {
739  bool ok;
740  const PositionVector shape = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, true);
741  myNBNode.setCustomShape(shape);
742  break;
743  }
744  case SUMO_ATTR_RADIUS:
745  myNBNode.setRadius(parse<SUMOReal>(value));
746  break;
747  case SUMO_ATTR_TLTYPE: {
748  const std::set<NBTrafficLightDefinition*> tls = myNBNode.getControllingTLS();
749  for (std::set<NBTrafficLightDefinition*>::iterator it = tls.begin(); it != tls.end(); it++) {
750  (*it)->setType(SUMOXMLDefinitions::TrafficLightTypes.get(value));
751  }
752  break;
753  }
755  myNBNode.setKeepClear(value == "true");
756  break;
757  default:
758  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
759  }
760 }
761 
762 
763 void
765  const Position& orig = myNBNode.getPosition();
766  myBoundary.moveby(pos.x() - orig.x(), pos.y() - orig.y());
768  /* //reshift also shifts the junction shape. this is not needed because shape is not yet computed
769  * const Position& orig = myNBNode.getPosition();
770  * myNBNode.reshiftPosition(pos.x() - orig.x(), pos.y() - orig.y());
771  */
772 }
773 
774 
775 SUMOReal
777  switch (s.junctionColorer.getActive()) {
778  case 0:
779  if (bubble) {
780  return 1;
781  } else {
782  return 0;
783  }
784  case 1:
785  return gSelected.isSelected(getType(), getGlID()) ? 1 : 0;
786  case 2:
787  switch (myNBNode.getType()) {
789  return 0;
791  return 1;
792  case NODETYPE_PRIORITY:
793  return 2;
795  return 3;
797  return 4;
799  return 5;
800  case NODETYPE_DISTRICT:
801  return 6;
802  case NODETYPE_NOJUNCTION:
803  return 7;
804  case NODETYPE_DEAD_END:
806  return 8;
807  case NODETYPE_UNKNOWN:
808  case NODETYPE_INTERNAL:
809  assert(false);
810  return 8;
812  return 9;
813  case NODETYPE_ZIPPER:
814  return 10;
816  return 11;
818  return 12;
819  }
820  default:
821  assert(false);
822  return 0;
823  }
824 }
825 
826 
827 void
828 GNEJunction::setColor(const GUIVisualizationSettings& s, bool bubble) const {
830  // override with special colors (unless the color scheme is based on selection)
833  }
834  if (myAmCreateEdgeSource) {
835  glColor3d(0, 1, 0);
836  }
837 }
838 
839 void
842  tlCont.insert(tlDef, forceInsert); // may return false for tlDef which controls multiple junctions
843  tlDef->addNode(&myNBNode);
844 }
845 
846 
847 void
850  if (tlDef->getNodes().size() == 1) {
851  tlCont.extract(tlDef);
852  }
854 }
855 
856 /****************************************************************************/
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:249
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:252
void setResponsible(bool newVal)
set responsibility for deleting internal strctures
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:240
std::string myLogicStatus
modification status of the junction logic (all connections across this junction)
Definition: GNEJunction.h:246
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:267
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
void addIncomingGNEEdge(GNEEdge *edge)
add incoming GNEEdge
static StringBijection< SumoXMLNodeType > NodeTypes
GNEEdge * retrieveEdge(const std::string &id, bool failHard=true)
get edge by id
Definition: GNENet.cpp:732
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 removeIncomingGNEEdge(GNEEdge *edge)
remove incoming GNEEdge
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
begin/end of the description of a junction
SUMOReal getRadius() const
Returns the turning radius of this node.
Definition: NBNode.h:262
PositionVector myPoly
the (outer) shape of the junction
Definition: NBNode.h:747
void refreshElement(GUIGlObject *o)
refreshes boundary information for o and update
Definition: GNENet.cpp:806
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:243
static GUIGlID getTexture(GUITexture which)
returns a texture previously defined in the enum GUITexture
static const NBConnection InvalidConnection
Definition: NBConnection.h:127
A container for traffic light definitions and built programs.
std::vector< GNEEdge * > myGNEIncomingEdges
vector with the incomings GNEEdges vinculated with this junction
Definition: GNEJunction.h:227
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:288
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:63
NBNode * getNBNode() const
Return net build node.
const std::vector< Crossing > & getCrossings() const
return this junctions pedestrian crossings
Definition: NBNode.h:620
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.
link,node: the traffic light id responsible for this link
void scaleRelative(SUMOReal factor)
enlarges/shrinks the polygon by a factor based at the centroid
T MAX2(T a, T b)
Definition: StdDefs.h:70
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:493
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition: GNENet.cpp:1135
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
check if node is removable
Definition: NBNode.cpp:1646
bool myAmTLSSelected
whether this junction is selected in tls-mode
Definition: GNEJunction.h:255
const std::vector< GNEEdge * > & getGNEEdges() const
Returns all GNEEdges vinculated with this Junction.
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:1726
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:38
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:233
SUMOReal scale
information about a lane&#39;s width (temporary, used for a single view)
void setColor(const GUIVisualizationSettings &s, bool bubble) const
sets junction color depending on circumstances
whether a feature has been loaded,guessed,modified or approved
SUMOTime getOffset()
Returns the offset.
void renameJunction(GNEJunction *junction, const std::string &newID)
updates the map and reserves new id
Definition: GNENet.cpp:1126
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.
void removeOutgoingGNEEdge(GNEEdge *edge)
remove outgoing GNEEdge
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:245
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()
invalidate incoming connections
Definition: NBNode.cpp:1353
void removeCrossing(const EdgeVector &edges)
remove a pedestrian crossing from this node (identified by its edges)
Definition: NBNode.cpp:2557
const Position & getPosition() const
Definition: NBNode.h:232
The turning radius at an intersection in m.
std::set< NBEdge * > EdgeSet
container for unique edges
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 (The set of tls that control this node) ...
Definition: NBNode.h:298
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
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 buildCrossingsAndWalkingAreas(bool discardInvalid=true)
build crossings, and walkingareas. Also removes invalid loaded crossings if wished ...
Definition: NBNode.cpp:2012
void setRadius(SUMOReal radius)
set the turning radius
Definition: NBNode.h:483
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
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:719
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
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:257
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
turn junction into geometry node
Definition: GUIAppEnum.h:609
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:236
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node) ...
Definition: NBNode.h:250
void dropGNECrossings()
drop crossings
const T getColor(const SUMOReal value) const
NBTrafficLightLogic * getLogic()
Returns the internal logic.
node: the type of traffic light
edge: the shape in xml-definition
GUIColorer junctionColorer
The junction colorer.
void addOutgoingGNEEdge(GNEEdge *edge)
add outgoing GNEEdge
std::vector< GNEEdge * > myGNEEdges
vector with the GNEEdges vinculated with this junction
Definition: GNEJunction.h:224
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
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:1720
NBNode & myNBNode
A reference to the represented junction.
Definition: GNEJunction.h:221
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:488
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) ...
begin/end of the description of an edge
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:54
Boundary & grow(SUMOReal by)
extends the boundary by the given amount
Definition: Boundary.cpp:238
bool hasCommandGroup() const
Check if undoList has command group.
virtual ~GNEJunction()
Destructor.
Definition: GNEJunction.cpp:82
edit junction shape
Definition: GUIAppEnum.h:607
bool haveNetworkCrossings()
notify about style of loaded network (Without Crossings)
Definition: NBNetBuilder.h:175
void updateGeometry()
Update the boundary of the junction.
Definition: GNEJunction.cpp:91
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&#39;s boundary.
Definition: GNEJunction.h:239
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:41
std::vector< GNECrossing * > myGNECrossings
the built crossing objects
Definition: GNEJunction.h:258
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
void rebuildGNECrossings()
rebuilds crossing objects for this junction
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:245
The popup menu of a globject.
std::vector< GNEEdge * > myGNEOutgoingEdges
vector with the outgoings GNEEdges vinculated with this junction
Definition: GNEJunction.h:230
void buildSelectionPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to (de)select the object.
Represents a single node (junction) during network building.
Definition: NBNode.h:75
T get(const std::string &str) const
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
GNEJunction(NBNode &nbn, GNENet *net, bool loaded=false)
Constructor.
Definition: GNEJunction.cpp:69
SumoXMLTag getTag() const
get XML Tag assigned to this object
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:208
static const std::string GUESSED
feature has been reguessed (may still be unchanged be we can&#39;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
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
mode for connecting lanes
Definition: GNEViewNet.h:61
mode for creating new edges
Definition: GNEViewNet.h:51
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:258
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:387
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:810
void moveby(SUMOReal x, SUMOReal y, SUMOReal z=0)
Moves the boundary by the given amount.
Definition: Boundary.cpp:287
A window containing a gl-object&#39;s parameter.
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2527
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition: GNENet.cpp:1120
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1114
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:2682
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:978
void addTrafficLight(NBTrafficLightDefinition *tlDef, bool forceInsert)
adds a traffic light
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
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
NBNetBuilder * getNetBuilder() const
get net builder
Definition: GNENet.cpp:1001