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
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge&#39;s lanes&#39; lateral offset is computed.
Definition: NBEdge.h:684
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 rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
Position getPositionInView() const
Return current position.
double length2D() const
Returns the length.
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
const std::vector< T > & getSchemes() const
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)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
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 drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEEdge.cpp:335
void removeIncomingGNEEdge(GNEEdge *edge)
remove incoming GNEEdge
double z() const
Returns the z-position.
Definition: Position.h:72
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
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GNEEdge.cpp:294
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
PositionVector myOrigShape
restore point for undo
Definition: GNEEdge.h:277
int indexOfClosest(const Position &p) const
index of the closest position to p
void setMicrosimID(const std::string &newID)
override to also set lane ids
Definition: GNEEdge.cpp:1227
static StringBijection< LaneSpreadFunction > LaneSpreadFunctions
lane spread functions
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:249
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition: GNEEdge.cpp:1258
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 exaggeration
The size exaggeration (upscale)
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
GUIColorer laneColorer
The lane colorer.
Stores the information about how to visualize structures.
PositionVector resample(double maxLength) const
resample shape with the given number of points (equal spacing)
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:419
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:982
static const double SNAP_RADIUS
Definition: GNEEdge.h:237
double y() const
Returns the y-position.
Definition: Position.h:67
GUIVisualizationSettings * getVisualisationSettings() const
get visualitation settings
The representation of a single edge during network building.
Definition: NBEdge.h:70
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:1795
bool hasRestrictedLane(SUMOVehicleClass vclass) const
check if edge has a restricted lane
Definition: GNEEdge.cpp:1236
double x() const
Returns the x-position.
Definition: Position.h:62
Representation of a RouteProbe in netedit.
Definition: GNERouteProbe.h:42
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
T MAX2(T a, T b)
Definition: StdDefs.h:73
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
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2774
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
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:53
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.
PositionVector interpolateZ(double zStart, double zEnd) const
returned vector that varies z smoothly over its length
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
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::vector< GNEConnection * > & getGNEConnections()
returns a reference to the GNEConnection vector
Definition: GNEEdge.cpp:659
const std::string & getID() const
Returns the id.
Definition: Named.h:65
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
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
const std::vector< GNEEdge * > & getGNEEdges() const
Returns all GNEEdges vinculated with this Junction.
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
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
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:254
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
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 std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:121
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
std::string getAttribute(SumoXMLAttr key) const
This functions has to be implemented in all GNEAttributeCarriers.
Definition: GNEEdge.cpp:671
GNEUndoList * getUndoList() const
get the undoList object
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:683
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.
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1806
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1817
the edges of a route
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
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
double beginEndAngle() const
returns the angle in radians of the line connecting the first and the last position ...
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:412
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.
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:502
friend class GNEChange_Attribute
declare friend class
GNEEdge * getOppositeEdge() const
get opposite edge
Definition: GNEEdge.cpp:329
Representation of a vaporizer in netedit.
Definition: GNEVaporizer.h:42
GNEJunction * getGNEJunctionDestiny() const
returns the destination-junction
Definition: GNEEdge.cpp:323
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
int myPriority
The priority of the edge.
Definition: NBEdge.h:1389
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:2596
T MIN2(T a, T b)
Definition: StdDefs.h:67
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0) const
draw name of item
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:535
edge: the shape in xml-definition
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:301
GUIColorer junctionColorer
The junction colorer.
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:590
void addOutgoingGNEEdge(GNEEdge *edge)
add outgoing GNEEdge
const std::string getID() const
function to support debugging
int insertAtClosest(const Position &p)
inserts p between the two closest positions and returns the insertion index
double getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:547
#define DEG2RAD(x)
Definition: GeomHelper.h:44
int getVaporizerRelativePosition(GNEVaporizer *vaporizer) const
obtain relative positions of Vaporizer
Definition: GNEEdge.cpp:556
GNEJunction * getGNEJunctionSource() const
returns the source-junction
Definition: GNEEdge.cpp:317
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 getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
double width
This lane&#39;s width.
Definition: NBEdge.h:141
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3025
void removeLane(GNELane *lane)
the number of lanes by one. argument is only used to increase robustness (assertions) ...
Definition: GNEEdge.cpp:1115
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3269
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:1781
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
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:506
bool canParseVehicleClasses(const std::string &classes)
Checks whether the given string contains only known vehicle classes.
#define DEBUGCOND(PEDID)
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:602
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:56
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition: GNEEdge.cpp:538
ConnectionVector myGNEConnections
vector with the connections of this edge
Definition: GNEEdge.h:283
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:522
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
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 length() 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.
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:249
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:845
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
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
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
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
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:2450
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
const Position & getPosition() const
Definition: NBNode.h:241
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
GUIGlID getGlID() const
Returns the numerical id of the object.
LaneVector myLanes
vectgor with the lanes of this edge
Definition: GNEEdge.h:280
std::vector< GNEAdditional * > myAdditionalChilds
list of Additional Childs of this NetElement
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition: GNEEdge.cpp:1180
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
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:426
void mul(double val)
Multiplies both positions with the given value.
Definition: Position.h:112
bool hasString(const std::string &str) const
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
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
Boundary getBoundary() const
Returns the street&#39;s geometry.
Definition: GNEEdge.cpp:277
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
NBNode * getNBNode() const
Return net build node.
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNEEdge.cpp:747
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
GUISelectedStorage gSelected
A global holder of selected objects.
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
int removeClosest(const Position &p)
removes the point closest to p and return the removal index
std::string getAttributeForSelection(SumoXMLAttr key) const
method for getting the attribute in the context of object selection
Definition: GNEEdge.cpp:738
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
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:433
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
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1607
a junction
void bezier(int npts, double b[], int cpts, double p[])
Definition: bezier.cpp:96
SumoXMLTag getTag() const
get XML Tag assigned to this object