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-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
15 // A road/street connecting two junctions (netedit-version, adapted from GUIEdge)
16 // Basically a container for an NBEdge with drawing and editing capabilities
17 /****************************************************************************/
18 
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24 
25 #include <vector>
26 #include <cmath>
27 #include <string>
28 #include <algorithm>
32 #include <utils/geom/GeomHelper.h>
34 #include <utils/geom/bezier.h>
35 #include <utils/gui/div/GLHelper.h>
40 #include <netedit/GNENet.h>
41 #include <netedit/GNEViewNet.h>
42 #include <netedit/GNEViewParent.h>
43 #include <netedit/GNEUndoList.h>
47 
48 #include "GNEConnection.h"
49 #include "GNECrossing.h"
50 #include "GNEJunction.h"
51 #include "GNELane.h"
52 #include "GNEEdge.h"
53 
54 //#define DEBUG_SMOOTH_GEOM
55 //#define DEBUGCOND(obj) (true)
56 
57 // ===========================================================================
58 // static
59 // ===========================================================================
61 
62 // ===========================================================================
63 // members methods
64 // ===========================================================================
65 
66 GNEEdge::GNEEdge(NBEdge& nbe, GNENet* net, bool wasSplit, bool loaded):
67  GNENetElement(net, nbe.getID(), GLO_EDGE, SUMO_TAG_EDGE),
68  myNBEdge(nbe) ,
69  myGNEJunctionSource(myNet->retrieveJunction(myNBEdge.getFromNode()->getID())),
70  myGNEJunctionDestiny(myNet->retrieveJunction(myNBEdge.getToNode()->getID())),
71  myOrigShape(nbe.getInnerGeometry()),
72  myLanes(0),
73  myAmResponsible(false),
74  myWasSplit(wasSplit),
75  myConnectionStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED) {
76  // Create lanes
77  int numLanes = myNBEdge.getNumLanes();
78  myLanes.reserve(numLanes);
79  for (int i = 0; i < numLanes; i++) {
80  myLanes.push_back(new GNELane(*this, i));
81  myLanes.back()->incRef("GNEEdge::GNEEdge");
82  }
83  // update Lane geometries
84  for (auto i : myLanes) {
85  i->updateGeometry(true);
86  }
87 }
88 
89 
91  // Delete references to this eddge in lanes
92  for (auto i : myLanes) {
93  i->decRef("GNEEdge::~GNEEdge");
94  if (i->unreferenced()) {
95  // show extra information for tests
96  WRITE_DEBUG("Deleting unreferenced " + toString(i->getTag()) + " '" + i->getID() + "' in GNEEdge destructor");
97  delete i;
98  }
99  }
100  // delete references to this eddge in connections
101  for (auto i : myGNEConnections) {
102  i->decRef("GNEEdge::~GNEEdge");
103  if (i->unreferenced()) {
104  // show extra information for tests
105  WRITE_DEBUG("Deleting unreferenced " + toString(i->getTag()) + " '" + i->getID() + "' in GNEEdge destructor");
106  delete i;
107  }
108  }
109  if (myAmResponsible) {
110  delete &myNBEdge;
111  }
112 }
113 
114 
115 void
116 GNEEdge::updateGeometry(bool updateGrid) {
117  // first check if object has to be removed from grid (SUMOTree)
118  if (updateGrid) {
120  }
121  // Update geometry of lanes
122  for (auto i : myLanes) {
123  i->updateGeometry(updateGrid);
124  }
125  // Update geometry of connections (Only if updateGrid is enabled, because in move mode connections are hidden
126  // (note: only the previous marked as deprecated will be updated)
127  if (updateGrid) {
128  for (auto i : myGNEConnections) {
129  i->updateGeometry(updateGrid);
130  }
131  }
132  // Update geometry of additionals childs vinculated to this edge
133  for (auto i : myAdditionalChilds) {
134  i->updateGeometry(updateGrid);
135  }
136  // Update geometry of additional parents that have this edge as parent
137  for (auto i : myFirstAdditionalParents) {
138  i->updateGeometry(updateGrid);
139  }
140  // last step is to check if object has to be added into grid (SUMOTree) again
141  if (updateGrid) {
142  myNet->addGLObjectIntoGrid(this);
143  }
144 }
145 
146 
147 bool
150  return (myNBEdge.getGeometry().front().distanceTo2D(pos) < SNAP_RADIUS);
151  } else {
152  return false;
153  }
154 }
155 
156 
157 bool
160  return (myNBEdge.getGeometry().back().distanceTo2D(pos) < SNAP_RADIUS);
161  } else {
162  return false;
163  }
164 }
165 
166 
167 void
168 GNEEdge::moveShapeStart(const Position& oldPos, const Position& offset) {
169  // change shape startPosition using oldPosition and offset
170  Position shapeStartEdited = oldPos;
171  shapeStartEdited.add(offset);
172  setShapeStartPos(shapeStartEdited);
173  updateGeometry(true);
174 }
175 
176 
177 void
178 GNEEdge::moveShapeEnd(const Position& oldPos, const Position& offset) {
179  // change shape endPosition using oldPosition and offset
180  Position shapeEndEdited = oldPos;
181  shapeEndEdited.add(offset);
182  setShapeEndPos(shapeEndEdited);
183  updateGeometry(true);
184 }
185 
186 
187 void
189  // first save current shape start position
190  Position modifiedShapeStartPos = myNBEdge.getGeometry().front();
191  // restore old shape start position
192  setShapeStartPos(oldPos);
193  // set attribute using undolist
194  undoList->p_begin("shape start of " + toString(getTag()));
195  undoList->p_add(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_START, toString(modifiedShapeStartPos), true, toString(oldPos)));
196  undoList->p_end();
197 }
198 
199 
200 void
202  // first save current shape end position
203  Position modifiedShapeEndPos = myNBEdge.getGeometry().back();
204  // restore old shape end position
205  setShapeEndPos(oldPos);
206  // set attribute using undolist
207  undoList->p_begin("shape end of " + toString(getTag()));
208  undoList->p_add(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_END, toString(modifiedShapeEndPos), true, toString(oldPos)));
209  undoList->p_end();
210 }
211 
212 
213 void
215  // save current centering boundary
217  // Save current centering boundary of lanes (and their childs)
218  for (auto i : myLanes) {
219  i->startGeometryMoving();
220  }
221  // Save current centering boundary of additionals childs vinculated to this edge
222  for (auto i : myAdditionalChilds) {
223  i->startGeometryMoving();
224  }
225  // Save current centering boundary of additional parents that have this edge as parent
226  for (auto i : myFirstAdditionalParents) {
227  i->startGeometryMoving();
228  }
229 }
230 
231 
232 void
234  // check that endGeometryMoving was called only once
236  // Remove object from net
238  // reset myMovingGeometryBoundary
240  // update geometry without updating grid
241  updateGeometry(false);
242  // Restore centering boundary of lanes (and their childs)
243  for (auto i : myLanes) {
244  i->endGeometryMoving();
245  }
246  // Restore centering boundary of additionals childs vinculated to this edge
247  for (auto i : myAdditionalChilds) {
248  i->endGeometryMoving();
249  }
250  // Restore centering boundary of additional parents that have this edge as parent
251  for (auto i : myFirstAdditionalParents) {
252  i->endGeometryMoving();
253  }
254  // add object into grid again (using the new centering boundary)
255  myNet->addGLObjectIntoGrid(this);
256  }
257 }
258 
259 
260 int
261 GNEEdge::getVertexIndex(const Position& pos, bool createIfNoExist) {
262  PositionVector entireGeometry = myNBEdge.getGeometry();
263  double offset = entireGeometry.nearest_offset_to_point2D(pos, true);
264  if (offset == GeomHelper::INVALID_OFFSET) {
265  return -1;
266  }
267  Position newPos = entireGeometry.positionAtOffset2D(offset);
268 
269  // first check if vertex already exists in the inner geometry
270  for (int i = 0; i < (int)entireGeometry.size(); i++) {
271  if (entireGeometry[i].distanceTo2D(newPos) < SNAP_RADIUS) {
272  if (i == 0 || i == (int)(entireGeometry.size() - 1)) {
273  return -1;
274  }
275  // index refers to inner geometry
276  return i - 1;
277  }
278  }
279  // if vertex doesn't exist, insert it
280  if (createIfNoExist) {
281  int index = entireGeometry.insertAtClosest(newPos);
282  setGeometry(entireGeometry, false, true);
283  // index refers to inner geometry
284  return (index - 1);
285  } else {
286  return -1;
287  }
288 }
289 
290 
291 int
292 GNEEdge::getVertexIndex(const double offset, bool createIfNoExist) {
293  return getVertexIndex(myNBEdge.getGeometry().positionAtOffset2D(offset), createIfNoExist);
294 }
295 
296 
297 int
298 GNEEdge::moveVertexShape(const int index, const Position& oldPos, const Position& offset) {
299  // obtain inner geometry of edge
300  PositionVector edgeGeometry = myNBEdge.getInnerGeometry();
301  // Make sure that index is valid AND ins't the first and last index
302  if (index != -1) {
303  // check that index is correct before change position
304  if (index < (int)edgeGeometry.size()) {
305  // save Z value
306  double zValue = edgeGeometry[index].z();
307  // change position of vertex (only X-Y)
308  edgeGeometry[index] = oldPos;
309  edgeGeometry[index].add(offset);
310  // restore Z value
311  edgeGeometry[index].setz(zValue);
312  // update edge's geometry without updating RTree (To avoid unnecesary changes in RTree)
313  setGeometry(edgeGeometry, true, false);
314  return index;
315  } else {
316  throw InvalidArgument("Index greater than shape size");
317  }
318  } else {
319  return index;
320  }
321 }
322 
323 
324 void
325 GNEEdge::moveEntireShape(const PositionVector& oldShape, const Position& offset) {
326  // first remove object from net grid
328  // make a copy of the old shape to change it
329  PositionVector modifiedShape = oldShape;
330  // change all points of the inner geometry using offset
331  for (auto& i : modifiedShape) {
332  i.add(offset);
333  }
334  // restore modified shape
335  setGeometry(modifiedShape, true, true);
336  // add object into net again
337  myNet->addGLObjectIntoGrid(this);
338 }
339 
340 
341 void
343  // restore original shape into shapeToCommit
344  PositionVector innerShapeToCommit = myNBEdge.getInnerGeometry();
345  // first check if second and penultimate isn't in Junction's buubles
347  if (myNBEdge.getGeometry().size() > 2 && myNBEdge.getGeometry()[0].distanceTo(myNBEdge.getGeometry()[1]) < buubleRadius) {
348  innerShapeToCommit.removeClosest(innerShapeToCommit[0]);
349  }
350  if (myNBEdge.getGeometry().size() > 2 && myNBEdge.getGeometry()[(int)myNBEdge.getGeometry().size() - 2].distanceTo(myNBEdge.getGeometry()[(int)myNBEdge.getGeometry().size() - 1]) < buubleRadius) {
351  innerShapeToCommit.removeClosest(innerShapeToCommit[(int)innerShapeToCommit.size() - 1]);
352  }
353  // second check if double points has to be removed
354  innerShapeToCommit.removeDoublePoints(SNAP_RADIUS);
355  // show warning if some of edge's shape was merged
356  if (innerShapeToCommit.size() != myNBEdge.getInnerGeometry().size()) {
357  WRITE_WARNING("Merged shape's point")
358  }
359  // finish geometry moving
361  updateGeometry(false);
362  // restore old geometry to allow change attribute (And restore shape if during movement a new point was created
363  setGeometry(oldShape, true, true);
364  // commit new shape
365  undoList->p_begin("moving " + toString(SUMO_ATTR_SHAPE) + " of " + toString(getTag()));
366  undoList->p_add(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(innerShapeToCommit)));
367  undoList->p_end();
368 }
369 
370 
371 void
372 GNEEdge::deleteGeometryPoint(const Position& pos, bool allowUndo) {
373  // obtain index and remove point
374  PositionVector modifiedShape = myNBEdge.getInnerGeometry();
375  int index = modifiedShape.indexOfClosest(pos);
376  modifiedShape.erase(modifiedShape.begin() + index);
377  // set new shape depending of allowUndo
378  if (allowUndo) {
379  myNet->getViewNet()->getUndoList()->p_begin("delete geometry point");
382  } else {
383  // set new shape
384  setGeometry(modifiedShape, true, true);
385  }
386 }
387 
388 
389 void
390 GNEEdge::updateJunctionPosition(GNEJunction* junction, const Position& origPos, bool updateGrid) {
391  Position delta = junction->getNBNode()->getPosition() - origPos;
393  // geometry endpoint need not equal junction position hence we modify it with delta
394  if (junction == myGNEJunctionSource) {
395  geom[0].add(delta);
396  } else {
397  geom[-1].add(delta);
398  }
399  setGeometry(geom, false, updateGrid);
400 }
401 
402 
403 Boundary
405  Boundary ret;
406  for (auto i : myLanes) {
407  ret.add(i->getBoundary());
408  }
409  // ensure that geometry points are selectable even if the lane geometry is strange
410  for (const Position& pos : myNBEdge.getGeometry()) {
411  ret.add(pos);
412  }
413  ret.grow(10); // !!! magic value
414  return ret;
415 }
416 
417 
418 Boundary
420  // Return Boundary depending if myMovingGeometryBoundary is initialised (important for move geometry)
423  } else {
424  Boundary b = getBoundary();
425  b.grow(20);
426  return b;
427  }
428 }
429 
430 
433  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
434  buildPopupHeader(ret, app);
437  // build selection and show parameters menu
440  // build position copy entry
441  buildPositionCopyEntry(ret, false);
442  return ret;
443 }
444 
445 
448  return myGNEJunctionSource;
449 }
450 
451 
454  return myGNEJunctionDestiny;
455 }
456 
457 
458 GNEEdge*
461 }
462 
463 
464 void
466  /* do something different for connectors?
467  if (myNBEdge.isMacroscopicConnector()) {
468  }
469  */
470  // obtain circle width
471  double circleWidth = SNAP_RADIUS * MIN2((double)1, s.laneWidthExaggeration);
472  double circleWidthSquared = circleWidth * circleWidth;
473  int circleResolution = GNEAttributeCarrier::getCircleResolution(s);
474  // draw the lanes
475  for (auto i : myLanes) {
476  i->drawGL(s);
477  }
478  // draw geometry points if isnt's too small
479  if (s.scale > 8.0) {
480  GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
482  // override with special colors (unless the color scheme is based on selection)
483  GLHelper::setColor(GNENet::selectionColor.changedBrightness(-20));
484  }
485  // recognize full transparency and simply don't draw
486  GLfloat color[4];
487  glGetFloatv(GL_CURRENT_COLOR, color);
488  if (color[3] > 0) {
489  // push name
490  glPushName(getGlID());
491  // draw geometry points expect initial and final
492  for (int i = 1; i < (int)myNBEdge.getGeometry().size() - 1; i++) {
493  Position pos = myNBEdge.getGeometry()[i];
494  if (!s.drawForSelecting || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo(pos) <= (circleWidthSquared + 2))) {
495  glPushMatrix();
496  glTranslated(pos.x(), pos.y(), GLO_JUNCTION - 0.01);
497  // resolution of drawn circle depending of the zoom (To improve smothness)
498  GLHelper::drawFilledCircle(circleWidth, circleResolution);
499  glPopMatrix();
500  }
501  }
502  // draw line geometry, start and end points if shapeStart or shape end is edited, and depending of drawForSelecting
505  (!s.drawForSelecting || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo(myNBEdge.getGeometry().front()) <= (circleWidthSquared + 2)))) {
506  glPushMatrix();
507  glTranslated(myNBEdge.getGeometry().front().x(), myNBEdge.getGeometry().front().y(), GLO_JUNCTION + 0.01);
508  // resolution of drawn circle depending of the zoom (To improve smothness)
509  GLHelper::drawFilledCircle(circleWidth, circleResolution);
510  glPopMatrix();
511  // draw a "s" over last point depending of drawForSelecting
512  if (!s.drawForSelecting) {
513  glPushMatrix();
514  glTranslated(myNBEdge.getGeometry().front().x(), myNBEdge.getGeometry().front().y(), GLO_JUNCTION + 0.02);
515  GLHelper::drawText("S", Position(), 0, circleWidth, RGBColor::WHITE);
516  glPopMatrix();
517  // draw line between Junction and point
518  glPushMatrix();
519  glTranslated(0, 0, GLO_JUNCTION - 0.01);
520  glLineWidth(4);
522  glPopMatrix();
523  }
524  }
526  (!s.drawForSelecting || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo(myNBEdge.getGeometry().back()) <= (circleWidthSquared + 2)))) {
527  glPushMatrix();
528  glTranslated(myNBEdge.getGeometry().back().x(), myNBEdge.getGeometry().back().y(), GLO_JUNCTION + 0.01);
529  // resolution of drawn circle depending of the zoom (To improve smothness)
530  GLHelper::drawFilledCircle(circleWidth, circleResolution);
531  glPopMatrix();
532  // draw a "e" over last point depending of drawForSelecting
533  if (!s.drawForSelecting) {
534  glPushMatrix();
535  glTranslated(myNBEdge.getGeometry().back().x(), myNBEdge.getGeometry().back().y(), GLO_JUNCTION + 0.02);
536  GLHelper::drawText("E", Position(), 0, circleWidth, RGBColor::WHITE);
537  glPopMatrix();
538  // draw line between Junction and point
539  glPushMatrix();
540  glTranslated(0, 0, GLO_JUNCTION - 0.01);
541  glLineWidth(4);
543  glPopMatrix();
544  }
545  }
546  }
547  // pop name
548  glPopName();
549  }
550  }
551 
552  // (optionally) draw the name and/or the street name if isn't being drawn for selecting
553  const bool drawStreetName = s.streetName.show && (myNBEdge.getStreetName() != "");
554  if (!s.drawForSelecting && (s.edgeName.show || drawStreetName)) {
555  glPushName(getGlID());
556  GNELane* lane1 = myLanes[0];
557  GNELane* lane2 = myLanes[myLanes.size() - 1];
558  Position p = lane1->getShape().positionAtOffset(lane1->getShape().length() / (double) 2.);
559  p.add(lane2->getShape().positionAtOffset(lane2->getShape().length() / (double) 2.));
560  p.mul(.5);
561  double angle = lane1->getShape().rotationDegreeAtOffset(lane1->getShape().length() / (double) 2.);
562  angle += 90;
563  if (angle > 90 && angle < 270) {
564  angle -= 180;
565  }
566  if (s.edgeName.show) {
567  drawName(p, s.scale, s.edgeName, angle);
568  }
569  if (drawStreetName) {
571  s.streetName.scaledSize(s.scale), s.streetName.color, angle);
572  }
573  glPopName();
574  }
575  if (!s.drawForSelecting && (myNet->getViewNet()->getACUnderCursor() == this)) {
576  // draw dotted contor around the first and last lane
577  const double myHalfLaneWidthFront = myNBEdge.getLaneWidth(myLanes.front()->getIndex()) / 2;
578  const double myHalfLaneWidthBack = myNBEdge.getLaneWidth(myLanes.back()->getIndex()) / 2;
579  GLHelper::drawShapeDottedContour(GLO_JUNCTION, myLanes.front()->getShape(), myHalfLaneWidthFront, myLanes.back()->getShape(), -1 * myHalfLaneWidthBack);
580  }
581  glPopMatrix();
582 }
583 
584 
585 NBEdge*
587  return &myNBEdge;
588 }
589 
590 
591 Position
592 GNEEdge::getSplitPos(const Position& clickPos) {
593  const PositionVector& geom = myNBEdge.getGeometry();
594  int index = geom.indexOfClosest(clickPos);
595  if (geom[index].distanceTo(clickPos) < SNAP_RADIUS) {
596  // split at existing geometry point
597  return geom[index];
598  } else {
599  // split straight between the next two points
600  return geom.positionAtOffset(geom.nearest_offset_to_point2D(clickPos));
601  }
602 }
603 
604 
605 void
607  if ((myNBEdge.getGeometry().front() != myGNEJunctionSource->getPositionInView()) && (myNBEdge.getGeometry().front().distanceTo(pos) < SNAP_RADIUS)) {
608  undoList->p_begin("remove endpoint");
609  setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
610  undoList->p_end();
611  } else if ((myNBEdge.getGeometry().back() != myGNEJunctionDestiny->getPositionInView()) && (myNBEdge.getGeometry().back().distanceTo(pos) < SNAP_RADIUS)) {
612  undoList->p_begin("remove endpoint");
613  setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
614  undoList->p_end();
615  } else {
616  undoList->p_begin("set endpoint");
618  int index = geom.indexOfClosest(pos);
619  if (geom[index].distanceTo(pos) < SNAP_RADIUS) { // snap to existing geometry
620  pos = geom[index];
621  }
624  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
625  setAttribute(GNE_ATTR_SHAPE_END, toString(pos), undoList);
627  } else {
628  setAttribute(GNE_ATTR_SHAPE_START, toString(pos), undoList);
630  }
631  // possibly existing inner point is no longer needed
632  if (myNBEdge.getInnerGeometry().size() > 0 && getVertexIndex(pos, false) != -1) {
633  deleteGeometryPoint(pos, false);
634  }
635  undoList->p_end();
636  }
637 }
638 
639 
640 void
644  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
645  setAttribute(GNE_ATTR_SHAPE_END, toString(destPos), undoList);
647  } else {
648  setAttribute(GNE_ATTR_SHAPE_START, toString(sourcePos), undoList);
650  }
651 }
652 
653 
654 void
655 GNEEdge::setGeometry(PositionVector geom, bool inner, bool updateGrid) {
656  if (updateGrid) {
657  // first remove object from net grid
659  }
660  // set new geometry
661  myNBEdge.setGeometry(geom, inner);
662  if (updateGrid) {
663  // add object into net again
664  myNet->addGLObjectIntoGrid(this);
665  }
666  updateGeometry(updateGrid);
669 }
670 
671 
672 void
674  // create new and removed unused GNEConnectinos
675  const std::vector<NBEdge::Connection>& connections = myNBEdge.getConnections();
676  // create a vector to keep retrieved and created connections
677  std::vector<GNEConnection*> retrievedConnections;
678  // iterate over NBEdge::Connections of GNEEdge
679  for (auto it : connections) {
680  // retrieve existent GNEConnection, or create it
681  GNEConnection* retrievedGNEConnection = retrieveGNEConnection(it.fromLane, it.toEdge, it.toLane);
682  retrievedGNEConnection->updateLinkState();
683  retrievedConnections.push_back(retrievedGNEConnection);
684  // check if previously this GNEConnections exists, and if true, remove it from myGNEConnections
685  std::vector<GNEConnection*>::iterator retrievedExists = std::find(myGNEConnections.begin(), myGNEConnections.end(), retrievedGNEConnection);
686  if (retrievedExists != myGNEConnections.end()) {
687  myGNEConnections.erase(retrievedExists);
688  } else {
689  // include reference to created GNEConnection
690  retrievedGNEConnection->incRef("GNEEdge::remakeGNEConnections");
691  }
692  // mark it as deprecated
693  retrievedGNEConnection->markConnectionGeometryDeprecated();
694  }
695  // delete non retrieved GNEConnections
696  for (auto it : myGNEConnections) {
697  // remove it from Tree
699  it->decRef();
700  if (it->unreferenced()) {
701  // show extra information for tests
702  WRITE_DEBUG("Deleting unreferenced " + toString(it->getTag()) + " '" + it->getID() + "' in rebuildGNEConnections()");
703  delete it;
704  }
705  }
706  // copy retrieved (existent and created) GNECrossigns to myGNEConnections
707  myGNEConnections = retrievedConnections;
708 }
709 
710 
711 void
713  // Drop all existents connections that aren't referenced anymore
714  for (auto i : myGNEConnections) {
715  // check if connection is selected
716  if (i->isAttributeCarrierSelected()) {
717  i->unselectAttributeCarrier();
718  }
719  // remove it from Tree
721  // Dec reference of connection
722  i->decRef("GNEEdge::clearGNEConnections");
723  // Delete GNEConnectionToErase if is unreferenced
724  if (i->unreferenced()) {
725  // show extra information for tests
726  WRITE_DEBUG("Deleting unreferenced " + toString(i->getTag()) + " '" + i->getID() + "' in clearGNEConnections()");
727  delete i;
728  }
729  }
730  myGNEConnections.clear();
731 }
732 
733 
734 int
736  std::vector<GNEAdditional*> routeProbes;
737  for (auto i : myAdditionalChilds) {
738  if (i->getTag() == routeProbe->getTag()) {
739  routeProbes.push_back(i);
740  }
741  }
742  // return index of routeProbe in routeProbes vector
743  auto it = std::find(routeProbes.begin(), routeProbes.end(), routeProbe);
744  if (it == routeProbes.end()) {
745  return -1;
746  } else {
747  return (int)(it - routeProbes.begin());
748  }
749 }
750 
751 
752 std::vector<GNECrossing*>
754  std::vector<GNECrossing*> crossings;
755  for (auto i : myGNEJunctionSource->getGNECrossings()) {
756  if (i->checkEdgeBelong(this)) {
757  crossings.push_back(i);
758  }
759  }
760  for (auto i : myGNEJunctionDestiny->getGNECrossings()) {
761  if (i->checkEdgeBelong(this)) {
762  crossings.push_back(i);
763  }
764  }
765  return crossings;
766 }
767 
768 
769 void
771  // iterate over all additional parents of edge
772  for (auto i : myFirstAdditionalParents) {
773  // Obtain attribute EDGES of additional
774  std::vector<std::string> edgeIDs = parse<std::vector<std::string> >(i->getAttribute(SUMO_ATTR_EDGES));
775  // check that at least there is an Edge
776  if (edgeIDs.empty()) {
777  throw ProcessError("Additional edge childs is empty");
778  } else if ((edgeIDs.size() == 1) && (allowEmpty == false)) {
779  // remove entire Additional if SUMO_ATTR_EDGES cannot be empty
780  if (edgeIDs.front() == getID()) {
781  undoList->add(new GNEChange_Additional(i, false), true);
782  } else {
783  throw ProcessError("Edge ID wasnt' found in Additional");
784  }
785  } else {
786  auto it = std::find(edgeIDs.begin(), edgeIDs.end(), getID());
787  if (it != edgeIDs.end()) {
788  // set new attribute in Additional
789  edgeIDs.erase(it);
790  i->setAttribute(SUMO_ATTR_EDGES, toString(edgeIDs), undoList);
791  } else {
792  throw ProcessError("Edge ID wasnt' found in Additional");
793  }
794  }
795  }
796 }
797 
798 
799 void
801  undoList->p_begin("copy template");
809  // copy lane attributes as well
810  for (int i = 0; i < (int)myLanes.size(); i++) {
811  myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, tpl->myLanes[i]->getAttribute(SUMO_ATTR_ALLOW), undoList);
812  myLanes[i]->setAttribute(SUMO_ATTR_DISALLOW, tpl->myLanes[i]->getAttribute(SUMO_ATTR_DISALLOW), undoList);
813  myLanes[i]->setAttribute(SUMO_ATTR_SPEED, tpl->myLanes[i]->getAttribute(SUMO_ATTR_SPEED), undoList);
814  myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, tpl->myLanes[i]->getAttribute(SUMO_ATTR_WIDTH), undoList);
815  myLanes[i]->setAttribute(SUMO_ATTR_ENDOFFSET, tpl->myLanes[i]->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
816  }
817  undoList->p_end();
818 }
819 
820 
821 std::set<GUIGlID>
823  std::set<GUIGlID> result;
824  for (auto i : myLanes) {
825  result.insert(i->getGlID());
826  }
827  return result;
828 }
829 
830 
831 const std::vector<GNELane*>&
833  return myLanes;
834 }
835 
836 
837 const std::vector<GNEConnection*>&
839  return myGNEConnections;
840 }
841 
842 
843 bool
845  return myWasSplit;
846 }
847 
848 
849 std::string
851  switch (key) {
852  case SUMO_ATTR_ID:
853  return getMicrosimID();
854  case SUMO_ATTR_FROM:
856  case SUMO_ATTR_TO:
858  case SUMO_ATTR_NUMLANES:
859  return toString(myNBEdge.getNumLanes());
860  case SUMO_ATTR_PRIORITY:
861  return toString(myNBEdge.getPriority());
862  case SUMO_ATTR_LENGTH:
863  return toString(myNBEdge.getFinalLength());
864  case SUMO_ATTR_TYPE:
865  return myNBEdge.getTypeID();
866  case SUMO_ATTR_SHAPE:
870  case SUMO_ATTR_NAME:
871  return myNBEdge.getStreetName();
872  case SUMO_ATTR_ALLOW:
873  return (getVehicleClassNames(myNBEdge.getPermissions()) + (myNBEdge.hasLaneSpecificPermissions() ? " (combined!)" : ""));
874  case SUMO_ATTR_DISALLOW: {
876  }
877  case SUMO_ATTR_SPEED:
879  return "lane specific";
880  } else {
881  return toString(myNBEdge.getSpeed());
882  }
883  case SUMO_ATTR_WIDTH:
885  return "lane specific";
886  } else {
887  return toString(myNBEdge.getLaneWidth());
888  }
889  case SUMO_ATTR_ENDOFFSET:
891  return "lane specific";
892  } else {
893  return toString(myNBEdge.getEndOffset());
894  }
896  return myConnectionStatus;
899  return "";
900  } else {
901  return toString(myNBEdge.getGeometry().front());
902  }
903  case GNE_ATTR_SHAPE_END:
905  return "";
906  } else {
907  return toString(myNBEdge.getGeometry().back());
908  }
909  case GNE_ATTR_BIDIR:
910  return toString(myNBEdge.isBidiRail());
911  case GNE_ATTR_SELECTED:
913  case GNE_ATTR_GENERIC:
914  return getGenericParametersStr();
915  default:
916  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
917  }
918 }
919 
920 std::string
922  std::string result = getAttribute(key);
923  if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
924  result += " " + getVehicleClassNames(SVCAll, true);
925  }
926  return result;
927 }
928 
929 void
930 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
931  switch (key) {
932  case SUMO_ATTR_WIDTH:
933  case SUMO_ATTR_ENDOFFSET:
934  case SUMO_ATTR_SPEED:
935  case SUMO_ATTR_ALLOW:
936  case SUMO_ATTR_DISALLOW: {
937  undoList->p_begin("change " + toString(getTag()) + " attribute");
938  const std::string origValue = myLanes.at(0)->getAttribute(key); // will have intermediate value of "lane specific"
939  // lane specific attributes need to be changed via lanes to allow undo
940  for (auto it : myLanes) {
941  it->setAttribute(key, value, undoList);
942  }
943  // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
944  undoList->p_add(new GNEChange_Attribute(this, key, value, true, origValue));
945  undoList->p_end();
946  break;
947  }
948  case SUMO_ATTR_FROM: {
949  undoList->p_begin("change " + toString(getTag()) + " attribute");
950  // Remove edge from crossings of junction source
952  // continue changing from junction
953  GNEJunction* oldGNEJunctionSource = myGNEJunctionSource;
954  myGNEJunctionSource->setLogicValid(false, undoList);
955  undoList->p_add(new GNEChange_Attribute(this, key, value));
956  myGNEJunctionSource->setLogicValid(false, undoList);
957  myNet->retrieveJunction(value)->setLogicValid(false, undoList);
960  undoList->p_end();
961  // update geometries of all implicated junctions
962  oldGNEJunctionSource->updateGeometry(true);
965  break;
966  }
967  case SUMO_ATTR_TO: {
968  undoList->p_begin("change " + toString(getTag()) + " attribute");
969  // Remove edge from crossings of junction destiny
971  // continue changing destiny junction
972  GNEJunction* oldGNEJunctionDestiny = myGNEJunctionDestiny;
973  myGNEJunctionDestiny->setLogicValid(false, undoList);
974  undoList->p_add(new GNEChange_Attribute(this, key, value));
975  myGNEJunctionDestiny->setLogicValid(false, undoList);
976  myNet->retrieveJunction(value)->setLogicValid(false, undoList);
979  undoList->p_end();
980  // update geometries of all implicated junctions
981  oldGNEJunctionDestiny->updateGeometry(true);
984  break;
985  }
986  case SUMO_ATTR_ID:
987  case SUMO_ATTR_PRIORITY:
988  case SUMO_ATTR_LENGTH:
989  case SUMO_ATTR_TYPE:
993  case GNE_ATTR_SHAPE_END:
994  case GNE_ATTR_SELECTED:
995  case GNE_ATTR_GENERIC:
996  undoList->p_add(new GNEChange_Attribute(this, key, value));
997  break;
998  case SUMO_ATTR_NAME:
999  // user cares about street names. Make sure they appear in the output
1001  OptionsCont::getOptions().set("output.street-names", "true");
1002  undoList->p_add(new GNEChange_Attribute(this, key, value));
1003  break;
1004  case SUMO_ATTR_NUMLANES:
1005  if (value != getAttribute(key)) {
1006  // Remove edge from crossings of junction source
1008  // Remove edge from crossings of junction destiny
1010  // set num lanes
1011  setNumLanes(parse<int>(value), undoList);
1012  }
1013  break;
1014  case SUMO_ATTR_SHAPE:
1015  // @note: assumes value of inner geometry!
1016  // actually the geometry is already updated (incrementally
1017  // during mouse movement). We set the restore point to the end
1018  // of the last change-set
1020  undoList->p_add(new GNEChange_Attribute(this, key, value));
1021  break;
1022  case GNE_ATTR_BIDIR:
1023  throw InvalidArgument("Attribute of '" + toString(key) + "' cannot be modified");
1024  default:
1025  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
1026  }
1027 }
1028 
1029 
1030 bool
1031 GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
1032  switch (key) {
1033  case SUMO_ATTR_ID:
1034  return SUMOXMLDefinitions::isValidNetID(value) && (myNet->retrieveEdge(value, false) == 0);
1035  case SUMO_ATTR_FROM: {
1036  // check that is a valid ID and is different of ID of junction destiny
1038  GNEJunction* junctionFrom = myNet->retrieveJunction(value, false);
1039  // check that there isn't already another edge with the same From and To Edge
1040  if ((junctionFrom != nullptr) && (myNet->retrieveEdge(junctionFrom, myGNEJunctionDestiny, false) == nullptr)) {
1041  return true;
1042  } else {
1043  return false;
1044  }
1045  } else {
1046  return false;
1047  }
1048  }
1049  case SUMO_ATTR_TO: {
1050  // check that is a valid ID and is different of ID of junction Source
1052  GNEJunction* junctionTo = myNet->retrieveJunction(value, false);
1053  // check that there isn't already another edge with the same From and To Edge
1054  if ((junctionTo != nullptr) && (myNet->retrieveEdge(myGNEJunctionSource, junctionTo, false) == nullptr)) {
1055  return true;
1056  } else {
1057  return false;
1058  }
1059  } else {
1060  return false;
1061  }
1062  }
1063  case SUMO_ATTR_SPEED:
1064  return canParse<double>(value) && (parse<double>(value) > 0);
1065  case SUMO_ATTR_NUMLANES:
1066  return canParse<int>(value) && (parse<double>(value) > 0);
1067  case SUMO_ATTR_PRIORITY:
1068  return canParse<int>(value);
1069  case SUMO_ATTR_LENGTH:
1070  return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
1071  case SUMO_ATTR_ALLOW:
1072  case SUMO_ATTR_DISALLOW:
1073  return canParseVehicleClasses(value);
1074  case SUMO_ATTR_TYPE:
1075  return true;
1076  case SUMO_ATTR_SHAPE: {
1077  bool ok = true;
1078  PositionVector shape = GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, true);
1079  return ok;
1080  }
1081  case SUMO_ATTR_SPREADTYPE:
1083  case SUMO_ATTR_NAME:
1084  return true;
1085  case SUMO_ATTR_WIDTH:
1086  return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
1087  case SUMO_ATTR_ENDOFFSET:
1088  return canParse<double>(value) && (parse<double>(value) >= 0);
1089  case GNE_ATTR_SHAPE_START: {
1090  bool ok;
1091  if (value != "") {
1092  PositionVector shapeStart = GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, false);
1093  return ((shapeStart.size() == 1) && (shapeStart[0] != myNBEdge.getGeometry()[-1]));
1094  } else {
1095  return true;
1096  }
1097  }
1098  case GNE_ATTR_SHAPE_END: {
1099  bool ok;
1100  if (value != "") {
1101  PositionVector shapeStart = GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, false);
1102  return ((shapeStart.size() == 1) && (shapeStart[0] != myNBEdge.getGeometry()[0]));
1103  } else {
1104  return true;
1105  }
1106  }
1107  case GNE_ATTR_BIDIR:
1108  return false;
1109  case GNE_ATTR_SELECTED:
1110  return canParse<bool>(value);
1111  case GNE_ATTR_GENERIC:
1112  return isGenericParametersValid(value);
1113  default:
1114  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
1115  }
1116 }
1117 
1118 
1119 bool
1120 GNEEdge::addGenericParameter(const std::string& key, const std::string& value) {
1121  if (!myNBEdge.knowsParameter(key)) {
1122  myNBEdge.setParameter(key, value);
1123  return true;
1124  } else {
1125  return false;
1126  }
1127 }
1128 
1129 
1130 bool
1131 GNEEdge::removeGenericParameter(const std::string& key) {
1132  if (myNBEdge.knowsParameter(key)) {
1133  myNBEdge.unsetParameter(key);
1134  return true;
1135  } else {
1136  return false;
1137  }
1138 }
1139 
1140 
1141 bool
1142 GNEEdge::updateGenericParameter(const std::string& oldKey, const std::string& newKey) {
1143  if (myNBEdge.knowsParameter(oldKey) && !myNBEdge.knowsParameter(newKey)) {
1144  std::string value = myNBEdge.getParameter(oldKey);
1145  myNBEdge.unsetParameter(oldKey);
1146  myNBEdge.setParameter(newKey, value);
1147  return true;
1148  } else {
1149  return false;
1150  }
1151 }
1152 
1153 
1154 bool
1155 GNEEdge::updateGenericParameterValue(const std::string& key, const std::string& newValue) {
1156  if (myNBEdge.knowsParameter(key)) {
1157  myNBEdge.setParameter(key, newValue);
1158  return true;
1159  } else {
1160  return false;
1161  }
1162 }
1163 
1164 
1165 std::string
1167  std::string result;
1168  // Generate an string using the following structure: "key1=value1|key2=value2|...
1169  for (auto i : myNBEdge.getParametersMap()) {
1170  result += i.first + "=" + i.second + "|";
1171  }
1172  // remove the last "|"
1173  if (!result.empty()) {
1174  result.pop_back();
1175  }
1176  return result;
1177 }
1178 
1179 
1180 std::vector<std::pair<std::string, std::string> >
1182  std::vector<std::pair<std::string, std::string> > result;
1183  // iterate over parameters map and fill result
1184  for (auto i : myNBEdge.getParametersMap()) {
1185  result.push_back(std::make_pair(i.first, i.second));
1186  }
1187  return result;
1188 }
1189 
1190 
1191 void
1192 GNEEdge::setGenericParametersStr(const std::string& value) {
1193  // clear parameters
1195  // separate value in a vector of string using | as separator
1196  std::vector<std::string> parsedValues;
1197  StringTokenizer stValues(value, "|", true);
1198  while (stValues.hasNext()) {
1199  parsedValues.push_back(stValues.next());
1200  }
1201  // check that parsed values (A=B)can be parsed in generic parameters
1202  for (auto i : parsedValues) {
1203  std::vector<std::string> parsedParameters;
1204  StringTokenizer stParam(i, "=", true);
1205  while (stParam.hasNext()) {
1206  parsedParameters.push_back(stParam.next());
1207  }
1208  // Check that parsed parameters are exactly two and contains valid chracters
1209  if (parsedParameters.size() == 2 && SUMOXMLDefinitions::isValidGenericParameterKey(parsedParameters.front()) && SUMOXMLDefinitions::isValidGenericParameterValue(parsedParameters.back())) {
1210  myNBEdge.setParameter(parsedParameters.front(), parsedParameters.back());
1211  }
1212  }
1213 }
1214 
1215 
1216 void
1218  myAmResponsible = newVal;
1219 }
1220 
1221 // ===========================================================================
1222 // private
1223 // ===========================================================================
1224 
1225 void
1226 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
1227  switch (key) {
1228  case SUMO_ATTR_ID:
1229  myNet->renameEdge(this, value);
1230  break;
1231  case SUMO_ATTR_FROM:
1233  // update this edge of list of outgoings edges of the old GNEJunctionSource
1235  // update GNEJunctionSource
1237  // update this edge of list of outgoings edges of the new GNEJunctionSource
1239  break;
1240  case SUMO_ATTR_TO:
1242  // update this edge of list of incomings edges of the old GNEJunctionDestiny
1244  // update GNEJunctionDestiny
1246  // update this edge of list of incomings edges of the new GNEJunctionDestiny
1248  break;
1249  case SUMO_ATTR_NUMLANES:
1250  throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
1251  break;
1252  case SUMO_ATTR_PRIORITY:
1253  myNBEdge.myPriority = parse<int>(value);
1254  break;
1255  case SUMO_ATTR_LENGTH:
1256  myNBEdge.setLoadedLength(parse<double>(value));
1257  break;
1258  case SUMO_ATTR_TYPE:
1259  myNBEdge.myType = value;
1260  break;
1261  case SUMO_ATTR_SHAPE:
1262  bool ok;
1263  myOrigShape = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, true);
1264  setGeometry(myOrigShape, true, true);
1265  break;
1266  case SUMO_ATTR_SPREADTYPE:
1268  break;
1269  case SUMO_ATTR_NAME:
1270  myNBEdge.setStreetName(value);
1271  break;
1272  case SUMO_ATTR_SPEED:
1273  myNBEdge.setSpeed(-1, parse<double>(value));
1274  break;
1275  case SUMO_ATTR_WIDTH:
1276  myNBEdge.setLaneWidth(-1, parse<double>(value));
1277  break;
1278  case SUMO_ATTR_ENDOFFSET:
1279  myNBEdge.setEndOffset(-1, parse<double>(value));
1280  break;
1281  case SUMO_ATTR_ALLOW:
1282  break; // no edge value
1283  case SUMO_ATTR_DISALLOW:
1284  break; // no edge value
1286  myConnectionStatus = value;
1287  if (value == FEATURE_GUESSED) {
1288  WRITE_DEBUG("invalidating (removing) connections of edge '" + getID() + "' due it were guessed");
1291  } else if (value != FEATURE_GUESSED) {
1292  WRITE_DEBUG("declaring connections of edge '" + getID() + "' as loaded (It will not be removed)");
1294  }
1295  break;
1296  case GNE_ATTR_SHAPE_START: {
1297  // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1298  Position newShapeStart;
1299  if (value == "") {
1300  newShapeStart = myGNEJunctionSource->getPositionInView();
1301  } else {
1302  newShapeStart = parse<Position>(value);
1303  }
1304  // set shape start position
1305  setShapeStartPos(newShapeStart);
1306  break;
1307  }
1308  case GNE_ATTR_SHAPE_END: {
1309  // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destiny position) and set it back to edge
1310  Position newShapeEnd;
1311  if (value == "") {
1312  newShapeEnd = myGNEJunctionDestiny->getPositionInView();
1313  } else {
1314  newShapeEnd = parse<Position>(value);
1315  }
1316  // set shape end position
1317  setShapeEndPos(newShapeEnd);
1318  break;
1319  }
1320  case GNE_ATTR_BIDIR:
1321  throw InvalidArgument("Attribute of '" + toString(key) + "' cannot be modified");
1322  case GNE_ATTR_SELECTED:
1323  if (parse<bool>(value)) {
1325  } else {
1327  }
1328  break;
1329  case GNE_ATTR_GENERIC:
1330  setGenericParametersStr(value);
1331  break;
1332  default:
1333  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
1334  }
1335  // After setting attribute always update Geometry
1336  updateGeometry(true);
1337 }
1338 
1339 
1340 void
1342 }
1343 
1344 
1345 void
1346 GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
1347  undoList->p_begin("change number of " + toString(SUMO_TAG_LANE) + "s");
1348  myGNEJunctionSource->setLogicValid(false, undoList);
1349  myGNEJunctionDestiny->setLogicValid(false, undoList);
1350 
1351  const int oldNumLanes = (int)myLanes.size();
1352  for (int i = oldNumLanes; i < numLanes; i++) {
1353  // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
1354  undoList->add(new GNEChange_Lane(this, 0,
1355  myNBEdge.getLaneStruct(oldNumLanes - 1), true), true);
1356  }
1357  for (int i = oldNumLanes - 1; i > numLanes - 1; i--) {
1358  // delete leftmost lane
1359  undoList->add(new GNEChange_Lane(this, myLanes[i], myNBEdge.getLaneStruct(i), false), true);
1360  }
1361  undoList->p_end();
1362 }
1363 
1364 
1365 void
1366 GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections) {
1367  // boundary of edge depends of number of lanes. We need to extract if before add or remove lane
1369  const int index = lane ? lane->getIndex() : myNBEdge.getNumLanes();
1370  // the laneStruct must be created first to ensure we have some geometry
1371  // unless the connections are fully recomputed, existing indices must be shifted
1372  myNBEdge.addLane(index, true, recomputeConnections, !recomputeConnections);
1373  if (lane) {
1374  // restore a previously deleted lane
1375  myLanes.insert(myLanes.begin() + index, lane);
1376 
1377  } else {
1378  // create a new lane by copying leftmost lane
1379  lane = new GNELane(*this, index);
1380  myLanes.push_back(lane);
1381  }
1382  lane->incRef("GNEEdge::addLane");
1383  // check if lane is selected
1384  if (lane->isAttributeCarrierSelected()) {
1385  lane->selectAttributeCarrier();
1386  }
1387  // we copy all attributes except shape since this is recomputed from edge shape
1388  myNBEdge.setSpeed(lane->getIndex(), laneAttrs.speed);
1389  myNBEdge.setPermissions(laneAttrs.permissions, lane->getIndex());
1391  myNBEdge.setEndOffset(lane->getIndex(), laneAttrs.endOffset);
1392  myNBEdge.setLaneWidth(lane->getIndex(), laneAttrs.width);
1393  // udate indices
1394  for (int i = 0; i < (int)myLanes.size(); ++i) {
1395  myLanes[i]->setIndex(i);
1396  }
1397  /* while technically correct, this looks ugly
1398  myGNEJunctionSource->invalidateShape();
1399  myGNEJunctionDestiny->invalidateShape();
1400  */
1401  // Remake connections for this edge and all edges that target this lane
1403  // remake connections of all edges of junction source and destiny
1404  for (auto i : myGNEJunctionSource->getGNEEdges()) {
1405  i->remakeGNEConnections();
1406  }
1407  // remake connections of all edges of junction source and destiny
1408  for (auto i : myGNEJunctionDestiny->getGNEEdges()) {
1409  i->remakeGNEConnections();
1410  }
1411  // add object again
1412  myNet->addGLObjectIntoGrid(this);
1413  // Update geometry with the new lane
1414  updateGeometry(true);
1415 }
1416 
1417 
1418 void
1419 GNEEdge::removeLane(GNELane* lane, bool recomputeConnections) {
1420  // boundary of edge depends of number of lanes. We need to extract if before add or remove lane
1422  if (myLanes.size() == 0) {
1423  throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + toString(getTag()));
1424  }
1425  if (lane == 0) {
1426  lane = myLanes.back();
1427  }
1428  // check if lane is selected
1429  if (lane->isAttributeCarrierSelected()) {
1430  lane->unselectAttributeCarrier();
1431  }
1432  // Delete lane of edge's container
1433  // unless the connections are fully recomputed, existing indices must be shifted
1434  myNBEdge.deleteLane(lane->getIndex(), recomputeConnections, !recomputeConnections);
1435  lane->decRef("GNEEdge::removeLane");
1436  myLanes.erase(myLanes.begin() + lane->getIndex());
1437  // Delete lane if is unreferenced
1438  if (lane->unreferenced()) {
1439  // show extra information for tests
1440  WRITE_DEBUG("Deleting unreferenced " + toString(lane->getTag()) + " '" + lane->getID() + "' in removeLane()");
1441  delete lane;
1442  }
1443  // udate indices
1444  for (int i = 0; i < (int)myLanes.size(); ++i) {
1445  myLanes[i]->setIndex(i);
1446  }
1447  /* while technically correct, this looks ugly
1448  myGNEJunctionSource->invalidateShape();
1449  myGNEJunctionDestiny->invalidateShape();
1450  */
1451  // Remake connections of this edge
1453  // remake connections of all edges of junction source and destiny
1454  for (auto i : myGNEJunctionSource->getGNEEdges()) {
1455  i->remakeGNEConnections();
1456  }
1457  // remake connections of all edges of junction source and destiny
1458  for (auto i : myGNEJunctionDestiny->getGNEEdges()) {
1459  i->remakeGNEConnections();
1460  }
1461  // add object again
1462  myNet->addGLObjectIntoGrid(this);
1463  // Update element
1464  updateGeometry(true);
1465 }
1466 
1467 
1468 void
1469 GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
1470  // If a new connection was sucesfully created
1471  if (myNBEdge.setConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, NBEdge::L2L_USER, true, nbCon.mayDefinitelyPass,
1472  nbCon.keepClear, nbCon.contPos, nbCon.visibility,
1473  nbCon.speed, nbCon.customShape, nbCon.uncontrolled)) {
1474  // Create or retrieve existent GNEConection
1475  GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
1476  // add it to GNEConnection container
1477  myGNEConnections.push_back(con);
1478  // Add reference
1479  myGNEConnections.back()->incRef("GNEEdge::addConnection");
1480  // select GNEConnection if needed
1481  if (selectAfterCreation) {
1482  con->selectAttributeCarrier();
1483  }
1484  // update geometry
1485  con->updateGeometry(true);
1486  }
1487  // actually we only do this to force a redraw
1488  updateGeometry(true);
1489 }
1490 
1491 
1492 void
1494  // check if is a explicit turnaround
1495  if (nbCon.toEdge == myNBEdge.getTurnDestination()) {
1497  }
1498  // remove NBEdge::connection from NBEdge
1500  // remove their associated GNEConnection
1501  GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
1502  if (con != nullptr) {
1503  con->decRef("GNEEdge::removeConnection");
1504  myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), con));
1505  // remove it from Tree
1507  // check if connection is selected
1508  if (con->isAttributeCarrierSelected()) {
1509  con->unselectAttributeCarrier();
1510  }
1511  if (con->unreferenced()) {
1512  // show extra information for tests
1513  WRITE_DEBUG("Deleting unreferenced " + toString(con->getTag()) + " '" + con->getID() + "' in removeConnection()");
1514  delete con;
1515  // actually we only do this to force a redraw
1516  updateGeometry(true);
1517  }
1518  }
1519 }
1520 
1521 
1523 GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
1524  for (auto i : myGNEConnections) {
1525  if ((i->getFromLaneIndex() == fromLane) && (i->getEdgeTo()->getNBEdge() == to) && (i->getToLaneIndex() == toLane)) {
1526  return i;
1527  }
1528  }
1529  if (createIfNoExist) {
1530  // create new connection. Will be added to the rTree on first geometry computation
1531  GNEConnection* createdConnection = new GNEConnection(myLanes[fromLane], myNet->retrieveEdge(to->getID())->getLanes()[toLane]);
1532  // show extra information for tests
1533  WRITE_DEBUG("Created " + toString(createdConnection->getTag()) + " '" + createdConnection->getID() + "' in retrieveGNEConnection()");
1534  // insert it in Tree
1535  myNet->addGLObjectIntoGrid(createdConnection);
1536  return createdConnection;
1537  } else {
1538  return nullptr;
1539  }
1540 }
1541 
1542 
1543 
1544 void
1545 GNEEdge::setMicrosimID(const std::string& newID) {
1547  for (auto i : myLanes) {
1548  i->setMicrosimID(getNBEdge()->getLaneID(i->getIndex()));
1549  }
1550 }
1551 
1552 
1553 bool
1555  for (auto i : myLanes) {
1556  if (i->isRestricted(vclass)) {
1557  return true;
1558  }
1559  }
1560  return false;
1561 }
1562 
1563 
1564 void
1566  // Remove all crossings that contain this edge in parameter "edges"
1567  for (GNECrossing* const i : junction->getGNECrossings()) {
1568  if (i->checkEdgeBelong(this)) {
1569  myNet->deleteCrossing(i, undoList);
1570  }
1571  }
1572 }
1573 
1574 
1575 void
1577  PositionVector modifiedShape = myNBEdge.getGeometry().interpolateZ(
1579  myNBEdge.getToNode()->getPosition().z());
1580  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
1581  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
1582 }
1583 
1584 
1586 GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
1587  const OptionsCont& oc = OptionsCont::getOptions();
1588  // distinguish 3 cases:
1589  // a) if the edge has exactly 3 or 4 points, use these as control points
1590  // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
1591  // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
1592  PositionVector init;
1593 #ifdef DEBUG_SMOOTH_GEOM
1594  if (DEBUGCOND(this)) std::cout << getID()
1595  << " forElevation=" << forElevation
1596  << " fromGeometryLike=" << myNBEdge.getFromNode()->geometryLike()
1597  << " toGeometryLike=" << myNBEdge.getToNode()->geometryLike()
1598  << " smoothShape old=" << old << "\n";
1599 #endif
1600  if (old.size() == 3 || old.size() == 4) {
1601  init = old;
1602  } else if (old.size() > 4 && !forElevation) {
1603  // for elevation, the initial segments are not useful
1604  init.push_back(old[0]);
1605  init.push_back(old[1]);
1606  init.push_back(old[-2]);
1607  init.push_back(old[-1]);
1608  } else if (myNBEdge.getFromNode()->geometryLike() && myNBEdge.getToNode()->geometryLike()) {
1609  PositionVector begShape;
1610  PositionVector endShape;
1611  const EdgeVector& incoming = myNBEdge.getFromNode()->getIncomingEdges();
1612  const EdgeVector& outgoing = myNBEdge.getToNode()->getOutgoingEdges();
1613  if (incoming.size() == 1) {
1614  begShape = incoming[0]->getGeometry();
1615  } else {
1616  assert(incoming.size() == 2);
1617  begShape = myNBEdge.isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
1618  }
1619  if (outgoing.size() == 1) {
1620  endShape = outgoing[0]->getGeometry();
1621  } else {
1622  assert(outgoing.size() == 2);
1623  endShape = myNBEdge.isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
1624  }
1625  const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
1626  if (forElevation) {
1627  // initialize control point elevation for smooth continuation
1628  init.push_back(old[0]);
1629  init.push_back(old.positionAtOffset2D(dist));
1630  init.push_back(old.positionAtOffset2D(old.length2D() - dist));
1631  init.push_back(old[-1]);
1632  double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
1633  double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
1634  // continue incline
1635  init[1].setz(2 * init[0].z() - begZ);
1636  init[2].setz(2 * init[-1].z() - endZ);
1637  } else {
1638  bool ok = true;
1639  const double straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold"));
1640  init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, 0, straightThresh);
1641  }
1642 #ifdef DEBUG_SMOOTH_GEOM
1643  if (DEBUGCOND(this)) {
1644  std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
1645  }
1646 #endif
1647  }
1648  if (init.size() == 0) {
1649  return PositionVector::EMPTY;
1650  } else {
1651  const int numPoints = MAX2(oc.getInt("junctions.internal-link-detail"),
1652  int(old.length2D() / oc.getFloat("opendrive.curve-resolution")));
1653  return bezier(init, numPoints);
1654  }
1655 }
1656 
1657 
1658 void
1660  PositionVector modifiedShape = smoothShape(myNBEdge.getGeometry(), false);
1661  if (modifiedShape.size() < 2) {
1662  WRITE_WARNING("Could not compute smooth shape for edge '" + getID() + "'");
1663  } else {
1664  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
1665  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
1666  }
1667 }
1668 
1669 
1670 void
1672  PositionVector elevationBase;
1673  for (const Position& pos : myNBEdge.getGeometry()) {
1674  if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
1675  elevationBase.push_back(pos);
1676  }
1677  }
1678  PositionVector elevation = smoothShape(elevationBase, true);
1679  if (elevation.size() <= 2) {
1680  WRITE_WARNING("Could not compute smooth elevation for edge '" + getID() + "'");
1681  } else {
1682  PositionVector modifiedShape = myNBEdge.getGeometry();
1683  if (modifiedShape.size() < 5) {
1684  modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"));
1685  }
1686  const double scale = elevation.length2D() / modifiedShape.length2D();
1687  //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
1688  double seen = 0;
1689  for (int i = 1; i < (int)modifiedShape.size(); ++i) {
1690  seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
1691  modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
1692  }
1693  //std::cout << " mod2=" << modifiedShape << "\n";
1694  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
1695  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
1696  }
1697 }
1698 
1699 
1700 void
1702  // remove start position and add it the new position
1704  geom.erase(geom.begin());
1705  geom.push_front_noDoublePos(pos);
1706  // restore modified shape
1707  setGeometry(geom, false, true);
1708 }
1709 
1710 
1711 void
1713  // remove end position and add it the new position
1715  geom.pop_back();
1716  geom.push_back_noDoublePos(pos);
1717  // restore modified shape
1718  setGeometry(geom, false, true);
1719 }
1720 
1721 /****************************************************************************/
GUIVisualizationSizeSettings junctionSize
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge&#39;s lanes&#39; lateral offset is computed.
Definition: NBEdge.h:702
static const PositionVector EMPTY
empty Vector
void copyTemplate(GNEEdge *tpl, GNEUndoList *undolist)
copy edge attributes from tpl
Definition: GNEEdge.cpp:800
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1316
GNEJunction * myGNEJunctionSource
pointer to GNEJunction source
Definition: GNEEdge.h:318
The information about how to spread the lanes from the given position.
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:673
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
const GNEAttributeCarrier * getACUnderCursor() const
get AttributeCarrier under cursor
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:160
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:1346
int toLane
The lane the connections yields in.
Definition: NBEdge.h:188
const std::vector< T > & getSchemes() const
GNEEdge * retrieveEdge(const std::string &id, bool failHard=true)
get edge by id
Definition: GNENet.cpp:915
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)
bool removeGenericParameter(const std::string &key)
remove generic parameter
Definition: GNEEdge.cpp:1131
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:271
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:333
mode for moving things
Definition: GNEViewNet.h:48
std::string next()
void smoothElevation(GNEUndoList *undoList)
smooth elevation with regard to adjoining edges
Definition: GNEEdge.cpp:1671
void invalidateShape()
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEEdge.cpp:465
void removeIncomingGNEEdge(GNEEdge *edge)
remove incoming GNEEdge
double z() const
Returns the z-position.
Definition: Position.h:66
void addLane(GNELane *lane, const NBEdge::Lane &laneAttrs, bool recomputeConnections)
increase number of lanes by one use the given attributes and restore the GNELane
Definition: GNEEdge.cpp:1366
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:185
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GNEEdge.cpp:419
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:339
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:126
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3190
GNEJunction * myGNEJunctionDestiny
pointer to GNEJunction destiny
Definition: GNEEdge.h:321
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, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:1010
PositionVector myOrigShape
restore point for undo
Definition: GNEEdge.h:324
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:1545
static const RGBColor WHITE
Definition: RGBColor.h:179
void endGeometryMoving()
begin movement (used when user click over edge to start a movement, to avoid problems with problems w...
Definition: GNEEdge.cpp:233
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:243
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition: GNEEdge.cpp:1576
std::set< GUIGlID > getLaneGlIDs()
returns GLIDs of all lanes
Definition: GNEEdge.cpp:822
void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices)
add lane
Definition: NBEdge.cpp:3010
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3240
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:425
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1002
static const double SNAP_RADIUS
Definition: GNEEdge.h:284
double y() const
Returns the y-position.
Definition: Position.h:61
GUIVisualizationSettings * getVisualisationSettings() const
get visualitation settings
The representation of a single edge during network building.
Definition: NBEdge.h:65
void unsetParameter(const std::string &key)
Removes a parameter.
void moveShapeStart(const Position &oldPos, const Position &offset)
move position of shape start without commiting change
Definition: GNEEdge.cpp:168
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:1960
bool hasRestrictedLane(SUMOVehicleClass vclass) const
check if edge has a restricted lane
Definition: GNEEdge.cpp:1554
double x() const
Returns the x-position.
Definition: Position.h:56
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition: NBEdge.cpp:650
Representation of a RouteProbe in netedit.
Definition: GNERouteProbe.h:36
void setStreetName(const std::string &name)
sets the street name of this edge
Definition: NBEdge.h:546
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:1659
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:611
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:1249
T MAX2(T a, T b)
Definition: StdDefs.h:76
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:80
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2981
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:3271
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:47
void setLoadedLength(double val)
set loaded lenght
Definition: NBEdge.cpp:3314
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:78
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:197
void setShapeEndPos(const Position &pos)
change Shape EndPos
Definition: GNEEdge.cpp:1712
double endOffset
This lane&#39;s offset to the intersection begin.
Definition: NBEdge.h:133
void clearGNEConnections()
clear current connections
Definition: GNEEdge.cpp:712
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
void moveShapeEnd(const Position &oldPos, const Position &offset)
move position of shape end without commiting change
Definition: GNEEdge.cpp:178
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:206
void removeEdgeFromCrossings(GNEJunction *junction, GNEUndoList *undoList)
remove crossing of junction
Definition: GNEEdge.cpp:1565
const std::vector< GNEConnection * > & getGNEConnections()
returns a reference to the GNEConnection vector
Definition: GNEEdge.cpp:838
const std::string & getID() const
Returns the id.
Definition: Named.h:69
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:1204
void commitShapeStartChange(const Position &oldPos, GNEUndoList *undoList)
commit position changing in shape start
Definition: GNEEdge.cpp:188
PositionVector smoothShape(const PositionVector &shape, bool forElevation)
return smoothed shape
Definition: GNEEdge.cpp:1586
void removeLane(GNELane *lane, bool recomputeConnections)
the number of lanes by one. argument is only used to increase robustness (assertions) ...
Definition: GNEEdge.cpp:1419
bool myWasSplit
whether this edge was created from a split
Definition: GNEEdge.h:336
~GNEEdge()
Destructor.
Definition: GNEEdge.cpp:90
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:344
const std::vector< GNEEdge * > & getGNEEdges() const
Returns all GNEEdges vinculated with this Junction.
first coordinate of edge shape
static bool isValidGenericParameterKey(const std::string &value)
whether the given string is a valid key for a generic parameter
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:552
generic attribute
void editEndpoint(Position pos, GNEUndoList *undoList)
makes pos the new geometry endpoint at the appropriate end, or remove current existent endpoint ...
Definition: GNEEdge.cpp:606
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:256
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
PositionVector customShape
custom shape for connection
Definition: NBEdge.h:212
void deleteGeometryPoint(const Position &pos, bool allowUndo=true)
delete the geometry point closest to the given pos
Definition: GNEEdge.cpp:372
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:242
Boundary myMovingGeometryBoundary
boundary used during moving of elements
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
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
void setGeometry(PositionVector geom, bool inner, bool updateGrid)
update edge geometry and inform the lanes
Definition: GNEEdge.cpp:655
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:261
void removeOutgoingGNEEdge(GNEEdge *edge)
remove outgoing GNEEdge
bool keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:200
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:116
void updateJunctionPosition(GNEJunction *junction, const Position &origPos, bool updateGrid)
update edge geometry after junction move
Definition: GNEEdge.cpp:390
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:127
bool updateGenericParameter(const std::string &oldKey, const std::string &newKey)
update generic parameter
Definition: GNEEdge.cpp:1142
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEEdge.cpp:850
GNEUndoList * getUndoList() const
get the undoList object
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:767
void push_front_noDoublePos(const Position &p)
insert in front a non double position
void updateGeometry(bool updateGrid)
update pre-computed geometry information
Definition: GNEEdge.cpp:116
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
whether an edge is part of a bidirectional railway
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1971
static bool isValidGenericParameterValue(const std::string &value)
whether the given string is a valid value for a generic parameter
double speed
custom speed for connection
Definition: NBEdge.h:209
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1982
the edges of a route
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:573
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
Definition: GNECrossing.h:45
const double SUMO_const_halfLaneWidth
Definition: StdDefs.h:53
bool clickedOverShapeStart(const Position &pos)
Definition: GNEEdge.cpp:148
void commitShapeEndChange(const Position &oldPos, GNEUndoList *undoList)
commit position changing in shape end
Definition: GNEEdge.cpp:201
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition: NBEdge.h:130
std::string getGenericParametersStr() const
return generic parameters in string format
Definition: GNEEdge.cpp:1166
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:418
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:182
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:85
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true)
get junction by id
Definition: GNENet.cpp:902
A list of positions.
double scaledSize(double scale, double constFactor=0.1) const
static bool isGenericParametersValid(const std::string &value)
check if given string can be parsed to a map/list of generic parameters
void removeGLObjectFromGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1175
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:522
double distanceSquaredTo(const Position &p2) const
returns the square of the distance to another position
Definition: Position.h:238
friend class GNEChange_Attribute
declare friend class
GNEEdge * getOppositeEdge() const
get opposite edge
Definition: GNEEdge.cpp:459
std::vector< std::pair< std::string, std::string > > getGenericParameters() const
return generic parameters as vector of pairs format
Definition: GNEEdge.cpp:1181
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition: NBEdge.cpp:3064
void updateGeometry(bool updateGrid)
Update the boundary of the junction.
GNEJunction * getGNEJunctionDestiny() const
returns the destination-junction
Definition: GNEEdge.cpp:453
static const std::string FEATURE_GUESSED
feature has been reguessed (may still be unchanged be we can&#39;t tell (yet)
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:1523
int myPriority
The priority of the edge.
Definition: NBEdge.h:1465
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:2797
T MIN2(T a, T b)
Definition: StdDefs.h:70
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:541
void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
void startGeometryMoving()
Definition: GNEEdge.cpp:214
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:579
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
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, bool &ok, NBNode *recordError=0, double straightThresh=DEG2RAD(5), int shapeFlag=0)
get bezier control points
Definition: NBNode.cpp:501
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition: GLHelper.cpp:270
double getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:553
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:249
#define DEG2RAD(x)
Definition: GeomHelper.h:38
bool clickedOverShapeEnd(const Position &pos)
return true if user clicked over ShapeEnd
Definition: GNEEdge.cpp:158
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
Definition: GeomHelper.h:52
GNEJunction * getGNEJunctionSource() const
returns the source-junction
Definition: GNEEdge.cpp:447
void incRef(const std::string &debugMsg="")
Increarse reference.
The connection was given by the user.
Definition: NBEdge.h:107
double speed
The speed allowed on this lane.
Definition: NBEdge.h:124
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:140
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3299
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3543
void selectAttributeCarrier(bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:1946
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEEdge.cpp:432
void decRef(const std::string &debugMsg="")
Decrease reference.
std::vector< GNECrossing * > getGNECrossings()
get GNECrossings vinculated with this Edge
Definition: GNEEdge.cpp:753
bool updateGenericParameterValue(const std::string &key, const std::string &newValue)
update value generic parameter
Definition: GNEEdge.cpp:1155
begin/end of the description of an edge
GNEEdge(NBEdge &nbe, GNENet *net, bool wasSplit=false, bool loaded=false)
Constructor.
Definition: GNEEdge.cpp:66
void unselectAttributeCarrier(bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
EditMode getCurrentEditMode() const
get the current edit mode
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:512
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:620
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:50
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition: GNEEdge.cpp:735
ConnectionVector myGNEConnections
vector with the connections of this edge
Definition: GNEEdge.h:330
void updateGeometry(bool updateGrid)
update pre-computed geometry information
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:528
int moveVertexShape(const int index, const Position &oldPos, const Position &offset)
change position of a vertex of shape without commiting change
Definition: GNEEdge.cpp:298
static const double BUBBLE_RADIUS
constant values for drawing buubles
Definition: GNEJunction.h:56
void reset()
Resets the boundary.
Definition: Boundary.cpp:67
void setResponsible(bool newVal)
set responsibility for deleting internal strctures
Definition: GNEEdge.cpp:1217
void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation=false)
adds a connection
Definition: GNEEdge.cpp:1469
const PositionVector & getShape() const
returns the shape of the lane
Definition: GNELane.cpp:679
const std::vector< GNELane * > & getLanes()
returns a reference to the lane vector
Definition: GNEEdge.cpp:832
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:263
double length() const
Returns the length.
bool set(const std::string &name, const std::string &value)
Sets the given value for the named option.
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:865
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
void setGenericParametersStr(const std::string &value)
set generic parameters in string format
Definition: GNEEdge.cpp:1192
static void drawShapeDottedContour(const int type, const PositionVector &shape, const double width)
draw a dotted contour around the given Non closed shape with certain width
Definition: GLHelper.cpp:471
void moveEntireShape(const PositionVector &oldShape, const Position &offset)
move entire shape without commiting change
Definition: GNEEdge.cpp:325
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:34
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
Definition: NBEdge.cpp:3285
bool addGenericParameter(const std::string &key, const std::string &value)
add generic parameter
Definition: GNEEdge.cpp:1120
double contPos
custom position for internal junction on this connection
Definition: NBEdge.h:203
element is selected
bool isInitialised() const
check if Boundary is Initialised
Definition: Boundary.cpp:217
A storage for options typed value containers)
Definition: OptionsCont.h:92
bool uncontrolled
check if Connection is uncontrolled
Definition: NBEdge.h:242
void markConnectionGeometryDeprecated()
check that connection&#39;s Geometry has to be updated
void mouseOverObject(const GUIVisualizationSettings &s) const
method for check if mouse is over objects
Definition: GNEEdge.cpp:1341
The popup menu of a globject.
an edge
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
static int getCircleResolution(const GUIVisualizationSettings &settings)
function to calculate circle resolution for all circles drawn in drawGL(...) functions ...
std::string myType
The type of the edge.
Definition: NBEdge.h:1449
void renameEdge(GNEEdge *edge, const std::string &newID)
updates the map and reserves new id
Definition: GNENet.cpp:1722
bool isValid(SumoXMLAttr key, const std::string &value)
Definition: GNEEdge.cpp:1031
void removeEdgeOfAdditionalParents(GNEUndoList *undoList, bool allowEmpty)
remove Edge of Additional Parent
Definition: GNEEdge.cpp:770
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:2652
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:1218
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:1789
void commitShapeChange(const PositionVector &oldShape, GNEUndoList *undoList)
commit geometry changes in the attributes of an element after use of changeShapeGeometry(...)
Definition: GNEEdge.cpp:342
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value map.
GUIGlID getGlID() const
Returns the numerical id of the object.
LaneVector myLanes
vectgor with the lanes of this edge
Definition: GNEEdge.h:327
std::vector< GNEAdditional * > myAdditionalChilds
list of Additional Childs of this NetElement
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition: GNEEdge.cpp:1493
void updateLinkState()
recompute cached myLinkState
Position getPositionInformation() const
Returns the cursor&#39;s x/y position within the network.
last coordinate of edge shape
std::vector< GNEAdditional * > myFirstAdditionalParents
list of Additional parents of this NetElement
void push_back_noDoublePos(const Position &p)
insert in back a non double position
static const RGBColor selectionColor
Definition: GNENet.h:96
empty max
NBEdge & myNBEdge
the underlying NBEdge
Definition: GNEEdge.h:312
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:432
void mul(double val)
Multiplies both positions with the given value.
Definition: Position.h:106
bool hasString(const std::string &str) const
NBEdge * getNBEdge()
returns the internal NBEdge
Definition: GNEEdge.cpp:586
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:79
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:829
bool drawForSelecting
whether drawing is performed for the purpose of selecting objects
Boundary getBoundary() const
Returns the street&#39;s geometry.
Definition: GNEEdge.cpp:404
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
void setShapeStartPos(const Position &pos)
change Shape StartPos
Definition: GNEEdge.cpp:1701
NBNode * getNBNode() const
Return net build node.
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNEEdge.cpp:930
void addGLObjectIntoGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1168
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void resetEndpoint(const Position &pos, GNEUndoList *undoList)
restores the endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:641
void setLogicValid(bool valid, GNEUndoList *undoList, const std::string &status=FEATURE_GUESSED)
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition: GNENet.cpp:1735
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:921
bool wasSplit()
whether this edge was created from a split
Definition: GNEEdge.cpp:844
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:439
Position getSplitPos(const Position &clickPos)
Definition: GNEEdge.cpp:592
bool unreferenced()
check if object ins&#39;t referenced
friend class GNEChange_Lane
Friend class.
Definition: GNEEdge.h:53
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 occurred errors.
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3142
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1745
void clearParameter()
Clears the parameter map.
a junction
void bezier(int npts, double b[], int cpts, double p[])
Definition: bezier.cpp:90
SumoXMLTag getTag() const
get XML Tag assigned to this object