SUMO - Simulation of Urban MObility
GNEEdge.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
17 // A road/street connecting two junctions (netedit-version, adapted from GUIEdge)
18 // Basically a container for an NBEdge with drawing and editing capabilities
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #ifdef _MSC_VER
26 #include <windows_config.h>
27 #else
28 #include <config.h>
29 #endif
30 
31 #include <vector>
32 #include <cmath>
33 #include <string>
34 #include <algorithm>
37 #include <utils/geom/GeomHelper.h>
39 #include <utils/geom/bezier.h>
40 #include <utils/gui/div/GLHelper.h>
43 
44 #include "GNEEdge.h"
45 #include "GNENet.h"
46 #include "GNEViewNet.h"
47 #include "GNEUndoList.h"
48 #include "GNEChange_Attribute.h"
49 #include "GNEChange_Lane.h"
50 #include "GNEJunction.h"
51 #include "GNELane.h"
52 #include "GNEAdditional.h"
53 #include "GNEConnection.h"
54 #include "GNERouteProbe.h"
55 #include "GNEVaporizer.h"
56 #include "GNECrossing.h"
57 #include "GNEChange_Additional.h"
58 
59 //#define DEBUG_SMOOTH_GEOM
60 //#define DEBUGCOND(obj) (true)
61 
62 // ===========================================================================
63 // static
64 // ===========================================================================
66 
67 // ===========================================================================
68 // members methods
69 // ===========================================================================
70 GNEEdge::GNEEdge(NBEdge& nbe, GNENet* net, bool wasSplit, bool loaded):
71  GNENetElement(net, nbe.getID(), GLO_EDGE, SUMO_TAG_EDGE, ICON_EDGE),
72  myNBEdge(nbe) ,
73  myGNEJunctionSource(myNet->retrieveJunction(myNBEdge.getFromNode()->getID())),
74  myGNEJunctionDestiny(myNet->retrieveJunction(myNBEdge.getToNode()->getID())),
75  myOrigShape(nbe.getInnerGeometry()),
76  myLanes(0),
77  myAmResponsible(false),
78  myWasSplit(wasSplit),
79  myConnectionStatus(loaded ? LOADED : GUESSED) {
80  // Create lanes
81  int numLanes = myNBEdge.getNumLanes();
82  myLanes.reserve(numLanes);
83  for (int i = 0; i < numLanes; i++) {
84  myLanes.push_back(new GNELane(*this, i));
85  myLanes.back()->incRef("GNEEdge::GNEEdge");
86  }
87  // update Lane geometries
88  for (LaneVector::iterator i = myLanes.begin(); i != myLanes.end(); i++) {
89  (*i)->updateGeometry();
90  }
91 }
92 
93 
95  // Delete references to this eddge in lanes
96  for (auto i : myLanes) {
97  i->decRef("GNEEdge::~GNEEdge");
98  if (i->unreferenced()) {
99  // show extra information for tests
100  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
101  WRITE_WARNING("Deleting unreferenced " + toString(i->getTag()) + " '" + i->getID() + "' in GNEEdge destructor");
102  }
103  delete i;
104  }
105  }
106  // delete references to this eddge in connections
107  for (auto i : myGNEConnections) {
108  i->decRef("GNEEdge::~GNEEdge");
109  if (i->unreferenced()) {
110  // show extra information for tests
111  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
112  WRITE_WARNING("Deleting unreferenced " + toString(i->getTag()) + " '" + i->getID() + "' in GNEEdge destructor");
113  }
114  delete i;
115  }
116  }
117  if (myAmResponsible) {
118  delete &myNBEdge;
119  }
120 }
121 
122 
123 void
125  // Update geometry of lanes
126  for (auto i : myLanes) {
127  i->updateGeometry();
128  }
129  // Update geometry of additionals childs vinculated to this edge
130  for (auto i : myAdditionalChilds) {
131  i->updateGeometry();
132  }
133  // Update geometry of additional parents vinculated to this edge
134  for (auto i : myAdditionalParents) {
135  i->updateGeometry();
136  }
137  // refresh element
138  myNet->refreshElement(this);
139 }
140 
141 
142 int
143 GNEEdge::getVertexIndex(const Position& pos, bool createIfNoExist) {
144  PositionVector innerGeometry = myNBEdge.getInnerGeometry();
145  // first check if vertex already exists in the inner geometry
146  for (auto i : innerGeometry) {
147  if (i.distanceTo2D(pos) < SNAP_RADIUS) {
148  return innerGeometry.indexOfClosest(i);
149  }
150  }
151  // if vertex doesn't exist, insert it
152  if (createIfNoExist) {
153  if (innerGeometry.size() == 0) {
154  innerGeometry.push_back(pos);
155  setGeometry(innerGeometry, true);
156  return 0;
157  } else {
158  PositionVector entireGeometry = myNBEdge.getGeometry();
159  int index = entireGeometry.insertAtClosest(pos);
160  setGeometry(entireGeometry, false);
161  return (index - 1);
162  }
163  } else {
164  return -1;
165  }
166 }
167 
168 
169 int
170 GNEEdge::getVertexIndex(const double offset, bool createIfNoExist) {
171  if (offset < myNBEdge.getGeometry().length()) {
172  return getVertexIndex(myNBEdge.getGeometry().positionAtOffset2D(offset), createIfNoExist);
173  } else {
174  return -1;
175  }
176 }
177 
178 
179 int
180 GNEEdge::moveVertexShape(const int index, const Position& oldPos, const Position& offset) {
181  // obtain inner geometry of edge
182  PositionVector edgeGeometry = myNBEdge.getInnerGeometry();
183  // Make sure that index is valid AND ins't the first and last index
184  if (index != -1) {
185  // check that index is correct before change position
186  if (index < (int)edgeGeometry.size()) {
187  // change position of vertex
188  edgeGeometry[index] = oldPos;
189  edgeGeometry[index].add(offset);
190  // update edge's geometry
191  setGeometry(edgeGeometry, true);
192  return index;
193  } else {
194  throw InvalidArgument("Index greater than shape size");
195  }
196  } else {
197  return index;
198  }
199 }
200 
201 
202 void
203 GNEEdge::moveEntireShape(const PositionVector& oldShape, const Position& offset) {
204  // make a copy of the old shape to change it
205  PositionVector modifiedShape = oldShape;
206  // change all points of the inner geometry using offset
207  for (auto& i : modifiedShape) {
208  i.add(offset);
209  }
210  // restore modified shape
211  setGeometry(modifiedShape, true);
212  // refresh element
213  myNet->refreshElement(this);
214 }
215 
216 
217 void
219  // restore original shape into shapeToCommit
220  PositionVector innerShapeToCommit = myNBEdge.getInnerGeometry();
221  // first check if second and penultimate ins't in Junction's buubles
223  if (myNBEdge.getGeometry().size() > 2 && myNBEdge.getGeometry()[0].distanceTo(myNBEdge.getGeometry()[1]) < buubleRadius) {
224  innerShapeToCommit.removeClosest(innerShapeToCommit[0]);
225  }
226  if (myNBEdge.getGeometry().size() > 2 && myNBEdge.getGeometry()[(int)myNBEdge.getGeometry().size() - 2].distanceTo(myNBEdge.getGeometry()[(int)myNBEdge.getGeometry().size() - 1]) < buubleRadius) {
227  innerShapeToCommit.removeClosest(innerShapeToCommit[(int)innerShapeToCommit.size() - 1]);
228  }
229  // second check if double points has to be removed
230  innerShapeToCommit.removeDoublePoints(SNAP_RADIUS);
231  // show warning if some of edge's shape was merged
232  if (innerShapeToCommit.size() != myNBEdge.getInnerGeometry().size()) {
233  WRITE_WARNING("Merged shape's point")
234  }
235  // restore old geometry to allow change attribute
236  setGeometry(oldShape, true);
237  // commit new shape
238  undoList->p_begin("moving " + toString(SUMO_ATTR_SHAPE) + " of " + toString(getTag()));
239  undoList->p_add(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(innerShapeToCommit)));
240  undoList->p_end();
241 }
242 
243 
244 void
245 GNEEdge::deleteGeometryPoint(const Position& pos, bool allowUndo) {
246  // obtain index and remove point
247  PositionVector modifiedShape = myNBEdge.getInnerGeometry();
248  int index = modifiedShape.indexOfClosest(pos);
249  modifiedShape.erase(modifiedShape.begin() + index);
250  // set new shape depending of allowUndo
251  if (allowUndo) {
252  myNet->getViewNet()->getUndoList()->p_begin("delete geometry point");
255  } else {
256  // set new shape
257  setGeometry(modifiedShape, true);
258  }
259 }
260 
261 
262 void
264  Position delta = junction->getNBNode()->getPosition() - origPos;
266  // geometry endpoint need not equal junction position hence we modify it with delta
267  if (junction == myGNEJunctionSource) {
268  geom[0].add(delta);
269  } else {
270  geom[-1].add(delta);
271  }
272  setGeometry(geom, false);
273 }
274 
275 
276 Boundary
278  Boundary ret;
279  for (auto i : myLanes) {
280  ret.add(i->getBoundary());
281  }
282  ret.grow(10); // !!! magic value
283  return ret;
284 }
285 
286 bool
288  double angleBetweenOriginAndDestiny = myNBEdge.getGeometry().beginEndAngle();
289  return (angleBetweenOriginAndDestiny < -1.5707) || (angleBetweenOriginAndDestiny > 1.5707);
290 }
291 
292 
293 Boundary
295  Boundary b = getBoundary();
296  b.grow(20);
297  return b;
298 }
299 
300 
303  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
304  buildPopupHeader(ret, app);
307  // build selection and show parameters menu
310  // build position copy entry
311  buildPositionCopyEntry(ret, false);
312  return ret;
313 }
314 
315 
318  return myGNEJunctionSource;
319 }
320 
321 
324  return myGNEJunctionDestiny;
325 }
326 
327 
328 GNEEdge*
331 }
332 
333 
334 void
336  /* do something different for connectors?
337  if (myNBEdge.isMacroscopicConnector()) {
338  }
339  */
340  // draw the lanes
341  for (auto i : myLanes) {
342  i->drawGL(s);
343  }
344  // draw the connections
345  if (s.scale >= 2) {
346  for (auto i : myGNEConnections) {
347  i->drawGL(s);
348  }
349  }
350 
351  // draw geometry hints
352  if (s.scale * SNAP_RADIUS > 1.) { // check whether it is not too small
353  GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
354  if (gSelected.isSelected(getType(), getGlID()) && s.laneColorer.getActive() != 1) {
355  // override with special colors (unless the color scheme is based on selection)
356  GLHelper::setColor(GNENet::selectionColor.changedBrightness(-20));
357  }
358  // recognize full transparency and simply don't draw
359  GLfloat color[4];
360  glGetFloatv(GL_CURRENT_COLOR, color);
361  if (color[3] > 0) {
362  glPushName(getGlID());
364  // draw geometry points
365  for (int i = 1; i < (int)geom.size() - 1; i++) {
366  Position pos = geom[i];
367  glPushMatrix();
368  glTranslated(pos.x(), pos.y(), GLO_JUNCTION - 0.01);
369  // resolution of drawn circle depending of the zoom (To improve smothness)
370  if (s.scale >= 10) {
372  } else if (s.scale >= 2) {
374  } else if (s.scale >= 1) {
376  } else {
378  }
379  glPopMatrix();
380  }
381  glPopName();
382  }
383  }
384 
385  // (optionally) draw the name and/or the street name
386  const bool drawStreetName = s.streetName.show && myNBEdge.getStreetName() != "";
387  if (s.edgeName.show || drawStreetName) {
388  glPushName(getGlID());
389  GNELane* lane1 = myLanes[0];
390  GNELane* lane2 = myLanes[myLanes.size() - 1];
391  Position p = lane1->getShape().positionAtOffset(lane1->getShape().length() / (double) 2.);
392  p.add(lane2->getShape().positionAtOffset(lane2->getShape().length() / (double) 2.));
393  p.mul(.5);
394  double angle = lane1->getShape().rotationDegreeAtOffset(lane1->getShape().length() / (double) 2.);
395  angle += 90;
396  if (angle > 90 && angle < 270) {
397  angle -= 180;
398  }
399  if (s.edgeName.show) {
400  drawName(p, s.scale, s.edgeName, angle);
401  }
402  if (drawStreetName) {
404  s.streetName.size / s.scale, s.streetName.color, angle);
405  }
406  glPopName();
407  }
408 }
409 
410 
411 NBEdge*
413  return &myNBEdge;
414 }
415 
416 
417 Position
418 GNEEdge::getSplitPos(const Position& clickPos) {
419  const PositionVector& geom = myNBEdge.getGeometry();
420  int index = geom.indexOfClosest(clickPos);
421  if (geom[index].distanceTo(clickPos) < SNAP_RADIUS) {
422  // split at existing geometry point
423  return geom[index];
424  } else {
425  // split straight between the next two points
426  return geom.positionAtOffset(geom.nearest_offset_to_point2D(clickPos));
427  }
428 }
429 
430 
431 void
433  undoList->p_begin("set endpoint");
435  int index = geom.indexOfClosest(pos);
436  if (geom[index].distanceTo(pos) < SNAP_RADIUS) { // snap to existing geometry
437  pos = geom[index];
438  }
441  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
442  setAttribute(GNE_ATTR_SHAPE_END, toString(pos), undoList);
444  } else {
445  setAttribute(GNE_ATTR_SHAPE_START, toString(pos), undoList);
447  }
448  // possibly existing inner point is no longer needed
449  if (myNBEdge.getInnerGeometry().size() > 0 && getVertexIndex(pos, false) != -1) {
450  deleteGeometryPoint(pos, false);
451  }
452  undoList->p_end();
453 }
454 
455 
456 void
460  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
461  setAttribute(GNE_ATTR_SHAPE_END, toString(destPos), undoList);
463  } else {
464  setAttribute(GNE_ATTR_SHAPE_START, toString(sourcePos), undoList);
466  }
467 }
468 
469 
470 void
472  myNBEdge.setGeometry(geom, inner);
473  updateGeometry();
476  myNet->refreshElement(this);
477 
478 }
479 
480 
481 void
483  // create new and removed unused GNEConnectinos
484  const std::vector<NBEdge::Connection>& connections = myNBEdge.getConnections();
485  // create a vector to keep retrieved and created connections
486  std::vector<GNEConnection*> retrievedConnections;
487  // iterate over NBEdge::Connections of GNEEdge
488  for (auto it : connections) {
489  // retrieve existent GNEConnection, or create it
490  GNEConnection* retrievedGNEConnection = retrieveGNEConnection(it.fromLane, it.toEdge, it.toLane);
491  retrievedGNEConnection->updateLinkState();
492  retrievedConnections.push_back(retrievedGNEConnection);
493  // check if previously this GNEConnections exists, and if true, remove it from myGNEConnections
494  std::vector<GNEConnection*>::iterator retrievedExists = std::find(myGNEConnections.begin(), myGNEConnections.end(), retrievedGNEConnection);
495  if (retrievedExists != myGNEConnections.end()) {
496  myGNEConnections.erase(retrievedExists);
497  } else {
498  // include reference to created GNEConnection
499  retrievedGNEConnection->incRef("GNEEdge::remakeGNEConnections");
500  }
501  }
502  // delete non retrieved GNEConnections
503  for (auto it : myGNEConnections) {
504  it->decRef();
505  if (it->unreferenced()) {
506  // show extra information for tests
507  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
508  WRITE_WARNING("Deleting unreferenced " + toString(it->getTag()) + " '" + it->getID() + "' in rebuildGNEConnections()");
509  }
510  delete it;
511  }
512  }
513  // copy retrieved (existent and created) GNECrossigns to myGNEConnections
514  myGNEConnections = retrievedConnections;
515 }
516 
517 
518 void
520  // Drop all existents connections that aren't referenced anymore
521  for (auto i : myGNEConnections) {
522  // Dec reference of connection
523  i->decRef("GNEEdge::clearGNEConnections");
524  // Delete GNEConnectionToErase if is unreferenced
525  if (i->unreferenced()) {
526  // show extra information for tests
527  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
528  WRITE_WARNING("Deleting unreferenced " + toString(i->getTag()) + " '" + i->getID() + "' in clearGNEConnections()");
529  }
530  delete i;
531  }
532  }
533  myGNEConnections.clear();
534 }
535 
536 
537 int
539  std::vector<GNEAdditional*> routeProbes;
540  for (auto i : myAdditionalChilds) {
541  if (i->getTag() == routeProbe->getTag()) {
542  routeProbes.push_back(i);
543  }
544  }
545  // return index of routeProbe in routeProbes vector
546  auto it = std::find(routeProbes.begin(), routeProbes.end(), routeProbe);
547  if (it == routeProbes.end()) {
548  return -1;
549  } else {
550  return (int)(it - routeProbes.begin());
551  }
552 }
553 
554 
555 int
557  std::vector<GNEAdditional*> vaporizers;
558  for (auto i : myAdditionalChilds) {
559  if (i->getTag() == vaporizer->getTag()) {
560  vaporizers.push_back(i);
561  }
562  }
563  // return index of routeProbe in routeProbes vector
564  auto it = std::find(vaporizers.begin(), vaporizers.end(), vaporizer);
565  if (it == vaporizers.end()) {
566  return -1;
567  } else {
568  return (int)(it - vaporizers.begin());
569  }
570 }
571 
572 
573 std::vector<GNECrossing*>
575  std::vector<GNECrossing*> crossings;
576  for (auto i : myGNEJunctionSource->getGNECrossings()) {
577  if (i->checkEdgeBelong(this)) {
578  crossings.push_back(i);
579  }
580  }
581  for (auto i : myGNEJunctionDestiny->getGNECrossings()) {
582  if (i->checkEdgeBelong(this)) {
583  crossings.push_back(i);
584  }
585  }
586  return crossings;
587 }
588 
589 
590 void
592  // iterate over all additional parents of edge
593  for (auto i : myAdditionalParents) {
594  // Obtain attribute EDGES of additional
595  std::vector<std::string> edgeIDs = parse<std::vector<std::string> >(i->getAttribute(SUMO_ATTR_EDGES));
596  // check that at least there is an Edge
597  if (edgeIDs.empty()) {
598  throw ProcessError("Additional edge childs is empty");
599  } else if ((edgeIDs.size() == 1) && (allowEmpty == false)) {
600  // remove entire Additional if SUMO_ATTR_EDGES cannot be empty
601  if (edgeIDs.front() == getID()) {
602  undoList->add(new GNEChange_Additional(i, false), true);
603  } else {
604  throw ProcessError("Edge ID wasnt' found in Additional");
605  }
606  } else {
607  auto it = std::find(edgeIDs.begin(), edgeIDs.end(), getID());
608  if (it != edgeIDs.end()) {
609  // set new attribute in Additional
610  edgeIDs.erase(it);
611  i->setAttribute(SUMO_ATTR_EDGES, toString(edgeIDs), undoList);
612  } else {
613  throw ProcessError("Edge ID wasnt' found in Additional");
614  }
615  }
616  }
617 }
618 
619 
620 void
622  undoList->p_begin("copy template");
630  // copy lane attributes as well
631  for (int i = 0; i < (int)myLanes.size(); i++) {
632  myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, tpl->myLanes[i]->getAttribute(SUMO_ATTR_ALLOW), undoList);
633  myLanes[i]->setAttribute(SUMO_ATTR_DISALLOW, tpl->myLanes[i]->getAttribute(SUMO_ATTR_DISALLOW), undoList);
634  myLanes[i]->setAttribute(SUMO_ATTR_SPEED, tpl->myLanes[i]->getAttribute(SUMO_ATTR_SPEED), undoList);
635  myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, tpl->myLanes[i]->getAttribute(SUMO_ATTR_WIDTH), undoList);
636  myLanes[i]->setAttribute(SUMO_ATTR_ENDOFFSET, tpl->myLanes[i]->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
637  }
638  undoList->p_end();
639 }
640 
641 
642 std::set<GUIGlID>
644  std::set<GUIGlID> result;
645  for (auto i : myLanes) {
646  result.insert(i->getGlID());
647  }
648  return result;
649 }
650 
651 
652 const std::vector<GNELane*>&
654  return myLanes;
655 }
656 
657 
658 const std::vector<GNEConnection*>&
660  return myGNEConnections;
661 }
662 
663 
664 bool
666  return myWasSplit;
667 }
668 
669 
670 std::string
672  switch (key) {
673  case SUMO_ATTR_ID:
674  return getMicrosimID();
675  case SUMO_ATTR_FROM:
677  case SUMO_ATTR_TO:
679  case SUMO_ATTR_NUMLANES:
680  return toString(myNBEdge.getNumLanes());
681  case SUMO_ATTR_PRIORITY:
682  return toString(myNBEdge.getPriority());
683  case SUMO_ATTR_LENGTH:
684  return toString(myNBEdge.getFinalLength());
685  case SUMO_ATTR_TYPE:
686  return myNBEdge.getTypeID();
687  case SUMO_ATTR_SHAPE:
691  case SUMO_ATTR_NAME:
692  return myNBEdge.getStreetName();
693  case SUMO_ATTR_ALLOW:
694  return (getVehicleClassNames(myNBEdge.getPermissions()) + (myNBEdge.hasLaneSpecificPermissions() ? " (combined!)" : ""));
695  case SUMO_ATTR_DISALLOW: {
697  }
698  case SUMO_ATTR_SPEED:
700  return "lane specific";
701  } else {
702  return toString(myNBEdge.getSpeed());
703  }
704  case SUMO_ATTR_WIDTH:
706  return "lane specific";
708  return "default";
709  } else {
710  return toString(myNBEdge.getLaneWidth());
711  }
712  case SUMO_ATTR_ENDOFFSET:
714  return "lane specific";
715  } else {
716  return toString(myNBEdge.getEndOffset());
717  }
719  return myConnectionStatus;
722  return "";
723  } else {
724  return toString(myNBEdge.getGeometry()[0]);
725  }
726  case GNE_ATTR_SHAPE_END:
728  return "";
729  } else {
730  return toString(myNBEdge.getGeometry()[-1]);
731  }
732  default:
733  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
734  }
735 }
736 
737 std::string
739  std::string result = getAttribute(key);
740  if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
741  result += " " + getVehicleClassNames(SVCAll, true);
742  }
743  return result;
744 }
745 
746 void
747 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
748  switch (key) {
749  case SUMO_ATTR_WIDTH:
750  case SUMO_ATTR_ENDOFFSET:
751  case SUMO_ATTR_SPEED:
752  case SUMO_ATTR_ALLOW:
753  case SUMO_ATTR_DISALLOW: {
754  undoList->p_begin("change " + toString(getTag()) + " attribute");
755  const std::string origValue = myLanes.at(0)->getAttribute(key); // will have intermediate value of "lane specific"
756  // lane specific attributes need to be changed via lanes to allow undo
757  for (auto it : myLanes) {
758  it->setAttribute(key, value, undoList);
759  }
760  // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
761  undoList->p_add(new GNEChange_Attribute(this, key, value, true, origValue));
762  undoList->p_end();
763  break;
764  }
765  case SUMO_ATTR_FROM: {
766  undoList->p_begin("change " + toString(getTag()) + " attribute");
767  // Remove edge from crossings of junction source
769  // continue changing from junction
770  GNEJunction* oldGNEJunctionSource = myGNEJunctionSource;
771  myGNEJunctionSource->setLogicValid(false, undoList);
772  undoList->p_add(new GNEChange_Attribute(this, key, value));
773  myGNEJunctionSource->setLogicValid(false, undoList);
774  myNet->retrieveJunction(value)->setLogicValid(false, undoList);
777  undoList->p_end();
778  // update geometries of all implicated junctions
779  oldGNEJunctionSource->updateGeometry();
782  break;
783  }
784  case SUMO_ATTR_TO: {
785  undoList->p_begin("change " + toString(getTag()) + " attribute");
786  // Remove edge from crossings of junction destiny
788  // continue changing destiny junction
789  GNEJunction* oldGNEJunctionDestiny = myGNEJunctionDestiny;
790  myGNEJunctionDestiny->setLogicValid(false, undoList);
791  undoList->p_add(new GNEChange_Attribute(this, key, value));
792  myGNEJunctionDestiny->setLogicValid(false, undoList);
793  myNet->retrieveJunction(value)->setLogicValid(false, undoList);
796  undoList->p_end();
797  // update geometries of all implicated junctions
798  oldGNEJunctionDestiny->updateGeometry();
801  break;
802  }
803  case SUMO_ATTR_ID:
804  case SUMO_ATTR_PRIORITY:
805  case SUMO_ATTR_LENGTH:
806  case SUMO_ATTR_TYPE:
810  case GNE_ATTR_SHAPE_END:
811  undoList->p_add(new GNEChange_Attribute(this, key, value));
812  break;
813  case SUMO_ATTR_NAME:
814  // user cares about street names. Make sure they appear in the output
816  OptionsCont::getOptions().set("output.street-names", "true");
817  undoList->p_add(new GNEChange_Attribute(this, key, value));
818  break;
819  case SUMO_ATTR_NUMLANES:
820  if (value != getAttribute(key)) {
821  // Remove edge from crossings of junction source
823  // Remove edge from crossings of junction destiny
825  // set num lanes
826  setNumLanes(parse<int>(value), undoList);
827  }
828  break;
829  case SUMO_ATTR_SHAPE:
830  // @note: assumes value of inner geometry!
831  // actually the geometry is already updated (incrementally
832  // during mouse movement). We set the restore point to the end
833  // of the last change-set
835  undoList->p_add(new GNEChange_Attribute(this, key, value));
836  break;
837  default:
838  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
839  }
840 }
841 
842 
843 bool
844 GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
845  switch (key) {
846  case SUMO_ATTR_ID:
847  return isValidID(value) && (myNet->retrieveEdge(value, false) == 0);
848  case SUMO_ATTR_FROM: {
849  // check that is a valid ID and is different of ID of junction destiny
850  if (isValidID(value) && (value != myGNEJunctionDestiny->getMicrosimID())) {
851  GNEJunction* junctionFrom = myNet->retrieveJunction(value, false);
852  // check that there isn't already another edge with the same From and To Edge
853  if ((junctionFrom != NULL) && (myNet->retrieveEdge(junctionFrom, myGNEJunctionDestiny, false) == NULL)) {
854  return true;
855  } else {
856  return false;
857  }
858  } else {
859  return false;
860  }
861  }
862  case SUMO_ATTR_TO: {
863  // check that is a valid ID and is different of ID of junction Source
864  if (isValidID(value) && (value != myGNEJunctionSource->getMicrosimID())) {
865  GNEJunction* junctionTo = myNet->retrieveJunction(value, false);
866  // check that there isn't already another edge with the same From and To Edge
867  if ((junctionTo != NULL) && (myNet->retrieveEdge(myGNEJunctionSource, junctionTo, false) == NULL)) {
868  return true;
869  } else {
870  return false;
871  }
872  } else {
873  return false;
874  }
875  }
876  case SUMO_ATTR_SPEED:
877  return canParse<double>(value) && isPositive<double>(value);
878  case SUMO_ATTR_NUMLANES:
879  return canParse<int>(value) && isPositive<int>(value);
880  case SUMO_ATTR_PRIORITY:
881  return canParse<int>(value);
882  case SUMO_ATTR_LENGTH:
883  return canParse<double>(value) && (isPositive<double>(value) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
884  case SUMO_ATTR_ALLOW:
885  case SUMO_ATTR_DISALLOW:
886  return canParseVehicleClasses(value);
887  case SUMO_ATTR_TYPE:
888  return true;
889  case SUMO_ATTR_SHAPE: {
890  bool ok = true;
891  PositionVector shape = GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, true);
892  return ok;
893  }
896  case SUMO_ATTR_NAME:
897  return true;
898  case SUMO_ATTR_WIDTH:
899  if (value == "default") {
900  return true;
901  } else {
902  return canParse<double>(value) && (isPositive<double>(value) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
903  }
904  case SUMO_ATTR_ENDOFFSET:
905  return canParse<double>(value);
906  case GNE_ATTR_SHAPE_START: {
907  bool ok;
908  if (value != "") {
909  PositionVector shapeStart = GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, false);
910  if ((shapeStart.size() == 1) && (shapeStart[0] != myNBEdge.getGeometry()[-1])) {
911  return true;
912  } else {
913  return false;
914  }
915  } else {
916  return true;
917  }
918  }
919  case GNE_ATTR_SHAPE_END: {
920  bool ok;
921  if (value != "") {
922  PositionVector shapeStart = GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, false);
923  if ((shapeStart.size() == 1) && (shapeStart[0] != myNBEdge.getGeometry()[0])) {
924  return true;
925  } else {
926  return false;
927  }
928  } else {
929  return true;
930  }
931  }
932  default:
933  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
934  }
935 }
936 
937 
938 void
940  myAmResponsible = newVal;
941 }
942 
943 // ===========================================================================
944 // private
945 // ===========================================================================
946 
947 void
948 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
949  switch (key) {
950  case SUMO_ATTR_ID:
951  myNet->renameEdge(this, value);
952  break;
953  case SUMO_ATTR_FROM:
955  // update this edge of list of outgoings edges of the old GNEJunctionSource
957  // update GNEJunctionSource
959  // update this edge of list of outgoings edges of the new GNEJunctionSource
961  break;
962  case SUMO_ATTR_TO:
964  // update this edge of list of incomings edges of the old GNEJunctionDestiny
966  // update GNEJunctionDestiny
968  // update this edge of list of incomings edges of the new GNEJunctionDestiny
970  break;
971  case SUMO_ATTR_NUMLANES:
972  throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
973  break;
974  case SUMO_ATTR_PRIORITY:
975  myNBEdge.myPriority = parse<int>(value);
976  break;
977  case SUMO_ATTR_LENGTH:
978  myNBEdge.setLoadedLength(parse<double>(value));
979  break;
980  case SUMO_ATTR_TYPE:
981  myNBEdge.myType = value;
982  break;
983  case SUMO_ATTR_SHAPE:
984  bool ok;
985  myOrigShape = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, true);
986  setGeometry(myOrigShape, true);
987  break;
990  break;
991  case SUMO_ATTR_NAME:
992  myNBEdge.setStreetName(value);
993  break;
994  case SUMO_ATTR_SPEED:
995  myNBEdge.setSpeed(-1, parse<double>(value));
996  break;
997  case SUMO_ATTR_WIDTH:
998  if (value == "default") {
1000  } else {
1001  myNBEdge.setLaneWidth(-1, parse<double>(value));
1002  }
1003  break;
1004  case SUMO_ATTR_ENDOFFSET:
1005  myNBEdge.setEndOffset(-1, parse<double>(value));
1006  break;
1007  case SUMO_ATTR_ALLOW:
1008  break; // no edge value
1009  case SUMO_ATTR_DISALLOW:
1010  break; // no edge value
1012  myConnectionStatus = value;
1013  if (value == GUESSED) {
1016  } else if (value != GUESSED) {
1018  }
1019  break;
1020  case GNE_ATTR_SHAPE_START: {
1021  // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1023  geom.erase(geom.begin());
1024  if (value == "") {
1026  } else {
1027  geom.push_front_noDoublePos(GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, false)[0]);
1028  }
1029  setGeometry(geom, false);
1030  break;
1031  }
1032  case GNE_ATTR_SHAPE_END: {
1033  // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destiny position) and set it back to edge
1035  geom.pop_back();
1036  if (value == "") {
1038  } else {
1039  geom.push_back_noDoublePos(GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, false)[0]);
1040  }
1041  setGeometry(geom, false);
1042  break;
1043  }
1044  default:
1045  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
1046  }
1047 }
1048 
1049 
1050 void
1051 GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
1052  undoList->p_begin("change number of " + toString(SUMO_TAG_LANE) + "s");
1053  myGNEJunctionSource->setLogicValid(false, undoList);
1054  myGNEJunctionDestiny->setLogicValid(false, undoList);
1055 
1056  const int oldNumLanes = (int)myLanes.size();
1057  for (int i = oldNumLanes; i < numLanes; i++) {
1058  // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
1059  undoList->add(new GNEChange_Lane(this, 0,
1060  myNBEdge.getLaneStruct(oldNumLanes - 1), true), true);
1061  }
1062  for (int i = oldNumLanes - 1; i > numLanes - 1; i--) {
1063  // delete leftmost lane
1064  undoList->add(new GNEChange_Lane(this, myLanes[i], myNBEdge.getLaneStruct(i), false), true);
1065  }
1066  undoList->p_end();
1067 }
1068 
1069 
1070 void
1071 GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs) {
1072  const int index = lane ? lane->getIndex() : myNBEdge.getNumLanes();
1073  // the laneStruct must be created first to ensure we have some geometry
1074  myNBEdge.addLane(index);
1075  if (lane) {
1076  // restore a previously deleted lane
1077  myLanes.insert(myLanes.begin() + index, lane);
1078 
1079  } else {
1080  // create a new lane by copying leftmost lane
1081  lane = new GNELane(*this, index);
1082  myLanes.push_back(lane);
1083  }
1084  lane->incRef("GNEEdge::addLane");
1085  // we copy all attributes except shape since this is recomputed from edge shape
1086  myNBEdge.setSpeed(lane->getIndex(), laneAttrs.speed);
1087  myNBEdge.setPermissions(laneAttrs.permissions, lane->getIndex());
1089  myNBEdge.setEndOffset(lane->getIndex(), laneAttrs.endOffset);
1090  myNBEdge.setLaneWidth(lane->getIndex(), laneAttrs.width);
1091  // udate indices
1092  for (int i = 0; i < (int)myLanes.size(); ++i) {
1093  myLanes[i]->setIndex(i);
1094  }
1095  /* while technically correct, this looks ugly
1096  myGNEJunctionSource->invalidateShape();
1097  myGNEJunctionDestiny->invalidateShape();
1098  */
1099  // Remake connections for this edge and all edges that target this lane
1101  // remake connections of all edges of junction source and destiny
1102  for (auto i : myGNEJunctionSource->getGNEEdges()) {
1103  i->remakeGNEConnections();
1104  }
1105  // remake connections of all edges of junction source and destiny
1106  for (auto i : myGNEJunctionDestiny->getGNEEdges()) {
1107  i->remakeGNEConnections();
1108  }
1109  // Update geometry with the new lane
1110  updateGeometry();
1111 }
1112 
1113 
1114 void
1116  if (myLanes.size() == 0) {
1117  throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + toString(getTag()));
1118  }
1119  if (lane == 0) {
1120  lane = myLanes.back();
1121  }
1122  // Delete lane of edge's container
1123  myNBEdge.deleteLane(lane->getIndex());
1124  lane->decRef("GNEEdge::removeLane");
1125  myLanes.erase(myLanes.begin() + lane->getIndex());
1126  // Delete lane if is unreferenced
1127  if (lane->unreferenced()) {
1128  // show extra information for tests
1129  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
1130  WRITE_WARNING("Deleting unreferenced " + toString(lane->getTag()) + " '" + lane->getID() + "' in removeLane()");
1131  }
1132  delete lane;
1133  }
1134  // udate indices
1135  for (int i = 0; i < (int)myLanes.size(); ++i) {
1136  myLanes[i]->setIndex(i);
1137  }
1138  /* while technically correct, this looks ugly
1139  myGNEJunctionSource->invalidateShape();
1140  myGNEJunctionDestiny->invalidateShape();
1141  */
1142  // Remake connections of this edge
1144  // remake connections of all edges of junction source and destiny
1145  for (auto i : myGNEJunctionSource->getGNEEdges()) {
1146  i->remakeGNEConnections();
1147  }
1148  // remake connections of all edges of junction source and destiny
1149  for (auto i : myGNEJunctionDestiny->getGNEEdges()) {
1150  i->remakeGNEConnections();
1151  }
1152  // Update element
1153  myNet->refreshElement(this);
1154  updateGeometry();
1155 }
1156 
1157 
1158 void
1159 GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
1160  // If a new connection was sucesfully created
1161  if (myNBEdge.setConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, NBEdge::L2L_USER, true, nbCon.mayDefinitelyPass, nbCon.keepClear, nbCon.contPos, nbCon.visibility)) {
1162  // Create or retrieve existent GNEConection
1163  GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
1164  // add it to GNEConnection container
1165  myGNEConnections.push_back(con);
1166  // Add reference
1167  myGNEConnections.back()->incRef("GNEEdge::addConnection");
1168  // select GNEConnection if needed
1169  if (selectAfterCreation) {
1170  gSelected.deselect(con->getGlID());
1171  }
1172  // update geometry
1173  con->updateGeometry();
1174  }
1175  myNet->refreshElement(this); // actually we only do this to force a redraw
1176 }
1177 
1178 
1179 void
1181  // check if is a explicit turnaround
1182  if (nbCon.toEdge == myNBEdge.getTurnDestination()) {
1184  }
1185  // remove NBEdge::connection from NBEdge
1187  // remove their associated GNEConnection
1188  GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
1189  if (con != NULL) {
1190  con->decRef("GNEEdge::removeConnection");
1191  myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), con));
1192  if (con->unreferenced()) {
1193  // show extra information for tests
1194  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
1195  WRITE_WARNING("Deleting unreferenced " + toString(con->getTag()) + " '" + con->getID() + "' in removeConnection()");
1196  }
1197  delete con;
1198  myNet->refreshElement(this); // actually we only do this to force a redraw
1199  }
1200  }
1201 }
1202 
1203 
1205 GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
1206  for (auto i : myGNEConnections) {
1207  if ((i->getFromLaneIndex() == fromLane) && (i->getEdgeTo()->getNBEdge() == to) && (i->getToLaneIndex() == toLane)) {
1208  return i;
1209  }
1210  }
1211  if (createIfNoExist) {
1212  // create new connection
1213  GNEConnection* createdConnection = new GNEConnection(myLanes[fromLane], myNet->retrieveEdge(to->getID())->getLanes()[toLane]);
1214  // show extra information for tests
1215  if (OptionsCont::getOptions().getBool("gui-testing-debug")) {
1216  WRITE_WARNING("Created " + toString(createdConnection->getTag()) + " '" + createdConnection->getID() + "' in retrieveGNEConnection()");
1217  }
1218  return createdConnection;
1219  } else {
1220  return NULL;
1221  }
1222 }
1223 
1224 
1225 
1226 void
1227 GNEEdge::setMicrosimID(const std::string& newID) {
1229  for (auto i : myLanes) {
1230  i->setMicrosimID(getNBEdge()->getLaneID(i->getIndex()));
1231  }
1232 }
1233 
1234 
1235 bool
1237  for (auto i : myLanes) {
1238  if (i->isRestricted(vclass)) {
1239  return true;
1240  }
1241  }
1242  return false;
1243 }
1244 
1245 
1246 void
1248  // Remove all crossings that contain this edge in parameter "edges"
1249  for (GNECrossing* const i : junction->getGNECrossings()) {
1250  if (i->checkEdgeBelong(this)) {
1251  myNet->deleteCrossing(i, undoList);
1252  }
1253  }
1254 }
1255 
1256 
1257 void
1259  PositionVector modifiedShape = myNBEdge.getGeometry().interpolateZ(
1261  myNBEdge.getToNode()->getPosition().z());
1262  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
1263  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
1264 }
1265 
1266 
1268 GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
1269  const OptionsCont& oc = OptionsCont::getOptions();
1270  // distinguish 3 cases:
1271  // a) if the edge has exactly 3 or 4 points, use these as control points
1272  // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
1273  // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
1274  PositionVector init;
1275 #ifdef DEBUG_SMOOTH_GEOM
1276  if (DEBUGCOND(this)) std::cout << getID()
1277  << " forElevation=" << forElevation
1278  << " fromGeometryLike=" << myNBEdge.getFromNode()->geometryLike()
1279  << " toGeometryLike=" << myNBEdge.getToNode()->geometryLike()
1280  << " smoothShape old=" << old << "\n";
1281 #endif
1282  if (old.size() == 3 || old.size() == 4) {
1283  init = old;
1284  } else if (old.size() > 4 && !forElevation) {
1285  // for elevation, the initial segments are not useful
1286  init.push_back(old[0]);
1287  init.push_back(old[1]);
1288  init.push_back(old[-2]);
1289  init.push_back(old[-1]);
1290  } else if (myNBEdge.getFromNode()->geometryLike() && myNBEdge.getToNode()->geometryLike()) {
1291  PositionVector begShape;
1292  PositionVector endShape;
1293  const EdgeVector& incoming = myNBEdge.getFromNode()->getIncomingEdges();
1294  const EdgeVector& outgoing = myNBEdge.getToNode()->getOutgoingEdges();
1295  if (incoming.size() == 1) {
1296  begShape = incoming[0]->getGeometry();
1297  } else {
1298  assert(incoming.size() == 2);
1299  begShape = myNBEdge.isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
1300  }
1301  if (outgoing.size() == 1) {
1302  endShape = outgoing[0]->getGeometry();
1303  } else {
1304  assert(outgoing.size() == 2);
1305  endShape = myNBEdge.isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
1306  }
1307  const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
1308  if (forElevation) {
1309  // initialize control point elevation for smooth continuation
1310  init.push_back(old[0]);
1311  init.push_back(old.positionAtOffset2D(dist));
1312  init.push_back(old.positionAtOffset2D(old.length2D() - dist));
1313  init.push_back(old[-1]);
1314  double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
1315  double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
1316  // continue incline
1317  init[1].setz(2 * init[0].z() - begZ);
1318  init[2].setz(2 * init[-1].z() - endZ);
1319  } else {
1320  bool ok = true;
1321  const double straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold"));
1322  init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, 0, straightThresh);
1323  }
1324 #ifdef DEBUG_SMOOTH_GEOM
1325  if (DEBUGCOND(this)) {
1326  std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
1327  }
1328 #endif
1329  }
1330  if (init.size() == 0) {
1331  return PositionVector::EMPTY;
1332  } else {
1333  const int numPoints = MAX2(oc.getInt("junctions.internal-link-detail"),
1334  int(old.length2D() / oc.getFloat("opendrive.curve-resolution")));
1335  return bezier(init, numPoints);
1336  }
1337 }
1338 
1339 
1340 void
1342  PositionVector modifiedShape = smoothShape(myNBEdge.getGeometry(), false);
1343  if (modifiedShape.size() < 2) {
1344  WRITE_WARNING("Could not compute smooth shape for edge '" + getID() + "'");
1345  } else {
1346  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
1347  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
1348  }
1349 }
1350 
1351 
1352 void
1354  PositionVector elevationBase;
1355  for (const Position& pos : myNBEdge.getGeometry()) {
1356  if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
1357  elevationBase.push_back(pos);
1358  }
1359  }
1360  PositionVector elevation = smoothShape(elevationBase, true);
1361  if (elevation.size() <= 2) {
1362  WRITE_WARNING("Could not compute smooth elevation for edge '" + getID() + "'");
1363  } else {
1364  PositionVector modifiedShape = myNBEdge.getGeometry();
1365  if (modifiedShape.size() < 5) {
1366  modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"));
1367  }
1368  const double scale = elevation.length2D() / modifiedShape.length2D();
1369  //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
1370  double seen = 0;
1371  for (int i = 1; i < (int)modifiedShape.size(); ++i) {
1372  seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
1373  modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
1374  }
1375  //std::cout << " mod2=" << modifiedShape << "\n";
1376  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
1377  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
1378  }
1379 }
1380 
1381 
1382 /****************************************************************************/
GUIVisualizationSizeSettings junctionSize
void addLane(GNELane *lane, const NBEdge::Lane &laneAttrs)
increase number of lanes by one use the given attributes and restore the GNELane
Definition: GNEEdge.cpp:1071
static const PositionVector EMPTY
empty Vector
void copyTemplate(GNEEdge *tpl, GNEUndoList *undolist)
copy edge attributes from tpl
Definition: GNEEdge.cpp:621
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1268
GNEJunction * myGNEJunctionSource
pointer to GNEJunction source
Definition: GNEEdge.h:271
The information about how to spread the lanes from the given position.
void updateGeometry()
update pre-computed geometry information
std::string getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a &#39; &#39;.
void remakeGNEConnections()
remake connections
Definition: GNEEdge.cpp:482
double z() const
Returns the z-position.
Definition: Position.h:72
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0) const
draw name of item
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:249
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:982
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:161
std::vector< GNEAdditional * > myAdditionalParents
list of Additional parents of this NetElement
void addIncomingGNEEdge(GNEEdge *edge)
add incoming GNEEdge
void setNumLanes(int numLanes, GNEUndoList *undoList)
changes the number of lanes. When reducing the number of lanes, higher-numbered lanes are removed fir...
Definition: GNEEdge.cpp:1051
void setLogicValid(bool valid, GNEUndoList *undoList, const std::string &status=GUESSED)
int toLane
The lane the connections yields in.
Definition: NBEdge.h:189
GNEEdge * retrieveEdge(const std::string &id, bool failHard=true)
get edge by id
Definition: GNENet.cpp:902
double scale
information about a lane&#39;s width (temporary, used for a single view)
GUIVisualizationTextSettings streetName
double laneWidthExaggeration
The lane exaggeration (upscale thickness)
GNEJunction * getGNEJunctionSource() const
returns the source-junction
Definition: GNEEdge.cpp:317
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:249
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:269
void resetWritable()
Resets all options to be writeable.
GNENet * myNet
the net to inform about updates
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition: GNEEdge.h:286
void smoothElevation(GNEUndoList *undoList)
smooth elevation with regard to adjoining edges
Definition: GNEEdge.cpp:1353
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.
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:186
begin/end of the description of a single lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types...
std::string myConnectionStatus
modification status of the connections
Definition: GNEEdge.h:292
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:132
void refreshElement(GUIGlObject *o)
refreshes boundary information for o and update
Definition: GNENet.cpp:1082
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2950
GNEJunction * myGNEJunctionDestiny
pointer to GNEJunction destiny
Definition: GNEEdge.h:274
bool hasString(const std::string &str) const
PositionVector myOrigShape
restore point for undo
Definition: GNEEdge.h:277
void setMicrosimID(const std::string &newID)
override to also set lane ids
Definition: GNEEdge.cpp:1227
static StringBijection< LaneSpreadFunction > LaneSpreadFunctions
lane spread functions
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition: GNEEdge.cpp:1258
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1817
std::set< GUIGlID > getLaneGlIDs()
returns GLIDs of all lanes
Definition: GNEEdge.cpp:643
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2966
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
double exaggeration
The size exaggeration (upscale)
GUIColorer laneColorer
The lane colorer.
double x() const
Returns the x-position.
Definition: Position.h:62
Stores the information about how to visualize structures.
static const double SNAP_RADIUS
Definition: GNEEdge.h:237
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
Definition: NBEdge.h:70
const std::vector< T > & getSchemes() const
bool hasRestrictedLane(SUMOVehicleClass vclass) const
check if edge has a restricted lane
Definition: GNEEdge.cpp:1236
Representation of a RouteProbe in netedit.
Definition: GNERouteProbe.h:42
NBNode * getNBNode() const
Return net build node.
void setStreetName(const std::string &name)
sets the street name of this edge
Definition: NBEdge.h:540
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void smooth(GNEUndoList *undoList)
make geometry smooth
Definition: GNEEdge.cpp:1341
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, int align=0, double width=-1)
Definition: GLHelper.cpp:487
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:1201
std::string getAttribute(SumoXMLAttr key) const
This functions has to be implemented in all GNEAttributeCarriers.
Definition: GNEEdge.cpp:671
T MAX2(T a, T b)
Definition: StdDefs.h:73
Position getPositionInView() const
Return current position.
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:91
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given ...
Definition: NBEdge.cpp:2997
double getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:547
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:53
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:506
void setLoadedLength(double val)
set loaded lenght
Definition: NBEdge.cpp:3040
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:84
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:198
double endOffset
This lane&#39;s offset to the intersection begin.
Definition: NBEdge.h:138
void clearGNEConnections()
clear current connections
Definition: GNEEdge.cpp:519
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
double visibility
custom foe visiblity for connection
Definition: NBEdge.h:207
void removeEdgeFromCrossings(GNEJunction *junction, GNEUndoList *undoList)
remove crossing of junction
Definition: GNEEdge.cpp:1247
const std::vector< GNEConnection * > & getGNEConnections()
returns a reference to the GNEConnection vector
Definition: GNEEdge.cpp:659
bool isInverted() const
return true if edge is inverted (Angle between origin and destiny junction is -PI/2 <= angle < PI/2 ...
Definition: GNEEdge.cpp:287
const std::vector< GNEEdge * > & getGNEEdges() const
Returns all GNEEdges vinculated with this Junction.
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
const SVCPermissions SVCAll
all VClasses are allowed
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1177
PositionVector smoothShape(const PositionVector &shape, bool forElevation)
return smoothed shape
Definition: GNEEdge.cpp:1268
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition: GNEEdge.cpp:538
bool myWasSplit
whether this edge was created from a split
Definition: GNEEdge.h:289
~GNEEdge()
Destructor.
Definition: GNEEdge.cpp:94
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:350
PositionVector interpolateZ(double zStart, double zEnd) const
returned vector that varies z smoothly over its length
first coordinate of edge shape
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.
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge&#39;s geometry
Definition: NBEdge.cpp:532
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:683
GUIGlID getGlID() const
Returns the numerical id of the object.
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:254
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:47
void deleteGeometryPoint(const Position &pos, bool allowUndo=true)
delete the geometry point closest to the given pos
Definition: GNEEdge.cpp:245
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:199
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:64
whether a feature has been loaded,guessed,modified or approved
SVCPermissions invertPermissions(SVCPermissions permissions)
negate the given permissions and ensure that only relevant bits are set
GNEUndoList * getUndoList() const
get the undoList object
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEEdge.cpp:335
int getVertexIndex(const Position &pos, bool createIfNoExist=true)
return index of a vertex of shape, or of a new vertex if position is over an shape&#39;s edge ...
Definition: GNEEdge.cpp:143
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
void removeOutgoingGNEEdge(GNEEdge *edge)
remove outgoing GNEEdge
bool keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:201
void p_add(GNEChange_Attribute *cmd)
special method, avoid empty changes, always execute
GUIVisualizationTextSettings edgeName
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:254
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:121
const std::string & getID() const
Returns the id.
Definition: Named.h:65
static bool isValidID(const std::string &value)
true if value is a valid sumo ID
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:132
void addLane(int index, bool recompute=true)
add lane
Definition: NBEdge.cpp:2803
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:502
void push_front_noDoublePos(const Position &p)
insert in front a non double position
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
const Position & getPosition() const
Definition: NBNode.h:241
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:522
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:1795
the edges of a route
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:419
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:449
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
Definition: GNECrossing.h:51
GNEEdge * getOppositeEdge() const
get opposite edge
Definition: GNEEdge.cpp:329
const double SUMO_const_halfLaneWidth
Definition: StdDefs.h:50
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition: NBEdge.h:135
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:183
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:91
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:45
void deleteLane(int index, bool recompute=true)
delete lane
Definition: NBEdge.cpp:2838
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true)
get junction by id
Definition: GNENet.cpp:889
A list of positions.
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
int indexOfClosest(const Position &p) const
index of the closest position to p
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:1781
friend class GNEChange_Attribute
declare friend class
PositionVector resample(double maxLength) const
resample shape with the given number of points (equal spacing)
Boundary getBoundary() const
Returns the street&#39;s geometry.
Definition: GNEEdge.cpp:277
double y() const
Returns the y-position.
Definition: Position.h:67
Representation of a vaporizer in netedit.
Definition: GNEVaporizer.h:42
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:2596
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:412
int getVaporizerRelativePosition(GNEVaporizer *vaporizer) const
obtain relative positions of Vaporizer
Definition: GNEEdge.cpp:556
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:2450
GNEConnection * retrieveGNEConnection(int fromLane, NBEdge *to, int toLane, bool createIfNoExist=true)
get GNEConnection if exist, and if not create it if create is enabled
Definition: GNEEdge.cpp:1205
double length() const
Returns the length.
int myPriority
The priority of the edge.
Definition: NBEdge.h:1389
T MIN2(T a, T b)
Definition: StdDefs.h:67
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GNEEdge.cpp:294
edge: the shape in xml-definition
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:301
GUIColorer junctionColorer
The junction colorer.
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:590
void addOutgoingGNEEdge(GNEEdge *edge)
add outgoing GNEEdge
int insertAtClosest(const Position &p)
inserts p between the two closest positions and returns the insertion index
const std::string getID() const
function to support debugging
#define DEG2RAD(x)
Definition: GeomHelper.h:44
void incRef(const std::string &debugMsg="")
Increarse reference.
The connection was given by the user.
Definition: NBEdge.h:112
double speed
The speed allowed on this lane.
Definition: NBEdge.h:129
double width
This lane&#39;s width.
Definition: NBEdge.h:141
void removeLane(GNELane *lane)
the number of lanes by one. argument is only used to increase robustness (assertions) ...
Definition: GNEEdge.cpp:1115
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEEdge.cpp:302
void decRef(const std::string &debugMsg="")
Decrease reference.
std::vector< GNECrossing * > getGNECrossings()
get GNECrossings vinculated with this Edge
Definition: GNEEdge.cpp:574
begin/end of the description of an edge
void setGeometry(PositionVector geom, bool inner)
update edge geometry and inform the lanes
Definition: GNEEdge.cpp:471
GNEEdge(NBEdge &nbe, GNENet *net, bool wasSplit=false, bool loaded=false)
Constructor.
Definition: GNEEdge.cpp:70
bool canParseVehicleClasses(const std::string &classes)
Checks whether the given string contains only known vehicle classes.
#define DEBUGCOND(PEDID)
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:56
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3025
ConnectionVector myGNEConnections
vector with the connections of this edge
Definition: GNEEdge.h:283
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, const PositionVector &customShape=PositionVector::EMPTY)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:964
int moveVertexShape(const int index, const Position &oldPos, const Position &offset)
change position of a vertex of shape without commiting change
Definition: GNEEdge.cpp:180
static const double BUBBLE_RADIUS
Definition: GNEJunction.h:62
void setResponsible(bool newVal)
set responsibility for deleting internal strctures
Definition: GNEEdge.cpp:939
void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation=false)
adds a connection
Definition: GNEEdge.cpp:1159
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:433
const PositionVector & getShape() const
returns the shape of the lane
Definition: GNELane.cpp:599
void deselect(GUIGlID id)
Deselects the object with the given id.
const std::vector< GNELane * > & getLanes()
returns a reference to the lane vector
Definition: GNEEdge.cpp:653
double length2D() const
Returns the length.
bool set(const std::string &name, const std::string &value)
Sets the given value for the named option.
void updateGeometry()
Update the boundary of the junction.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
void moveEntireShape(const PositionVector &oldShape, const Position &offset)
move entire shape without commiting change
Definition: GNEEdge.cpp:203
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:40
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
Definition: NBEdge.cpp:3011
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:602
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3269
double contPos
custom position for internal junction on this connection
Definition: NBEdge.h:204
A storage for options typed value containers)
Definition: OptionsCont.h:98
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition: GNEEdge.cpp:263
void updateGeometry()
update pre-computed geometry information
Definition: GNEEdge.cpp:124
The popup menu of a globject.
an edge
void buildSelectionPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to (de)select the object.
std::string myType
The type of the edge.
Definition: NBEdge.h:1373
void renameEdge(GNEEdge *edge, const std::string &newID)
updates the map and reserves new id
Definition: GNENet.cpp:1584
bool isValid(SumoXMLAttr key, const std::string &value)
Definition: GNEEdge.cpp:844
void removeEdgeOfAdditionalParents(GNEUndoList *undoList, bool allowEmpty)
remove Edge of Additional Parent
Definition: GNEEdge.cpp:591
void declareConnectionsAsLoaded(EdgeBuildingStep step=LANES2LANES_USER)
declares connections as fully loaded. This is needed to avoid recomputing connections if an edge has ...
Definition: NBEdge.h:1191
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge&#39;s lanes&#39; lateral offset is computed.
Definition: NBEdge.h:684
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition: GNENet.cpp:1634
void commitShapeChange(const PositionVector &oldShape, GNEUndoList *undoList)
commit geometry changes in the attributes of an element after use of changeShapeGeometry(...)
Definition: GNEEdge.cpp:218
LaneVector myLanes
vectgor with the lanes of this edge
Definition: GNEEdge.h:280
std::vector< GNEAdditional * > myAdditionalChilds
list of Additional Childs of this NetElement
SumoXMLTag getTag() const
get XML Tag assigned to this object
GUIVisualizationSettings * getVisualisationSettings() const
get visualitation settings
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition: GNEEdge.cpp:1180
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1806
void updateLinkState()
recompute cached myLinkState
static const std::string GUESSED
feature has been reguessed (may still be unchanged be we can&#39;t tell (yet)
last coordinate of edge shape
void setEndpoint(Position pos, GNEUndoList *undoList)
makes pos the new geometry endpoint at the appropriate end
Definition: GNEEdge.cpp:432
void push_back_noDoublePos(const Position &p)
insert in back a non double position
static const RGBColor selectionColor
Definition: GNENet.h:107
empty max
NBEdge & myNBEdge
the underlying NBEdge
Definition: GNEEdge.h:268
void mul(double val)
Multiplies both positions with the given value.
Definition: Position.h:112
NBEdge * getNBEdge()
returns the internal NBEdge
Definition: GNEEdge.cpp:412
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:85
std::string getAttributeForSelection(SumoXMLAttr key) const
method for getting the attribute in the context of object selection
Definition: GNEEdge.cpp:738
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
void add(double xoff, double yoff, double zoff)
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:784
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNEEdge.cpp:747
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:535
GUISelectedStorage gSelected
A global holder of selected objects.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:845
void resetEndpoint(const Position &pos, GNEUndoList *undoList)
restores the endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:457
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition: GNENet.cpp:1597
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2774
int removeClosest(const Position &p)
removes the point closest to p and return the removal index
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1607
bool wasSplit()
whether this edge was created from a split
Definition: GNEEdge.cpp:665
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, bool &ok, NBNode *recordError=0, double straightThresh=DEG2RAD(5))
get bezier control points
Definition: NBNode.cpp:486
Position getSplitPos(const Position &clickPos)
Definition: GNEEdge.cpp:418
bool unreferenced()
check if object ins&#39;t referenced
friend class GNEChange_Lane
Friend class.
Definition: GNEEdge.h:59
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 setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2911
double beginEndAngle() const
returns the angle in radians of the line connecting the first and the last position ...
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
a junction
GNEJunction * getGNEJunctionDestiny() const
returns the destination-junction
Definition: GNEEdge.cpp:323
void bezier(int npts, double b[], int cpts, double p[])
Definition: bezier.cpp:96
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:426