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.dev/sumo
3 // Copyright (C) 2001-2024 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>
40 #include <utils/gui/div/GLHelper.h>
44 
45 #include "GNEConnection.h"
46 #include "GNECrossing.h"
47 #include "GNEEdge.h"
48 #include "GNEEdgeType.h"
49 #include "GNELaneType.h"
50 #include "GNEEdgeTemplate.h"
51 #include "GNELaneTemplate.h"
52 
53 
54 //#define DEBUG_SMOOTH_GEOM
55 //#define DEBUGCOND(obj) (true)
56 #define VEHICLE_GAP 1
57 #define ENDPOINT_TOLERANCE 2
58 
59 // ===========================================================================
60 // static
61 // ===========================================================================
64 
65 // ===========================================================================
66 // members methods
67 // ===========================================================================
68 
69 GNEEdge::GNEEdge(GNENet* net, NBEdge* nbe, bool wasSplit, bool loaded):
70  GNENetworkElement(net, nbe->getID(), GLO_EDGE, SUMO_TAG_EDGE, GUIIconSubSys::getIcon(GUIIcon::EDGE), {
73 },
74 {}, {}, {}, {}, {}),
75 myNBEdge(nbe),
76 myLanes(0),
77 myAmResponsible(false),
78 myWasSplit(wasSplit),
79 myConnectionStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED),
80 myUpdateGeometry(true) {
81  // Create lanes
82  int numLanes = myNBEdge->getNumLanes();
83  myLanes.reserve(numLanes);
84  for (int i = 0; i < numLanes; i++) {
85  myLanes.push_back(new GNELane(this, i));
86  myLanes.back()->incRef("GNEEdge::GNEEdge");
87  }
88  // update Lane geometries
89  for (const auto& lane : myLanes) {
90  lane->updateGeometry();
91  }
92  // update centering boundary without updating grid
93  updateCenteringBoundary(false);
94 }
95 
96 
98  // Delete references to this edge in lanes
99  for (const auto& lane : myLanes) {
100  lane->decRef("GNEEdge::~GNEEdge");
101  if (lane->unreferenced()) {
102  // check if remove it from Attribute Carriers
103  if (myNet->getAttributeCarriers()->getLanes().count(lane) > 0) {
105  }
106  // show extra information for tests
107  WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in GNEEdge destructor");
108  delete lane;
109  }
110  }
111  // delete references to this edge in connections
112  for (const auto& connection : myGNEConnections) {
113  connection->decRef("GNEEdge::~GNEEdge");
114  if (connection->unreferenced()) {
115  // check if remove it from Attribute Carriers
116  if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
118  }
119  // show extra information for tests
120  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in GNEEdge destructor");
121  delete connection;
122  }
123  }
124  if (myAmResponsible) {
125  delete myNBEdge;
126  }
127 }
128 
129 
130 bool
132  if (getFromJunction()->getNBNode()->getPosition() != getToJunction()->getNBNode()->getPosition()) {
133  return true;
134  } else {
135  return false;
136  }
137 }
138 
139 
140 std::string
142  return TLF("Parent junctions are in the same position: %, %",
143  toString(getFromJunction()->getNBNode()->getPosition().x()),
144  toString(getFromJunction()->getNBNode()->getPosition().y()));
145 }
146 
147 
148 void
150  // first check if myUpdateGeometry flag is enabled
151  if (myUpdateGeometry) {
152  // Update geometry of lanes
153  for (const auto& lane : myLanes) {
154  lane->updateGeometry();
155  }
156  // Update geometry of connections
157  for (const auto& connection : myGNEConnections) {
158  connection->updateGeometry();
159  }
160  // Update geometry of additionals children vinculated to this edge
161  for (const auto& childAdditional : getChildAdditionals()) {
162  childAdditional->updateGeometry();
163  }
164  // Update geometry of additionals demand elements vinculated to this edge
165  for (const auto& childDemandElement : getChildDemandElements()) {
166  childDemandElement->updateGeometry();
167  }
168  // Update geometry of additionals generic datas vinculated to this edge
169  for (const auto& childGenericData : getChildGenericDatas()) {
170  childGenericData->updateGeometry();
171  }
172  // compute geometry of path elements elements vinculated with this edge (depending of showDemandElements)
174  for (const auto& childAdditional : getChildAdditionals()) {
175  childAdditional->computePathElement();
176  }
177  for (const auto& childDemandElement : getChildDemandElements()) {
178  childDemandElement->computePathElement();
179  }
180  for (const auto& childGenericData : getChildGenericDatas()) {
181  childGenericData->computePathElement();
182  }
183  }
184  }
185  // update vehicle geometry
187  // update stack labels
191 }
192 
193 
194 Position
196  return myLanes.front()->getPositionInView();
197 }
198 
199 
200 bool
202  // get modes
203  const auto& modes = myNet->getViewNet()->getEditModes();
204  // get current GNEPlanCreator
205  GNEPlanCreator* planCreator = nullptr;
206  if (modes.isCurrentSupermodeDemand() && (modes.demandEditMode == DemandEditMode::DEMAND_PERSON)) {
207  planCreator = myNet->getViewNet()->getViewParent()->getPersonFrame()->getPlanCreator();
208  } else if (modes.isCurrentSupermodeDemand() && (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN)) {
210  } else if (modes.isCurrentSupermodeDemand() && (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER)) {
212  } else if (modes.isCurrentSupermodeDemand() && (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN)) {
214  }
215  // continue depending of planCreator
216  if (planCreator) {
217  // check if this is the from edge
218  if (planCreator->getFromEdge() == this) {
219  return true;
220  } else {
221  // mark all consecutive edges
222  for (const auto& edge : planCreator->getConsecutiveEdges()) {
223  if (edge == this) {
224  return true;
225  }
226  }
227  }
228  }
229  return false;
230 }
231 
232 
233 bool
235  // get modes
236  const auto& modes = myNet->getViewNet()->getEditModes();
237  // get current GNEPlanCreator
238  GNEPlanCreator* planCreator = nullptr;
239  if (modes.isCurrentSupermodeDemand() && (modes.demandEditMode == DemandEditMode::DEMAND_PERSON)) {
240  planCreator = myNet->getViewNet()->getViewParent()->getPersonFrame()->getPlanCreator();
241  } else if (modes.isCurrentSupermodeDemand() && (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN)) {
243  } else if (modes.isCurrentSupermodeDemand() && (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER)) {
245  } else if (modes.isCurrentSupermodeDemand() && (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN)) {
247  }
248  // continue depending of planCreator
249  if (planCreator) {
250  // check if this is the to edge
251  if (planCreator->getToEdge() == this) {
252  return true;
253  }
254  }
255  return false;
256 }
257 
258 
259 bool
261  return false;
262 }
263 
264 
265 bool
267  // get modes
268  const auto& modes = myNet->getViewNet()->getEditModes();
269  // get frames
270  const auto& vehicleFrame = myNet->getViewNet()->getViewParent()->getVehicleFrame();
271  const auto& personFramePlanSelector = myNet->getViewNet()->getViewParent()->getPersonFrame()->getPlanSelector();
272  const auto& personPlanFramePlanSelector = myNet->getViewNet()->getViewParent()->getPersonPlanFrame()->getPlanSelector();
273  const auto& containerFramePlanSelector = myNet->getViewNet()->getViewParent()->getContainerFrame()->getPlanSelector();
274  const auto& containerPlanFramePlanSelector = myNet->getViewNet()->getViewParent()->getContainerPlanFrame()->getPlanSelector();
275  // check if we're in vehicle mode
276  if (vehicleFrame->shown()) {
277  // get current vehicle template
278  const auto vehicleTemplate = vehicleFrame->getVehicleTagSelector()->getCurrentTemplateAC();
279  // check if vehicle can be placed over from-to edges
280  if (vehicleTemplate && vehicleTemplate->getTagProperty().vehicleEdges()) {
282  }
283  } else if (modes.isCurrentSupermodeDemand()) {
284  // check if we're in person or personPlan modes
285  if (((modes.demandEditMode == DemandEditMode::DEMAND_PERSON) && personFramePlanSelector->markEdges()) ||
286  ((modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) && personPlanFramePlanSelector->markEdges()) ||
287  ((modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) && containerFramePlanSelector->markEdges()) ||
288  ((modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) && containerPlanFramePlanSelector->markEdges())) {
290  }
291  }
292  return false;
293 }
294 
295 
296 bool
298  // first check if we're selecting edges or lanes
299  if (myNet->getViewNet()->checkSelectEdges()) {
300  // get edit modes
301  const auto& editModes = myNet->getViewNet()->getEditModes();
302  // check if we're in delete mode
303  if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE)) {
304  // check lanes
305  for (const auto& lane : myLanes) {
308  return true;
309  }
310  }
311  // check edge
314  return true;
315  }
316  // nothing to draw
317  return false;
318  } else {
319  return false;
320  }
321  } else {
322  return false;
323  }
324 }
325 
326 
327 bool
329  // first check if we're selecting edges or lanes
330  if (myNet->getViewNet()->checkSelectEdges()) {
331  // get edit modes
332  const auto& editModes = myNet->getViewNet()->getEditModes();
333  // check if we're in select mode
334  if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_SELECT)) {
335  // check lanes
336  for (const auto& lane : myLanes) {
339  return true;
340  }
341  }
342  // check edge
345  return true;
346  }
347  // nothing to draw
348  return false;
349  } else {
350  return false;
351  }
352  } else {
353  return false;
354  }
355 }
356 
357 
358 bool
360  // get edit modes
361  const auto& editModes = myNet->getViewNet()->getEditModes();
362  // check if we're in move mode
363  if (!myNet->getViewNet()->isMovingElement() && editModes.isCurrentSupermodeNetwork() &&
364  (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE)) {
365  // check lanes
366  for (const auto& lane : myLanes) {
369  return true;
370  }
371  }
372  // check edge
375  return true;
376  }
377  // nothing to draw
378  return false;
379  } else {
380  return false;
381  }
382 }
383 
384 
387  // get geometry point radius
388  const double geometryPointRadius = getGeometryPointRadius();
389  // check if edge is selected
391  // check if both junctions are selected
396  } else if (getToJunction()->isAttributeCarrierSelected()) {
400  // special case: when only a single edge is selected, move all shape points (including custom end points)
402  } else {
403  // synchronized movement of a single point
404  return processNoneJunctionSelected(geometryPointRadius);
405  }
406  } else {
407  // calculate move shape operation (because there are only an edge selected)
408  return calculateMoveShapeOperation(this, myNBEdge->getGeometry(), false);
409  }
410  } else {
411  // calculate move shape operation
412  return calculateMoveShapeOperation(this, myNBEdge->getGeometry(), false);
413  }
414 }
415 
416 
417 void
418 GNEEdge::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
419  // get geometry point radius
420  const double geometryPointRadius = getGeometryPointRadius();
421  // declare shape to move
423  // obtain flags for start and end positions
424  const bool customStartPosition = (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE);
425  const bool customEndPosition = (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE);
426  // get variable for last index
427  const int lastIndex = (int)myNBEdge->getGeometry().size() - 1;
428  // flag to enable/disable remove geometry point
429  bool removeGeometryPoint = true;
430  // obtain index
431  const int index = myNBEdge->getGeometry().indexOfClosest(clickedPosition, true);
432  // check index
433  if (index == -1) {
434  removeGeometryPoint = false;
435  }
436  // check distance
437  if (shape[index].distanceSquaredTo2D(clickedPosition) > (geometryPointRadius * geometryPointRadius)) {
438  removeGeometryPoint = false;
439  }
440  // check custom start position
441  if (!customStartPosition && (index == 0)) {
442  removeGeometryPoint = false;
443  }
444  // check custom end position
445  if (!customEndPosition && (index == lastIndex)) {
446  removeGeometryPoint = false;
447  }
448  // check if we can remove geometry point
449  if (removeGeometryPoint) {
450  // check if we're removing first geometry proint
451  if (index == 0) {
452  // commit new geometry start
453  undoList->begin(this, "remove first geometry point of " + getTagStr());
455  undoList->end();
456  } else if (index == lastIndex) {
457  // commit new geometry end
458  undoList->begin(this, "remove last geometry point of " + getTagStr());
460  undoList->end();
461  } else {
462  // remove geometry point
463  shape.erase(shape.begin() + index);
464  // get innen shape
465  shape.pop_front();
466  shape.pop_back();
467  // remove double points
468  shape.removeDoublePoints((geometryPointRadius * geometryPointRadius));
469  // commit new shape
470  undoList->begin(this, "remove geometry point of " + getTagStr());
472  undoList->end();
473  }
474  }
475 }
476 
477 
478 bool
480  if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
481  return true;
482  } else if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
483  return true;
484  } else {
485  return false;
486  }
487 }
488 
489 
490 bool
492  // get geometry point radius
493  const double geometryPointRadius = getGeometryPointRadius();
494  if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
495  return (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius));
496  } else {
497  return false;
498  }
499 }
500 
501 
502 bool
504  // get geometry point radius
505  const double geometryPointRadius = getGeometryPointRadius();
506  if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
507  return (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius));
508  } else {
509  return false;
510  }
511 }
512 
513 
514 bool
516  // get geometry point radius
517  const auto geometryPointRadius = getGeometryPointRadius();
518  // first check inner geometry
519  const PositionVector innenShape = myNBEdge->getInnerGeometry();
520  // iterate over geometry point
521  for (const auto& geometryPoint : innenShape) {
522  if (geometryPoint.distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius)) {
523  return true;
524  }
525  }
526  // check start and end shapes
527  if (clickedOverShapeStart(pos) || clickedOverShapeEnd(pos)) {
528  return true;
529  } else {
530  return false;
531  }
532 }
533 
534 
535 void
537  Position delta = junction->getNBNode()->getPosition() - origPos;
539  // geometry endpoint need not equal junction position hence we modify it with delta
540  if (junction == getFromJunction()) {
541  geom[0].add(delta);
542  } else {
543  geom[-1].add(delta);
544  }
545  setGeometry(geom, false);
546 }
547 
548 
549 double
551  return s.addSize.getExaggeration(s, this);
552 }
553 
554 
555 Boundary
557  return myEdgeBoundary;
558 }
559 
560 
561 void
562 GNEEdge::updateCenteringBoundary(const bool updateGrid) {
563  // Remove object from net
564  if (updateGrid) {
566  }
567  // first add edge boundary
569  // add lane boundaries
570  for (const auto& lane : myLanes) {
571  const auto laneBoundary = lane->getCenteringBoundary();
572  if (laneBoundary.isInitialised()) {
573  myEdgeBoundary.add(laneBoundary);
574  // add additional and demand boundaries
575  for (const auto& additional : lane->getChildAdditionals()) {
576  const auto additionalBoundary = additional->getCenteringBoundary();
577  if (additionalBoundary.isInitialised()) {
578  myEdgeBoundary.add(additional->getCenteringBoundary());
579  }
580  }
581  }
582  }
583  // add additional and demand boundaries
584  for (const auto& additional : getChildAdditionals()) {
585  const auto additionalBoundary = additional->getCenteringBoundary();
586  if (additionalBoundary.isInitialised()) {
587  myEdgeBoundary.add(additionalBoundary);
588  }
589  }
590  // add junction positions
593  // grow boundary
594  myEdgeBoundary.grow(5);
595  // add object into net
596  if (updateGrid) {
597  myNet->addGLObjectIntoGrid(this);
598  }
599 }
600 
601 
602 const std::string
604  return myNBEdge->getStreetName();
605 }
606 
607 
610  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
611  buildPopupHeader(ret, app);
614  // build selection and show parameters menu
617  // build position copy entry
618  buildPositionCopyEntry(ret, app);
619  return ret;
620 }
621 
622 
623 std::vector<GNEEdge*>
626 }
627 
628 
629 void
631  // check drawing boundary selection and size boundary
633  // draw boundary
635  // get detail level from the first lane
636  const auto d = myLanes.front()->getDrawingConstants()->getDetail();
637  // check if draw details
638  if (!s.drawForViewObjectsHandler) {
639  // draw geometry points
641  // draw edge shape (a red line only visible if lane shape is strange)
642  drawEdgeShape(s, d);
643  // draw edge stopOffset
644  drawLaneStopOffset(s, d);
645  // draw edge name
646  drawEdgeName(s);
647  // draw lock icon
649  // draw dotted contour
651  }
652  // calculate edge contour (always before children)
653  calculateEdgeContour(s, d);
654  // draw lanes
655  for (const auto& lane : myLanes) {
656  lane->drawGL(s);
657  }
658  // draw junctions
659  getFromJunction()->drawGL(s);
660  getToJunction()->drawGL(s);
661  // draw childrens
662  drawChildrens(s, d);
663  }
664 }
665 
666 
667 void
669  // Check if edge can be deleted
671  myNet->deleteEdge(this, myNet->getViewNet()->getUndoList(), false);
672  }
673 }
674 
675 
676 void
678  updateGeometry();
679 }
680 
681 
682 NBEdge*
684  return myNBEdge;
685 }
686 
687 
688 Position
689 GNEEdge::getSplitPos(const Position& clickPos) {
690  // get geometry point radius
691  const double geometryPointRadius = getGeometryPointRadius();
692  const PositionVector& geom = myNBEdge->getGeometry();
693  int index = geom.indexOfClosest(clickPos, true);
694  if (geom[index].distanceSquaredTo2D(clickPos) < (geometryPointRadius * geometryPointRadius)) {
695  // split at existing geometry point
696  return myNet->getViewNet()->snapToActiveGrid(geom[index]);
697  } else {
698  // split straight between the next two points
700  }
701 }
702 
703 
704 void
706  // get geometry point radius
707  const double geometryPointRadius = getGeometryPointRadius();
708  if ((myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
709  (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius))) {
710  undoList->begin(this, "remove endpoint");
711  setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
712  undoList->end();
713  } else if ((myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
714  (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius))) {
715  undoList->begin(this, "remove endpoint");
716  setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
717  undoList->end();
718  } else {
719  // we need to create new Start/End position over Edge shape, not over clicked position
721  if (offset != GeomHelper::INVALID_OFFSET) {
723  // calculate position over edge shape relative to clicked position
724  Position newPos = geom.positionAtOffset2D(offset);
725  // snap new position to grid
726  newPos = myNet->getViewNet()->snapToActiveGrid(newPos);
727  undoList->begin(this, "set endpoint");
728  const int index = geom.indexOfClosest(pos, true);
729  const Position destPos = getToJunction()->getNBNode()->getPosition();
730  const Position sourcePos = getFromJunction()->getNBNode()->getPosition();
731  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
732  // check if snap to existing geometrypoint
733  if (geom[index].distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius)) {
734  newPos = geom[index];
735  // remove existent geometry point to avoid double points
736  removeGeometryPoint(newPos, undoList);
737  }
738  setAttribute(GNE_ATTR_SHAPE_END, toString(newPos), undoList);
740  } else {
741  // check if snap to existing geometry point
742  if (geom[index].distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius)) {
743  newPos = geom[index];
744  // remove existent geometry point to avoid double points
745  removeGeometryPoint(newPos, undoList);
746  }
747  setAttribute(GNE_ATTR_SHAPE_START, toString(newPos), undoList);
749  }
750  undoList->end();
751  }
752  }
753 }
754 
755 
756 void
758  Position destPos = getToJunction()->getNBNode()->getPosition();
759  Position sourcePos = getFromJunction()->getNBNode()->getPosition();
760  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
761  setAttribute(GNE_ATTR_SHAPE_END, toString(destPos), undoList);
763  } else {
764  setAttribute(GNE_ATTR_SHAPE_START, toString(sourcePos), undoList);
766  }
767 }
768 
769 
770 void
772  // reset shape start
773  setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
775  // reset shape end
776  setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
778 }
779 
780 void
782  // set new geometry
783  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
784  if (lefthand) {
785  geom.mirrorX();
786  myNBEdge->mirrorX();
787  }
788  myNBEdge->setGeometry(geom, inner);
789  if (lefthand) {
790  myNBEdge->mirrorX();
791  }
792  // update geometry
793  updateGeometry();
794  // invalidate junction source shape
796  // iterate over first parent junction edges and update geometry
797  for (const auto& edge : getFromJunction()->getGNEIncomingEdges()) {
798  edge->updateGeometry();
799  }
800  for (const auto& edge : getFromJunction()->getGNEOutgoingEdges()) {
801  edge->updateGeometry();
802  }
803  // invalidate junction destination shape
805  // iterate over second parent junction edges and update geometry
806  for (const auto& edge : getToJunction()->getGNEIncomingEdges()) {
807  edge->updateGeometry();
808  }
809  for (const auto& edge : getToJunction()->getGNEOutgoingEdges()) {
810  edge->updateGeometry();
811  }
812 }
813 
814 
815 const Position
817  PositionVector laneShape = myLanes.front()->getLaneShape();
818  laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
819  return laneShape.front();
820 }
821 
822 
823 const Position
825  PositionVector laneShape = myLanes.back()->getLaneShape();
826  laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
827  return laneShape.front();
828 }
829 
830 
831 const Position
833  PositionVector laneShape = myLanes.front()->getLaneShape();
834  laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
835  return laneShape.back();
836 }
837 
838 
839 const Position
841  PositionVector laneShape = myLanes.back()->getLaneShape();
842  laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
843  return laneShape.back();
844 }
845 
846 void
847 GNEEdge::remakeGNEConnections(bool junctionsReady) {
848  // create new and removed unused GNEConnections
849  const std::vector<NBEdge::Connection>& connections = myNBEdge->getConnections();
850  // create a vector to keep retrieved and created connections
851  std::vector<GNEConnection*> retrievedConnections;
852  // iterate over NBEdge::Connections of GNEEdge
853  for (const auto& connection : connections) {
854  // retrieve existent GNEConnection, or create it
855  GNEConnection* retrievedGNEConnection = retrieveGNEConnection(connection.fromLane, connection.toEdge, connection.toLane);
856  if (junctionsReady) {
857  retrievedGNEConnection->updateLinkState();
858  }
859  retrievedConnections.push_back(retrievedGNEConnection);
860  // check if previously this GNEConnections exists, and if true, remove it from myGNEConnections
861  std::vector<GNEConnection*>::iterator retrievedExists = std::find(myGNEConnections.begin(), myGNEConnections.end(), retrievedGNEConnection);
862  if (retrievedExists != myGNEConnections.end()) {
863  myGNEConnections.erase(retrievedExists);
864  } else {
865  // include reference to created GNEConnection
866  retrievedGNEConnection->incRef("GNEEdge::remakeGNEConnections");
867  }
868  // mark it as deprecated
869  retrievedGNEConnection->markConnectionGeometryDeprecated();
870  }
871  // delete non retrieved GNEConnections
872  for (const auto& connection : myGNEConnections) {
873  // decrease reference
874  connection->decRef();
875  // remove it from network
876  myNet->removeGLObjectFromGrid(connection);
877  // and from AttributeCarriers
878  if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
880  }
881  // delete GNEConnection if is unreferenced
882  if (connection->unreferenced()) {
883 
884  // show extra information for tests
885  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in rebuildGNEConnections()");
886  delete connection;
887  }
888  }
889  // copy retrieved (existent and created) GNECrossings to myGNEConnections
890  myGNEConnections = retrievedConnections;
891 }
892 
893 
894 void
896  // Drop all existents connections that aren't referenced anymore
897  for (const auto& connection : myGNEConnections) {
898  // check if connection is selected
899  if (connection->isAttributeCarrierSelected()) {
900  connection->unselectAttributeCarrier();
901  }
902  // Dec reference of connection
903  connection->decRef("GNEEdge::clearGNEConnections");
904  // remove it from network
905  myNet->removeGLObjectFromGrid(connection);
906  // and from AttributeCarriers
907  if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
909  }
910  // Delete GNEConnectionToErase if is unreferenced
911  if (connection->unreferenced()) {
912  // show extra information for tests
913  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in clearGNEConnections()");
914  delete connection;
915  }
916  }
917  myGNEConnections.clear();
918 }
919 
920 
921 int
923  std::vector<GNEAdditional*> routeProbes;
924  for (auto i : getChildAdditionals()) {
925  if (i->getTagProperty().getTag() == routeProbe->getTagProperty().getTag()) {
926  routeProbes.push_back(i);
927  }
928  }
929  // return index of routeProbe in routeProbes vector
930  auto it = std::find(routeProbes.begin(), routeProbes.end(), routeProbe);
931  if (it == routeProbes.end()) {
932  return -1;
933  } else {
934  return (int)(it - routeProbes.begin());
935  }
936 }
937 
938 
939 std::vector<GNECrossing*>
941  std::vector<GNECrossing*> crossings;
942  for (auto i : getFromJunction()->getGNECrossings()) {
943  if (i->checkEdgeBelong(this)) {
944  crossings.push_back(i);
945  }
946  }
947  for (auto i : getToJunction()->getGNECrossings()) {
948  if (i->checkEdgeBelong(this)) {
949  crossings.push_back(i);
950  }
951  }
952  return crossings;
953 }
954 
955 
956 void
957 GNEEdge::copyTemplate(const GNEEdgeTemplate* edgeTemplate, GNEUndoList* undoList) {
958  // copy edge-specific attributes
960  setAttribute(SUMO_ATTR_TYPE, edgeTemplate->getAttribute(SUMO_ATTR_TYPE), undoList);
965  // copy raw values for lane-specific attributes
966  if (isValid(SUMO_ATTR_SPEED, edgeTemplate->getAttribute(SUMO_ATTR_SPEED))) {
967  setAttribute(SUMO_ATTR_SPEED, edgeTemplate->getAttribute(SUMO_ATTR_SPEED), undoList);
968  }
971  }
972  if (isValid(SUMO_ATTR_WIDTH, edgeTemplate->getAttribute(SUMO_ATTR_WIDTH))) {
973  setAttribute(SUMO_ATTR_WIDTH, edgeTemplate->getAttribute(SUMO_ATTR_WIDTH), undoList);
974  }
977  }
978  // copy lane attributes as well
979  for (int i = 0; i < (int)myLanes.size(); i++) {
980  myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_ALLOW), undoList);
981  myLanes[i]->setAttribute(SUMO_ATTR_SPEED, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_SPEED), undoList);
982  myLanes[i]->setAttribute(SUMO_ATTR_FRICTION, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_FRICTION), undoList);
983  myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_WIDTH), undoList);
984  myLanes[i]->setAttribute(SUMO_ATTR_ENDOFFSET, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
985  myLanes[i]->setAttribute(GNE_ATTR_STOPOFFSET, edgeTemplate->getLaneTemplates().at(i)->getAttribute(GNE_ATTR_STOPOFFSET), undoList);
986  myLanes[i]->setAttribute(GNE_ATTR_STOPOEXCEPTION, edgeTemplate->getLaneTemplates().at(i)->getAttribute(GNE_ATTR_STOPOEXCEPTION), undoList);
987  }
988 }
989 
990 
991 void
992 GNEEdge::copyEdgeType(const GNEEdgeType* edgeType, GNEUndoList* undoList) {
993  // get lane type properties
994  const auto laneTypeProperties = getTagProperty(SUMO_TAG_LANETYPE);
995  // set type (only for info)
996  setAttribute(SUMO_ATTR_TYPE, edgeType->getAttribute(SUMO_ATTR_ID), undoList);
997  // set num lanes
999  // set speed
1001  // set friction
1003  // set allow (no disallow)
1005  // set spreadType
1007  // set width
1009  // set priority
1011  // set parameters
1013  // copy lane attributes as well
1014  for (int i = 0; i < (int)myLanes.size(); i++) {
1015  // now copy custom lane values
1016  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_SPEED) != laneTypeProperties.getAttributeProperties(SUMO_ATTR_SPEED).getDefaultValue()) {
1017  myLanes[i]->setAttribute(SUMO_ATTR_SPEED, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_SPEED), undoList);
1018  }
1019  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_ALLOW) != laneTypeProperties.getAttributeProperties(SUMO_ATTR_ALLOW).getDefaultValue()) {
1020  myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_ALLOW), undoList);
1021  }
1022  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_DISALLOW) != laneTypeProperties.getAttributeProperties(SUMO_ATTR_DISALLOW).getDefaultValue()) {
1023  myLanes[i]->setAttribute(SUMO_ATTR_DISALLOW, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_DISALLOW), undoList);
1024  }
1025  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_WIDTH) != laneTypeProperties.getAttributeProperties(SUMO_ATTR_WIDTH).getDefaultValue()) {
1026  myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_WIDTH), undoList);
1027  }
1028  if (edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS).size() > 0) {
1029  myLanes[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
1030  }
1031  // more checks here
1032  }
1033 }
1034 
1035 
1036 std::set<GUIGlID>
1038  std::set<GUIGlID> result;
1039  for (auto i : myLanes) {
1040  result.insert(i->getGlID());
1041  }
1042  return result;
1043 }
1044 
1045 
1046 const std::vector<GNELane*>&
1048  return myLanes;
1049 }
1050 
1051 
1052 const std::vector<GNEConnection*>&
1054  return myGNEConnections;
1055 }
1056 
1057 
1058 bool
1060  return myWasSplit;
1061 }
1062 
1063 
1064 std::string
1066  switch (key) {
1067  case SUMO_ATTR_ID:
1068  return getMicrosimID();
1069  case SUMO_ATTR_FROM:
1071  return getFromJunction()->getID();
1072  case SUMO_ATTR_TO:
1073  case SUMO_ATTR_TO_JUNCTION:
1074  return getToJunction()->getID();
1075  case SUMO_ATTR_NUMLANES:
1076  return toString(myNBEdge->getNumLanes());
1077  case SUMO_ATTR_PRIORITY:
1078  return toString(myNBEdge->getPriority());
1079  case SUMO_ATTR_LENGTH:
1080  return toString(myNBEdge->getFinalLength());
1081  case SUMO_ATTR_TYPE:
1082  return myNBEdge->getTypeID();
1083  case SUMO_ATTR_SHAPE:
1084  return toString(myNBEdge->getInnerGeometry());
1085  case SUMO_ATTR_SPREADTYPE:
1087  case SUMO_ATTR_NAME:
1088  return myNBEdge->getStreetName();
1089  case SUMO_ATTR_ALLOW:
1090  return (getVehicleClassNames(myNBEdge->getPermissions()) + (myNBEdge->hasLaneSpecificPermissions() ? " (combined!)" : ""));
1091  case SUMO_ATTR_DISALLOW: {
1093  }
1094  case SUMO_ATTR_SPEED:
1095  if (myNBEdge->hasLaneSpecificSpeed()) {
1096  return "lane specific";
1097  } else {
1098  return toString(myNBEdge->getSpeed());
1099  }
1100  case SUMO_ATTR_FRICTION:
1102  return "lane specific";
1103  } else {
1104  return toString(myNBEdge->getFriction());
1105  }
1106  case SUMO_ATTR_WIDTH:
1107  if (myNBEdge->hasLaneSpecificWidth()) {
1108  return "lane specific";
1109  } else if (myNBEdge->getLaneWidth() == NBEdge::UNSPECIFIED_WIDTH) {
1110  return "default";
1111  } else {
1112  return toString(myNBEdge->getLaneWidth());
1113  }
1114  case SUMO_ATTR_ENDOFFSET:
1116  return "lane specific";
1117  } else {
1118  return toString(myNBEdge->getEndOffset());
1119  }
1120  case SUMO_ATTR_DISTANCE:
1121  return toString(myNBEdge->getDistance());
1123  return myConnectionStatus;
1124  case GNE_ATTR_SHAPE_START:
1125  if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
1126  return "";
1127  } else {
1128  return toString(myNBEdge->getGeometry().front());
1129  }
1130  case GNE_ATTR_SHAPE_END:
1131  if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
1132  return "";
1133  } else {
1134  return toString(myNBEdge->getGeometry().back());
1135  }
1136  case GNE_ATTR_BIDIR:
1137  return toString(myNBEdge->getBidiEdge() != nullptr);
1138  case GNE_ATTR_STOPOFFSET:
1143  } else {
1144  return "";
1145  }
1148  case GNE_ATTR_SELECTED:
1150  case GNE_ATTR_PARAMETERS:
1151  return myNBEdge->getParametersStr();
1152  default:
1153  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1154  }
1155 }
1156 
1157 
1158 std::string
1160  std::string result = getAttribute(key);
1161  if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
1162  result += " " + getVehicleClassNames(SVCAll, true);
1163  }
1164  return result;
1165 }
1166 
1167 
1168 void
1169 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1170  // get template editor
1172  // check if we have to update template
1173  const bool updateTemplate = templateEditor->getEdgeTemplate() ? (templateEditor->getEdgeTemplate()->getID() == getID()) : false;
1174  switch (key) {
1175  case SUMO_ATTR_WIDTH:
1176  case SUMO_ATTR_ENDOFFSET:
1177  case SUMO_ATTR_SPEED:
1178  case SUMO_ATTR_FRICTION:
1179  case SUMO_ATTR_ALLOW:
1180  case SUMO_ATTR_DISALLOW: {
1181  undoList->begin(this, "change " + getTagStr() + " attribute");
1182  const std::string origValue = myLanes.at(0)->getAttribute(key); // will have intermediate value of "lane specific"
1183  // lane specific attributes need to be changed via lanes to allow undo
1184  for (auto it : myLanes) {
1185  it->setAttribute(key, value, undoList);
1186  }
1187  // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
1188  GNEChange_Attribute::changeAttribute(this, key, value, origValue, undoList);
1189  undoList->end();
1190  break;
1191  }
1192  case SUMO_ATTR_FROM: {
1193  if (value != getAttribute(key)) {
1194  undoList->begin(this, "change " + getTagStr() + " attribute");
1195  // Remove edge from crossings of junction source
1197  // continue changing from junction
1198  GNEJunction* originalFirstParentJunction = getFromJunction();
1199  getFromJunction()->setLogicValid(false, undoList);
1200  GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1201  getFromJunction()->setLogicValid(false, undoList);
1202  myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1203  setAttribute(GNE_ATTR_SHAPE_START, toString(getFromJunction()->getNBNode()->getPosition()), undoList);
1205  undoList->end();
1206  // update geometries of all implicated junctions
1207  originalFirstParentJunction->updateGeometry();
1210  }
1211  break;
1212  }
1213  case SUMO_ATTR_TO: {
1214  if (value != getAttribute(key)) {
1215  undoList->begin(this, "change " + getTagStr() + " attribute");
1216  // Remove edge from crossings of junction destination
1218  // continue changing destination junction
1219  GNEJunction* originalSecondParentJunction = getToJunction();
1220  getToJunction()->setLogicValid(false, undoList);
1221  GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1222  getToJunction()->setLogicValid(false, undoList);
1223  myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1224  setAttribute(GNE_ATTR_SHAPE_END, toString(getToJunction()->getNBNode()->getPosition()), undoList);
1226  undoList->end();
1227  // update geometries of all implicated junctions
1228  originalSecondParentJunction->updateGeometry();
1231  }
1232  break;
1233  }
1234  case SUMO_ATTR_ID:
1235  case SUMO_ATTR_PRIORITY:
1236  case SUMO_ATTR_LENGTH:
1237  case SUMO_ATTR_TYPE:
1238  case SUMO_ATTR_SPREADTYPE:
1239  case SUMO_ATTR_DISTANCE:
1241  case GNE_ATTR_SELECTED:
1242  case GNE_ATTR_STOPOFFSET:
1244  case GNE_ATTR_PARAMETERS:
1245  GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1246  break;
1247  case GNE_ATTR_SHAPE_START:
1248  case GNE_ATTR_SHAPE_END: {
1249  // due to ENDPOINT_TOLERANCE, force change
1250  GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1251  break;
1252  }
1253  case SUMO_ATTR_NAME:
1254  // user cares about street names. Make sure they appear in the output
1256  OptionsCont::getOptions().set("output.street-names", "true");
1257  GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1258  break;
1259  case SUMO_ATTR_NUMLANES:
1260  if (value != getAttribute(key)) {
1261  // set num lanes
1262  setNumLanes(parse<int>(value), undoList);
1263  }
1264  break;
1265  case GNE_ATTR_BIDIR:
1266  undoList->begin(this, "change " + getTagStr() + " attribute");
1267  GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1268  if (myNBEdge->getTurnDestination(true) != nullptr) {
1270  GNEChange_Attribute::changeAttribute(bidi, key, value, undoList);
1271  if (myNBEdge->getGeometry() != bidi->getNBEdge()->getGeometry().reverse()
1272  && myNBEdge->getGeometry().size() == 2
1273  && bidi->getNBEdge()->getGeometry().size() == 2
1274  && myNBEdge->getBidiEdge() == nullptr) {
1275  // NBEdge::avoidOverlap was already active so we need to reset the
1276  // geometry to its default
1277  resetBothEndpoint(undoList);
1278  bidi->resetBothEndpoint(undoList);
1279  }
1280  }
1281  undoList->end();
1282  break;
1283  case SUMO_ATTR_SHAPE:
1284  // @note: assumes value of inner geometry!
1285  // actually the geometry is already updated (incrementally
1286  // during mouse movement). We set the restore point to the end
1287  // of the last change-set
1288  GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1289  break;
1290  default:
1291  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1292  }
1293  // update template
1294  if (updateTemplate) {
1295  templateEditor->setEdgeTemplate(this);
1296  }
1297 }
1298 
1299 
1300 bool
1301 GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
1302  switch (key) {
1303  case SUMO_ATTR_ID:
1304  return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveEdge(value, false) == nullptr);
1305  case SUMO_ATTR_FROM: {
1306  // check that is a valid ID and is different of ID of junction destination
1307  if (value == getFromJunction()->getID()) {
1308  return true;
1309  } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getToJunction()->getID())) {
1310  return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1311  } else {
1312  return false;
1313  }
1314  }
1315  case SUMO_ATTR_TO: {
1316  // check that is a valid ID and is different of ID of junction Source
1317  if (value == getToJunction()->getID()) {
1318  return true;
1319  } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getFromJunction()->getID())) {
1320  return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1321  } else {
1322  return false;
1323  }
1324  }
1325  case SUMO_ATTR_SPEED:
1326  return canParse<double>(value) && (parse<double>(value) > 0);
1327  case SUMO_ATTR_FRICTION:
1328  return canParse<double>(value) && (parse<double>(value) > 0);
1329  case SUMO_ATTR_NUMLANES:
1330  return canParse<int>(value) && (parse<double>(value) > 0);
1331  case SUMO_ATTR_PRIORITY:
1332  return canParse<int>(value);
1333  case SUMO_ATTR_LENGTH:
1334  if (value.empty()) {
1335  return true;
1336  } else {
1337  return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
1338  }
1339  case SUMO_ATTR_ALLOW:
1340  case SUMO_ATTR_DISALLOW:
1341  return canParseVehicleClasses(value);
1342  case SUMO_ATTR_TYPE:
1343  return true;
1344  case SUMO_ATTR_SHAPE:
1345  // empty shapes are allowed
1346  return canParse<PositionVector>(value);
1347  case SUMO_ATTR_SPREADTYPE:
1349  case SUMO_ATTR_NAME:
1350  return true;
1351  case SUMO_ATTR_WIDTH:
1352  if (value.empty() || (value == "default")) {
1353  return true;
1354  } else {
1355  return canParse<double>(value) && ((parse<double>(value) >= -1) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
1356  }
1357  case SUMO_ATTR_ENDOFFSET:
1358  return canParse<double>(value) && parse<double>(value) >= 0 && parse<double>(value) < myNBEdge->getLoadedLength();
1359  case SUMO_ATTR_DISTANCE:
1360  if (value.empty()) {
1361  return true;
1362  } else {
1363  return canParse<double>(value);
1364  }
1365  case GNE_ATTR_SHAPE_START: {
1366  if (value.empty()) {
1367  return true;
1368  } else if (canParse<Position>(value)) {
1369  Position shapeStart = parse<Position>(value);
1370  return (shapeStart != myNBEdge->getGeometry()[-1]);
1371  } else {
1372  return false;
1373  }
1374  }
1375  case GNE_ATTR_SHAPE_END: {
1376  if (value.empty()) {
1377  return true;
1378  } else if (canParse<Position>(value)) {
1379  Position shapeEnd = parse<Position>(value);
1380  return (shapeEnd != myNBEdge->getGeometry()[0]);
1381  } else {
1382  return false;
1383  }
1384  }
1385  case GNE_ATTR_BIDIR:
1386  return canParse<bool>(value) && (!parse<bool>(value) || myNBEdge->isBidiEdge(true));
1387  case GNE_ATTR_STOPOFFSET:
1388  return canParse<double>(value) && (parse<double>(value) >= 0);
1390  return canParseVehicleClasses(value);
1391  case GNE_ATTR_SELECTED:
1392  return canParse<bool>(value);
1393  case GNE_ATTR_PARAMETERS:
1394  return Parameterised::areParametersValid(value);
1395  default:
1396  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1397  }
1398 }
1399 
1400 
1401 bool
1403  switch (key) {
1404  case GNE_ATTR_BIDIR:
1405  return myNBEdge->isBidiEdge(true);
1407  return myNBEdge->myEdgeStopOffset.getOffset() > 0;
1409  return false;
1410  default:
1411  return true;
1412  }
1413 }
1414 
1415 
1416 bool
1418  switch (key) {
1419  case SUMO_ATTR_LENGTH:
1420  return !myNBEdge->hasLoadedLength();
1421  case SUMO_ATTR_WIDTH:
1422  if (myNBEdge->hasLaneSpecificWidth()) {
1423  return false;
1424  } else {
1426  }
1427  default:
1428  return false;
1429  }
1430 }
1431 
1432 
1433 const Parameterised::Map&
1435  return myNBEdge->getParametersMap();
1436 }
1437 
1438 
1439 void
1441  myAmResponsible = newVal;
1442 }
1443 
1444 
1445 GNELane*
1447  // iterate over all NBEdge lanes
1448  for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1449  // if given VClass is in permissions, return lane
1450  if (myNBEdge->getLanes().at(i).permissions & vClass) {
1451  // return GNELane
1452  return myLanes.at(i);
1453  }
1454  }
1455  // return first lane
1456  return myLanes.front();
1457 }
1458 
1459 
1460 GNELane*
1462  // iterate over all NBEdge lanes
1463  for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1464  // if given VClass isn't in permissions, return lane
1465  if (~(myNBEdge->getLanes().at(i).permissions) & vClass) {
1466  // return GNELane
1467  return myLanes.at(i);
1468  }
1469  }
1470  // return first lane
1471  return myLanes.front();
1472 }
1473 
1474 
1475 void
1477  // get lane vehicles map
1478  const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1479  // iterate over every lane
1480  for (const auto& laneVehicle : laneVehiclesMap) {
1481  // obtain total length
1482  double totalLength = 0;
1483  for (const auto& vehicle : laneVehicle.second) {
1484  totalLength += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1485  }
1486  // calculate multiplier for vehicle positions
1487  double multiplier = 1;
1488  const double laneShapeLength = laneVehicle.first->getLaneShape().length();
1489  if (laneShapeLength == 0) {
1490  multiplier = 0;
1491  } else if (totalLength > laneShapeLength) {
1492  multiplier = (laneShapeLength / totalLength);
1493  }
1494  // declare current length
1495  double length = 0;
1496  // iterate over vehicles to calculate position and rotations
1497  for (const auto& vehicle : laneVehicle.second) {
1498  vehicle->updateDemandElementSpreadGeometry(laneVehicle.first, length * multiplier);
1499  // update length
1500  length += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1501  }
1502  }
1503 }
1504 
1505 
1506 void
1508  // get lane vehicles map
1509  const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1510  // iterate over laneVehiclesMap and obtain a vector with
1511  for (const auto& vehicleMap : laneVehiclesMap) {
1512  // declare map for sort vehicles using their departpos+length position (StackPosition)
1513  std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosVehicles;
1514  // declare vector of stack demand elements
1515  std::vector<GNEEdge::StackDemandElements> stackedVehicles;
1516  // iterate over vehicles
1517  for (const auto& vehicle : vehicleMap.second) {
1518  // get vehicle's depart pos and length
1519  const double departPos = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1520  const double length = vehicle->getAttributeDouble(SUMO_ATTR_LENGTH);
1521  double posOverLane = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1522  // check if we have to adapt posOverLane
1523  if (posOverLane < 0) {
1524  posOverLane += vehicleMap.first->getLaneShape().length();
1525  }
1526  // make a stack position using departPos and length
1527  departPosVehicles.push_back(std::make_pair(StackPosition(departPos, length), vehicle));
1528  // update depart element geometry
1529  vehicle->updateDemandElementGeometry(vehicleMap.first, posOverLane);
1530  // reset vehicle stack label
1531  vehicle->updateDemandElementStackLabel(0);
1532  }
1533 
1534  // sort departPosVehicles
1535  std::sort(departPosVehicles.begin(), departPosVehicles.end());
1536  // iterate over departPosVehicles
1537  for (const auto& departPosVehicle : departPosVehicles) {
1538  // obtain stack position and vehicle
1539  const GNEEdge::StackPosition& vehicleStackPosition = departPosVehicle.first;
1540  GNEDemandElement* vehicle = departPosVehicle.second;
1541  // if stackedVehicles is empty, add a new StackDemandElements
1542  if (stackedVehicles.empty()) {
1543  stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1544  } else if (areStackPositionOverlapped(vehicleStackPosition, stackedVehicles.back().getStackPosition())) {
1545  // add new vehicle to last inserted stackDemandElements
1546  stackedVehicles[stackedVehicles.size() - 1].addDemandElements(vehicle);
1547  } else {
1548  // No overlapping, then add a new StackDemandElements
1549  stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1550  }
1551  }
1552  // iterate over stackedVehicles
1553  for (const auto& vehicle : stackedVehicles) {
1554  // only update vehicles with one or more stack
1555  if (vehicle.getDemandElements().size() > 1) {
1556  // set stack labels
1557  vehicle.getDemandElements().front()->updateDemandElementStackLabel((int)vehicle.getDemandElements().size());
1558  }
1559  }
1560  }
1561 }
1562 
1563 
1564 void
1566  // get lane persons map
1567  const std::map<const GNELane*, std::vector<GNEDemandElement*> > lanePersonsMap = getPersonsOverEdgeMap();
1568  // iterate over lanePersonsMap and obtain a vector with
1569  for (const auto& personMap : lanePersonsMap) {
1570  // declare map for sort persons using their departpos+length position (StackPosition)
1571  std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosPersons;
1572  // declare vector of stack demand elements
1573  std::vector<GNEEdge::StackDemandElements> stackedPersons;
1574  // iterate over persons
1575  for (const auto& person : personMap.second) {
1576  // get person's depart pos and length
1577  const double departPos = person->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1578  // make a stack position using departPos and length
1579  departPosPersons.push_back(std::make_pair(StackPosition(departPos, 1.8), person));
1580  // update depart element geometry
1581  person->updateDemandElementGeometry(personMap.first, departPos);
1582  // reset person stack label
1583  person->updateDemandElementStackLabel(0);
1584  }
1585 
1586  // sort departPosPersons
1587  std::sort(departPosPersons.begin(), departPosPersons.end());
1588  // iterate over departPosPersons
1589  for (const auto& departPosPerson : departPosPersons) {
1590  // obtain stack position and person
1591  const GNEEdge::StackPosition& personStackPosition = departPosPerson.first;
1592  GNEDemandElement* person = departPosPerson.second;
1593  // if stackedPersons is empty, add a new StackDemandElements
1594  if (stackedPersons.empty()) {
1595  stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1596  } else if (areStackPositionOverlapped(personStackPosition, stackedPersons.back().getStackPosition())) {
1597  // add new person to last inserted stackDemandElements
1598  stackedPersons[stackedPersons.size() - 1].addDemandElements(person);
1599  } else {
1600  // No overlapping, then add a new StackDemandElements
1601  stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1602  }
1603  }
1604  // iterate over stackedPersons
1605  for (const auto& person : stackedPersons) {
1606  // only update persons with one or more stack
1607  if (person.getDemandElements().size() > 1) {
1608  // set stack labels
1609  person.getDemandElements().front()->updateDemandElementStackLabel((int)person.getDemandElements().size());
1610  }
1611  }
1612  }
1613 }
1614 
1615 
1616 void
1618  // get lane containers map
1619  const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneContainersMap = getContainersOverEdgeMap();
1620  // iterate over laneContainersMap and obtain a vector with
1621  for (const auto& containerMap : laneContainersMap) {
1622  // declare map for sort containers using their departpos+length position (StackPosition)
1623  std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosContainers;
1624  // declare vector of stack demand elements
1625  std::vector<GNEEdge::StackDemandElements> stackedContainers;
1626  // iterate over containers
1627  for (const auto& container : containerMap.second) {
1628  // get container's depart pos and length
1629  const double departPos = container->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1630  // make a stack position using departPos and length
1631  departPosContainers.push_back(std::make_pair(StackPosition(departPos, 1.8), container));
1632  // update depart element geometry
1633  container->updateDemandElementGeometry(containerMap.first, departPos);
1634  // reset container stack label
1635  container->updateDemandElementStackLabel(0);
1636  }
1637 
1638  // sort departPosContainers
1639  std::sort(departPosContainers.begin(), departPosContainers.end());
1640  // iterate over departPosContainers
1641  for (const auto& departPosContainer : departPosContainers) {
1642  // obtain stack position and container
1643  const GNEEdge::StackPosition& containerStackPosition = departPosContainer.first;
1644  GNEDemandElement* container = departPosContainer.second;
1645  // if stackedContainers is empty, add a new StackDemandElements
1646  if (stackedContainers.empty()) {
1647  stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1648  } else if (areStackPositionOverlapped(containerStackPosition, stackedContainers.back().getStackPosition())) {
1649  // add new container to last inserted stackDemandElements
1650  stackedContainers[stackedContainers.size() - 1].addDemandElements(container);
1651  } else {
1652  // No overlapping, then add a new StackDemandElements
1653  stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1654  }
1655  }
1656  // iterate over stackedContainers
1657  for (const auto& container : stackedContainers) {
1658  // only update containers with one or more stack
1659  if (container.getDemandElements().size() > 1) {
1660  // set stack labels
1661  container.getDemandElements().front()->updateDemandElementStackLabel((int)container.getDemandElements().size());
1662  }
1663  }
1664  }
1665 }
1666 
1667 
1668 bool
1670  // calculate angle between both junction positions
1671  double edgeAngle = RAD2DEG(getFromJunction()->getPositionInView().angleTo2D(getToJunction()->getPositionInView()));
1672  // adjust to 360 degrees
1673  while (edgeAngle < 0) {
1674  edgeAngle += 360;
1675  }
1676  // fmod round towards zero which is not want we want for negative numbers
1677  edgeAngle = fmod(edgeAngle, 360);
1678  // check angle
1679  return edgeAngle >= 0 && edgeAngle < 180;
1680 }
1681 
1682 
1683 bool
1685  // get incoming edges
1686  const auto incomingEdges = getFromJunction()->getGNEIncomingEdges();
1687  // iterate over connections
1688  for (const auto& incomingEdge : incomingEdges) {
1689  for (const auto& connection : incomingEdge->getGNEConnections()) {
1690  if (connection->getEdgeTo() == this) {
1691  return true;
1692  }
1693  }
1694  }
1695  return false;
1696 }
1697 
1698 
1699 bool
1701  return (myGNEConnections.size() > 0);
1702 }
1703 
1704 
1705 GNEEdge*
1707  for (const auto& outgoingEdge : getParentJunctions().back()->getGNEOutgoingEdges()) {
1708  if (outgoingEdge->getToJunction() == getFromJunction()) {
1709  return outgoingEdge;
1710  }
1711  }
1712  return nullptr;
1713 }
1714 
1715 // ===========================================================================
1716 // private
1717 // ===========================================================================
1718 
1719 GNEEdge::StackPosition::StackPosition(const double departPos, const double length) :
1720  pair(departPos, departPos + length) {
1721 }
1722 
1723 
1724 double
1726  return first;
1727 }
1728 
1729 
1730 double
1732  return second;
1733 }
1734 
1735 
1737  pair(stackedPosition, {
1738  demandElement
1739 }) {
1740 }
1741 
1742 
1743 void
1745  second.push_back(demandElement);
1746 }
1747 
1748 
1751  return first;
1752 }
1753 
1754 
1755 const std::vector<GNEDemandElement*>&
1757  return second;
1758 }
1759 
1760 
1761 void
1762 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
1763  switch (key) {
1764  case SUMO_ATTR_ID:
1765  myNet->getAttributeCarriers()->updateEdgeID(this, value);
1766  // enable save demand elements if there are stops
1767  for (const auto& stop : getChildDemandElements()) {
1768  if (stop->getTagProperty().isVehicleStop()) {
1770  }
1771  }
1772  // also for lanes
1773  for (const auto& lane : myLanes) {
1774  for (const auto& stop : lane->getChildDemandElements()) {
1775  if (stop->getTagProperty().isVehicleStop()) {
1777  }
1778  }
1779  }
1780  break;
1781  case SUMO_ATTR_FROM:
1782  myNet->changeEdgeEndpoints(this, value, getToJunction()->getID());
1783  // update this edge of list of outgoings edges of the old first parent junction
1785  // update first parent junction
1787  // update this edge of list of outgoings edges of the new first parent junction
1789  // update centering boundary and grid
1791  break;
1792  case SUMO_ATTR_TO:
1793  myNet->changeEdgeEndpoints(this, getFromJunction()->getID(), value);
1794  // update this edge of list of incomings edges of the old second parent junction
1796  // update second parent junction
1798  // update this edge of list of incomings edges of the new second parent junction
1800  // update centering boundary and grid
1802  break;
1803  case SUMO_ATTR_NUMLANES:
1804  throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
1805  case SUMO_ATTR_PRIORITY:
1806  myNBEdge->myPriority = parse<int>(value);
1807  break;
1808  case SUMO_ATTR_LENGTH:
1809  if (value.empty()) {
1811  } else {
1812  myNBEdge->setLoadedLength(parse<double>(value));
1813  }
1814  break;
1815  case SUMO_ATTR_TYPE:
1816  myNBEdge->myType = value;
1817  break;
1818  case SUMO_ATTR_SHAPE:
1819  // set new geometry
1820  setGeometry(parse<PositionVector>(value), true);
1821  // update centering boundary and grid
1823  break;
1824  case SUMO_ATTR_SPREADTYPE:
1826  break;
1827  case SUMO_ATTR_NAME:
1828  myNBEdge->setStreetName(value);
1829  break;
1830  case SUMO_ATTR_SPEED:
1831  myNBEdge->setSpeed(-1, parse<double>(value));
1832  break;
1833  case SUMO_ATTR_FRICTION:
1834  myNBEdge->setFriction(-1, parse<double>(value));
1835  break;
1836  case SUMO_ATTR_WIDTH:
1837  if (value.empty() || (value == "default")) {
1839  } else {
1840  myNBEdge->setLaneWidth(-1, parse<double>(value));
1841  }
1842  break;
1843  case SUMO_ATTR_ENDOFFSET:
1844  myNBEdge->setEndOffset(-1, parse<double>(value));
1845  break;
1846  case SUMO_ATTR_ALLOW:
1847  break; // no edge value
1848  case SUMO_ATTR_DISALLOW:
1849  break; // no edge value
1850  case SUMO_ATTR_DISTANCE:
1851  if (value.empty()) {
1852  myNBEdge->setDistance(0.0);
1853  } else {
1854  myNBEdge->setDistance(parse<double>(value));
1855  }
1856  break;
1858  myConnectionStatus = value;
1859  if (value == FEATURE_GUESSED) {
1860  WRITE_DEBUG("invalidating (removing) connections of edge '" + getID() + "' due it were guessed");
1863  } else if (value != FEATURE_GUESSED) {
1864  WRITE_DEBUG("declaring connections of edge '" + getID() + "' as loaded (It will not be removed)");
1866  }
1867  break;
1868  case GNE_ATTR_SHAPE_START: {
1869  // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1870  Position newShapeStart;
1871  if (value == "") {
1872  newShapeStart = getFromJunction()->getNBNode()->getPosition();
1873  } else {
1874  newShapeStart = parse<Position>(value);
1875  }
1876  // set shape start position
1877  setShapeStartPos(newShapeStart);
1878  // update centering boundary and grid
1880  break;
1881  }
1882  case GNE_ATTR_SHAPE_END: {
1883  // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destination position) and set it back to edge
1884  Position newShapeEnd;
1885  if (value == "") {
1886  newShapeEnd = getToJunction()->getNBNode()->getPosition();
1887  } else {
1888  newShapeEnd = parse<Position>(value);
1889  }
1890  // set shape end position
1891  setShapeEndPos(newShapeEnd);
1892  // update centering boundary and grid
1894  break;
1895  }
1896  case GNE_ATTR_BIDIR:
1897  myNBEdge->setBidi(parse<bool>(value));
1898  break;
1899  case GNE_ATTR_SELECTED:
1900  if (parse<bool>(value)) {
1902  } else {
1904  }
1905  break;
1906  case GNE_ATTR_STOPOFFSET:
1907  myNBEdge->myEdgeStopOffset.setOffset(parse<double>(value));
1908  break;
1910  if (value.empty()) {
1912  } else {
1914  }
1915  break;
1916  case GNE_ATTR_PARAMETERS:
1917  myNBEdge->setParametersStr(value);
1918  break;
1919  default:
1920  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1921  }
1922  // get template editor
1924  // check if update template (except for modification status)
1925  if (templateEditor->getEdgeTemplate() && (templateEditor->getEdgeTemplate()->getID() == getID()) &&
1926  (key != GNE_ATTR_MODIFICATION_STATUS)) {
1928  }
1929  // invalidate path calculator
1931 }
1932 
1933 
1934 void
1936  // get start and end points
1937  const Position shapeStart = moveResult.shapeToUpdate.front();
1938  const Position shapeEnd = moveResult.shapeToUpdate.back();
1939  // get innen shape
1940  PositionVector innenShape = moveResult.shapeToUpdate;
1941  innenShape.pop_front();
1942  innenShape.pop_back();
1943  // set shape start
1944  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
1945  setShapeStartPos(shapeStart);
1946  }
1947  // set innen geometry
1948  setGeometry(innenShape, true);
1949  // set shape end
1950  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), ((int)moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
1951  setShapeEndPos(shapeEnd);
1952  }
1953 }
1954 
1955 
1956 void
1957 GNEEdge::commitMoveShape(const GNEMoveResult& moveResult, GNEUndoList* undoList) {
1958  // make sure that newShape isn't empty
1959  if (moveResult.shapeToUpdate.size() > 0) {
1960  // get innen shape
1961  PositionVector innenShapeToUpdate = moveResult.shapeToUpdate;
1962  innenShapeToUpdate.pop_front();
1963  innenShapeToUpdate.pop_back();
1964  // commit new shape
1965  undoList->begin(this, "moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
1966  // update start position
1967  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
1969  }
1970  // check if update shape
1971  if (innenShapeToUpdate.size() > 0) {
1972  GNEChange_Attribute::changeAttribute(this, SUMO_ATTR_SHAPE, toString(innenShapeToUpdate), undoList);
1973  }
1974  // update end position
1975  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), ((int)moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
1977  }
1978  undoList->end();
1979  }
1980 }
1981 
1982 
1983 void
1984 GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
1985  // begin undo list
1986  undoList->begin(this, "change number of " + toString(SUMO_TAG_LANE) + "s");
1987  // invalidate logic of source/destination edges
1988  getFromJunction()->setLogicValid(false, undoList);
1989  getToJunction()->setLogicValid(false, undoList);
1990  // disable update geometry (see #6336)
1991  myUpdateGeometry = false;
1992  // remove edge from grid
1994  // save old number of lanes
1995  const int oldNumLanes = (int)myLanes.size();
1996  // get opposite ID
1997  const auto oppositeID = myLanes.back()->getAttribute(GNE_ATTR_OPPOSITE);
1998  if (oppositeID != "") {
1999  // we'll have a different leftmost lane after adding/removing lanes
2001  }
2002  for (int i = oldNumLanes; i < numLanes; i++) {
2003  // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
2004  undoList->add(new GNEChange_Lane(this, myNBEdge->getLaneStruct(oldNumLanes - 1)), true);
2005  }
2006  for (int i = (oldNumLanes - 1); i > (numLanes - 1); i--) {
2007  // delete leftmost lane
2008  undoList->add(new GNEChange_Lane(this, myLanes[i], myNBEdge->getLaneStruct(i), false), true);
2009  }
2010  if (oppositeID != "") {
2011  GNEChange_Attribute::changeAttribute(myLanes.back(), GNE_ATTR_OPPOSITE, oppositeID, undoList);
2012  }
2013  // enable updateGeometry again
2014  myUpdateGeometry = true;
2015  // update geometry of entire edge
2016  updateGeometry();
2017  // end undo list
2018  undoList->end();
2019  // update centering boundary (without updating RTREE)
2020  updateCenteringBoundary(false);
2021  // insert edge in grid again
2022  myNet->addGLObjectIntoGrid(this);
2023 }
2024 
2025 
2026 void
2027 GNEEdge::updateFirstParentJunction(const std::string& value) {
2028  std::vector<GNEJunction*> parentJunctions = getParentJunctions();
2029  parentJunctions[0] = myNet->getAttributeCarriers()->retrieveJunction(value);
2030  // replace parent junctions
2031  replaceParentElements(this, parentJunctions);
2032 }
2033 
2034 
2035 void
2036 GNEEdge::updateSecondParentJunction(const std::string& value) {
2037  std::vector<GNEJunction*> parentJunctions = getParentJunctions();
2038  parentJunctions[1] = myNet->getAttributeCarriers()->retrieveJunction(value);
2039  // replace parent junctions
2040  replaceParentElements(this, parentJunctions);
2041 }
2042 
2043 
2044 void
2045 GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections) {
2046  const int index = lane ? lane->getIndex() : myNBEdge->getNumLanes();
2047  // the laneStruct must be created first to ensure we have some geometry
2048  // unless the connections are fully recomputed, existing indices must be shifted
2049  myNBEdge->addLane(index, true, recomputeConnections, !recomputeConnections);
2050  if (lane) {
2051  // restore a previously deleted lane
2052  myLanes.insert(myLanes.begin() + index, lane);
2053  } else {
2054  // create a new lane by copying leftmost lane
2055  lane = new GNELane(this, index);
2056  myLanes.push_back(lane);
2057  }
2058  lane->incRef("GNEEdge::addLane");
2059  // add in attributeCarriers
2061  // check if lane is selected
2062  if (lane->isAttributeCarrierSelected()) {
2063  lane->selectAttributeCarrier();
2064  }
2065  // we copy all attributes except shape since this is recomputed from edge shape
2066  myNBEdge->setSpeed(lane->getIndex(), laneAttrs.speed);
2067  myNBEdge->setFriction(lane->getIndex(), laneAttrs.friction);
2068  myNBEdge->setPermissions(laneAttrs.permissions, lane->getIndex());
2069  myNBEdge->setPreferredVehicleClass(laneAttrs.preferred, lane->getIndex());
2070  myNBEdge->setEndOffset(lane->getIndex(), laneAttrs.endOffset);
2071  myNBEdge->setLaneWidth(lane->getIndex(), laneAttrs.width);
2072  // update indices
2073  for (int i = 0; i < (int)myLanes.size(); ++i) {
2074  myLanes[i]->setIndex(i);
2075  }
2076  /* while technically correct, this looks ugly
2077  getFromJunction()->invalidateShape();
2078  getToJunction()->invalidateShape();
2079  */
2080  // Remake connections for this edge and all edges that target this lane
2082  // remake connections of all edges of junction source and destination
2083  for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2084  fromEdge->remakeGNEConnections();
2085  }
2086  // remake connections of all edges of junction source and destination
2087  for (const auto& toEdge : getToJunction()->getChildEdges()) {
2088  toEdge->remakeGNEConnections();
2089  }
2090  // Update geometry with the new lane
2091  updateGeometry();
2092  // update boundary and grid
2094 }
2095 
2096 
2097 void
2098 GNEEdge::removeLane(GNELane* lane, bool recomputeConnections) {
2099  if (myLanes.size() == 0) {
2100  throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + getTagStr());
2101  }
2102  if (lane == nullptr) {
2103  lane = myLanes.back();
2104  }
2105  // check if lane is selected
2106  if (lane->isAttributeCarrierSelected()) {
2107  lane->unselectAttributeCarrier();
2108  }
2109  // before removing, check that lane isn't being inspected
2112  // Delete lane of edge's container
2113  // unless the connections are fully recomputed, existing indices must be shifted
2114  myNBEdge->deleteLane(lane->getIndex(), recomputeConnections, !recomputeConnections);
2115  lane->decRef("GNEEdge::removeLane");
2116  myLanes.erase(myLanes.begin() + lane->getIndex());
2117  // remove from attributeCarriers
2119  // Delete lane if is unreferenced
2120  if (lane->unreferenced()) {
2121  // show extra information for tests
2122  WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in removeLane()");
2123  delete lane;
2124  }
2125  // update indices
2126  for (int i = 0; i < (int)myLanes.size(); ++i) {
2127  myLanes[i]->setIndex(i);
2128  }
2129  /* while technically correct, this looks ugly
2130  getFromJunction()->invalidateShape();
2131  getToJunction()->invalidateShape();
2132  */
2133  // Remake connections of this edge
2135  // remake connections of all edges of junction source and destination
2136  for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2137  fromEdge->remakeGNEConnections();
2138  }
2139  // remake connections of all edges of junction source and destination
2140  for (const auto& toEdge : getToJunction()->getChildEdges()) {
2141  toEdge->remakeGNEConnections();
2142  }
2143  // Update element
2144  updateGeometry();
2145  // update boundary and grid
2147 }
2148 
2149 
2150 void
2151 GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
2152  // If a new connection was successfully created
2154  nbCon.keepClear, nbCon.contPos, nbCon.visibility,
2155  nbCon.speed, nbCon.friction, nbCon.customLength, nbCon.customShape, nbCon.uncontrolled)) {
2156  // Create or retrieve existent GNEConnection
2157  GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
2158  // add it to GNEConnection container
2159  myGNEConnections.push_back(con);
2160  // Add reference
2161  myGNEConnections.back()->incRef("GNEEdge::addConnection");
2162  // select GNEConnection if needed
2163  if (selectAfterCreation) {
2164  con->selectAttributeCarrier();
2165  }
2166  // update geometry
2167  con->updateGeometry();
2168  }
2169  // actually we only do this to force a redraw
2170  updateGeometry();
2171 }
2172 
2173 
2174 void
2176  // check if is a explicit turnaround
2177  if (nbCon.toEdge == myNBEdge->getTurnDestination()) {
2179  }
2180  // remove NBEdge::connection from NBEdge
2182  // remove their associated GNEConnection
2183  GNEConnection* connection = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
2184  if (connection != nullptr) {
2185  connection->decRef("GNEEdge::removeConnection");
2186  myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), connection));
2187  // check if connection is selected
2188  if (connection->isAttributeCarrierSelected()) {
2189  connection->unselectAttributeCarrier();
2190  }
2191  // remove it from network
2192  myNet->removeGLObjectFromGrid(connection);
2193  // check if remove it from Attribute Carriers
2194  if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
2196  }
2197  if (connection->unreferenced()) {
2198  // show extra information for tests
2199  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in removeConnection()");
2200  // actually we only do this to force a redraw
2201  updateGeometry();
2202  }
2203  }
2204 }
2205 
2206 
2208 GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
2209  for (const auto& connection : myGNEConnections) {
2210  if ((connection->getFromLaneIndex() == fromLane) && (connection->getEdgeTo()->getNBEdge() == to) && (connection->getToLaneIndex() == toLane)) {
2211  return connection;
2212  }
2213  }
2214  if (createIfNoExist) {
2215  // create new connection. Will be added to the rTree on first geometry computation
2216  GNEConnection* connection = new GNEConnection(myLanes[fromLane], myNet->getAttributeCarriers()->retrieveEdge(to->getID())->getLanes()[toLane]);
2217  // show extra information for tests
2218  WRITE_DEBUG("Created " + connection->getTagStr() + " '" + connection->getID() + "' in retrieveGNEConnection()");
2219  // add it into network
2220  myNet->addGLObjectIntoGrid(connection);
2221  // add it in attributeCarriers
2223  return connection;
2224  } else {
2225  return nullptr;
2226  }
2227 }
2228 
2229 
2230 void
2231 GNEEdge::setEdgeID(const std::string& newID) {
2232  setNetworkElementID(newID);
2233  for (const auto& lane : myLanes) {
2234  lane->setNetworkElementID(getNBEdge()->getLaneID(lane->getIndex()));
2235  }
2236 }
2237 
2238 
2239 bool
2241  for (const auto& lane : myLanes) {
2242  if (lane->isRestricted(vclass)) {
2243  return true;
2244  }
2245  }
2246  return false;
2247 }
2248 
2249 
2250 void
2252  // Remove all crossings that contain this edge in parameter "edges"
2253  for (const auto& crossing : junction->getGNECrossings()) {
2254  if (crossing->checkEdgeBelong(this)) {
2255  myNet->deleteCrossing(crossing, undoList);
2256  }
2257  }
2258 }
2259 
2260 
2261 void
2263  PositionVector modifiedShape = myNBEdge->getGeometry().interpolateZ(
2265  myNBEdge->getToNode()->getPosition().z());
2266  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2267  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2268 }
2269 
2270 
2272 GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
2273  const auto& neteditOptions = OptionsCont::getOptions();
2274  // distinguish 3 cases:
2275  // a) if the edge has exactly 3 or 4 points, use these as control points
2276  // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
2277  // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
2278  PositionVector init;
2279 #ifdef DEBUG_SMOOTH_GEOM
2280  if (DEBUGCOND(this)) std::cout << getID()
2281  << " forElevation=" << forElevation
2282  << " fromGeometryLike=" << myNBEdge->getFromNode()->geometryLike()
2283  << " toGeometryLike=" << myNBEdge->getToNode()->geometryLike()
2284  << " smoothShape old=" << old << "\n";
2285 #endif
2286  if (old.size() == 3 || old.size() == 4) {
2287  init = old;
2288  } else if (old.size() > 4 && !forElevation) {
2289  // for elevation, the initial segments are not useful
2290  init.push_back(old[0]);
2291  init.push_back(old[1]);
2292  init.push_back(old[-2]);
2293  init.push_back(old[-1]);
2294  } else if (myNBEdge->getFromNode()->geometryLike() && myNBEdge->getToNode()->geometryLike()) {
2295  PositionVector begShape;
2296  PositionVector endShape;
2297  const EdgeVector& incoming = myNBEdge->getFromNode()->getIncomingEdges();
2298  const EdgeVector& outgoing = myNBEdge->getToNode()->getOutgoingEdges();
2299  if (incoming.size() == 1) {
2300  begShape = incoming[0]->getGeometry();
2301  } else {
2302  assert(incoming.size() == 2);
2303  begShape = myNBEdge->isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
2304  }
2305  if (outgoing.size() == 1) {
2306  endShape = outgoing[0]->getGeometry();
2307  } else {
2308  assert(outgoing.size() == 2);
2309  endShape = myNBEdge->isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
2310  }
2311  const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
2312  if (forElevation) {
2313  // initialize control point elevation for smooth continuation
2314  init.push_back(old[0]);
2315  init.push_back(old.positionAtOffset2D(dist));
2316  init.push_back(old.positionAtOffset2D(old.length2D() - dist));
2317  init.push_back(old[-1]);
2318  double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
2319  double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
2320  // continue incline
2321  init[1].setz(2 * init[0].z() - begZ);
2322  init[2].setz(2 * init[-1].z() - endZ);
2323  } else {
2324  bool ok = true;
2325  const double straightThresh = DEG2RAD(neteditOptions.getFloat("opendrive-output.straight-threshold"));
2326  init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, nullptr, straightThresh);
2327  }
2328 #ifdef DEBUG_SMOOTH_GEOM
2329  if (DEBUGCOND(this)) {
2330  std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
2331  }
2332 #endif
2333  }
2334  if (init.size() == 0) {
2335  return PositionVector::EMPTY;
2336  } else {
2337  const int numPoints = MAX2(neteditOptions.getInt("junctions.internal-link-detail"),
2338  int(old.length2D() / neteditOptions.getFloat("opendrive.curve-resolution")));
2339  return init.bezier(numPoints);
2340  }
2341 }
2342 
2343 
2344 void
2346  PositionVector modifiedShape = smoothShape(myNBEdge->getGeometry(), false);
2347  if (modifiedShape.size() < 2) {
2348  WRITE_WARNINGF(TL("Could not compute smooth shape for edge '%'"), getID());
2349  } else {
2350  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2351  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2352  }
2353 }
2354 
2355 
2356 void
2358  PositionVector elevationBase;
2359  for (const Position& pos : myNBEdge->getGeometry()) {
2360  if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
2361  elevationBase.push_back(pos);
2362  }
2363  }
2364  PositionVector elevation = smoothShape(elevationBase, true);
2365  if (elevation.size() <= 2) {
2366  WRITE_WARNINGF(TL("Could not compute smooth elevation for edge '%'"), getID());
2367  } else {
2368  PositionVector modifiedShape = myNBEdge->getGeometry();
2369  if (modifiedShape.size() < 5) {
2370  modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"), false);
2371  }
2372  const double scale = elevation.length2D() / modifiedShape.length2D();
2373  //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
2374  double seen = 0;
2375  for (int i = 1; i < (int)modifiedShape.size(); ++i) {
2376  seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
2377  modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
2378  }
2379  //std::cout << " mod2=" << modifiedShape << "\n";
2380  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2381  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2382  }
2383 }
2384 
2385 
2386 void
2388  // remove start position and add it the new position
2390  geom.pop_front();
2391  geom.push_front(pos);
2392  // restore modified shape
2393  setGeometry(geom, false);
2394 }
2395 
2396 
2397 void
2399  // remove end position and add it the new position
2401  geom.pop_back();
2402  geom.push_back(pos);
2403  // restore modified shape
2404  setGeometry(geom, false);
2405 }
2406 
2407 
2408 const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2410  // declare vehicles over edge vector
2411  std::vector<GNEDemandElement*> vehiclesOverEdge;
2412  // declare solution map
2413  std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesOverEdgeMap;
2414  // declare a set of vehicles (to avoid duplicates)
2415  std::set<std::pair<double, GNEDemandElement*> > vehicles;
2416  // first obtain all vehicles of this edge
2417  for (const auto& edgeChild : getChildDemandElements()) {
2418  if (((edgeChild->getTagProperty().getTag() == SUMO_TAG_TRIP) || (edgeChild->getTagProperty().getTag() == SUMO_TAG_FLOW)) &&
2419  (edgeChild->getParentEdges().front() == this)) {
2420  vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2421  vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2422  } else if ((edgeChild->getTagProperty().getTag() == SUMO_TAG_ROUTE) && (edgeChild->getParentEdges().front() == this)) {
2423  for (const auto& routeChild : edgeChild->getChildDemandElements()) {
2424  if (routeChild->getTagProperty().vehicleRoute()) {
2425  vehicles.insert(std::make_pair(routeChild->getAttributeDouble(SUMO_ATTR_DEPART), routeChild));
2426  }
2427  }
2428  } else if ((edgeChild->getTagProperty().getTag() == GNE_TAG_ROUTE_EMBEDDED) && (edgeChild->getParentEdges().front() == this)) {
2429  vehicles.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild->getParentDemandElements().front()));
2430  }
2431  }
2432  // reserve
2433  vehiclesOverEdge.reserve(vehicles.size());
2434  // iterate over vehicles
2435  for (const auto& vehicle : vehicles) {
2436  // add it over vehiclesOverEdge;
2437  vehiclesOverEdge.push_back(vehicle.second);
2438  }
2439  // now split vehicles by lanes
2440  for (const auto& vehicle : vehiclesOverEdge) {
2441  const GNELane* vehicleLane = vehicle->getFirstPathLane();
2442  if (vehicleLane) {
2443  vehiclesOverEdgeMap[vehicleLane].push_back(vehicle);
2444  }
2445  }
2446  return vehiclesOverEdgeMap;
2447 }
2448 
2449 
2450 const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2452  // declare persons over edge vector
2453  std::vector<GNEDemandElement*> personsOverEdge;
2454  // declare solution map
2455  std::map<const GNELane*, std::vector<GNEDemandElement*> > personsOverEdgeMap;
2456  // declare a set of persons (to avoid duplicates)
2457  std::set<std::pair<double, GNEDemandElement*> > persons;
2458  // first obtain all persons of this edge
2459  for (const auto& edgeChild : getChildDemandElements()) {
2460  if (edgeChild->getTagProperty().isPlanPerson()) {
2461  persons.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2462  }
2463  }
2464  // reserve
2465  personsOverEdge.reserve(persons.size());
2466  // iterate over persons
2467  for (const auto& person : persons) {
2468  // add it over personsOverEdge;
2469  personsOverEdge.push_back(person.second);
2470  }
2471  // now split persons by lanes
2472  for (const auto& person : personsOverEdge) {
2473  const GNELane* personLane = person->getFirstPathLane();
2474  if (personLane) {
2475  personsOverEdgeMap[personLane].push_back(person);
2476  }
2477  }
2478  return personsOverEdgeMap;
2479 }
2480 
2481 
2482 
2483 const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2485  // declare containers over edge vector
2486  std::vector<GNEDemandElement*> containersOverEdge;
2487  // declare solution map
2488  std::map<const GNELane*, std::vector<GNEDemandElement*> > containersOverEdgeMap;
2489  // declare a set of containers (to avoid duplicates)
2490  std::set<std::pair<double, GNEDemandElement*> > containers;
2491  // first obtain all containers of this edge
2492  for (const auto& edgeChild : getChildDemandElements()) {
2493  if (edgeChild->getTagProperty().isPlanContainer()) {
2494  containers.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2495  }
2496  }
2497  // reserve
2498  containersOverEdge.reserve(containers.size());
2499  // iterate over containers
2500  for (const auto& container : containers) {
2501  // add it over containersOverEdge;
2502  containersOverEdge.push_back(container.second);
2503  }
2504  // now split containers by lanes
2505  for (const auto& container : containersOverEdge) {
2506  const GNELane* containerLane = container->getFirstPathLane();
2507  if (containerLane) {
2508  containersOverEdgeMap[containerLane].push_back(container);
2509  }
2510  }
2511  return containersOverEdgeMap;
2512 }
2513 
2514 
2515 void
2517  // first check conditions
2519  // check if draw geometry points
2520  const bool bigGeometryPoints = drawBigGeometryPoints();
2521  // Obtain exaggeration of the draw
2522  const double exaggeration = getExaggeration(s);
2523  // get geometry point radius
2524  const double geometryPointRadius = getGeometryPointRadius();
2525  // obtain geometry point color
2526  RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2527  if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2528  // override with special colors (unless the color scheme is based on selection)
2529  geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2530  }
2531  // draw geometry points except initial and final
2532  for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
2533  // obtain geometry point
2534  const auto geometryPointPos = myNBEdge->getGeometry()[i];
2535  // push geometry point drawing matrix
2537  // set color
2538  GLHelper::setColor(geometryPointColor);
2539  // move geometry point geometryPointPos
2540  glTranslated(geometryPointPos.x(), geometryPointPos.y(), bigGeometryPoints ? GLO_GEOMETRYPOINT : GLO_LANE + 1);
2541  // draw filled circle (resolution of drawn circle depending of the zoom, to improve smoothness)
2542  GLHelper::drawFilledCircleDetailled(d, geometryPointRadius);
2543  // draw elevation or special symbols (Start, End and Block)
2545  // Translate to top
2546  glTranslated(0, 0, 0.2);
2547  // draw Z value
2548  GLHelper::drawText(toString(geometryPointPos.z()), Position(), 0, s.edgeValue.scaledSize(s.scale) / 2, s.edgeValue.color);
2549  }
2550  // pop geometry point drawing matrix
2552  }
2553  // draw start and end points
2554  if (bigGeometryPoints) {
2555  drawStartGeometryPoint(s, d, geometryPointRadius, exaggeration);
2556  drawEndGeometryPoint(s, d, geometryPointRadius, exaggeration);
2557  }
2558  // draw dotted contour geometry points
2560  exaggeration, s.dottedContourSettings.segmentWidthSmall);
2561  }
2562 }
2563 
2564 
2565 void
2567  const double geometryPointRadius, const double exaggeration) const {
2568  // check detail level
2570  // get first geometry point
2571  const auto& startGeometryPointPos = myNBEdge->getGeometry().front();
2572  // get flags
2573  const bool startPosEdited = (startGeometryPointPos != getParentJunctions().front()->getPositionInView());
2575  // check drawing conditions
2576  if (startPosEdited || forceDraw) {
2577  // calculate angle betwen first and second geometry point
2578  const double angle = RAD2DEG(startGeometryPointPos.angleTo2D(myNBEdge->getGeometry()[1])) * -1;
2579  // get selected geometry points
2580  const auto selectedGeometryPoints = gViewObjectsHandler.getGeometryPoints(this);
2581  // override with special colors (unless the color scheme is based on selection)
2582  if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2584  } else {
2585  GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2586  }
2587  // push drawing matrix
2589  // move to point position
2590  glTranslated(startGeometryPointPos.x(), startGeometryPointPos.y(), GLO_GEOMETRYPOINT);
2591  // resolution of drawn circle depending of detail
2592  GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2593  // pop drawing matrix
2595  // draw a "s" over last point depending of detail level
2597  // push drawing matrix
2599  // move top
2600  glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2601  // draw S
2602  GLHelper::drawText("S", startGeometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2603  // pop drawing matrix
2605  // check if draw line between junctions
2606  if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.front() == 0)) {
2607  // set base color
2609  // push drawing matrix
2611  // draw line between geometry point and from junction
2612  const PositionVector lineA = {startGeometryPointPos, getFromJunction()->getNBNode()->getPosition()};
2613  GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2614  // draw line between begin point of last lane shape and the first edge shape point
2615  const PositionVector lineB = {startGeometryPointPos, myNBEdge->getLanes().back().shape.front()};
2616  GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2617  // pop drawing matrix
2619  }
2620  }
2621  // draw dotted contour geometry points
2623  geometryPointRadius, exaggeration);
2624  }
2625  }
2626 }
2627 
2628 
2629 void
2631  const double geometryPointRadius, const double exaggeration) const {
2632  // check detail level
2634  // get first geometry point
2635  const auto& geometryPointPos = myNBEdge->getGeometry().back();
2636  // get flags
2637  const bool endPosEdited = (geometryPointPos != getParentJunctions().back()->getPositionInView());
2639  // check drawing conditions
2640  if (endPosEdited || forceDraw) {
2641  // calculate angle last and previous geometry point
2642  const double angle = RAD2DEG(geometryPointPos.angleTo2D(myNBEdge->getGeometry()[-2])) * -1;
2643  // get selected geometry points
2644  const auto selectedGeometryPoints = gViewObjectsHandler.getGeometryPoints(this);
2645  // override with special colors (unless the color scheme is based on selection)
2646  if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2648  } else {
2649  GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2650  }
2651  // push drawing matrix
2653  // move to point position
2654  glTranslated(geometryPointPos.x(), geometryPointPos.y(), GLO_GEOMETRYPOINT);
2655  // resolution of drawn circle depending of detail
2656  GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2657  // pop drawing matrix
2659  // draw a "s" over last point depending of detail level
2661  // push drawing matrix
2663  // move top
2664  glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2665  // draw S
2666  GLHelper::drawText("E", geometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2667  // pop drawing matrix
2669  // check if draw line between junctions
2670  if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.back() == ((int)myNBEdge->getGeometry().size() - 1))) {
2671  // set base color
2673  // push drawing matrix
2675  // draw line between geometry point and from junction
2676  const PositionVector lineA = {geometryPointPos, getToJunction()->getNBNode()->getPosition()};
2677  GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2678  // draw line between begin point of last lane shape and the first edge shape point
2679  const PositionVector lineB = {geometryPointPos, myNBEdge->getLanes().back().shape.back()};
2680  GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2681  // pop drawing matrix
2683  }
2684  }
2685  // draw dotted contour geometry points
2687  geometryPointRadius, exaggeration);
2688  }
2689  }
2690 }
2691 
2692 
2693 void
2695  // draw the name and/or the street name
2696  const bool drawStreetName = s.streetName.show(this) && (myNBEdge->getStreetName() != "");
2697  const bool spreadSuperposed = s.spreadSuperposed && myNBEdge->getBidiEdge() != nullptr;
2698  // check conditions
2699  if (s.edgeName.show(this) || drawStreetName || s.edgeValue.show(this)) {
2700  // get first and last lanes
2701  const GNELane* firstLane = myLanes[0];
2702  const GNELane* lastLane = myLanes[myLanes.size() - 1];
2703  // calculate draw position
2704  Position drawPosition = firstLane->getLaneShape().positionAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2705  drawPosition.add(lastLane->getLaneShape().positionAtOffset(lastLane->getLaneShape().length() / (double) 2.));
2706  drawPosition.mul(.5);
2707  if (spreadSuperposed) {
2708  // move name to the right of the edge and towards its beginning
2709  const double dist = 0.6 * s.edgeName.scaledSize(s.scale);
2710  const double shiftA = firstLane->getLaneShape().rotationAtOffset(firstLane->getLaneShape().length() / (double) 2.) - DEG2RAD(135);
2711  const Position shift(dist * cos(shiftA), dist * sin(shiftA));
2712  drawPosition.add(shift);
2713  }
2714  // calculate drawing angle
2715  double drawAngle = firstLane->getLaneShape().rotationDegreeAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2716  drawAngle += 90;
2717  // avoid draw inverted text
2718  if (drawAngle > 90 && drawAngle < 270) {
2719  drawAngle -= 180;
2720  }
2721  // draw edge name
2722  if (s.edgeName.show(this)) {
2723  drawName(drawPosition, s.scale, s.edgeName, drawAngle);
2724  }
2725  // draw street name
2726  if (drawStreetName) {
2727  GLHelper::drawTextSettings(s.streetName, myNBEdge->getStreetName(), drawPosition, s.scale, drawAngle);
2728  }
2729  // draw edge values
2730  if (s.edgeValue.show(this)) {
2731  // get current scheme
2732  const int activeScheme = s.laneColorer.getActive();
2733  // calculate value depending of active scheme
2734  std::string value;
2735  if (activeScheme == 12) {
2736  // edge param, could be non-numerical
2737  value = getNBEdge()->getParameter(s.edgeParam, "");
2738  } else if (activeScheme == 13) {
2739  // lane param, could be non-numerical
2740  value = getNBEdge()->getLaneStruct(lastLane->getIndex()).getParameter(s.laneParam, "");
2741  } else {
2742  // use numerical value value of leftmost lane to hopefully avoid sidewalks, bikelanes etc
2743  const double doubleValue = lastLane->getColorValue(s, activeScheme);
2744  const RGBColor color = s.laneColorer.getScheme().getColor(doubleValue);
2745  value = color.alpha() == 0 ? "" : toString(doubleValue);
2746  }
2747  // check if value is empty
2748  if (value != "") {
2749  GLHelper::drawTextSettings(s.edgeValue, value, drawPosition, s.scale, drawAngle);
2750  }
2751  }
2752  }
2753 }
2754 
2755 
2756 void
2758  // draw geometry only if we'rent in drawForObjectUnderCursor mode
2760  // Push stopOffset matrix
2762  // translate to front (note: Special case)
2763  if (myNet->getViewNet()->getFrontAttributeCarrier() == this) {
2764  glTranslated(0, 0, GLO_FRONTELEMENT);
2765  } else {
2767  }
2769  for (const auto& lane : getLanes()) {
2770  lane->drawLaneStopOffset(s);
2771  }
2772  }
2773  // Push stopOffset matrix
2775  }
2776 }
2777 
2778 
2779 void
2781  // check if draw children elements
2783  // draw child additional
2784  for (const auto& additional : getChildAdditionals()) {
2785  additional->drawGL(s);
2786  }
2787  // draw person stops
2789  for (const auto& stopEdge : getChildDemandElements()) {
2790  if ((stopEdge->getTagProperty().getTag() == GNE_TAG_STOPPERSON_EDGE) || (stopEdge->getTagProperty().getTag() == GNE_TAG_STOPCONTAINER_EDGE)) {
2791  stopEdge->drawGL(s);
2792  }
2793  }
2794  }
2795  // draw vehicles
2796  const std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesMap = getVehiclesOverEdgeMap();
2797  for (const auto& vehicleMap : vehiclesMap) {
2798  for (const auto& vehicle : vehicleMap.second) {
2799  vehicle->drawGL(s);
2800  }
2801  }
2802  // draw TAZ elements
2803  drawTAZElements(s);
2804  }
2805 }
2806 
2807 
2808 void
2810  // if we're selecting using a boundary, first don't calculate contour bt check if edge boundary is within selection boundary
2812  // simply add object in ViewObjectsHandler with full boundary
2813  gViewObjectsHandler.addElementUnderCursor(this, false, true);
2814  } else {
2815  // get geometry point radius
2816  const auto geometryPointRadius = getGeometryPointRadius();
2817  // check if edit extrems
2818  const bool forceDrawExtrems = myNet->getViewNet()->getViewParent()->getMoveFrame()->getNetworkModeOptions()->getForceDrawGeometryPoints();
2819  const bool firstExtrem = forceDrawExtrems || (myNBEdge->getGeometry().front() != getParentJunctions().front()->getPositionInView());
2820  const bool lastExtrem = forceDrawExtrems || (myNBEdge->getGeometry().back() != getParentJunctions().back()->getPositionInView());
2821  // check if we're in move mode
2823  // calculate contour
2824  myNetworkElementContour.calculateContourEdge(s, d, this, this, true, true);
2825  // calculate edge geometry points
2826  myNetworkElementContour.calculateContourEdgeGeometryPoints(s, d, this, geometryPointRadius, moveMode, firstExtrem, lastExtrem);
2827  }
2828 }
2829 
2830 
2831 void
2833  // first check if draw TAZ Elements is enabled
2835  std::vector<GNEAdditional*> TAZSourceSinks;
2836  // get all TAZ source/sinks vinculated with this edge
2837  for (const auto& additional : getChildAdditionals()) {
2838  if ((additional->getTagProperty().getTag() == SUMO_TAG_TAZSOURCE) ||
2839  (additional->getTagProperty().getTag() == SUMO_TAG_TAZSINK)) {
2840  TAZSourceSinks.push_back(additional);
2841  }
2842  }
2843  if (TAZSourceSinks.size() > 0) {
2844  // check if TAZ Source/sink is selected
2845  bool selected = false;
2846  for (const auto& TAZSourceSink : TAZSourceSinks) {
2847  if (TAZSourceSink->isAttributeCarrierSelected()) {
2848  selected = true;
2849  }
2850  }
2851  // iterate over lanes
2852  for (const auto& lane : myLanes) {
2853  // Push layer matrix
2855  // translate to front (note: Special case)
2856  if (myNet->getViewNet()->getFrontAttributeCarrier() == this) {
2857  glTranslated(0, 0, GLO_FRONTELEMENT);
2858  } else if (lane->getLaneShape().length2D() <= (s.neteditSizeSettings.junctionBubbleRadius * 2)) {
2860  } else {
2862  }
2863  // move to front
2864  glTranslated(0, 0, 0.1);
2865  // set color
2866  if (selected) {
2868  } else {
2870  }
2871  // draw as box lines
2873  lane->getDrawingConstants()->getDrawingWidth());
2874  // Pop layer matrix
2876  }
2877  /*
2878  // check if curently we're inspecting a TAZ Source/Sink
2879  for (const auto& TAZSourceSink : TAZSourceSinks) {
2880  if (myNet->getViewNet()->isAttributeCarrierInspected(TAZSourceSink)) {
2881  drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::INSPECT, this, true, true);
2882  } else if (TAZSourceSink == frontAC) {
2883  drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::FRONT, this, true, true);
2884  }
2885  }
2886  */
2887  }
2888  }
2889 }
2890 
2891 
2892 void
2894  // avoid draw for railways
2895  if ((d <= GUIVisualizationSettings::Detail::LaneDetails) && !myLanes.front()->getDrawingConstants()->drawAsRailway() &&
2897  // push draw matrix
2899  // translate to front depending of big points
2900  if (drawBigGeometryPoints()) {
2901  glTranslated(0, 0, GLO_GEOMETRYPOINT - 1);
2902  } else {
2903  glTranslated(0, 0, GLO_EDGE);
2904  }
2905  // obtain color
2906  RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2907  if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2908  // override with special colors (unless the color scheme is based on selection)
2909  geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2910  }
2911  // set color
2912  GLHelper::setColor(geometryPointColor);
2913  // iterate over NBEdge geometry
2914  for (int i = 1; i < (int)myNBEdge->getGeometry().size(); i++) {
2915  // calculate line between previous and current geometry point
2916  PositionVector line = {myNBEdge->getGeometry()[i - 1], myNBEdge->getGeometry()[i]};
2917  line.move2side(0.2);
2918  // draw box line
2919  GLHelper::drawBoxLine(line[1], RAD2DEG(line[0].angleTo2D(line[1])) - 90, line[0].distanceTo2D(line[1]), .1);
2920  }
2921  // pop draw matrix
2923  }
2924 }
2925 
2926 
2927 bool
2929  // get edit modes
2930  const auto& editModes = myNet->getViewNet()->getEditModes();
2931  // continue depending of conditions
2932  if (!editModes.isCurrentSupermodeNetwork()) {
2933  return false;
2934  } else if (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) {
2935  return true;
2936  } else if ((editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE) &&
2938  return true;
2939  } else {
2940  return false;
2941  }
2942 }
2943 
2944 
2945 bool
2947  if ((vehicleA.beginPosition() == vehicleB.beginPosition()) && (vehicleA.endPosition() == vehicleB.endPosition())) {
2948  return true;
2949  } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2950  return true;
2951  } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.beginPosition())) {
2952  return true;
2953  } else if ((vehicleA.beginPosition() < vehicleB.endPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2954  return true;
2955  } else {
2956  return false;
2957  }
2958 }
2959 
2960 
2962 GNEEdge::processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
2963  // calculate squared snapRadius
2964  const double squaredSnapRadius = (snapRadius * snapRadius);
2965  // declare shape to move
2966  PositionVector shapeToMove = originalShape;
2967  // obtain nearest index
2968  const int nearestIndex = originalShape.indexOfClosest(mousePosition);
2969  // obtain nearest position
2970  const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
2971  // generate indexes
2972  std::vector<int> indexes;
2973  // check conditions
2974  if (nearestIndex == -1) {
2975  return nullptr;
2976  } else if (nearestPosition == Position::INVALID) {
2977  // special case for extremes
2978  if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2979  for (int i = 1; i <= nearestIndex; i++) {
2980  indexes.push_back(i);
2981  }
2982  // move extrem without creating new geometry point
2983  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2984  } else {
2985  return nullptr;
2986  }
2987  } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2988  for (int i = 1; i <= nearestIndex; i++) {
2989  indexes.push_back(i);
2990  }
2991  // move geometry point without creating new geometry point
2992  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2993  } else {
2994  // create new geometry point and keep new index (if we clicked near of shape)
2995  const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
2996  for (int i = 1; i <= newIndex; i++) {
2997  indexes.push_back(i);
2998  }
2999  // move after setting new geometry point in shapeToMove
3000  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3001  }
3002 }
3003 
3004 
3006 GNEEdge::processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
3007  // calculate squared snapRadius
3008  const double squaredSnapRadius = (snapRadius * snapRadius);
3009  // declare shape to move
3010  PositionVector shapeToMove = originalShape;
3011  // obtain nearest index
3012  const int nearestIndex = originalShape.indexOfClosest(mousePosition);
3013  // obtain nearest position
3014  const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
3015  // generate indexes
3016  std::vector<int> indexes;
3017  // check conditions
3018  if (nearestIndex == -1) {
3019  return nullptr;
3020  } else if (nearestPosition == Position::INVALID) {
3021  // special case for extremes
3022  if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3023  for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
3024  indexes.push_back(i);
3025  }
3026  // move extrem without creating new geometry point
3027  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3028  } else {
3029  return nullptr;
3030  }
3031  } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3032  for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
3033  indexes.push_back(i);
3034  }
3035  // move geometry point without creating new geometry point
3036  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3037  } else {
3038  // create new geometry point and keep new index (if we clicked near of shape)
3039  const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
3040  for (int i = newIndex; i < ((int)originalShape.size() - 1); i++) {
3041  indexes.push_back(i);
3042  }
3043  // move after setting new geometry point in shapeToMove
3044  return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3045  }
3046 }
3047 
3048 
3051  std::vector<int> geometryPointsToMove;
3052  for (int i = 0; i < (int)myNBEdge->getGeometry().size(); i++) {
3053  geometryPointsToMove.push_back(i);
3054  }
3055  // move entire shape (including extremes)
3056  return new GNEMoveOperation(this, myNBEdge->getGeometry(), geometryPointsToMove, myNBEdge->getGeometry(), geometryPointsToMove);
3057 }
3058 
3059 
3061 GNEEdge::processNoneJunctionSelected(const double snapRadius) {
3062  // get move multiple element values
3063  const auto& moveMultipleElementValues = myNet->getViewNet()->getMoveMultipleElementValues();
3064  // declare shape to move
3065  PositionVector shapeToMove = myNBEdge->getGeometry();
3066  // first check if kept offset is larger than geometry
3067  if (shapeToMove.length2D() < moveMultipleElementValues.getEdgeOffset()) {
3068  return nullptr;
3069  }
3070  // declare offset
3071  double offset = 0;
3072  // set offset depending of convex angle
3073  if (isConvexAngle()) {
3074  offset = moveMultipleElementValues.getEdgeOffset();
3075  } else {
3076  offset = shapeToMove.length2D() - moveMultipleElementValues.getEdgeOffset();
3077  }
3078  // obtain offset position
3079  const Position offsetPosition = myNBEdge->getGeometry().positionAtOffset2D(offset);
3080  // obtain nearest index to offset position
3081  const int nearestIndex = myNBEdge->getGeometry().indexOfClosest(offsetPosition);
3082  // check conditions
3083  if ((nearestIndex == -1) || (offsetPosition == Position::INVALID)) {
3084  return nullptr;
3085  } else if (offsetPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= (snapRadius * snapRadius)) {
3086  // move geometry point without creating new geometry point
3087  return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {nearestIndex});
3088  } else {
3089  // create new geometry point and keep new index (if we clicked near of shape)
3090  const int newIndex = shapeToMove.insertAtClosest(offsetPosition, true);
3091  // move after setting new geometry point in shapeToMove
3092  return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {newIndex});
3093  }
3094 }
3095 
3096 
3097 double
3100 }
3101 
3102 
3103 /****************************************************************************/
#define ENDPOINT_TOLERANCE
Definition: GNEEdge.cpp:57
#define VEHICLE_GAP
Definition: GNEEdge.cpp:56
@ NETWORK_DELETE
mode for deleting network elements
@ NETWORK_MOVE
mode for moving network elements
@ NETWORK_SELECT
mode for selecting network elements
@ DEMAND_PERSONPLAN
Mode for editing person plan.
@ DEMAND_CONTAINER
Mode for editing container.
@ DEMAND_PERSON
Mode for editing person.
@ DEMAND_CONTAINERPLAN
Mode for editing container plan.
@ GLO_JUNCTION
a junction
@ GLO_FRONTELEMENT
front element (used in netedit)
@ GLO_LANE
a lane
@ GLO_GEOMETRYPOINT
geometry point (used in netedit)
@ GLO_EDGE
an edge
GUIViewObjectsHandler gViewObjectsHandler
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:306
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
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_LANETYPE
lane type
@ SUMO_TAG_FLOW
a flow definition using from and to edges or a route
@ 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
@ 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_FROM_JUNCTION
@ SUMO_ATTR_SPEED
@ GNE_ATTR_STOPOFFSET
stop offset (virtual, used by edge and lanes)
@ GNE_ATTR_OPPOSITE
to busStop (used by personPlans)
@ SUMO_ATTR_TO_JUNCTION
@ 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.
@ GNE_ATTR_IS_ROUNDABOUT
@ 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:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
const double SUMO_const_halfLaneWidth
Definition: StdDefs.h:49
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:78
bool isInitialised() const
check if Boundary is Initialised
Definition: Boundary.cpp:235
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:319
double getHeight() const
Returns the height of the boundary (y-axis)
Definition: Boundary.cpp:160
double getWidth() const
Returns the width of the boudary (x-axis)
Definition: Boundary.cpp:154
double contains(const Boundary &b) const
return true if this boundary contains the given boundary (only X-Y)
Definition: Boundary.cpp:224
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:654
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:130
static void drawBoundary(const GUIVisualizationSettings &s, const Boundary &b)
Draw a boundary (used for debugging)
Definition: GLHelper.cpp:967
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition: GLHelper.cpp:295
static void drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius)
Draws a filled circle around (0,0) depending of level of detail.
Definition: GLHelper.cpp:539
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:756
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:787
const std::string getID() const
get ID (all Attribute Carriers have one)
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
bool mySelected
boolean to check if this AC is selected (instead of GUIGlObjectStorage)
static const std::string True
true value in string format (used for comparing boolean values in getAttribute(......
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
static const std::string False
true value in string format(used for comparing boolean values in getAttribute(...))
static void changeAttribute(GNEAttributeCarrier *AC, SumoXMLAttr key, const std::string &value, GNEUndoList *undoList, const bool force=false)
change attribute
void markConnectionGeometryDeprecated()
check that connection's Geometry has to be updated
void updateGeometry()
update pre-computed geometry information
void updateLinkState()
recompute cached myLinkState
GNEPlanCreator * getPlanCreator() const
get plan creator module
GNEPlanSelector * getPlanSelector() const
get containerPlan selector
GNEPlanCreator * getPlanCreator() const
get plan creator module
GNEPlanSelector * getPlanSelector() const
get containerPlan selector
void calculateContourEdge(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEEdge *edge, const GUIGlObject *elementToRegister, const bool closeFirstExtrem, const bool closeLastExtrem) const
calculate contour edge
Definition: GNEContour.cpp:130
void drawDottedContourGeometryPoints(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, const PositionVector &shape, const double radius, const double scale, const double lineWidth) const
draw dotted contour for geometry points
Definition: GNEContour.cpp:307
void calculateContourEdgeGeometryPoints(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEEdge *edge, const double radius, const bool calculatePosOverShape, const bool firstExtrem, const bool lastExtrem) const
calculate contour for edge geometry points
Definition: GNEContour.cpp:210
void drawDottedContours(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, const double lineWidth, const bool addOffset) const
drawing contour functions
Definition: GNEContour.cpp:265
void calculateContourFirstGeometryPoint(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const PositionVector &shape, const double radius, const double scale) const
calculate contour for first geometry point
Definition: GNEContour.cpp:152
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
void updateDemandElementStackLabel(const int stack)
update stack label
Stack demand elements.
Definition: GNEEdge.h:396
const StackPosition & getStackPosition() const
get stack position
Definition: GNEEdge.cpp:1750
const std::vector< GNEDemandElement * > & getDemandElements() const
get demand elements
Definition: GNEEdge.cpp:1756
void addDemandElements(GNEDemandElement *demandElement)
add demand elment to current StackDemandElements
Definition: GNEEdge.cpp:1744
StackDemandElements(const StackPosition stackedPosition, GNEDemandElement *demandElement)
constructor
Definition: GNEEdge.cpp:1736
Stack position (used to stack demand elements over edges)
Definition: GNEEdge.h:382
double beginPosition() const
get begin position
Definition: GNEEdge.cpp:1725
StackPosition(const double departPos, const double length)
constructor
Definition: GNEEdge.cpp:1719
double endPosition() const
get end position
Definition: GNEEdge.cpp:1731
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:53
const Position getFrontDownShapePosition() const
get front down shape position
Definition: GNEEdge.cpp:824
Boundary myEdgeBoundary
edge boundary
Definition: GNEEdge.h:413
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
Definition: GNEEdge.cpp:562
void drawEdgeName(const GUIVisualizationSettings &s) const
draw edge name
Definition: GNEEdge.cpp:2694
void drawStartGeometryPoint(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double geometryPointRadius, const double exaggeration) const
draw start extreme geometry point
Definition: GNEEdge.cpp:2566
bool isConvexAngle() const
check if edge makes a convex angle [0 - 180) degrees
Definition: GNEEdge.cpp:1669
bool checkDrawRelatedContour() const
check if draw related contour (cyan)
Definition: GNEEdge.cpp:260
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:1984
std::string getNetworkElementProblem() const
return a string with the current network element problem
Definition: GNEEdge.cpp:141
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getPersonsOverEdgeMap() const
get persons a that start over this edge
Definition: GNEEdge.cpp:2451
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getContainersOverEdgeMap() const
get containers a that start over this edge
Definition: GNEEdge.cpp:2484
void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)
commit move shape
Definition: GNEEdge.cpp:1957
bool hasPredecessors() const
check if this edge has predecessors (note: only for vehicles, this function ignore walking areas!...
Definition: GNEEdge.cpp:1684
void setMoveShape(const GNEMoveResult &moveResult)
set move shape
Definition: GNEEdge.cpp:1935
void drawEndGeometryPoint(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double geometryPointRadius, const double exaggeration) const
draw end extreme geometry point
Definition: GNEEdge.cpp:2630
bool checkDrawMoveContour() const
check if draw move contour (red)
Definition: GNEEdge.cpp:359
friend class GNEChange_Lane
Friend class.
Definition: GNEEdge.h:56
bool checkDrawOverContour() const
check if draw over contour (orange)
Definition: GNEEdge.cpp:266
~GNEEdge()
Destructor.
Definition: GNEEdge.cpp:97
void smooth(GNEUndoList *undoList)
make geometry smooth
Definition: GNEEdge.cpp:2345
void updateGeometry()
update pre-computed geometry information
Definition: GNEEdge.cpp:149
double getGeometryPointRadius() const
get geometry point radius
Definition: GNEEdge.cpp:3098
GNEMoveOperation * getMoveOperation()
get move operation
Definition: GNEEdge.cpp:386
std::string getAttributeForSelection(SumoXMLAttr key) const
method for getting the attribute in the context of object selection
Definition: GNEEdge.cpp:1159
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:1440
void copyEdgeType(const GNEEdgeType *edgeType, GNEUndoList *undoList)
copy edge attributes from edgeType
Definition: GNEEdge.cpp:992
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition: GNEEdge.cpp:683
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEEdge.cpp:609
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getVehiclesOverEdgeMap() const
get vehicles a that start over this edge
Definition: GNEEdge.cpp:2409
std::set< GUIGlID > getLaneGlIDs() const
returns GLIDs of all lanes
Definition: GNEEdge.cpp:1037
GNEEdge * getReverseEdge() const
get reverse edge (if exist)
Definition: GNEEdge.cpp:1706
const Position getFrontUpShapePosition() const
get front up shape position
Definition: GNEEdge.cpp:816
void setGeometry(PositionVector geom, bool inner)
update edge geometry and inform the lanes
Definition: GNEEdge.cpp:781
void smoothElevation(GNEUndoList *undoList)
smooth elevation with regard to adjoining edges
Definition: GNEEdge.cpp:2357
bool clickedOverGeometryPoint(const Position &pos) const
return true if user clicked over a Geometry Point
Definition: GNEEdge.cpp:515
bool clickedOverShapeEnd(const Position &pos) const
return true if user clicked over ShapeEnd
Definition: GNEEdge.cpp:503
void updateVehicleStackLabels()
Definition: GNEEdge.cpp:1507
void drawChildrens(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d) const
draw children
Definition: GNEEdge.cpp:2780
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:1301
void remakeGNEConnections(bool junctionsReady=false)
remake connections
Definition: GNEEdge.cpp:847
GNEMoveOperation * processMoveBothJunctionSelected()
process moving edge when both junctions are selected
Definition: GNEEdge.cpp:3050
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList)
remove geometry point in the clicked position
Definition: GNEEdge.cpp:418
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:1047
LaneVector myLanes
vector with the lanes of this edge
Definition: GNEEdge.h:363
static const double SNAP_RADIUS
Definition: GNEEdge.h:302
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:1446
bool hasCustomEndPoints() const
Definition: GNEEdge.cpp:479
void updatePersonStackLabels()
Definition: GNEEdge.cpp:1565
void setEdgeID(const std::string &newID)
set edge ID
Definition: GNEEdge.cpp:2231
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition: GNEEdge.cpp:2175
bool hasSuccessors() const
check if this edge has successors (note: only for vehicles, this function ignore walking areas!...
Definition: GNEEdge.cpp:1700
bool isAttributeComputed(SumoXMLAttr key) const
Definition: GNEEdge.cpp:1417
bool drawBigGeometryPoints() const
check if draw big geometry points
Definition: GNEEdge.cpp:2928
bool myWasSplit
whether this edge was created from a split
Definition: GNEEdge.h:375
void removeLane(GNELane *lane, bool recomputeConnections)
@briefdecrease the number of lanes by one. argument is only used to increase robustness (assertions)
Definition: GNEEdge.cpp:2098
bool checkDrawSelectContour() const
check if draw select contour (blue)
Definition: GNEEdge.cpp:328
double getExaggeration(const GUIVisualizationSettings &s) const
return exaggeration associated with this GLObject
Definition: GNEEdge.cpp:550
bool hasRestrictedLane(SUMOVehicleClass vclass) const
check if edge has a restricted lane
Definition: GNEEdge.cpp:2240
static const double SNAP_RADIUS_SQUARED
Definition: GNEEdge.h:305
void updateSecondParentJunction(const std::string &value)
update last parent junction
Definition: GNEEdge.cpp:2036
std::vector< GNEEdge * > getOppositeEdges() const
get opposite edges
Definition: GNEEdge.cpp:624
PositionVector smoothShape(const PositionVector &shape, bool forElevation)
return smoothed shape
Definition: GNEEdge.cpp:2272
bool wasSplit()
whether this edge was created from a split
Definition: GNEEdge.cpp:1059
NBEdge * myNBEdge
the underlying NBEdge
Definition: GNEEdge.h:360
void copyTemplate(const GNEEdgeTemplate *edgeTemplate, GNEUndoList *undoList)
copy edge attributes from edgetemplate
Definition: GNEEdge.cpp:957
void removeEdgeFromCrossings(GNEJunction *junction, GNEUndoList *undoList)
remove crossing of junction
Definition: GNEEdge.cpp:2251
Position getPositionInView() const
Returns position of hierarchical element in view.
Definition: GNEEdge.cpp:195
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:2045
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:2208
ConnectionVector myGNEConnections
vector with the connections of this edge
Definition: GNEEdge.h:366
void calculateEdgeContour(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d) const
calculate contours
Definition: GNEEdge.cpp:2809
void editEndpoint(Position pos, GNEUndoList *undoList)
makes pos the new geometry endpoint at the appropriate end, or remove current existent endpoint
Definition: GNEEdge.cpp:705
void resetBothEndpoint(GNEUndoList *undoList)
restores both endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:771
Position getSplitPos(const Position &clickPos)
Definition: GNEEdge.cpp:689
void drawEdgeGeometryPoints(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d) const
draw edge geometry points (note: This function is called by GNELane::drawGL(...)
Definition: GNEEdge.cpp:2516
const std::vector< GNEConnection * > & getGNEConnections() const
returns a reference to the GNEConnection vector
Definition: GNEEdge.cpp:1053
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEEdge.cpp:1065
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition: GNEEdge.cpp:922
bool checkDrawFromContour() const
check if draw from contour (green)
Definition: GNEEdge.cpp:201
std::string myConnectionStatus
modification status of the connections
Definition: GNEEdge.h:378
bool checkDrawDeleteContour() const
check if draw delete contour (pink/white)
Definition: GNEEdge.cpp:297
void deleteGLObject()
delete element
Definition: GNEEdge.cpp:668
const std::string getOptionalName() const
Returns the street name.
Definition: GNEEdge.cpp:603
void clearGNEConnections()
clear current connections
Definition: GNEEdge.cpp:895
bool myUpdateGeometry
flag to enable/disable update geometry of lanes (used mainly by setNumLanes)
Definition: GNEEdge.h:416
const Position getBackDownShapePosition() const
get back down shape position
Definition: GNEEdge.cpp:840
bool areStackPositionOverlapped(const GNEEdge::StackPosition &vehicleA, const GNEEdge::StackPosition &vehicleB) const
check if given stacked positions are overlapped
Definition: GNEEdge.cpp:2946
void updateFirstParentJunction(const std::string &value)
update front parent junction
Definition: GNEEdge.cpp:2027
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition: GNEEdge.cpp:2262
void updateContainerStackLabels()
Definition: GNEEdge.cpp:1617
void drawEdgeShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d) const
draw edge shape (only one line)
Definition: GNEEdge.cpp:2893
bool checkDrawToContour() const
check if draw from contour (magenta)
Definition: GNEEdge.cpp:234
bool clickedOverShapeStart(const Position &pos) const
return true if user clicked over ShapeStart
Definition: GNEEdge.cpp:491
bool isNetworkElementValid() const
check if current network element is valid to be written into XML
Definition: GNEEdge.cpp:131
void setShapeStartPos(const Position &pos)
change Shape StartPos
Definition: GNEEdge.cpp:2387
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNEEdge.cpp:1169
const Position getBackUpShapePosition() const
get back up shape position
Definition: GNEEdge.cpp:832
void resetEndpoint(const Position &pos, GNEUndoList *undoList)
restores the endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:757
bool isAttributeEnabled(SumoXMLAttr key) const
Definition: GNEEdge.cpp:1402
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEEdge.cpp:630
void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation=false)
adds a connection
Definition: GNEEdge.cpp:2151
void drawLaneStopOffset(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d) const
draw edgeStopOffset
Definition: GNEEdge.cpp:2757
GNEMoveOperation * processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only from junction is selected
Definition: GNEEdge.cpp:2962
GNEMoveOperation * processNoneJunctionSelected(const double snapRadius)
process moving edge when none junction are selected
Definition: GNEEdge.cpp:3061
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GNEEdge.cpp:556
const Parameterised::Map & getACParametersMap() const
get parameters map
Definition: GNEEdge.cpp:1434
void drawTAZElements(const GUIVisualizationSettings &s) const
draw TAZElements
Definition: GNEEdge.cpp:2832
std::vector< GNECrossing * > getGNECrossings()
get GNECrossings vinculated with this Edge
Definition: GNEEdge.cpp:940
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:1461
void updateVehicleSpreadGeometries()
Definition: GNEEdge.cpp:1476
GNEMoveOperation * processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only to junction is selected
Definition: GNEEdge.cpp:3006
void updateGLObject()
update GLObject (geometry, ID, etc.)
Definition: GNEEdge.cpp:677
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition: GNEEdge.cpp:536
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition: GNEEdge.h:372
GNEEdge(GNENet *net, NBEdge *nbe, bool wasSplit=false, bool loaded=false)
Constructor.
Definition: GNEEdge.cpp:69
void setShapeEndPos(const Position &pos)
change Shape EndPos
Definition: GNEEdge.cpp:2398
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 drawGL(const GUIVisualizationSettings &s) const
Draws the object.
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
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:214
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:642
double getColorValue(const GUIVisualizationSettings &s, int activeScheme) const
return value for lane coloring according to the given scheme
Definition: GNELane.cpp:1553
GNEMoveOperation * calculateMoveShapeOperation(const GUIGlObject *obj, const PositionVector originalShape, const bool maintainShapeClosed)
calculate move shape operation
bool getForceDrawGeometryPoints() const
force draw geometry points
NetworkModeOptions * getNetworkModeOptions() const
get network mode options
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
void insertLane(GNELane *lane)
insert lane in container
void deleteConnection(GNEConnection *connection)
delete connection from container
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
void insertConnection(GNEConnection *connection)
insert connection in container
const std::map< const GUIGlObject *, GNELane * > & getLanes() const
get lanes
void updateEdgeID(GNEEdge *edge, const std::string &newID)
update edge ID in container
const std::map< const GUIGlObject *, GNEConnection * > & getConnections() const
get connections
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
void deleteLane(GNELane *lane)
delete lane from container
int getNumberOfSelectedEdges() const
get number of selected edges
void requireSaveDemandElements()
inform that demand elements has to be saved
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:414
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:633
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1282
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1291
GNENetHelper::SavingStatus * getSavingStatus() const
get saving status
Definition: GNENet.cpp:128
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition: GNENet.cpp:2079
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:122
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition: GNENet.cpp:2046
GNEPathManager * getPathManager()
get path manager
Definition: GNENet.cpp:134
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:2055
bool checkDrawingBoundarySelection() const
GNEContour myNetworkElementContour
network element contour
void setNetworkElementID(const std::string &newID)
set network element id
void invalidatePathCalculator()
invalidate pathCalculator
PathCalculator * getPathCalculator()
obtain instance of PathCalculator
GNEPlanCreator * getPlanCreator() const
get plan creator module
GNEPlanSelector * getPlanSelector() const
get personPlan selector
GNEPlanCreator * getPlanCreator() const
get plan creator module
GNEPlanSelector * getPlanSelector() const
get personPlan selector
GNEEdge * getToEdge() const
get to edge
const std::vector< GNEEdge * > getConsecutiveEdges() const
get consecutive edge
GNEEdge * getFromEdge() const
get from edge
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...
const GUIGlObject * getGUIGlObjectFront() const
get front attribute carrier or a pointer to nullptr
const GNEViewNetHelper::DataViewOptions & getDataViewOptions() const
get data view options
Definition: GNEViewNet.cpp:727
const GNEAttributeCarrier * getFrontAttributeCarrier() const
get front attributeCarrier
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:703
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
Definition: GNEViewNet.cpp:715
void drawTranslateFrontAttributeCarrier(const GNEAttributeCarrier *AC, double typeOrLayer, const double extraOffset=0)
draw front attributeCarrier
bool isMovingElement() const
check if an element is being moved
GNEViewParent * getViewParent() const
get the net object
bool checkOverLockedElement(const GUIGlObject *GLObject, const bool isSelected) const
check if given element is locked (used for drawing select and delete contour)
bool checkSelectEdges() const
check if select edges (toggle using button or shift)
GNEUndoList * getUndoList() const
get the undoList object
const GNEViewNetHelper::MoveMultipleElementModul & getMoveMultipleElementValues() const
get move multiple element values
Definition: GNEViewNet.cpp:532
const GNEViewNetHelper::ViewObjectsSelector & getViewObjectsSelector() const
get objects under cursor
Definition: GNEViewNet.cpp:468
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:538
GNEPersonPlanFrame * getPersonPlanFrame() const
get frame for DEMAND_PERSONFRAME
GNEMoveFrame * getMoveFrame() const
get frame for move elements
GNEContainerPlanFrame * getContainerPlanFrame() const
get frame for DEMAND_CONTAINERFRAME
GNEDeleteFrame * getDeleteFrame() const
get frame for delete elements
GNEVehicleFrame * getVehicleFrame() const
get frame for DEMAND_VEHICLE
GNEContainerFrame * getContainerFrame() const
get frame for DEMAND_CONTAINER
GNEPersonFrame * getPersonFrame() const
get frame for DEMAND_PERSON
GNEInspectorFrame * getInspectorFrame() const
get frame for inspect elements
The popup menu of a globject.
static void drawGeometry(const GUIVisualizationSettings::Detail d, const GUIGeometry &geometry, const double width, double offset=0)
draw geometry
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
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:156
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
Definition: GUIGlObject.h:143
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
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.
const Boundary & getSelectionBoundary() const
get selection boundary (usually the mouse position)
const std::vector< int > & getGeometryPoints(const GUIGlObject *GLObject) const
get geometry points for the given glObject
bool addElementUnderCursor(const GUIGlObject *GLObject, const bool checkDuplicated, const bool fullBoundary)
add element into list of elements under cursor
const GUIGlObject * markedFirstGeometryPoint
marked first geometry point (used for moving/delete geometry points)
Stores the information about how to visualize structures.
GUIVisualizationSizeSettings addSize
GUIVisualizationTextSettings edgeValue
double laneWidthExaggeration
The lane exaggeration (upscale thickness)
GUIVisualizationColorSettings colorSettings
color settings
GUIVisualizationDottedContourSettings dottedContourSettings
dotted contour settings
double scale
information about a lane's width (temporary, used for a single view)
GUIVisualizationTextSettings streetName
bool drawForViewObjectsHandler
whether drawing is performed for the purpose of selecting objects in view using ViewObjectsHandler
GUIColorer laneColorer
The lane colorer.
GUIVisualizationTextSettings edgeName
bool spreadSuperposed
Whether to improve visualisation of superposed (rail) edges.
GUIColorer junctionColorer
The junction colorer.
std::string edgeParam
key for coloring by edge parameter
bool checkBoundarySizeDrawing(const double w, const double h) const
check if draw element depending of boundarySize
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:670
void mirrorX()
mirror coordinates along the x-axis
Definition: NBEdge.cpp:563
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
Definition: NBEdge.cpp:4285
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:4308
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:4271
StopOffset myEdgeStopOffset
A vClass specific stop offset - assumed of length 0 (unspecified) or 1. For the latter case the int i...
Definition: NBEdge.h:1790
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition: NBEdge.h:598
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4223
bool hasLaneSpecificFriction() const
whether lanes differ in friction
Definition: NBEdge.cpp:2412
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:638
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:665
void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices)
add lane
Definition: NBEdge.cpp:3960
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:2402
std::string myType
The type of the edge.
Definition: NBEdge.h:1727
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition: NBEdge.cpp:979
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:608
void setDistance(double distance)
set kilometrage at start of edge (negative value implies couting down along the edge)
Definition: NBEdge.h:1407
const std::string & getID() const
Definition: NBEdge.h:1522
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:726
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:542
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:615
double getDistance() const
get distance
Definition: NBEdge.h:675
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:360
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4094
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:973
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:3594
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:2388
bool isBidiEdge(bool checkPotential=false) const
whether this edge is part of a bidirectional edge pair
Definition: NBEdge.cpp:742
void setBidi(bool isBidi)
mark this edge as a bidi edge
Definition: NBEdge.h:1412
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:516
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:779
void setFriction(int lane, double friction)
set lane specific friction (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4239
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:1413
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1494
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition: NBEdge.cpp:4015
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:2422
@ USER
The connection was given by the user.
double getFriction() const
Returns the friction on this edge.
Definition: NBEdge.h:622
const NBEdge * getBidiEdge() const
Definition: NBEdge.h:1508
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:1151
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:2444
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3937
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:523
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:342
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:1035
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1175
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:1436
double getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:685
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4177
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1422
void setLoadedLength(double val)
set loaded length
Definition: NBEdge.cpp:4323
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:583
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:4644
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition: NBEdge.cpp:618
int myPriority
The priority of the edge.
Definition: NBEdge.h:1746
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:535
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:273
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:268
const Position & getPosition() const
Definition: NBNode.h:260
bool isRoundabout() const
return whether this node is part of a roundabout
Definition: NBNode.cpp:3799
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:3753
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:575
const std::string & getID() const
Returns the id.
Definition: Named.h:74
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:60
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:276
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:317
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:271
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:132
void mul(double val)
Multiplies position with the given value.
Definition: Position.h:105
double z() const
Returns the z-position.
Definition: Position.h:65
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 amount
PositionVector interpolateZ(double zStart, double zEnd) const
returned vector that varies z smoothly over its length
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
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 ORANGE
Definition: RGBColor.h:191
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 isCurrentSupermodeNetwork() const
@check if current supermode is Network
static void drawLockIcon(const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, GUIGlObjectType type, const Position position, 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 segmentWidthSmall
width of small dotted contour segments
static const double segmentWidth
width of dotted contour segments
static const double junctionBubbleRadius
junction bubble 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:210
int toLane
The lane the connections yields in.
Definition: NBEdge.h:216
double speed
custom speed for connection
Definition: NBEdge.h:240
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:213
KeepClear keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:231
double customLength
custom length for connection
Definition: NBEdge.h:246
bool uncontrolled
check if Connection is uncontrolled
Definition: NBEdge.h:297
PositionVector customShape
custom shape for connection
Definition: NBEdge.h:249
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:228
double contPos
custom position for internal junction on this connection
Definition: NBEdge.h:234
double visibility
custom foe visiblity for connection
Definition: NBEdge.h:237
double friction
Definition: NBEdge.h:243
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