Eclipse 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-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // A road/street connecting two junctions (netedit-version, adapted from GUIEdge)
19 // Basically a container for an NBEdge with drawing and editing capabilities
20 /****************************************************************************/
21 #include <config.h>
22 
23 #include <netedit/GNENet.h>
24 #include <netedit/GNEUndoList.h>
25 #include <netedit/GNEViewNet.h>
26 #include <netedit/GNEViewParent.h>
34 #include <utils/gui/div/GLHelper.h>
37 
38 #include "GNEConnection.h"
39 #include "GNECrossing.h"
40 #include "GNEEdge.h"
41 #include "GNEEdgeType.h"
42 #include "GNELaneType.h"
43 #include "GNEEdgeTemplate.h"
44 #include "GNELaneTemplate.h"
45 
46 
47 //#define DEBUG_SMOOTH_GEOM
48 //#define DEBUGCOND(obj) (true)
49 #define VEHICLE_GAP 1
50 #define ENDPOINT_TOLERANCE 2
51 
52 // ===========================================================================
53 // static
54 // ===========================================================================
57 
58 // ===========================================================================
59 // members methods
60 // ===========================================================================
61 
62 GNEEdge::GNEEdge(GNENet* net, NBEdge* nbe, bool wasSplit, bool loaded):
63  GNENetworkElement(net, nbe->getID(), GLO_EDGE, SUMO_TAG_EDGE, GUIIconSubSys::getIcon(GUIIcon::EDGE), {
66 },
67 {}, {}, {}, {}, {}),
68 myNBEdge(nbe),
69 myLanes(0),
70 myAmResponsible(false),
71 myWasSplit(wasSplit),
72 myConnectionStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED),
73 myUpdateGeometry(true) {
74  // Create lanes
75  int numLanes = myNBEdge->getNumLanes();
76  myLanes.reserve(numLanes);
77  for (int i = 0; i < numLanes; i++) {
78  myLanes.push_back(new GNELane(this, i));
79  myLanes.back()->incRef("GNEEdge::GNEEdge");
80  }
81  // update Lane geometries
82  for (const auto& lane : myLanes) {
83  lane->updateGeometry();
84  }
85  // update centering boundary without updating grid
86  updateCenteringBoundary(false);
87 }
88 
89 
91  // Delete references to this edge in lanes
92  for (const auto& lane : myLanes) {
93  lane->decRef("GNEEdge::~GNEEdge");
94  if (lane->unreferenced()) {
95  // check if remove it from Attribute Carriers
96  if (myNet->getAttributeCarriers()->getLanes().count(lane) > 0) {
98  }
99  // show extra information for tests
100  WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in GNEEdge destructor");
101  delete lane;
102  }
103  }
104  // delete references to this edge in connections
105  for (const auto& connection : myGNEConnections) {
106  connection->decRef("GNEEdge::~GNEEdge");
107  if (connection->unreferenced()) {
108  // check if remove it from Attribute Carriers
109  if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
111  }
112  // show extra information for tests
113  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in GNEEdge destructor");
114  delete connection;
115  }
116  }
117  if (myAmResponsible) {
118  delete myNBEdge;
119  }
120 }
121 
122 
123 bool
125  if (getFromJunction()->getNBNode()->getPosition() != getToJunction()->getNBNode()->getPosition()) {
126  return true;
127  } else {
128  return false;
129  }
130 }
131 
132 
133 std::string
135  return "Parent junctions are in the same position: " +
136  toString(getFromJunction()->getNBNode()->getPosition().x()) + ", " +
137  toString(getFromJunction()->getNBNode()->getPosition().y());
138 }
139 
140 
141 void
143  // first check if myUpdateGeometry flag is enabled
144  if (myUpdateGeometry) {
145  // Update geometry of lanes
146  for (const auto& lane : myLanes) {
147  lane->updateGeometry();
148  }
149  // Update geometry of connections
150  for (const auto& connection : myGNEConnections) {
151  connection->updateGeometry();
152  }
153  // Update geometry of additionals children vinculated to this edge
154  for (const auto& childAdditional : getChildAdditionals()) {
155  childAdditional->updateGeometry();
156  }
157  // Update geometry of additionals demand elements vinculated to this edge
158  for (const auto& childDemandElement : getChildDemandElements()) {
159  childDemandElement->updateGeometry();
160  }
161  // Update geometry of additionals generic datas vinculated to this edge
162  for (const auto& childGenericData : getChildGenericDatas()) {
163  childGenericData->updateGeometry();
164  }
165  // compute geometry of path elements elements vinculated with this edge (depending of showDemandElements)
167  for (const auto& childAdditional : getChildAdditionals()) {
168  childAdditional->computePathElement();
169  }
170  for (const auto& childDemandElement : getChildDemandElements()) {
171  childDemandElement->computePathElement();
172  }
173  for (const auto& childGenericData : getChildGenericDatas()) {
174  childGenericData->computePathElement();
175  }
176  }
177  }
178  // update vehicle geometry
180  // update vehicle stack labels
182 }
183 
184 
185 Position
187  return myLanes.front()->getPositionInView();
188 }
189 
190 
193  // get snapRadius
195  // check if edge is selected
197  // check if both junctions are selected
202  } else if (getToJunction()->isAttributeCarrierSelected()) {
205  return processNoneJunctionSelected(snapRadius);
206  } else {
207  // calculate move shape operation (because there are only an edge selected)
209  }
210  } else {
211  // calculate move shape operation
213  }
214 }
215 
216 
217 void
218 GNEEdge::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
219  // declare shape to move
221  // obtain flags for start and end positions
222  const bool customStartPosition = (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE);
223  const bool customEndPosition = (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE);
224  // get variable for last index
225  const int lastIndex = (int)myNBEdge->getGeometry().size() - 1;
226  // flag to enable/disable remove geometry point
227  bool removeGeometryPoint = true;
228  // obtain index
229  const int index = myNBEdge->getGeometry().indexOfClosest(clickedPosition, true);
230  // check index
231  if (index == -1) {
232  removeGeometryPoint = false;
233  }
234  // check distance
235  if (shape[index].distanceSquaredTo2D(clickedPosition) > SNAP_RADIUS_SQUARED) {
236  removeGeometryPoint = false;
237  }
238  // check custom start position
239  if (!customStartPosition && (index == 0)) {
240  removeGeometryPoint = false;
241  }
242  // check custom end position
243  if (!customEndPosition && (index == lastIndex)) {
244  removeGeometryPoint = false;
245  }
246  // check if we can remove geometry point
247  if (removeGeometryPoint) {
248  // check if we're removing first geometry proint
249  if (index == 0) {
250  // commit new geometry start
251  undoList->begin(GUIIcon::EDGE, "remove first geometry point of " + getTagStr());
252  undoList->changeAttribute(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_START, ""));
253  undoList->end();
254  } else if (index == lastIndex) {
255  // commit new geometry end
256  undoList->begin(GUIIcon::EDGE, "remove last geometry point of " + getTagStr());
257  undoList->changeAttribute(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_END, ""));
258  undoList->end();
259  } else {
260  // remove geometry point
261  shape.erase(shape.begin() + index);
262  // get innen shape
263  shape.pop_front();
264  shape.pop_back();
265  // remove double points
267  // commit new shape
268  undoList->begin(GUIIcon::EDGE, "remove geometry point of " + getTagStr());
269  undoList->changeAttribute(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(shape)));
270  undoList->end();
271  }
272  }
273 }
274 
275 
276 bool
278  if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
279  return true;
280  } else if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
281  return true;
282  } else {
283  return false;
284  }
285 }
286 
287 
288 bool
290  if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
291  return (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED);
292  } else {
293  return false;
294  }
295 }
296 
297 
298 bool
300  if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
301  return (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED);
302  } else {
303  return false;
304  }
305 }
306 
307 
308 bool
310  // first check inner geometry
311  const PositionVector innenShape = myNBEdge->getInnerGeometry();
312  // iterate over geometry point
313  for (const auto& geometryPoint : innenShape) {
314  if (geometryPoint.distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED) {
315  return true;
316  }
317  }
318  // check start and end shapes
319  if (clickedOverShapeStart(pos) || clickedOverShapeEnd(pos)) {
320  return true;
321  } else {
322  return false;
323  }
324 }
325 
326 
327 void
329  Position delta = junction->getNBNode()->getPosition() - origPos;
331  // geometry endpoint need not equal junction position hence we modify it with delta
332  if (junction == getFromJunction()) {
333  geom[0].add(delta);
334  } else {
335  geom[-1].add(delta);
336  }
337  setGeometry(geom, false);
338 }
339 
340 
341 double
343  return s.addSize.getExaggeration(s, this);
344 }
345 
346 
347 void
348 GNEEdge::updateCenteringBoundary(const bool updateGrid) {
349  // Remove object from net
350  if (updateGrid) {
352  }
353  // use as boundary the first lane boundary
354  myBoundary = myLanes.front()->getCenteringBoundary();
355  // add lane boundaries
356  for (const auto& lane : myLanes) {
357  lane->updateCenteringBoundary(false);
358  myBoundary.add(lane->getCenteringBoundary());
359  // add parkingArea boundaries
360  for (const auto& additional : lane->getChildAdditionals()) {
361  if (additional->getTagProperty().getTag() == SUMO_TAG_PARKING_AREA) {
362  myBoundary.add(additional->getCenteringBoundary());
363  }
364  }
365  }
366  // ensure that geometry points are selectable even if the lane geometry is strange
367  for (const Position& pos : myNBEdge->getGeometry()) {
368  myBoundary.add(pos);
369  }
370  // add junction positions
373  // grow boundary
374  myBoundary.grow(10);
375  // add object into net
376  if (updateGrid) {
377  myNet->addGLObjectIntoGrid(this);
378  }
379 }
380 
381 
382 const std::string
384  return myNBEdge->getStreetName();
385 }
386 
387 
390  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
391  buildPopupHeader(ret, app);
394  // build selection and show parameters menu
397  // build position copy entry
398  buildPositionCopyEntry(ret, app);
399  return ret;
400 }
401 
402 
403 std::vector<GNEEdge*>
406 }
407 
408 
409 void
411  // check if boundary has to be drawn
412  if (s.drawBoundaries) {
414  }
415  // draw lanes
416  for (const auto& lane : myLanes) {
417  lane->drawGL(s);
418  }
419  // draw child additional
420  for (const auto& additional : getChildAdditionals()) {
421  additional->drawGL(s);
422  }
423  // draw person stops
425  for (const auto& stopEdge : getChildDemandElements()) {
426  if ((stopEdge->getTagProperty().getTag() == GNE_TAG_STOPPERSON_EDGE) || (stopEdge->getTagProperty().getTag() == GNE_TAG_STOPCONTAINER_EDGE)) {
427  stopEdge->drawGL(s);
428  }
429  }
430  }
431  // draw vehicles
432  const std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesMap = getVehiclesOverEdgeMap();
433  for (const auto& vehicleMap : vehiclesMap) {
434  for (const auto& vehicle : vehicleMap.second) {
435  vehicle->drawGL(s);
436  }
437  }
438  // draw edge stopOffset
440  // draw TAZ elements
441  drawTAZElements(s);
442  // draw name if isn't being drawn for selecting
443  drawEdgeName(s);
444  // draw dotted contours
445  if (myLanes.size() > 1) {
448  }
449  if ((myNet->getViewNet()->getFrontAttributeCarrier() == this)) {
451  }
452  if (myNet->getViewNet()->drawDeleteContour(this, this)) {
454  }
455  if (myNet->getViewNet()->drawSelectContour(this, this)) {
457  }
460  }
461  }
462 }
463 
464 
465 void
467  // Check if edge can be deleted
469  myNet->deleteEdge(this, myNet->getViewNet()->getUndoList(), false);
470  }
471 }
472 
473 
474 void
476  updateGeometry();
477 }
478 
479 
480 NBEdge*
482  return myNBEdge;
483 }
484 
485 
486 Position
487 GNEEdge::getSplitPos(const Position& clickPos) {
488  const PositionVector& geom = myNBEdge->getGeometry();
489  int index = geom.indexOfClosest(clickPos, true);
490  if (geom[index].distanceSquaredTo2D(clickPos) < SNAP_RADIUS_SQUARED) {
491  // split at existing geometry point
492  return myNet->getViewNet()->snapToActiveGrid(geom[index]);
493  } else {
494  // split straight between the next two points
496  }
497 }
498 
499 
500 void
502  if ((myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
503  (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED)) {
504  undoList->begin(GUIIcon::EDGE, "remove endpoint");
505  setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
506  undoList->end();
507  } else if ((myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
508  (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED)) {
509  undoList->begin(GUIIcon::EDGE, "remove endpoint");
510  setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
511  undoList->end();
512  } else {
513  // we need to create new Start/End position over Edge shape, not over clicked position
515  if (offset != GeomHelper::INVALID_OFFSET) {
517  // calculate position over edge shape relative to clicked position
518  Position newPos = geom.positionAtOffset2D(offset);
519  // snap new position to grid
520  newPos = myNet->getViewNet()->snapToActiveGrid(newPos);
521  undoList->begin(GUIIcon::EDGE, "set endpoint");
522  int index = geom.indexOfClosest(pos, true);
523  // check if snap to existing geometry
524  if (geom[index].distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED) {
525  pos = geom[index];
526  }
527  Position destPos = getToJunction()->getNBNode()->getPosition();
528  Position sourcePos = getFromJunction()->getNBNode()->getPosition();
529  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
530  setAttribute(GNE_ATTR_SHAPE_END, toString(newPos), undoList);
532  } else {
533  setAttribute(GNE_ATTR_SHAPE_START, toString(newPos), undoList);
535  }
536  /*
537  // possibly existing inner point is no longer needed
538  if (myNBEdge->getInnerGeometry().size() > 0 && getEdgeVertexIndex(pos, false) != -1) {
539  deleteEdgeGeometryPoint(pos, false);
540  }
541  */
542  undoList->end();
543  }
544  }
545 }
546 
547 
548 void
550  Position destPos = getToJunction()->getNBNode()->getPosition();
551  Position sourcePos = getFromJunction()->getNBNode()->getPosition();
552  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
553  setAttribute(GNE_ATTR_SHAPE_END, toString(destPos), undoList);
555  } else {
556  setAttribute(GNE_ATTR_SHAPE_START, toString(sourcePos), undoList);
558  }
559 }
560 
561 
562 void
564  // reset shape start
565  setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
567  // reset shape end
568  setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
570 }
571 
572 void
574  // set new geometry
575  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
576  if (lefthand) {
577  geom.mirrorX();
578  myNBEdge->mirrorX();
579  }
580  myNBEdge->setGeometry(geom, inner);
581  if (lefthand) {
582  myNBEdge->mirrorX();
583  }
584  // update geometry
585  updateGeometry();
586  // invalidate junction source shape
588  // iterate over first parent junction edges and update geometry
589  for (const auto& edge : getFromJunction()->getGNEIncomingEdges()) {
590  edge->updateGeometry();
591  }
592  for (const auto& edge : getFromJunction()->getGNEOutgoingEdges()) {
593  edge->updateGeometry();
594  }
595  // invalidate junction destiny shape
597  // iterate over second parent junction edges and update geometry
598  for (const auto& edge : getToJunction()->getGNEIncomingEdges()) {
599  edge->updateGeometry();
600  }
601  for (const auto& edge : getToJunction()->getGNEOutgoingEdges()) {
602  edge->updateGeometry();
603  }
604 }
605 
606 
607 const Position
609  PositionVector laneShape = myLanes.front()->getLaneShape();
610  laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
611  return laneShape.front();
612 }
613 
614 
615 const Position
617  PositionVector laneShape = myLanes.back()->getLaneShape();
618  laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
619  return laneShape.front();
620 }
621 
622 
623 const Position
625  PositionVector laneShape = myLanes.front()->getLaneShape();
626  laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
627  return laneShape.back();
628 }
629 
630 
631 const Position
633  PositionVector laneShape = myLanes.back()->getLaneShape();
634  laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
635  return laneShape.back();
636 }
637 
638 void
639 GNEEdge::remakeGNEConnections(bool junctionsReady) {
640  // create new and removed unused GNEConnections
641  const std::vector<NBEdge::Connection>& connections = myNBEdge->getConnections();
642  // create a vector to keep retrieved and created connections
643  std::vector<GNEConnection*> retrievedConnections;
644  // iterate over NBEdge::Connections of GNEEdge
645  for (const auto& connection : connections) {
646  // retrieve existent GNEConnection, or create it
647  GNEConnection* retrievedGNEConnection = retrieveGNEConnection(connection.fromLane, connection.toEdge, connection.toLane);
648  if (junctionsReady) {
649  retrievedGNEConnection->updateLinkState();
650  }
651  retrievedConnections.push_back(retrievedGNEConnection);
652  // check if previously this GNEConnections exists, and if true, remove it from myGNEConnections
653  std::vector<GNEConnection*>::iterator retrievedExists = std::find(myGNEConnections.begin(), myGNEConnections.end(), retrievedGNEConnection);
654  if (retrievedExists != myGNEConnections.end()) {
655  myGNEConnections.erase(retrievedExists);
656  } else {
657  // include reference to created GNEConnection
658  retrievedGNEConnection->incRef("GNEEdge::remakeGNEConnections");
659  }
660  // mark it as deprecated
661  retrievedGNEConnection->markConnectionGeometryDeprecated();
662  }
663  // delete non retrieved GNEConnections
664  for (const auto& connection : myGNEConnections) {
665  // decrease reference
666  connection->decRef();
667  // remove it from network
668  myNet->removeGLObjectFromGrid(connection);
669  // and from AttributeCarriers
670  if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
672  }
673  // delete GNEConnection if is unreferenced
674  if (connection->unreferenced()) {
675 
676  // show extra information for tests
677  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in rebuildGNEConnections()");
678  delete connection;
679  }
680  }
681  // copy retrieved (existent and created) GNECrossings to myGNEConnections
682  myGNEConnections = retrievedConnections;
683 }
684 
685 
686 void
688  // Drop all existents connections that aren't referenced anymore
689  for (const auto& connection : myGNEConnections) {
690  // check if connection is selected
691  if (connection->isAttributeCarrierSelected()) {
692  connection->unselectAttributeCarrier();
693  }
694  // Dec reference of connection
695  connection->decRef("GNEEdge::clearGNEConnections");
696  // remove it from network
697  myNet->removeGLObjectFromGrid(connection);
698  // and from AttributeCarriers
699  if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
701  }
702  // Delete GNEConnectionToErase if is unreferenced
703  if (connection->unreferenced()) {
704  // show extra information for tests
705  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in clearGNEConnections()");
706  delete connection;
707  }
708  }
709  myGNEConnections.clear();
710 }
711 
712 
713 int
715  std::vector<GNEAdditional*> routeProbes;
716  for (auto i : getChildAdditionals()) {
717  if (i->getTagProperty().getTag() == routeProbe->getTagProperty().getTag()) {
718  routeProbes.push_back(i);
719  }
720  }
721  // return index of routeProbe in routeProbes vector
722  auto it = std::find(routeProbes.begin(), routeProbes.end(), routeProbe);
723  if (it == routeProbes.end()) {
724  return -1;
725  } else {
726  return (int)(it - routeProbes.begin());
727  }
728 }
729 
730 
731 std::vector<GNECrossing*>
733  std::vector<GNECrossing*> crossings;
734  for (auto i : getFromJunction()->getGNECrossings()) {
735  if (i->checkEdgeBelong(this)) {
736  crossings.push_back(i);
737  }
738  }
739  for (auto i : getToJunction()->getGNECrossings()) {
740  if (i->checkEdgeBelong(this)) {
741  crossings.push_back(i);
742  }
743  }
744  return crossings;
745 }
746 
747 
748 void
749 GNEEdge::copyTemplate(const GNEEdgeTemplate* edgeTemplate, GNEUndoList* undoList) {
750  // copy edge-specific attributes
752  setAttribute(SUMO_ATTR_TYPE, edgeTemplate->getAttribute(SUMO_ATTR_TYPE), undoList);
757  // copy raw values for lane-specific attributes
758  if (isValid(SUMO_ATTR_SPEED, edgeTemplate->getAttribute(SUMO_ATTR_SPEED))) {
759  setAttribute(SUMO_ATTR_SPEED, edgeTemplate->getAttribute(SUMO_ATTR_SPEED), undoList);
760  }
763  }
764  if (isValid(SUMO_ATTR_WIDTH, edgeTemplate->getAttribute(SUMO_ATTR_WIDTH))) {
765  setAttribute(SUMO_ATTR_WIDTH, edgeTemplate->getAttribute(SUMO_ATTR_WIDTH), undoList);
766  }
769  }
770  // copy lane attributes as well
771  for (int i = 0; i < (int)myLanes.size(); i++) {
772  myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_ALLOW), undoList);
773  myLanes[i]->setAttribute(SUMO_ATTR_SPEED, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_SPEED), undoList);
774  myLanes[i]->setAttribute(SUMO_ATTR_FRICTION, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_FRICTION), undoList);
775  myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_WIDTH), undoList);
776  myLanes[i]->setAttribute(SUMO_ATTR_ENDOFFSET, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
777  myLanes[i]->setAttribute(GNE_ATTR_STOPOFFSET, edgeTemplate->getLaneTemplates().at(i)->getAttribute(GNE_ATTR_STOPOFFSET), undoList);
778  myLanes[i]->setAttribute(GNE_ATTR_STOPOEXCEPTION, edgeTemplate->getLaneTemplates().at(i)->getAttribute(GNE_ATTR_STOPOEXCEPTION), undoList);
779  }
780 }
781 
782 
783 void
784 GNEEdge::copyEdgeType(const GNEEdgeType* edgeType, GNEUndoList* undoList) {
785  // set type (only for info)
786  setAttribute(SUMO_ATTR_TYPE, edgeType->getAttribute(SUMO_ATTR_ID), undoList);
787  // set num lanes
789  // set speed
791  // set friction
793  // set allow (no disallow)
795  // set spreadType
797  // set width
799  // set priority
801  // set parameters
803  // copy lane attributes as well
804  for (int i = 0; i < (int)myLanes.size(); i++) {
805  // now copy custom lane values
806  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_SPEED).size() > 0) {
807  myLanes[i]->setAttribute(SUMO_ATTR_SPEED, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_SPEED), undoList);
808  }
809  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_FRICTION).size() > 0) {
810  myLanes[i]->setAttribute(SUMO_ATTR_FRICTION, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_FRICTION), undoList);
811  }
812  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_ALLOW).size() > 0) {
813  myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_ALLOW), undoList);
814  }
815  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_DISALLOW).size() > 0) {
816  myLanes[i]->setAttribute(SUMO_ATTR_DISALLOW, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_DISALLOW), undoList);
817  }
818  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_WIDTH).size() > 0) {
819  myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_WIDTH), undoList);
820  }
821  if (edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS).size() > 0) {
822  myLanes[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
823  }
824  }
825 }
826 
827 
828 std::set<GUIGlID>
830  std::set<GUIGlID> result;
831  for (auto i : myLanes) {
832  result.insert(i->getGlID());
833  }
834  return result;
835 }
836 
837 
838 const std::vector<GNELane*>&
840  return myLanes;
841 }
842 
843 
844 const std::vector<GNEConnection*>&
846  return myGNEConnections;
847 }
848 
849 
850 bool
852  return myWasSplit;
853 }
854 
855 
856 std::string
858  switch (key) {
859  case SUMO_ATTR_ID:
860  return getMicrosimID();
861  case SUMO_ATTR_FROM:
862  return getFromJunction()->getID();
863  case SUMO_ATTR_TO:
864  return getToJunction()->getID();
865  case SUMO_ATTR_NUMLANES:
866  return toString(myNBEdge->getNumLanes());
867  case SUMO_ATTR_PRIORITY:
868  return toString(myNBEdge->getPriority());
869  case SUMO_ATTR_LENGTH:
870  return toString(myNBEdge->getFinalLength());
871  case SUMO_ATTR_TYPE:
872  return myNBEdge->getTypeID();
873  case SUMO_ATTR_SHAPE:
877  case SUMO_ATTR_NAME:
878  return myNBEdge->getStreetName();
879  case SUMO_ATTR_ALLOW:
880  return (getVehicleClassNames(myNBEdge->getPermissions()) + (myNBEdge->hasLaneSpecificPermissions() ? " (combined!)" : ""));
881  case SUMO_ATTR_DISALLOW: {
883  }
884  case SUMO_ATTR_SPEED:
886  return "lane specific";
887  } else {
888  return toString(myNBEdge->getSpeed());
889  }
890  case SUMO_ATTR_FRICTION:
892  return "lane specific";
893  } else {
894  return toString(myNBEdge->getFriction());
895  }
896  case SUMO_ATTR_WIDTH:
898  return "lane specific";
900  return "default";
901  } else {
902  return toString(myNBEdge->getLaneWidth());
903  }
904  case SUMO_ATTR_ENDOFFSET:
906  return "lane specific";
907  } else {
908  return toString(myNBEdge->getEndOffset());
909  }
910  case SUMO_ATTR_DISTANCE:
911  return toString(myNBEdge->getDistance());
913  return myConnectionStatus;
915  if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
916  return "";
917  } else {
918  return toString(myNBEdge->getGeometry().front());
919  }
920  case GNE_ATTR_SHAPE_END:
921  if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
922  return "";
923  } else {
924  return toString(myNBEdge->getGeometry().back());
925  }
926  case GNE_ATTR_BIDIR:
927  return toString(myNBEdge->getBidiEdge() != nullptr);
928  case GNE_ATTR_STOPOFFSET:
933  } else {
934  return "";
935  }
936  case GNE_ATTR_SELECTED:
938  case GNE_ATTR_PARAMETERS:
939  return myNBEdge->getParametersStr();
940  default:
941  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
942  }
943 }
944 
945 
946 std::string
948  std::string result = getAttribute(key);
949  if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
950  result += " " + getVehicleClassNames(SVCAll, true);
951  }
952  return result;
953 }
954 
955 
956 void
957 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
958  // get template editor
960  // check if we have to update template
961  const bool updateTemplate = templateEditor->getEdgeTemplate() ? (templateEditor->getEdgeTemplate()->getID() == getID()) : false;
962  switch (key) {
963  case SUMO_ATTR_WIDTH:
964  case SUMO_ATTR_ENDOFFSET:
965  case SUMO_ATTR_SPEED:
966  case SUMO_ATTR_FRICTION:
967  case SUMO_ATTR_ALLOW:
968  case SUMO_ATTR_DISALLOW: {
969  undoList->begin(GUIIcon::EDGE, "change " + getTagStr() + " attribute");
970  const std::string origValue = myLanes.at(0)->getAttribute(key); // will have intermediate value of "lane specific"
971  // lane specific attributes need to be changed via lanes to allow undo
972  for (auto it : myLanes) {
973  it->setAttribute(key, value, undoList);
974  }
975  // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
976  undoList->changeAttribute(new GNEChange_Attribute(this, key, value, origValue));
977  undoList->end();
978  break;
979  }
980  case SUMO_ATTR_FROM: {
981  if (value != getAttribute(key)) {
982  undoList->begin(GUIIcon::EDGE, "change " + getTagStr() + " attribute");
983  // Remove edge from crossings of junction source
985  // continue changing from junction
986  GNEJunction* originalFirstParentJunction = getFromJunction();
987  getFromJunction()->setLogicValid(false, undoList);
988  undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
989  getFromJunction()->setLogicValid(false, undoList);
990  myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
991  setAttribute(GNE_ATTR_SHAPE_START, toString(getFromJunction()->getNBNode()->getPosition()), undoList);
993  undoList->end();
994  // update geometries of all implicated junctions
995  originalFirstParentJunction->updateGeometry();
998  }
999  break;
1000  }
1001  case SUMO_ATTR_TO: {
1002  if (value != getAttribute(key)) {
1003  undoList->begin(GUIIcon::EDGE, "change " + getTagStr() + " attribute");
1004  // Remove edge from crossings of junction destiny
1006  // continue changing destiny junction
1007  GNEJunction* originalSecondParentJunction = getToJunction();
1008  getToJunction()->setLogicValid(false, undoList);
1009  undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1010  getToJunction()->setLogicValid(false, undoList);
1011  myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1012  setAttribute(GNE_ATTR_SHAPE_END, toString(getToJunction()->getNBNode()->getPosition()), undoList);
1014  undoList->end();
1015  // update geometries of all implicated junctions
1016  originalSecondParentJunction->updateGeometry();
1019  }
1020  break;
1021  }
1022  case SUMO_ATTR_ID:
1023  case SUMO_ATTR_PRIORITY:
1024  case SUMO_ATTR_LENGTH:
1025  case SUMO_ATTR_TYPE:
1026  case SUMO_ATTR_SPREADTYPE:
1027  case SUMO_ATTR_DISTANCE:
1029  case GNE_ATTR_SELECTED:
1030  case GNE_ATTR_STOPOFFSET:
1032  case GNE_ATTR_PARAMETERS:
1033  undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1034  break;
1035  case GNE_ATTR_SHAPE_START:
1036  case GNE_ATTR_SHAPE_END: {
1037  auto change = new GNEChange_Attribute(this, key, value);
1038  // due to ENDPOINT_TOLERANCE, change might be ignored unless forced
1039  change->forceChange();
1040  undoList->changeAttribute(change);
1041  break;
1042  }
1043  case SUMO_ATTR_NAME:
1044  // user cares about street names. Make sure they appear in the output
1046  OptionsCont::getOptions().set("output.street-names", "true");
1047  undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1048  break;
1049  case SUMO_ATTR_NUMLANES:
1050  if (value != getAttribute(key)) {
1051  // set num lanes
1052  setNumLanes(parse<int>(value), undoList);
1053  }
1054  break;
1055  case GNE_ATTR_BIDIR:
1056  undoList->begin(GUIIcon::EDGE, "change " + getTagStr() + " attribute");
1057  undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1058  if (myNBEdge->getTurnDestination(true) != nullptr) {
1060  undoList->changeAttribute(new GNEChange_Attribute(bidi, key, value));
1061  if (myNBEdge->getGeometry() != bidi->getNBEdge()->getGeometry().reverse() && myNBEdge->getGeometry().size() == 2 && bidi->getNBEdge()->getGeometry().size() == 2) {
1062  // NBEdge::avoidOverlap was already active so we need to reset the
1063  // geometry to it's default
1064  resetBothEndpoint(undoList);
1065  bidi->resetBothEndpoint(undoList);
1066  }
1067  }
1068  undoList->end();
1069  break;
1070  case SUMO_ATTR_SHAPE:
1071  // @note: assumes value of inner geometry!
1072  // actually the geometry is already updated (incrementally
1073  // during mouse movement). We set the restore point to the end
1074  // of the last change-set
1075  undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1076  break;
1077  default:
1078  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1079  }
1080  // update template
1081  if (updateTemplate) {
1082  templateEditor->setEdgeTemplate(this);
1083  }
1084 }
1085 
1086 
1087 bool
1088 GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
1089  switch (key) {
1090  case SUMO_ATTR_ID:
1091  return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveEdge(value, false) == nullptr);
1092  case SUMO_ATTR_FROM: {
1093  // check that is a valid ID and is different of ID of junction destiny
1094  if (value == getFromJunction()->getID()) {
1095  return true;
1096  } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getToJunction()->getID())) {
1097  return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1098  } else {
1099  return false;
1100  }
1101  }
1102  case SUMO_ATTR_TO: {
1103  // check that is a valid ID and is different of ID of junction Source
1104  if (value == getToJunction()->getID()) {
1105  return true;
1106  } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getFromJunction()->getID())) {
1107  return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1108  } else {
1109  return false;
1110  }
1111  }
1112  case SUMO_ATTR_SPEED:
1113  return canParse<double>(value) && (parse<double>(value) > 0);
1114  case SUMO_ATTR_FRICTION:
1115  return canParse<double>(value) && (parse<double>(value) > 0);
1116  case SUMO_ATTR_NUMLANES:
1117  return canParse<int>(value) && (parse<double>(value) > 0);
1118  case SUMO_ATTR_PRIORITY:
1119  return canParse<int>(value);
1120  case SUMO_ATTR_LENGTH:
1121  if (value.empty()) {
1122  return true;
1123  } else {
1124  return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
1125  }
1126  case SUMO_ATTR_ALLOW:
1127  case SUMO_ATTR_DISALLOW:
1128  return canParseVehicleClasses(value);
1129  case SUMO_ATTR_TYPE:
1130  return true;
1131  case SUMO_ATTR_SHAPE:
1132  // empty shapes are allowed
1133  return canParse<PositionVector>(value);
1134  case SUMO_ATTR_SPREADTYPE:
1136  case SUMO_ATTR_NAME:
1137  return true;
1138  case SUMO_ATTR_WIDTH:
1139  if (value.empty() || (value == "default")) {
1140  return true;
1141  } else {
1142  return canParse<double>(value) && ((parse<double>(value) >= -1) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
1143  }
1144  case SUMO_ATTR_ENDOFFSET:
1145  return canParse<double>(value) && parse<double>(value) >= 0 && parse<double>(value) < myNBEdge->getLoadedLength();
1146  case SUMO_ATTR_DISTANCE:
1147  if (value.empty()) {
1148  return true;
1149  } else {
1150  return canParse<double>(value);
1151  }
1152  case GNE_ATTR_SHAPE_START: {
1153  if (value.empty()) {
1154  return true;
1155  } else if (canParse<Position>(value)) {
1156  Position shapeStart = parse<Position>(value);
1157  return (shapeStart != myNBEdge->getGeometry()[-1]);
1158  } else {
1159  return false;
1160  }
1161  }
1162  case GNE_ATTR_SHAPE_END: {
1163  if (value.empty()) {
1164  return true;
1165  } else if (canParse<Position>(value)) {
1166  Position shapeEnd = parse<Position>(value);
1167  return (shapeEnd != myNBEdge->getGeometry()[0]);
1168  } else {
1169  return false;
1170  }
1171  }
1172  case GNE_ATTR_BIDIR:
1173  return canParse<bool>(value) && (!parse<bool>(value) || myNBEdge->isBidiEdge(true));
1174  case GNE_ATTR_STOPOFFSET:
1175  return canParse<int>(value) && (parse<double>(value) >= 0);
1177  return canParseVehicleClasses(value);
1178  case GNE_ATTR_SELECTED:
1179  return canParse<bool>(value);
1180  case GNE_ATTR_PARAMETERS:
1181  return Parameterised::areParametersValid(value);
1182  default:
1183  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1184  }
1185 }
1186 
1187 
1188 bool
1190  switch (key) {
1191  case GNE_ATTR_BIDIR:
1192  return myNBEdge->isBidiEdge(true);
1193  default:
1194  return true;
1195  }
1196 }
1197 
1198 
1199 bool
1201  switch (key) {
1202  case SUMO_ATTR_LENGTH:
1203  return (myNBEdge->hasLoadedLength() == false);
1204  case SUMO_ATTR_WIDTH:
1205  if (myNBEdge->hasLaneSpecificWidth()) {
1206  return false;
1207  } else {
1209  }
1210  default:
1211  return false;
1212  }
1213 }
1214 
1215 
1216 const Parameterised::Map&
1218  return myNBEdge->getParametersMap();
1219 }
1220 
1221 
1222 void
1224  myAmResponsible = newVal;
1225 }
1226 
1227 
1228 GNELane*
1230  // iterate over all NBEdge lanes
1231  for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1232  // if given VClass is in permissions, return lane
1233  if (myNBEdge->getLanes().at(i).permissions & vClass) {
1234  // return GNELane
1235  return myLanes.at(i);
1236  }
1237  }
1238  // return first lane
1239  return myLanes.front();
1240 }
1241 
1242 
1243 GNELane*
1245  // iterate over all NBEdge lanes
1246  for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1247  // if given VClass isn't in permissions, return lane
1248  if (~(myNBEdge->getLanes().at(i).permissions) & vClass) {
1249  // return GNELane
1250  return myLanes.at(i);
1251  }
1252  }
1253  // return first lane
1254  return myLanes.front();
1255 }
1256 
1257 
1258 void
1260  // get lane vehicles map
1261  const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1262  // iterate over every lane
1263  for (const auto& laneVehicle : laneVehiclesMap) {
1264  // obtain total length
1265  double totalLength = 0;
1266  for (const auto& vehicle : laneVehicle.second) {
1267  totalLength += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1268  }
1269  // calculate multiplier for vehicle positions
1270  double multiplier = 1;
1271  const double laneShapeLength = laneVehicle.first->getLaneShape().length();
1272  if (laneShapeLength == 0) {
1273  multiplier = 0;
1274  } else if (totalLength > laneShapeLength) {
1275  multiplier = (laneShapeLength / totalLength);
1276  }
1277  // declare current length
1278  double length = 0;
1279  // iterate over vehicles to calculate position and rotations
1280  for (const auto& vehicle : laneVehicle.second) {
1281  vehicle->updateDemandElementSpreadGeometry(laneVehicle.first, length * multiplier);
1282  // update length
1283  length += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1284  }
1285  }
1286 }
1287 
1288 
1289 void
1291  // get lane vehicles map
1292  const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1293  // iterate over laneVehiclesMap and obtain a vector with
1294  for (const auto& vehicleMap : laneVehiclesMap) {
1295  // declare map for sort vehicles using their departpos+length position (StackPosition)
1296  std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosVehicles;
1297  // declare vector of stack demand elements
1298  std::vector<GNEEdge::StackDemandElements> stackedVehicles;
1299  // iterate over vehicles
1300  for (const auto& vehicle : vehicleMap.second) {
1301  // get vehicle's depart pos and length
1302  const double departPos = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1303  const double length = vehicle->getAttributeDouble(SUMO_ATTR_LENGTH);
1304  double posOverLane = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1305  // check if we have to adapt posOverLane
1306  if (posOverLane < 0) {
1307  posOverLane += vehicleMap.first->getLaneShape().length();
1308  }
1309  // make a stack position using departPos and length
1310  departPosVehicles.push_back(std::make_pair(StackPosition(departPos, length), vehicle));
1311  // update depart element geometry
1312  vehicle->updateDemandElementGeometry(vehicleMap.first, posOverLane);
1313  // reset vehicle stack label
1314  vehicle->updateDemandElementStackLabel(0);
1315  }
1316 
1317  // sort departPosVehicles
1318  std::sort(departPosVehicles.begin(), departPosVehicles.end());
1319  // iterate over departPosVehicles
1320  for (const auto& departPosVehicle : departPosVehicles) {
1321  // obtain stack position and vehicle
1322  const GNEEdge::StackPosition& vehicleStackPosition = departPosVehicle.first;
1323  GNEDemandElement* vehicle = departPosVehicle.second;
1324  // if stackedVehicles is empty, add a new StackDemandElements
1325  if (stackedVehicles.empty()) {
1326  stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1327  } else if (areStackPositionOverlapped(vehicleStackPosition, stackedVehicles.back().getStackPosition())) {
1328  // add new vehicle to last inserted stackDemandElements
1329  stackedVehicles[stackedVehicles.size() - 1].addDemandElements(vehicle);
1330  } else {
1331  // No overlapping, then add a new StackDemandElements
1332  stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1333  }
1334  }
1335  // iterate over stackedVehicles
1336  for (const auto& vehicle : stackedVehicles) {
1337  // only update vehicles with one or more stack
1338  if (vehicle.getDemandElements().size() > 1) {
1339  // set stack labels
1340  vehicle.getDemandElements().front()->updateDemandElementStackLabel((int)vehicle.getDemandElements().size());
1341  }
1342  }
1343  }
1344 }
1345 
1346 
1347 void
1349  // declare conditions
1350  const bool lastLane = (lane == myLanes.back());
1351  const bool validScale = (s.scale > 8.0);
1353  // first check conditions
1354  if (lastLane && (validScale || elevationMode) && !myNet->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {
1355  // Obtain exaggeration of the draw
1356  const double exaggeration = getExaggeration(s);
1357  // get circle width
1358  bool drawBigGeometryPoints = false;
1360  drawBigGeometryPoints = true;
1361  }
1364  drawBigGeometryPoints = true;
1365  }
1366  double circleWidth = drawBigGeometryPoints ? SNAP_RADIUS * MIN2((double)1, s.laneWidthExaggeration) : 0.5;
1367  double circleWidthSquared = circleWidth * circleWidth;
1368  // obtain color
1369  RGBColor color = s.junctionColorer.getSchemes()[0].getColor(2);
1370  if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
1371  // override with special colors (unless the color scheme is based on selection)
1373  }
1374  GLHelper::setColor(color);
1375  // recognize full transparency and simply don't draw
1376  if (color.alpha() > 0) {
1377  // add edge layer matrix
1379  // translate to front
1380  glTranslated(0, 0, 1);
1381  // draw geometry points expect initial and final
1382  for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
1383  Position pos = myNBEdge->getGeometry()[i];
1384  if (!s.drawForRectangleSelection || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(pos) <= (circleWidthSquared + 2))) {
1386  glTranslated(pos.x(), pos.y(), 0.1);
1387  // resolution of drawn circle depending of the zoom (To improve smoothness)
1390  // draw elevation or special symbols (Start, End and Block)
1393  // Translate to geometry point
1394  glTranslated(pos.x(), pos.y(), 0.2);
1395  // draw Z value
1398  }
1399  }
1400  }
1401  // draw line geometry, start and end points if shapeStart or shape end is edited, and depending of drawForRectangleSelection
1402  if (drawBigGeometryPoints) {
1403  if ((myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
1404  (!s.drawForRectangleSelection || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(myNBEdge->getGeometry().front()) <= (circleWidthSquared + 2)))) {
1405  // calculate angle
1406  const double angle = RAD2DEG(myNBEdge->getGeometry().front().angleTo2D(myNBEdge->getGeometry()[1])) * -1;
1408  glTranslated(myNBEdge->getGeometry().front().x(), myNBEdge->getGeometry().front().y(), 0.1);
1409  // resolution of drawn circle depending of the zoom (To improve smoothness)
1410  GLHelper::drawFilledCircle(circleWidth, s.getCircleResolution(), angle + 90, angle + 270);
1412  // draw a "s" over last point depending of drawForRectangleSelection
1415  glTranslated(myNBEdge->getGeometry().front().x(), myNBEdge->getGeometry().front().y(), 0.2);
1416  GLHelper::drawText("S", Position(), 0, circleWidth, RGBColor(0, 50, 255));
1418  // draw line between Junction and point
1420  glTranslated(0, 0, 0.1);
1421  glLineWidth(4);
1422  GLHelper::drawLine(myNBEdge->getGeometry().front(), getFromJunction()->getNBNode()->getPosition());
1423  // draw line between begin point of last lane shape and the first edge shape point
1424  GLHelper::drawLine(myNBEdge->getGeometry().front(), myNBEdge->getLanes().back().shape.front());
1426  }
1427  }
1428  if ((myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
1429  (!s.drawForRectangleSelection || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(myNBEdge->getGeometry().back()) <= (circleWidthSquared + 2)))) {
1430  // calculate angle
1431  const double angle = RAD2DEG(myNBEdge->getGeometry()[-1].angleTo2D(myNBEdge->getGeometry()[-2])) * -1;
1433  glTranslated(myNBEdge->getGeometry().back().x(), myNBEdge->getGeometry().back().y(), 0.1);
1434  // resolution of drawn circle depending of the zoom (To improve smoothness)
1435  GLHelper::drawFilledCircle(circleWidth, s.getCircleResolution(), angle - 90, angle + 90);
1437  // draw a "e" over last point depending of drawForRectangleSelection
1440  glTranslated(myNBEdge->getGeometry().back().x(), myNBEdge->getGeometry().back().y(), 0.2);
1441  GLHelper::drawText("E", Position(), 0, circleWidth, RGBColor(0, 50, 255));
1443  // draw line between Junction and point
1445  glTranslated(0, 0, 0.1);
1446  glLineWidth(4);
1447  GLHelper::drawLine(myNBEdge->getGeometry().back(), getToJunction()->getNBNode()->getPosition());
1448  // draw line between last point of first lane shape and the last edge shape point
1449  GLHelper::drawLine(myNBEdge->getGeometry().back(), myNBEdge->getLanes().back().shape.back());
1451  }
1452  }
1453  }
1454  // pop edge layer matrix
1456  // draw lock icon
1458  }
1459  }
1460 }
1461 
1462 
1463 void
1465  const bool drawFrontExtreme, const bool drawBackExtreme, const double exaggeration) {
1466  if (edge->getLanes().size() == 1) {
1467  GNELane::LaneDrawingConstants laneDrawingConstants(s, edge->getLanes().front());
1468  GUIDottedGeometry::drawDottedContourShape(s, type, edge->getLanes().front()->getLaneShape(),
1469  laneDrawingConstants.halfWidth * exaggeration, 1, drawFrontExtreme, drawBackExtreme);
1470  } else {
1471  // set left hand flag
1472  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
1473  // obtain lanes
1474  const GNELane* topLane = lefthand ? edge->getLanes().back() : edge->getLanes().front();
1475  const GNELane* botLane = lefthand ? edge->getLanes().front() : edge->getLanes().back();
1476  // obtain a copy of both geometries
1477  GUIDottedGeometry dottedGeometryTop(s, topLane->getLaneGeometry().getShape(), false);
1478  GUIDottedGeometry dottedGeometryBot(s, botLane->getLaneGeometry().getShape(), false);
1479  // obtain both LaneDrawingConstants
1480  GNELane::LaneDrawingConstants laneDrawingConstantsFront(s, topLane);
1481  GNELane::LaneDrawingConstants laneDrawingConstantsBack(s, botLane);
1482  // move shapes to side
1483  dottedGeometryTop.moveShapeToSide(laneDrawingConstantsFront.halfWidth * exaggeration);
1484  dottedGeometryBot.moveShapeToSide(laneDrawingConstantsBack.halfWidth * -1 * exaggeration);
1485  // invert offset of top dotted geometry
1486  dottedGeometryTop.invertOffset();
1487  // declare DottedGeometryColor
1488  GUIDottedGeometry::DottedGeometryColor dottedGeometryColor(s);
1489  // calculate extremes
1490  GUIDottedGeometry extremes(s, dottedGeometryTop, drawFrontExtreme, dottedGeometryBot, drawBackExtreme);
1491  // Push draw matrix
1493  // draw inspect or front dotted contour
1495  // translate to front
1496  glTranslated(0, 0, GLO_DOTTEDCONTOUR_FRONT);
1497  } else {
1498  // translate to front
1499  glTranslated(0, 0, GLO_DOTTEDCONTOUR_INSPECTED);
1500  }
1501  // draw top dotted geometry
1502  dottedGeometryTop.drawDottedGeometry(s, type, dottedGeometryColor);
1503  // reset color
1504  dottedGeometryColor.reset();
1505  // draw top dotted geometry
1506  dottedGeometryBot.drawDottedGeometry(s, type, dottedGeometryColor);
1507  // change color
1508  dottedGeometryColor.changeColor();
1509  // draw extrem dotted geometry
1510  extremes.drawDottedGeometry(s, type, dottedGeometryColor);
1511  // pop matrix
1513  }
1514 }
1515 
1516 
1517 bool
1519  // calculate angle between both junction positions
1520  double edgeAngle = RAD2DEG(getFromJunction()->getPositionInView().angleTo2D(getToJunction()->getPositionInView()));
1521  // adjust to 360 degrees
1522  while (edgeAngle < 0) {
1523  edgeAngle += 360;
1524  }
1525  // fmod round towards zero which is not want we want for negative numbers
1526  edgeAngle = fmod(edgeAngle, 360);
1527  // check angle
1528  return edgeAngle >= 0 && edgeAngle < 180;
1529 }
1530 
1531 
1532 bool
1534  // get incoming edges
1535  const auto incomingEdges = getFromJunction()->getGNEIncomingEdges();
1536  // iterate over connections
1537  for (const auto& incomingEdge : incomingEdges) {
1538  for (const auto& connection : incomingEdge->getGNEConnections()) {
1539  if (connection->getEdgeTo() == this) {
1540  return true;
1541  }
1542  }
1543  }
1544  return false;
1545 }
1546 
1547 
1548 bool
1550  return (myGNEConnections.size() > 0);
1551 }
1552 
1553 
1554 GNEEdge*
1556  for (const auto& outgoingEdge : getParentJunctions().back()->getGNEOutgoingEdges()) {
1557  if (outgoingEdge->getToJunction() == getFromJunction()) {
1558  return outgoingEdge;
1559  }
1560  }
1561  return nullptr;
1562 }
1563 
1564 // ===========================================================================
1565 // private
1566 // ===========================================================================
1567 
1568 GNEEdge::StackPosition::StackPosition(const double departPos, const double length) :
1569  pair(departPos, departPos + length) {
1570 }
1571 
1572 
1573 double
1575  return first;
1576 }
1577 
1578 
1579 double
1581  return second;
1582 }
1583 
1584 
1586  pair(stackedPosition, {
1587  demandElement
1588 }) {
1589 }
1590 
1591 
1592 void
1594  second.push_back(demandElement);
1595 }
1596 
1597 
1600  return first;
1601 }
1602 
1603 
1604 const std::vector<GNEDemandElement*>&
1606  return second;
1607 }
1608 
1609 
1610 void
1611 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
1612  switch (key) {
1613  case SUMO_ATTR_ID:
1614  myNet->getAttributeCarriers()->updateEdgeID(this, value);
1615  // enable save demand elements if there are stops
1616  for (const auto& stop : getChildDemandElements()) {
1617  if (stop->getTagProperty().isStop() || stop->getTagProperty().isStopPerson()) {
1619  }
1620  }
1621  // also for lanes
1622  for (const auto& lane : myLanes) {
1623  for (const auto& stop : lane->getChildDemandElements()) {
1624  if (stop->getTagProperty().isStop() || stop->getTagProperty().isStopPerson()) {
1626  }
1627  }
1628  }
1629  break;
1630  case SUMO_ATTR_FROM:
1631  myNet->changeEdgeEndpoints(this, value, getToJunction()->getID());
1632  // update this edge of list of outgoings edges of the old first parent junction
1634  // update first parent junction
1636  // update this edge of list of outgoings edges of the new first parent junction
1638  // update centering boundary and grid
1640  break;
1641  case SUMO_ATTR_TO:
1642  myNet->changeEdgeEndpoints(this, getFromJunction()->getID(), value);
1643  // update this edge of list of incomings edges of the old second parent junction
1645  // update second parent junction
1647  // update this edge of list of incomings edges of the new second parent junction
1649  // update centering boundary and grid
1651  break;
1652  case SUMO_ATTR_NUMLANES:
1653  throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
1654  case SUMO_ATTR_PRIORITY:
1655  myNBEdge->myPriority = parse<int>(value);
1656  break;
1657  case SUMO_ATTR_LENGTH:
1658  if (value.empty()) {
1660  } else {
1661  myNBEdge->setLoadedLength(parse<double>(value));
1662  }
1663  break;
1664  case SUMO_ATTR_TYPE:
1665  myNBEdge->myType = value;
1666  break;
1667  case SUMO_ATTR_SHAPE:
1668  // set new geometry
1669  setGeometry(parse<PositionVector>(value), true);
1670  // update centering boundary and grid
1672  break;
1673  case SUMO_ATTR_SPREADTYPE:
1675  break;
1676  case SUMO_ATTR_NAME:
1677  myNBEdge->setStreetName(value);
1678  break;
1679  case SUMO_ATTR_SPEED:
1680  myNBEdge->setSpeed(-1, parse<double>(value));
1681  break;
1682  case SUMO_ATTR_FRICTION:
1683  myNBEdge->setFriction(-1, parse<double>(value));
1684  break;
1685  case SUMO_ATTR_WIDTH:
1686  if (value.empty() || (value == "default")) {
1688  } else {
1689  myNBEdge->setLaneWidth(-1, parse<double>(value));
1690  }
1691  break;
1692  case SUMO_ATTR_ENDOFFSET:
1693  myNBEdge->setEndOffset(-1, parse<double>(value));
1694  break;
1695  case SUMO_ATTR_ALLOW:
1696  break; // no edge value
1697  case SUMO_ATTR_DISALLOW:
1698  break; // no edge value
1699  case SUMO_ATTR_DISTANCE:
1700  if (value.empty()) {
1701  myNBEdge->setDistance(0.0);
1702  } else {
1703  myNBEdge->setDistance(parse<double>(value));
1704  }
1705  break;
1707  myConnectionStatus = value;
1708  if (value == FEATURE_GUESSED) {
1709  WRITE_DEBUG("invalidating (removing) connections of edge '" + getID() + "' due it were guessed");
1712  } else if (value != FEATURE_GUESSED) {
1713  WRITE_DEBUG("declaring connections of edge '" + getID() + "' as loaded (It will not be removed)");
1715  }
1716  break;
1717  case GNE_ATTR_SHAPE_START: {
1718  // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1719  Position newShapeStart;
1720  if (value == "") {
1721  newShapeStart = getFromJunction()->getNBNode()->getPosition();
1722  } else {
1723  newShapeStart = parse<Position>(value);
1724  }
1725  // set shape start position
1726  setShapeStartPos(newShapeStart);
1727  // update centering boundary and grid
1729  break;
1730  }
1731  case GNE_ATTR_SHAPE_END: {
1732  // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destiny position) and set it back to edge
1733  Position newShapeEnd;
1734  if (value == "") {
1735  newShapeEnd = getToJunction()->getNBNode()->getPosition();
1736  } else {
1737  newShapeEnd = parse<Position>(value);
1738  }
1739  // set shape end position
1740  setShapeEndPos(newShapeEnd);
1741  // update centering boundary and grid
1743  break;
1744  }
1745  case GNE_ATTR_BIDIR:
1746  myNBEdge->setBidi(parse<bool>(value));
1747  break;
1748  case GNE_ATTR_SELECTED:
1749  if (parse<bool>(value)) {
1751  } else {
1753  }
1754  break;
1755  case GNE_ATTR_STOPOFFSET:
1756  myNBEdge->myEdgeStopOffset.setOffset(parse<double>(value));
1757  break;
1759  if (value.empty()) {
1761  } else {
1763  }
1764  break;
1765  case GNE_ATTR_PARAMETERS:
1766  myNBEdge->setParametersStr(value);
1767  break;
1768  default:
1769  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1770  }
1771  // get template editor
1773  // check update template
1774  if (templateEditor->getEdgeTemplate() && (templateEditor->getEdgeTemplate()->getID() == getID())) {
1776  }
1777  // invalidate path calculator
1779 }
1780 
1781 
1782 void
1784  // get start and end points
1785  const Position shapeStart = moveResult.shapeToUpdate.front();
1786  const Position shapeEnd = moveResult.shapeToUpdate.back();
1787  // get innen shape
1788  PositionVector innenShape = moveResult.shapeToUpdate;
1789  innenShape.pop_front();
1790  innenShape.pop_back();
1791  // set shape start
1792  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
1793  setShapeStartPos(shapeStart);
1794  }
1795  // set innen geometry
1796  setGeometry(innenShape, true);
1797  // set shape end
1798  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), ((int)moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
1799  setShapeEndPos(shapeEnd);
1800  }
1801 }
1802 
1803 
1804 void
1805 GNEEdge::commitMoveShape(const GNEMoveResult& moveResult, GNEUndoList* undoList) {
1806  // make sure that newShape isn't empty
1807  if (moveResult.shapeToUpdate.size() > 0) {
1808  // get start and end points
1809  const Position shapeStart = moveResult.shapeToUpdate.front();
1810  const Position shapeEnd = moveResult.shapeToUpdate.back();
1811  // get innen shape
1812  PositionVector innenShape = moveResult.shapeToUpdate;
1813  innenShape.pop_front();
1814  innenShape.pop_back();
1815  // commit new shape
1816  undoList->begin(GUIIcon::EDGE, "moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
1817  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
1818  undoList->changeAttribute(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_START, toString(shapeStart)));
1819  }
1820  // update shape
1821  undoList->changeAttribute(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(innenShape)));
1822  // check if we have to update shape end
1823  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), (int)(moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
1824  undoList->changeAttribute(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_END, toString(shapeEnd)));
1825  }
1826  undoList->end();
1827  }
1828 }
1829 
1830 
1831 void
1832 GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
1833  // begin undo list
1834  undoList->begin(GUIIcon::EDGE, "change number of " + toString(SUMO_TAG_LANE) + "s");
1835  // invalidate logic of source/destiny edges
1836  getFromJunction()->setLogicValid(false, undoList);
1837  getToJunction()->setLogicValid(false, undoList);
1838  // disable update geometry (see #6336)
1839  myUpdateGeometry = false;
1840  // remove edge from grid
1842  // save old number of lanes
1843  const int oldNumLanes = (int)myLanes.size();
1844  // get opposite ID
1845  const auto oppositeID = myLanes.back()->getAttribute(GNE_ATTR_OPPOSITE);
1846  if (oppositeID != "") {
1847  // we'll have a different leftmost lane after adding/removing lanes
1848  undoList->changeAttribute(new GNEChange_Attribute(myLanes.back(), GNE_ATTR_OPPOSITE, ""));
1849  }
1850  for (int i = oldNumLanes; i < numLanes; i++) {
1851  // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
1852  undoList->add(new GNEChange_Lane(this, myNBEdge->getLaneStruct(oldNumLanes - 1)), true);
1853  }
1854  for (int i = (oldNumLanes - 1); i > (numLanes - 1); i--) {
1855  // delete leftmost lane
1856  undoList->add(new GNEChange_Lane(this, myLanes[i], myNBEdge->getLaneStruct(i), false), true);
1857  }
1858  if (oppositeID != "") {
1859  undoList->changeAttribute(new GNEChange_Attribute(myLanes.back(), GNE_ATTR_OPPOSITE, oppositeID));
1860  }
1861  // enable updateGeometry again
1862  myUpdateGeometry = true;
1863  // update geometry of entire edge
1864  updateGeometry();
1865  // end undo list
1866  undoList->end();
1867  // update centering boundary (without updating RTREE)
1868  updateCenteringBoundary(false);
1869  // insert edge in grid again
1870  myNet->addGLObjectIntoGrid(this);
1871 }
1872 
1873 
1874 void
1875 GNEEdge::updateFirstParentJunction(const std::string& value) {
1876  std::vector<GNEJunction*> parentJunctions = getParentJunctions();
1877  parentJunctions[0] = myNet->getAttributeCarriers()->retrieveJunction(value);
1878  // replace parent junctions
1879  replaceParentElements(this, parentJunctions);
1880 }
1881 
1882 
1883 void
1884 GNEEdge::updateSecondParentJunction(const std::string& value) {
1885  std::vector<GNEJunction*> parentJunctions = getParentJunctions();
1886  parentJunctions[1] = myNet->getAttributeCarriers()->retrieveJunction(value);
1887  // replace parent junctions
1888  replaceParentElements(this, parentJunctions);
1889 }
1890 
1891 
1892 void
1893 GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections) {
1894  const int index = lane ? lane->getIndex() : myNBEdge->getNumLanes();
1895  // the laneStruct must be created first to ensure we have some geometry
1896  // unless the connections are fully recomputed, existing indices must be shifted
1897  myNBEdge->addLane(index, true, recomputeConnections, !recomputeConnections);
1898  if (lane) {
1899  // restore a previously deleted lane
1900  myLanes.insert(myLanes.begin() + index, lane);
1901  } else {
1902  // create a new lane by copying leftmost lane
1903  lane = new GNELane(this, index);
1904  myLanes.push_back(lane);
1905  }
1906  lane->incRef("GNEEdge::addLane");
1907  // add in attributeCarriers
1909  // check if lane is selected
1910  if (lane->isAttributeCarrierSelected()) {
1911  lane->selectAttributeCarrier();
1912  }
1913  // we copy all attributes except shape since this is recomputed from edge shape
1914  myNBEdge->setSpeed(lane->getIndex(), laneAttrs.speed);
1915  myNBEdge->setFriction(lane->getIndex(), laneAttrs.friction);
1916  myNBEdge->setPermissions(laneAttrs.permissions, lane->getIndex());
1917  myNBEdge->setPreferredVehicleClass(laneAttrs.preferred, lane->getIndex());
1918  myNBEdge->setEndOffset(lane->getIndex(), laneAttrs.endOffset);
1919  myNBEdge->setLaneWidth(lane->getIndex(), laneAttrs.width);
1920  // update indices
1921  for (int i = 0; i < (int)myLanes.size(); ++i) {
1922  myLanes[i]->setIndex(i);
1923  }
1924  /* while technically correct, this looks ugly
1925  getFromJunction()->invalidateShape();
1926  getToJunction()->invalidateShape();
1927  */
1928  // Remake connections for this edge and all edges that target this lane
1930  // remake connections of all edges of junction source and destiny
1931  for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
1932  fromEdge->remakeGNEConnections();
1933  }
1934  // remake connections of all edges of junction source and destiny
1935  for (const auto& toEdge : getToJunction()->getChildEdges()) {
1936  toEdge->remakeGNEConnections();
1937  }
1938  // Update geometry with the new lane
1939  updateGeometry();
1940  // update boundary and grid
1942 }
1943 
1944 
1945 void
1946 GNEEdge::removeLane(GNELane* lane, bool recomputeConnections) {
1947  if (myLanes.size() == 0) {
1948  throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + getTagStr());
1949  }
1950  if (lane == nullptr) {
1951  lane = myLanes.back();
1952  }
1953  // check if lane is selected
1954  if (lane->isAttributeCarrierSelected()) {
1955  lane->unselectAttributeCarrier();
1956  }
1957  // before removing, check that lane isn't being inspected
1960  // Delete lane of edge's container
1961  // unless the connections are fully recomputed, existing indices must be shifted
1962  myNBEdge->deleteLane(lane->getIndex(), recomputeConnections, !recomputeConnections);
1963  lane->decRef("GNEEdge::removeLane");
1964  myLanes.erase(myLanes.begin() + lane->getIndex());
1965  // remove from attributeCarriers
1967  // Delete lane if is unreferenced
1968  if (lane->unreferenced()) {
1969  // show extra information for tests
1970  WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in removeLane()");
1971  delete lane;
1972  }
1973  // update indices
1974  for (int i = 0; i < (int)myLanes.size(); ++i) {
1975  myLanes[i]->setIndex(i);
1976  }
1977  /* while technically correct, this looks ugly
1978  getFromJunction()->invalidateShape();
1979  getToJunction()->invalidateShape();
1980  */
1981  // Remake connections of this edge
1983  // remake connections of all edges of junction source and destiny
1984  for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
1985  fromEdge->remakeGNEConnections();
1986  }
1987  // remake connections of all edges of junction source and destiny
1988  for (const auto& toEdge : getToJunction()->getChildEdges()) {
1989  toEdge->remakeGNEConnections();
1990  }
1991  // Update element
1992  updateGeometry();
1993  // update boundary and grid
1995 }
1996 
1997 
1998 void
1999 GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
2000  // If a new connection was successfully created
2002  nbCon.keepClear, nbCon.contPos, nbCon.visibility,
2003  nbCon.speed, nbCon.friction, nbCon.customLength, nbCon.customShape, nbCon.uncontrolled)) {
2004  // Create or retrieve existent GNEConnection
2005  GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
2006  // add it to GNEConnection container
2007  myGNEConnections.push_back(con);
2008  // Add reference
2009  myGNEConnections.back()->incRef("GNEEdge::addConnection");
2010  // select GNEConnection if needed
2011  if (selectAfterCreation) {
2012  con->selectAttributeCarrier();
2013  }
2014  // update geometry
2015  con->updateGeometry();
2016  }
2017  // actually we only do this to force a redraw
2018  updateGeometry();
2019 }
2020 
2021 
2022 void
2024  // check if is a explicit turnaround
2025  if (nbCon.toEdge == myNBEdge->getTurnDestination()) {
2027  }
2028  // remove NBEdge::connection from NBEdge
2030  // remove their associated GNEConnection
2031  GNEConnection* connection = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
2032  if (connection != nullptr) {
2033  connection->decRef("GNEEdge::removeConnection");
2034  myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), connection));
2035  // check if connection is selected
2036  if (connection->isAttributeCarrierSelected()) {
2037  connection->unselectAttributeCarrier();
2038  }
2039  // remove it from network
2040  myNet->removeGLObjectFromGrid(connection);
2041  // check if remove it from Attribute Carriers
2042  if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
2044  }
2045  if (connection->unreferenced()) {
2046  // show extra information for tests
2047  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in removeConnection()");
2048  // actually we only do this to force a redraw
2049  updateGeometry();
2050  }
2051  }
2052 }
2053 
2054 
2056 GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
2057  for (const auto& connection : myGNEConnections) {
2058  if ((connection->getFromLaneIndex() == fromLane) && (connection->getEdgeTo()->getNBEdge() == to) && (connection->getToLaneIndex() == toLane)) {
2059  return connection;
2060  }
2061  }
2062  if (createIfNoExist) {
2063  // create new connection. Will be added to the rTree on first geometry computation
2064  GNEConnection* connection = new GNEConnection(myLanes[fromLane], myNet->getAttributeCarriers()->retrieveEdge(to->getID())->getLanes()[toLane]);
2065  // show extra information for tests
2066  WRITE_DEBUG("Created " + connection->getTagStr() + " '" + connection->getID() + "' in retrieveGNEConnection()");
2067  // add it into network
2068  myNet->addGLObjectIntoGrid(connection);
2069  // add it in attributeCarriers
2071  return connection;
2072  } else {
2073  return nullptr;
2074  }
2075 }
2076 
2077 
2078 void
2079 GNEEdge::setMicrosimID(const std::string& newID) {
2081  for (const auto& lane : myLanes) {
2082  lane->setMicrosimID(getNBEdge()->getLaneID(lane->getIndex()));
2083  }
2084 }
2085 
2086 
2087 bool
2089  for (const auto& lane : myLanes) {
2090  if (lane->isRestricted(vclass)) {
2091  return true;
2092  }
2093  }
2094  return false;
2095 }
2096 
2097 
2098 void
2100  // Remove all crossings that contain this edge in parameter "edges"
2101  for (const auto& crossing : junction->getGNECrossings()) {
2102  if (crossing->checkEdgeBelong(this)) {
2103  myNet->deleteCrossing(crossing, undoList);
2104  }
2105  }
2106 }
2107 
2108 
2109 void
2111  PositionVector modifiedShape = myNBEdge->getGeometry().interpolateZ(
2113  myNBEdge->getToNode()->getPosition().z());
2114  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2115  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2116 }
2117 
2118 
2120 GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
2121  const OptionsCont& oc = OptionsCont::getOptions();
2122  // distinguish 3 cases:
2123  // a) if the edge has exactly 3 or 4 points, use these as control points
2124  // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
2125  // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
2126  PositionVector init;
2127 #ifdef DEBUG_SMOOTH_GEOM
2128  if (DEBUGCOND(this)) std::cout << getID()
2129  << " forElevation=" << forElevation
2130  << " fromGeometryLike=" << myNBEdge->getFromNode()->geometryLike()
2131  << " toGeometryLike=" << myNBEdge->getToNode()->geometryLike()
2132  << " smoothShape old=" << old << "\n";
2133 #endif
2134  if (old.size() == 3 || old.size() == 4) {
2135  init = old;
2136  } else if (old.size() > 4 && !forElevation) {
2137  // for elevation, the initial segments are not useful
2138  init.push_back(old[0]);
2139  init.push_back(old[1]);
2140  init.push_back(old[-2]);
2141  init.push_back(old[-1]);
2142  } else if (myNBEdge->getFromNode()->geometryLike() && myNBEdge->getToNode()->geometryLike()) {
2143  PositionVector begShape;
2144  PositionVector endShape;
2145  const EdgeVector& incoming = myNBEdge->getFromNode()->getIncomingEdges();
2146  const EdgeVector& outgoing = myNBEdge->getToNode()->getOutgoingEdges();
2147  if (incoming.size() == 1) {
2148  begShape = incoming[0]->getGeometry();
2149  } else {
2150  assert(incoming.size() == 2);
2151  begShape = myNBEdge->isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
2152  }
2153  if (outgoing.size() == 1) {
2154  endShape = outgoing[0]->getGeometry();
2155  } else {
2156  assert(outgoing.size() == 2);
2157  endShape = myNBEdge->isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
2158  }
2159  const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
2160  if (forElevation) {
2161  // initialize control point elevation for smooth continuation
2162  init.push_back(old[0]);
2163  init.push_back(old.positionAtOffset2D(dist));
2164  init.push_back(old.positionAtOffset2D(old.length2D() - dist));
2165  init.push_back(old[-1]);
2166  double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
2167  double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
2168  // continue incline
2169  init[1].setz(2 * init[0].z() - begZ);
2170  init[2].setz(2 * init[-1].z() - endZ);
2171  } else {
2172  bool ok = true;
2173  const double straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold"));
2174  init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, nullptr, straightThresh);
2175  }
2176 #ifdef DEBUG_SMOOTH_GEOM
2177  if (DEBUGCOND(this)) {
2178  std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
2179  }
2180 #endif
2181  }
2182  if (init.size() == 0) {
2183  return PositionVector::EMPTY;
2184  } else {
2185  const int numPoints = MAX2(oc.getInt("junctions.internal-link-detail"),
2186  int(old.length2D() / oc.getFloat("opendrive.curve-resolution")));
2187  return init.bezier(numPoints);
2188  }
2189 }
2190 
2191 
2192 void
2194  PositionVector modifiedShape = smoothShape(myNBEdge->getGeometry(), false);
2195  if (modifiedShape.size() < 2) {
2196  WRITE_WARNING("Could not compute smooth shape for edge '" + getID() + "'");
2197  } else {
2198  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2199  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2200  }
2201 }
2202 
2203 
2204 void
2206  PositionVector elevationBase;
2207  for (const Position& pos : myNBEdge->getGeometry()) {
2208  if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
2209  elevationBase.push_back(pos);
2210  }
2211  }
2212  PositionVector elevation = smoothShape(elevationBase, true);
2213  if (elevation.size() <= 2) {
2214  WRITE_WARNING("Could not compute smooth elevation for edge '" + getID() + "'");
2215  } else {
2216  PositionVector modifiedShape = myNBEdge->getGeometry();
2217  if (modifiedShape.size() < 5) {
2218  modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"), false);
2219  }
2220  const double scale = elevation.length2D() / modifiedShape.length2D();
2221  //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
2222  double seen = 0;
2223  for (int i = 1; i < (int)modifiedShape.size(); ++i) {
2224  seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
2225  modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
2226  }
2227  //std::cout << " mod2=" << modifiedShape << "\n";
2228  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2229  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2230  }
2231 }
2232 
2233 
2234 void
2236  // remove start position and add it the new position
2238  geom.pop_front();
2239  geom.push_front(pos);
2240  // restore modified shape
2241  setGeometry(geom, false);
2242 }
2243 
2244 
2245 void
2247  // remove end position and add it the new position
2249  geom.pop_back();
2250  geom.push_back(pos);
2251  // restore modified shape
2252  setGeometry(geom, false);
2253 }
2254 
2255 
2256 const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2258  // declare vehicles over edge vector
2259  std::vector<GNEDemandElement*> vehiclesOverEdge;
2260  // declare solution map
2261  std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesOverEdgeMap;
2262  // declare a set of vehicles (to avoid duplicates)
2263  std::set<std::pair<double, GNEDemandElement*> > vehicles;
2264  // first obtain all vehicles of this edge
2265  for (const auto& edgeChild : getChildDemandElements()) {
2266  if (((edgeChild->getTagProperty().getTag() == SUMO_TAG_TRIP) || (edgeChild->getTagProperty().getTag() == SUMO_TAG_FLOW)) &&
2267  (edgeChild->getParentEdges().front() == this)) {
2268  vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2269  vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2270  } else if ((edgeChild->getTagProperty().getTag() == SUMO_TAG_ROUTE) && (edgeChild->getParentEdges().front() == this)) {
2271  for (const auto& routeChild : edgeChild->getChildDemandElements()) {
2272  if ((routeChild->getTagProperty().getTag() == SUMO_TAG_VEHICLE) || (routeChild->getTagProperty().getTag() == GNE_TAG_FLOW_ROUTE)) {
2273  vehicles.insert(std::make_pair(routeChild->getAttributeDouble(SUMO_ATTR_DEPART), routeChild));
2274  }
2275  }
2276  } else if ((edgeChild->getTagProperty().getTag() == GNE_TAG_ROUTE_EMBEDDED) && (edgeChild->getParentEdges().front() == this)) {
2277  vehicles.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild->getParentDemandElements().front()));
2278  }
2279  }
2280  // reserve
2281  vehiclesOverEdge.reserve(vehicles.size());
2282  // iterate over vehicles
2283  for (const auto& vehicle : vehicles) {
2284  // add it over vehiclesOverEdge;
2285  vehiclesOverEdge.push_back(vehicle.second);
2286  }
2287  // now split vehicles by lanes
2288  for (const auto& vehicle : vehiclesOverEdge) {
2289  const GNELane* vehicleLane = vehicle->getFirstPathLane();
2290  if (vehicleLane) {
2291  vehiclesOverEdgeMap[vehicleLane].push_back(vehicle);
2292  }
2293  }
2294  return vehiclesOverEdgeMap;
2295 }
2296 
2297 
2298 void
2300  // check if we can draw it
2302  // draw the name and/or the street name
2303  const bool drawStreetName = s.streetName.show(this) && (myNBEdge->getStreetName() != "");
2304  const bool spreadSuperposed = s.spreadSuperposed && myNBEdge->getBidiEdge() != nullptr;
2305  // check conditions
2306  if (s.edgeName.show(this) || drawStreetName || s.edgeValue.show(this)) {
2307  // get first and last lanes
2308  const GNELane* firstLane = myLanes[0];
2309  const GNELane* lastLane = myLanes[myLanes.size() - 1];
2310  // calculate draw position
2311  Position drawPosition = firstLane->getLaneShape().positionAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2312  drawPosition.add(lastLane->getLaneShape().positionAtOffset(lastLane->getLaneShape().length() / (double) 2.));
2313  drawPosition.mul(.5);
2314  if (spreadSuperposed) {
2315  // move name to the right of the edge and towards its beginning
2316  const double dist = 0.6 * s.edgeName.scaledSize(s.scale);
2317  const double shiftA = firstLane->getLaneShape().rotationAtOffset(firstLane->getLaneShape().length() / (double) 2.) - DEG2RAD(135);
2318  const Position shift(dist * cos(shiftA), dist * sin(shiftA));
2319  drawPosition.add(shift);
2320  }
2321  // calculate drawing angle
2322  double drawAngle = firstLane->getLaneShape().rotationDegreeAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2323  drawAngle += 90;
2324  // avoid draw inverted text
2325  if (drawAngle > 90 && drawAngle < 270) {
2326  drawAngle -= 180;
2327  }
2328  // draw edge name
2329  if (s.edgeName.show(this)) {
2330  drawName(drawPosition, s.scale, s.edgeName, drawAngle);
2331  }
2332  // draw street name
2333  if (drawStreetName) {
2334  GLHelper::drawTextSettings(s.streetName, myNBEdge->getStreetName(), drawPosition, s.scale, drawAngle);
2335  }
2336  // draw edge values
2337  if (s.edgeValue.show(this)) {
2338  // get current scheme
2339  const int activeScheme = s.laneColorer.getActive();
2340  // calculate value depending of active scheme
2341  std::string value;
2342  if (activeScheme == 12) {
2343  // edge param, could be non-numerical
2344  value = getNBEdge()->getParameter(s.edgeParam, "");
2345  } else if (activeScheme == 13) {
2346  // lane param, could be non-numerical
2347  value = getNBEdge()->getLaneStruct(lastLane->getIndex()).getParameter(s.laneParam, "");
2348  } else {
2349  // use numerical value value of leftmost lane to hopefully avoid sidewalks, bikelanes etc
2350  const double doubleValue = lastLane->getColorValue(s, activeScheme);
2351  const RGBColor color = s.laneColorer.getScheme().getColor(doubleValue);
2352  value = color.alpha() == 0 ? "" : toString(doubleValue);
2353  }
2354  // check if value is empty
2355  if (value != "") {
2356  GLHelper::drawTextSettings(s.edgeValue, value, drawPosition, s.scale, drawAngle);
2357  }
2358  }
2359  }
2360  }
2361 }
2362 
2363 
2364 void
2366  // Push stopOffset matrix
2368  // translate to front (note: Special case)
2369  if (myNet->getViewNet()->getFrontAttributeCarrier() == this) {
2370  glTranslated(0, 0, GLO_DOTTEDCONTOUR_FRONT);
2371  } else {
2373  }
2375  for (const auto& lane : getLanes()) {
2376  lane->drawLaneStopOffset(s, myNBEdge->myEdgeStopOffset.getOffset());
2377  }
2378  }
2379  // Push stopOffset matrix
2381 }
2382 
2383 
2384 void
2386  // first check if draw TAZ Elements is enabled
2388  std::vector<GNEAdditional*> TAZSourceSinks;
2389  // get all TAZ source/sinks vinculated with this edge
2390  for (const auto& additional : getChildAdditionals()) {
2391  if ((additional->getTagProperty().getTag() == SUMO_TAG_TAZSOURCE) ||
2392  (additional->getTagProperty().getTag() == SUMO_TAG_TAZSINK)) {
2393  TAZSourceSinks.push_back(additional);
2394  }
2395  }
2396  if (TAZSourceSinks.size() > 0) {
2397  // check if current front element is a Source/sink
2398  const auto frontAC = myNet->getViewNet()->getFrontAttributeCarrier();
2399  // push all GLIDs
2400  for (const auto& TAZSourceSink : TAZSourceSinks) {
2401  if (TAZSourceSink == frontAC) {
2402  GLHelper::pushName(TAZSourceSink->getGUIGlObject()->getGlID());
2403  }
2404  }
2405  for (const auto& TAZSourceSink : TAZSourceSinks) {
2406  if (TAZSourceSink != frontAC) {
2407  GLHelper::pushName(TAZSourceSink->getGlID());
2408  }
2409  }
2410  // check if TAZ Source/sink is selected
2411  bool selected = false;
2412  for (const auto& TAZSourceSink : TAZSourceSinks) {
2413  if (TAZSourceSink->isAttributeCarrierSelected()) {
2414  selected = true;
2415  }
2416  }
2417  // iterate over lanes
2418  for (const auto& lane : myLanes) {
2419  // get lane drawing constants
2420  GNELane::LaneDrawingConstants laneDrawingConstants(s, lane);
2421  // Push layer matrix
2423  // translate to front (note: Special case)
2424  if (myNet->getViewNet()->getFrontAttributeCarrier() == this) {
2425  glTranslated(0, 0, GLO_DOTTEDCONTOUR_FRONT);
2426  } else if (lane->getLaneShape().length2D() <= (s.neteditSizeSettings.junctionBubbleRadius * 2)) {
2428  } else {
2430  }
2431  // move to front
2432  glTranslated(0, 0, 0.1);
2433  // set color
2434  if (selected) {
2436  } else {
2438  }
2439  // draw as box lines
2441  lane->getLaneGeometry(), laneDrawingConstants.halfWidth);
2442  // Pop layer matrix
2444  }
2445  // pop all GLIDs
2446  for (const auto& TAZSourceSink : TAZSourceSinks) {
2447  if (TAZSourceSink == frontAC) {
2449  }
2450  }
2451  for (const auto& TAZSourceSink : TAZSourceSinks) {
2452  if (TAZSourceSink != frontAC) {
2454  }
2455  }
2456  // check if curently we're inspecting a TAZ Source/Sink
2457  for (const auto& TAZSourceSink : TAZSourceSinks) {
2458  if (myNet->getViewNet()->isAttributeCarrierInspected(TAZSourceSink)) {
2460  } else if (TAZSourceSink == frontAC) {
2462  }
2463  }
2464  }
2465  }
2466 }
2467 
2468 
2469 bool
2471  if ((vehicleA.beginPosition() == vehicleB.beginPosition()) && (vehicleA.endPosition() == vehicleB.endPosition())) {
2472  return true;
2473  } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2474  return true;
2475  } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.beginPosition())) {
2476  return true;
2477  } else if ((vehicleA.beginPosition() < vehicleB.endPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2478  return true;
2479  } else {
2480  return false;
2481  }
2482 }
2483 
2484 
2486 GNEEdge::processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
2487  // calculate squared snapRadius
2488  const double squaredSnapRadius = (snapRadius * snapRadius);
2489  // declare shape to move
2490  PositionVector shapeToMove = originalShape;
2491  // obtain nearest index
2492  const int nearestIndex = originalShape.indexOfClosest(mousePosition);
2493  // obtain nearest position
2494  const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
2495  // generate indexes
2496  std::vector<int> indexes;
2497  // check conditions
2498  if (nearestIndex == -1) {
2499  return nullptr;
2500  } else if (nearestPosition == Position::INVALID) {
2501  // special case for extremes
2502  if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2503  for (int i = 1; i <= nearestIndex; i++) {
2504  indexes.push_back(i);
2505  }
2506  // move extrem without creating new geometry point
2507  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2508  } else {
2509  return nullptr;
2510  }
2511  } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2512  for (int i = 1; i <= nearestIndex; i++) {
2513  indexes.push_back(i);
2514  }
2515  // move geometry point without creating new geometry point
2516  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2517  } else {
2518  // create new geometry point and keep new index (if we clicked near of shape)
2519  const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
2520  for (int i = 1; i <= newIndex; i++) {
2521  indexes.push_back(i);
2522  }
2523  // move after setting new geometry point in shapeToMove
2524  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2525  }
2526 }
2527 
2528 
2530 GNEEdge::processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
2531  // calculate squared snapRadius
2532  const double squaredSnapRadius = (snapRadius * snapRadius);
2533  // declare shape to move
2534  PositionVector shapeToMove = originalShape;
2535  // obtain nearest index
2536  const int nearestIndex = originalShape.indexOfClosest(mousePosition);
2537  // obtain nearest position
2538  const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
2539  // generate indexes
2540  std::vector<int> indexes;
2541  // check conditions
2542  if (nearestIndex == -1) {
2543  return nullptr;
2544  } else if (nearestPosition == Position::INVALID) {
2545  // special case for extremes
2546  if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2547  for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
2548  indexes.push_back(i);
2549  }
2550  // move extrem without creating new geometry point
2551  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2552  } else {
2553  return nullptr;
2554  }
2555  } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2556  for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
2557  indexes.push_back(i);
2558  }
2559  // move geometry point without creating new geometry point
2560  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2561  } else {
2562  // create new geometry point and keep new index (if we clicked near of shape)
2563  const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
2564  for (int i = newIndex; i < ((int)originalShape.size() - 1); i++) {
2565  indexes.push_back(i);
2566  }
2567  // move after setting new geometry point in shapeToMove
2568  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2569  }
2570 }
2571 
2572 
2575  // declare a vector for saving geometry points to move (all except extremes)
2576  std::vector<int> geometryPointsToMove;
2577  for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
2578  geometryPointsToMove.push_back(i);
2579  }
2580  // move entire shape (except extremes)
2581  return new GNEMoveOperation(this, myNBEdge->getGeometry(), geometryPointsToMove, myNBEdge->getGeometry(), geometryPointsToMove);
2582 }
2583 
2584 
2586 GNEEdge::processNoneJunctionSelected(const double snapRadius) {
2587  // get move multiple element values
2588  const auto& moveMultipleElementValues = myNet->getViewNet()->getMoveMultipleElementValues();
2589  // declare shape to move
2590  PositionVector shapeToMove = myNBEdge->getGeometry();
2591  // first check if kept offset is larger than geometry
2592  if (shapeToMove.length2D() < moveMultipleElementValues.getEdgeOffset()) {
2593  return nullptr;
2594  }
2595  // declare offset
2596  double offset = 0;
2597  // set offset depending of convex angle
2598  if (isConvexAngle()) {
2599  offset = moveMultipleElementValues.getEdgeOffset();
2600  } else {
2601  offset = shapeToMove.length2D() - moveMultipleElementValues.getEdgeOffset();
2602  }
2603  // obtain offset position
2604  const Position offsetPosition = myNBEdge->getGeometry().positionAtOffset2D(offset);
2605  // obtain nearest index to offset position
2606  const int nearestIndex = myNBEdge->getGeometry().indexOfClosest(offsetPosition);
2607  // check conditions
2608  if ((nearestIndex == -1) || (offsetPosition == Position::INVALID)) {
2609  return nullptr;
2610  } else if (offsetPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= (snapRadius * snapRadius)) {
2611  // move geometry point without creating new geometry point
2612  return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {nearestIndex});
2613  } else {
2614  // create new geometry point and keep new index (if we clicked near of shape)
2615  const int newIndex = shapeToMove.insertAtClosest(offsetPosition, true);
2616  // move after setting new geometry point in shapeToMove
2617  return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {newIndex});
2618  }
2619 }
2620 
2621 /****************************************************************************/
#define ENDPOINT_TOLERANCE
Definition: GNEEdge.cpp:50
#define VEHICLE_GAP
Definition: GNEEdge.cpp:49
@ NETWORK_DELETE
mode for deleting network elements
@ NETWORK_MOVE
mode for moving network elements
@ GLO_DOTTEDCONTOUR_INSPECTED
dotted contour inspected element (used in NETEDIT)
@ GLO_DOTTEDCONTOUR_FRONT
dotted contour front element (used in NETEDIT)
@ GLO_MAX
empty max
@ GLO_JUNCTION
a junction
@ GLO_LANE
a lane
@ GLO_EDGE
an edge
GUIIcon
An enumeration of icons used by the gui applications.
Definition: GUIIcons.h:33
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define RAD2DEG(x)
Definition: GeomHelper.h:36
#define DEBUGCOND(PEDID)
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:276
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
const SVCPermissions SVCAll
all VClasses are allowed
SVCPermissions invertPermissions(SVCPermissions permissions)
negate the given permissions and ensure that only relevant bits are set
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
bool canParseVehicleClasses(const std::string &classes)
Checks whether the given string contains only known vehicle classes.
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SUMO_TAG_TAZSINK
a sink within a district (connection road)
@ GNE_TAG_STOPCONTAINER_EDGE
@ SUMO_TAG_VEHICLE
description of a vehicle
@ GNE_TAG_FLOW_ROUTE
a flow definition using a route instead of a from-to edges route (used in NETEDIT)
@ SUMO_TAG_FLOW
a flow definitio nusing a from-to edges instead of a route (used by router)
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_ROUTE
begin/end of the description of a route
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_TAZSOURCE
a source within a district (connection road)
@ GNE_TAG_ROUTE_EMBEDDED
embedded route (used in NETEDIT)
@ GNE_TAG_STOPPERSON_EDGE
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_TAG_EDGE
begin/end of the description of an edge
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_DISALLOW
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_SPEED
@ GNE_ATTR_STOPOFFSET
stop offset (virtual, used by edge and lanes)
@ GNE_ATTR_OPPOSITE
neighboring lane, simplified lane attr instead of child element
@ GNE_ATTR_SELECTED
element is selected
@ GNE_ATTR_PARAMETERS
parameters "key1=value1|key2=value2|...|keyN=valueN"
@ SUMO_ATTR_PRIORITY
@ GNE_ATTR_STOPOEXCEPTION
stop exceptions (virtual, used by edge and lanes)
@ SUMO_ATTR_NUMLANES
@ GNE_ATTR_MODIFICATION_STATUS
whether a feature has been loaded,guessed,modified or approved
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_NAME
@ SUMO_ATTR_SPREADTYPE
The information about how to spread the lanes from the given position.
@ SUMO_ATTR_ENDOFFSET
@ GNE_ATTR_SHAPE_END
last coordinate of edge shape
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_DISTANCE
@ GNE_ATTR_BIDIR
whether an edge is part of a bidirectional railway
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_ID
@ GNE_ATTR_SHAPE_START
first coordinate of edge shape
@ SUMO_ATTR_WIDTH
@ SUMO_ATTR_FRICTION
T MIN2(T a, T b)
Definition: StdDefs.h:71
T MAX2(T a, T b)
Definition: StdDefs.h:77
const double SUMO_const_halfLaneWidth
Definition: StdDefs.h:49
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:78
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:300
static void drawBoundary(const Boundary &b)
Draw a boundary (used for debugging)
Definition: GLHelper.cpp:894
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition: GLHelper.cpp:421
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:583
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:498
static void pushName(unsigned int name)
push Name
Definition: GLHelper.cpp:139
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:130
static void popName()
pop Name
Definition: GLHelper.cpp:148
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:117
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, const int align=0, double width=-1)
Definition: GLHelper.cpp:685
static void drawTextSettings(const GUIVisualizationTextSettings &settings, const std::string &text, const Position &pos, const double scale, const double angle=0, const double layer=2048, const int align=0)
Definition: GLHelper.cpp:716
GNENetworkSelector * getEdgesSelector() const
get edges selector
const std::string getID() const
get ID (all Attribute Carriers have one)
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
friend class GNEChange_Attribute
declare friend class
const std::string & getTagStr() const
get tag assigned to this object in string format
static const std::string FEATURE_GUESSED
feature has been reguessed (may still be unchanged be we can't tell (yet)
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
void unselectAttributeCarrier(const bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
GNENet * myNet
pointer to net
void selectAttributeCarrier(const bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
void markConnectionGeometryDeprecated()
check that connection's Geometry has to be updated
void updateGeometry()
update pre-computed geometry information
void updateLinkState()
recompute cached myLinkState
bool deleteOnlyGeometryPoints() const
check if only delete geometry points checkbox is enabled
struct for saving subordinated elements (Junction->Edge->Lane->(Additional | DemandElement)
ProtectElements * getProtectElements() const
get protect elements modul
DeleteOptions * getDeleteOptions() const
get delete options modul
An Element which don't belong to GNENet but has influence in the simulation.
void updateDemandElementStackLabel(const int stack)
update stack label
Stack demand elements.
Definition: GNEEdge.h:366
const StackPosition & getStackPosition() const
get stack position
Definition: GNEEdge.cpp:1599
const std::vector< GNEDemandElement * > & getDemandElements() const
get demand elements
Definition: GNEEdge.cpp:1605
void addDemandElements(GNEDemandElement *demandElement)
add demand elment to current StackDemandElements
Definition: GNEEdge.cpp:1593
StackDemandElements(const StackPosition stackedPosition, GNEDemandElement *demandElement)
constructor
Definition: GNEEdge.cpp:1585
Stack position (used to stack demand elements over edges)
Definition: GNEEdge.h:352
double beginPosition() const
get begin position
Definition: GNEEdge.cpp:1574
StackPosition(const double departPos, const double length)
constructor
Definition: GNEEdge.cpp:1568
double endPosition() const
get end position
Definition: GNEEdge.cpp:1580
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:53
const Position getFrontDownShapePosition() const
get front down shape position
Definition: GNEEdge.cpp:616
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
Definition: GNEEdge.cpp:348
void drawEdgeName(const GUIVisualizationSettings &s) const
draw edge name
Definition: GNEEdge.cpp:2299
bool isConvexAngle() const
check if edge makes a convex angle [0 - 180) degrees
Definition: GNEEdge.cpp:1518
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:1832
std::string getNetworkElementProblem() const
return a string with the current network element problem
Definition: GNEEdge.cpp:134
void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)
commit move shape
Definition: GNEEdge.cpp:1805
bool hasPredecessors() const
check if this edge has predecessors (note: only for vehicles, this function ignore walking areas!...
Definition: GNEEdge.cpp:1533
void setMoveShape(const GNEMoveResult &moveResult)
set move shape
Definition: GNEEdge.cpp:1783
friend class GNEChange_Lane
Friend class.
Definition: GNEEdge.h:56
~GNEEdge()
Destructor.
Definition: GNEEdge.cpp:90
void smooth(GNEUndoList *undoList)
make geometry smooth
Definition: GNEEdge.cpp:2193
void updateGeometry()
update pre-computed geometry information
Definition: GNEEdge.cpp:142
GNEMoveOperation * getMoveOperation()
get move operation
Definition: GNEEdge.cpp:192
std::string getAttributeForSelection(SumoXMLAttr key) const
method for getting the attribute in the context of object selection
Definition: GNEEdge.cpp:947
GNEJunction * getFromJunction() const
get from Junction (only used to increase readability)
Definition: GNEEdge.h:77
void setResponsible(bool newVal)
set responsibility for deleting internal structures
Definition: GNEEdge.cpp:1223
static void drawDottedContourEdge(const GUIVisualizationSettings &s, const GUIDottedGeometry::DottedContourType type, const GNEEdge *edge, const bool drawFrontExtreme, const bool drawBackExtreme, const double exaggeration=1)
draw dotted contour for the given dottedGeometries
Definition: GNEEdge.cpp:1464
void copyEdgeType(const GNEEdgeType *edgeType, GNEUndoList *undoList)
copy edge attributes from edgeType
Definition: GNEEdge.cpp:784
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition: GNEEdge.cpp:481
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEEdge.cpp:389
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getVehiclesOverEdgeMap() const
get vehicles a that start over this edge
Definition: GNEEdge.cpp:2257
std::set< GUIGlID > getLaneGlIDs() const
returns GLIDs of all lanes
Definition: GNEEdge.cpp:829
GNEEdge * getReverseEdge() const
get reverse edge (if exist)
Definition: GNEEdge.cpp:1555
const Position getFrontUpShapePosition() const
get front up shape position
Definition: GNEEdge.cpp:608
void setGeometry(PositionVector geom, bool inner)
update edge geometry and inform the lanes
Definition: GNEEdge.cpp:573
void smoothElevation(GNEUndoList *undoList)
smooth elevation with regard to adjoining edges
Definition: GNEEdge.cpp:2205
void drawLaneStopOffset(const GUIVisualizationSettings &s) const
draw edgeStopOffset
Definition: GNEEdge.cpp:2365
bool clickedOverGeometryPoint(const Position &pos) const
return true if user clicked over a Geometry Point
Definition: GNEEdge.cpp:309
bool clickedOverShapeEnd(const Position &pos) const
return true if user clicked over ShapeEnd
Definition: GNEEdge.cpp:299
void updateVehicleStackLabels()
Definition: GNEEdge.cpp:1290
GNEJunction * getToJunction() const
get from Junction (only used to increase readability)
Definition: GNEEdge.h:82
bool isValid(SumoXMLAttr key, const std::string &value)
Definition: GNEEdge.cpp:1088
void remakeGNEConnections(bool junctionsReady=false)
remake connections
Definition: GNEEdge.cpp:639
GNEMoveOperation * processMoveBothJunctionSelected()
process moving edge when both junctions are selected
Definition: GNEEdge.cpp:2574
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList)
remove geometry point in the clicked position
Definition: GNEEdge.cpp:218
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:839
LaneVector myLanes
vector with the lanes of this edge
Definition: GNEEdge.h:333
static const double SNAP_RADIUS
Definition: GNEEdge.h:271
GNELane * getLaneByAllowedVClass(const SUMOVehicleClass vClass) const
return the first lane that allow a vehicle of type vClass (or the first lane, if none was found)
Definition: GNEEdge.cpp:1229
bool hasCustomEndPoints() const
Definition: GNEEdge.cpp:277
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition: GNEEdge.cpp:2023
bool hasSuccessors() const
check if this edge has successors (note: only for vehicles, this function ignore walking areas!...
Definition: GNEEdge.cpp:1549
bool isAttributeComputed(SumoXMLAttr key) const
Definition: GNEEdge.cpp:1200
bool myWasSplit
whether this edge was created from a split
Definition: GNEEdge.h:345
void removeLane(GNELane *lane, bool recomputeConnections)
@briefdecrease the number of lanes by one. argument is only used to increase robustness (assertions)
Definition: GNEEdge.cpp:1946
double getExaggeration(const GUIVisualizationSettings &s) const
return exaggeration associated with this GLObject
Definition: GNEEdge.cpp:342
bool hasRestrictedLane(SUMOVehicleClass vclass) const
check if edge has a restricted lane
Definition: GNEEdge.cpp:2088
static const double SNAP_RADIUS_SQUARED
Definition: GNEEdge.h:274
void updateSecondParentJunction(const std::string &value)
update last parent junction
Definition: GNEEdge.cpp:1884
std::vector< GNEEdge * > getOppositeEdges() const
get opposite edges
Definition: GNEEdge.cpp:404
PositionVector smoothShape(const PositionVector &shape, bool forElevation)
return smoothed shape
Definition: GNEEdge.cpp:2120
bool wasSplit()
whether this edge was created from a split
Definition: GNEEdge.cpp:851
NBEdge * myNBEdge
the underlying NBEdge
Definition: GNEEdge.h:330
void copyTemplate(const GNEEdgeTemplate *edgeTemplate, GNEUndoList *undoList)
copy edge attributes from edgetemplate
Definition: GNEEdge.cpp:749
void removeEdgeFromCrossings(GNEJunction *junction, GNEUndoList *undoList)
remove crossing of junction
Definition: GNEEdge.cpp:2099
Position getPositionInView() const
Returns position of hierarchical element in view.
Definition: GNEEdge.cpp:186
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:1893
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:2056
ConnectionVector myGNEConnections
vector with the connections of this edge
Definition: GNEEdge.h:336
void editEndpoint(Position pos, GNEUndoList *undoList)
makes pos the new geometry endpoint at the appropriate end, or remove current existent endpoint
Definition: GNEEdge.cpp:501
void resetBothEndpoint(GNEUndoList *undoList)
restores both endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:563
Position getSplitPos(const Position &clickPos)
Definition: GNEEdge.cpp:487
const std::vector< GNEConnection * > & getGNEConnections() const
returns a reference to the GNEConnection vector
Definition: GNEEdge.cpp:845
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEEdge.cpp:857
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition: GNEEdge.cpp:714
std::string myConnectionStatus
modification status of the connections
Definition: GNEEdge.h:348
void deleteGLObject()
delete element
Definition: GNEEdge.cpp:466
const std::string getOptionalName() const
Returns the street name.
Definition: GNEEdge.cpp:383
void clearGNEConnections()
clear current connections
Definition: GNEEdge.cpp:687
bool myUpdateGeometry
flag to enable/disable update geometry of lanes (used mainly by setNumLanes)
Definition: GNEEdge.h:383
const Position getBackDownShapePosition() const
get back down shape position
Definition: GNEEdge.cpp:632
bool areStackPositionOverlapped(const GNEEdge::StackPosition &vehicleA, const GNEEdge::StackPosition &vehicleB) const
check if given stacked positions are overlapped
Definition: GNEEdge.cpp:2470
void updateFirstParentJunction(const std::string &value)
update front parent junction
Definition: GNEEdge.cpp:1875
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition: GNEEdge.cpp:2110
bool clickedOverShapeStart(const Position &pos) const
return true if user clicked over ShapeStart
Definition: GNEEdge.cpp:289
bool isNetworkElementValid() const
check if current network element is valid to be written into XML
Definition: GNEEdge.cpp:124
void setShapeStartPos(const Position &pos)
change Shape StartPos
Definition: GNEEdge.cpp:2235
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNEEdge.cpp:957
void setMicrosimID(const std::string &newID)
override to also set lane ids
Definition: GNEEdge.cpp:2079
const Position getBackUpShapePosition() const
get back up shape position
Definition: GNEEdge.cpp:624
void resetEndpoint(const Position &pos, GNEUndoList *undoList)
restores the endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:549
bool isAttributeEnabled(SumoXMLAttr key) const
Definition: GNEEdge.cpp:1189
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEEdge.cpp:410
void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation=false)
adds a connection
Definition: GNEEdge.cpp:1999
GNEMoveOperation * processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only from junction is selected
Definition: GNEEdge.cpp:2486
void drawEdgeGeometryPoints(const GUIVisualizationSettings &s, const GNELane *lane) const
draw edge geometry points (note: This function is called by GNELane::drawGL(...)
Definition: GNEEdge.cpp:1348
GNEMoveOperation * processNoneJunctionSelected(const double snapRadius)
process moving edge when none junction are selected
Definition: GNEEdge.cpp:2586
const Parameterised::Map & getACParametersMap() const
get parameters map
Definition: GNEEdge.cpp:1217
void drawTAZElements(const GUIVisualizationSettings &s) const
draw TAZElements
Definition: GNEEdge.cpp:2385
std::vector< GNECrossing * > getGNECrossings()
get GNECrossings vinculated with this Edge
Definition: GNEEdge.cpp:732
GNELane * getLaneByDisallowedVClass(const SUMOVehicleClass vClass) const
return the first lane that disallow a vehicle of type vClass (or the first lane, if none was found)
Definition: GNEEdge.cpp:1244
void updateVehicleSpreadGeometries()
Definition: GNEEdge.cpp:1259
GNEMoveOperation * processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only to junction is selected
Definition: GNEEdge.cpp:2530
void updateGLObject()
update GLObject (geometry, ID, etc.)
Definition: GNEEdge.cpp:475
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition: GNEEdge.cpp:328
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition: GNEEdge.h:342
GNEEdge(GNENet *net, NBEdge *nbe, bool wasSplit=false, bool loaded=false)
Constructor.
Definition: GNEEdge.cpp:62
void setShapeEndPos(const Position &pos)
change Shape EndPos
Definition: GNEEdge.cpp:2246
std::string getAttribute(SumoXMLAttr key) const
const std::vector< GNELaneTemplate * > & getLaneTemplates() const
get vector with the lane templates of this edge
const std::vector< GNELaneType * > & getLaneTypes() const
get laneTypes
std::string getAttribute(SumoXMLAttr key) const
void removeCurrentEditedAttributeCarrier(const GNEAttributeCarrier *HE)
if given AttributeCarrier is the same of myHE, set it as nullptr
const std::vector< GNEJunction * > & getParentJunctions() const
get parent junctions
const std::vector< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
const std::vector< GNEEdge * > & getChildEdges() const
get child edges
const std::vector< GNEAdditional * > & getChildAdditionals() const
return child additionals
void replaceParentElements(T *elementChild, const U &newParents)
replace parent elements
const std::vector< GNEGenericData * > & getChildGenericDatas() const
return child generic data elements
void setEdgeTemplate(const GNEEdge *edge)
set edge template
GNEEdgeTemplate * getEdgeTemplate() const
get edge template (to copy attributes from)
void updateEdgeTemplate()
update edge template
TemplateEditor * getTemplateEditor() const
get template editor
GNEElementTree * getHierarchicalElementTree() const
get GNEElementTree modul
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
void invalidateShape()
void updateGeometry()
update pre-computed geometry information (including crossings)
void removeOutgoingGNEEdge(GNEEdge *edge)
remove outgoing GNEEdge
void removeIncomingGNEEdge(GNEEdge *edge)
remove incoming GNEEdge
void addIncomingGNEEdge(GNEEdge *edge)
add incoming GNEEdge
NBNode * getNBNode() const
Return net build node.
void setLogicValid(bool valid, GNEUndoList *undoList, const std::string &status=FEATURE_GUESSED)
void addOutgoingGNEEdge(GNEEdge *edge)
add outgoing GNEEdge
FOX-declaration.
Definition: GNELane.h:52
const double halfWidth
Draw as a normal lane, and reduce width to make sure that a selected edge can still be seen.
Definition: GNELane.h:68
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:46
const PositionVector & getLaneShape() const
get elements shape
Definition: GNELane.cpp:142
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:876
const GUIGeometry & getLaneGeometry() const
Definition: GNELane.cpp:136
double getColorValue(const GUIVisualizationSettings &s, int activeScheme) const
return value for lane coloring according to the given scheme
Definition: GNELane.cpp:1375
GNEMoveOperation * calculateMoveShapeOperation(const PositionVector originalShape, const Position mousePosition, const double snapRadius, const bool onlyContour)
calculate move shape operation
move operation
move result
std::vector< int > geometryPointsToMove
shape points to move (of shapeToMove)
PositionVector shapeToUpdate
shape to update (edited in moveElement)
std::vector< GNEEdge * > retrieveEdges(GNEJunction *from, GNEJunction *to) const
get all edges by from and to GNEJunction
const std::set< GNELane * > & getLanes() const
get lanes
const std::set< GNEConnection * > & getConnections() const
get connections
void insertLane(GNELane *lane)
insert lane
void deleteConnection(GNEConnection *connection)
delete connection
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
void insertConnection(GNEConnection *connection)
insert connection
void updateEdgeID(GNEEdge *edge, const std::string &newID)
update edge ID in container
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
void deleteLane(GNELane *lane)
delete lane
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:42
void deleteEdge(GNEEdge *edge, GNEUndoList *undoList, bool recomputeConnections)
removes edge
Definition: GNENet.cpp:420
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:611
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1245
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1257
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition: GNENet.cpp:2011
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:132
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition: GNENet.cpp:1978
void requireSaveDemandElements(bool value)
inform that demand elements has to be saved
Definition: GNENet.cpp:2083
GNEPathManager * getPathManager()
get path manager
Definition: GNENet.cpp:138
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1987
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Boundary myBoundary
object boundary
bool isNetworkElementSelected(const GNENetworkElement *networkElement) const
check if the given networkElement is being selected
void invalidatePathCalculator()
invalidate pathCalculator
PathCalculator * getPathCalculator()
obtain instance of PathCalculator
void decRef(const std::string &debugMsg="")
Decrease reference.
void incRef(const std::string &debugMsg="")
Increase reference.
bool unreferenced()
check if object ins't referenced
Representation of a RouteProbe in netedit.
Definition: GNERouteProbe.h:32
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
void begin(GUIIcon icon, const std::string &description)
Begin undo command sub-group with current supermode. This begins a new group of commands that are tre...
void add(GNEChange *command, bool doit=false, bool merge=true)
Add new command, executing it if desired. The new command will be merged with the previous command if...
void changeAttribute(GNEChange_Attribute *change)
special method for change attributes, avoid empty changes, always execute
const GNEViewNetHelper::DataViewOptions & getDataViewOptions() const
get data view options
Definition: GNEViewNet.cpp:656
const GNEAttributeCarrier * getFrontAttributeCarrier() const
get front attributeCarrier
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:632
bool drawSelectContour(const GUIGlObject *GLObject, const GNEAttributeCarrier *AC) const
check if draw select contour
bool drawDeleteContour(const GUIGlObject *GLObject, const GNEAttributeCarrier *AC) const
check if draw delete contour
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
Definition: GNEViewNet.cpp:644
void drawTranslateFrontAttributeCarrier(const GNEAttributeCarrier *AC, double typeOrLayer, const double extraOffset=0)
draw front attributeCarrier
GNEViewParent * getViewParent() const
get the net object
GNEUndoList * getUndoList() const
get the undoList object
void removeFromAttributeCarrierInspected(const GNEAttributeCarrier *AC)
remove given AC of list of inspected Attribute Carriers
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:474
bool isAttributeCarrierInspected(const GNEAttributeCarrier *AC) const
check if attribute carrier is being inspected
const GNEViewNetHelper::MoveMultipleElementValues & getMoveMultipleElementValues() const
get move multiple element values
Definition: GNEViewNet.cpp:468
GNEDeleteFrame * getDeleteFrame() const
get frame for delete elements
GNEAdditionalFrame * getAdditionalFrame() const
get frame for NETWORK_ADDITIONAL
GNEInspectorFrame * getInspectorFrame() const
get frame for inspect elements
class for pack all variables related with GUIDottedGeometry color
void reset()
rest Dotted Geometry Color
void drawDottedGeometry(const GUIVisualizationSettings &s, GUIDottedGeometry::DottedContourType type, DottedGeometryColor &dottedGeometryColor, const double customWidth=1) const
draw inspected dottedShape
void moveShapeToSide(const double value)
move shape to side
void invertOffset()
invert offset of all segments
static void drawDottedContourShape(const GUIVisualizationSettings &s, const DottedContourType type, const PositionVector &shape, const double width, const double exaggeration, const bool drawFirstExtrem, const bool drawLastExtrem)
draw dotted contour for the given shape (used by additionals)
The popup menu of a globject.
static void drawGeometry(const GUIVisualizationSettings &s, const Position &mousePos, const GUIGeometry &geometry, const double width, double offset=0)
draw geometry
const PositionVector & getShape() const
The shape of the additional element.
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
Definition: GUIGlObject.h:154
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
Definition: GUIGlObject.h:141
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, const GUIMainWindow &app) const
Builds an entry which allows to copy the cursor position if geo projection is used,...
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0, bool forceShow=false) const
draw name of item
const T getColor(const double value) const
const std::vector< T > & getSchemes() const
Position snapToActiveGrid(const Position &pos, bool snapXY=true) const
Returns a position that is mapped to the closest grid point if the grid is active.
const GUIVisualizationSettings & getVisualisationSettings() const
get visualization settings (read only)
virtual Position getPositionInformation() const
Returns the cursor's x/y position within the network.
Stores the information about how to visualize structures.
bool drawBoundaries
enable or disable draw boundaries
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
GUIVisualizationDetailSettings detailSettings
detail settings
GUIVisualizationSizeSettings addSize
bool drawForPositionSelection
whether drawing is performed for the purpose of selecting objects with a single click
GUIVisualizationTextSettings edgeValue
double laneWidthExaggeration
The lane exaggeration (upscale thickness)
GUIVisualizationColorSettings colorSettings
color settings
double scale
information about a lane's width (temporary, used for a single view)
bool drawDetail(const double detail, const double exaggeration) const
check if details can be drawn for the given GUIVisualizationDetailSettings and current scale and exxa...
GUIVisualizationTextSettings streetName
GUIColorer laneColorer
The lane colorer.
GUIVisualizationTextSettings edgeName
int getCircleResolution() const
function to calculate circle resolution for all circles drawn in drawGL(...) functions
bool spreadSuperposed
Whether to improve visualisation of superposed (rail) edges.
GUIColorer junctionColorer
The junction colorer.
std::string edgeParam
key for coloring by edge parameter
GUIVisualizationNeteditSizeSettings neteditSizeSettings
netedit size settings
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
Definition: GeomHelper.h:50
The representation of a single edge during network building.
Definition: NBEdge.h:92
void setStreetName(const std::string &name)
sets the street name of this edge
Definition: NBEdge.h:680
void mirrorX()
mirror coordinates along the x-axis
Definition: NBEdge.cpp:595
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
Definition: NBEdge.cpp:4114
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:4137
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:4100
StopOffset myEdgeStopOffset
A vClass specific stop offset - assumed of length 0 (unspecified) or 1. For the latter case the int i...
Definition: NBEdge.h:1793
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition: NBEdge.h:608
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4052
bool hasLaneSpecificFriction() const
whether lanes differ in friction
Definition: NBEdge.cpp:2387
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:648
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:675
void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices)
add lane
Definition: NBEdge.cpp:3790
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:2377
std::string myType
The type of the edge.
Definition: NBEdge.h:1730
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition: NBEdge.cpp:974
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:618
void setDistance(double distance)
set kilometrage at start of edge (negative value implies couting down along the edge)
Definition: NBEdge.h:1416
const std::string & getID() const
Definition: NBEdge.h:1526
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:736
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:552
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:625
double getDistance() const
get distance
Definition: NBEdge.h:685
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:375
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3923
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:968
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:3430
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:2363
bool isBidiEdge(bool checkPotential=false) const
whether this edge is part of a bidirectional edge pair
Definition: NBEdge.cpp:773
void setBidi(bool isBidi)
mark this edge as a bidi edge
Definition: NBEdge.h:1421
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:526
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:787
void setFriction(int lane, double friction)
set lane specific friction (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4068
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false, const bool keepPossibleTurns=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:1402
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1483
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition: NBEdge.cpp:3845
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:2397
@ USER
The connection was given by the user.
double getFriction() const
Returns the friction on this edge.
Definition: NBEdge.h:632
const NBEdge * getBidiEdge() const
Definition: NBEdge.h:1512
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double friction=UNSPECIFIED_FRICTION, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:1145
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:2419
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3767
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:533
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:357
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:1043
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1183
void declareConnectionsAsLoaded(EdgeBuildingStep step=EdgeBuildingStep::LANES2LANES_USER)
declares connections as fully loaded. This is needed to avoid recomputing connections if an edge has ...
Definition: NBEdge.h:1440
double getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:695
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4006
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1426
void setLoadedLength(double val)
set loaded length
Definition: NBEdge.cpp:4152
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:615
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:4469
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition: NBEdge.cpp:650
int myPriority
The priority of the edge.
Definition: NBEdge.h:1749
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:545
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:263
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:258
const Position & getPosition() const
Definition: NBNode.h:250
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:3468
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:544
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
bool set(const std::string &name, const std::string &value, const bool append=false)
Sets the given value for the named option.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
void resetWritable()
Resets all options to be writeable.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:59
static bool areParametersValid(const std::string &value, bool report=false, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to a parameters map "key1=value1|key2=value2|....
std::map< std::string, std::string > Map
parameters map
Definition: Parameterised.h:45
void setParametersStr(const std::string &paramsString, const std::string kvsep="=", const std::string sep="|")
set the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN"
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
std::string getParametersStr(const std::string kvsep="=", const std::string sep="|") const
Returns the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN".
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition: Position.h:257
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:298
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:252
double x() const
Returns the x-position.
Definition: Position.h:55
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:125
void mul(double val)
Multiplies both positions with the given value.
Definition: Position.h:105
double z() const
Returns the z-position.
Definition: Position.h:65
double y() const
Returns the y-position.
Definition: Position.h:60
A list of positions.
double length2D() const
Returns the length.
double length() const
Returns the length.
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
PositionVector resample(double maxLength, const bool adjustEnd) const
resample shape (i.e. transform to segments, equal spacing)
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void add(double xoff, double yoff, double zoff)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
int indexOfClosest(const Position &p, bool twoD=false) const
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
PositionVector interpolateZ(double zStart, double zEnd) const
returned vector that varies z smoothly over its length
static const PositionVector EMPTY
empty Vector
PositionVector bezier(int numPoints)
return a bezier interpolation
int insertAtClosest(const Position &p, bool interpolateZ)
inserts p between the two closest positions
void push_front(const Position &p)
insert in front a Position
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false, int beginOffset=0, int endOffset=0, bool resample=false)
Removes positions if too near.
void pop_front()
pop first Position
PositionVector reverse() const
reverse position vector
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
static const RGBColor BLUE
Definition: RGBColor.h:187
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition: RGBColor.cpp:92
static const RGBColor CYAN
Definition: RGBColor.h:189
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:200
static StringBijection< LaneSpreadFunction > LaneSpreadFunctions
lane spread functions
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
void setOffset(const double offset)
set offset
bool isDefined() const
check if stopOffset was defined
void reset()
reset stopOffset
SVCPermissions getPermissions() const
get permissions
void setExceptions(const std::string permissions)
set exceptions (used in NETEDIT)
std::string getExceptions() const
get exceptions (used in NETEDIT)
double getOffset() const
get offset
bool hasString(const std::string &str) const
const std::string & getString(const T key) const
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:4451
bool showDemandElements() const
check if show demand elements checkbox is enabled
NetworkEditMode networkEditMode
the current Network edit mode
bool isCurrentSupermodeDemand() const
@check if current supermode is Demand
bool isCurrentSupermodeNetwork() const
@check if current supermode is Network
static void drawLockIcon(const GNEAttributeCarrier *AC, GUIGlObjectType type, const Position viewPosition, const double exaggeration, const double size=0.5, const double offsetx=0, const double offsety=0)
draw lock icon
bool isMovingSelectedEdge() const
flag for moving edge
bool editingElevation() const
check if we're editing elevation
bool showDemandElements() const
check if show demand elements checkbox is enabled
bool showTAZElements() const
check if show TAZ Elements
RGBColor selectedEdgeColor
edge selection color
static const double geometryPointsText
details for Geometry Points Texts
static const double junctionBubbleRadius
junction bubble radius
static const double edgeGeometryPointRadius
moving edge geometry point radius
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
bool show(const GUIGlObject *o) const
whether to show the text
double scaledSize(double scale, double constFactor=0.1) const
get scale size
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:201
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:227
int toLane
The lane the connections yields in.
Definition: NBEdge.h:233
double speed
custom speed for connection
Definition: NBEdge.h:257
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:230
KeepClear keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:248
double customLength
custom length for connection
Definition: NBEdge.h:263
bool uncontrolled
check if Connection is uncontrolled
Definition: NBEdge.h:314
PositionVector customShape
custom shape for connection
Definition: NBEdge.h:266
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:245
double contPos
custom position for internal junction on this connection
Definition: NBEdge.h:251
double visibility
custom foe visiblity for connection
Definition: NBEdge.h:254
double friction
Definition: NBEdge.h:260
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:143
double width
This lane's width.
Definition: NBEdge.h:176
double endOffset
This lane's offset to the intersection begin.
Definition: NBEdge.h:169
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition: NBEdge.h:160
double speed
The speed allowed on this lane.
Definition: NBEdge.h:151
double friction
The friction on this lane.
Definition: NBEdge.h:154
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:157