Eclipse SUMO - Simulation of Urban MObility
GNEEdge.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 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>
32 #include <utils/gui/div/GLHelper.h>
35 
36 #include "GNEConnection.h"
37 #include "GNECrossing.h"
38 #include "GNEEdge.h"
39 #include "GNEEdgeType.h"
40 #include "GNELaneType.h"
41 
42 //#define DEBUG_SMOOTH_GEOM
43 //#define DEBUGCOND(obj) (true)
44 #define VEHICLE_GAP 1
45 
46 // ===========================================================================
47 // static
48 // ===========================================================================
50 
51 // ===========================================================================
52 // members methods
53 // ===========================================================================
54 
55 GNEEdge::GNEEdge(GNENet* net, NBEdge* nbe, bool wasSplit, bool loaded):
56  GNENetworkElement(net, nbe->getID(), GLO_EDGE, SUMO_TAG_EDGE, {
57  net->retrieveJunction(nbe->getFromNode()->getID()), net->retrieveJunction(nbe->getToNode()->getID())
58 },
59 {}, {}, {}, {}, {}, {}, {}),
60 myNBEdge(nbe),
61 myLanes(0),
62 myAmResponsible(false),
63 myWasSplit(wasSplit),
64 myConnectionStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED),
65 myUpdateGeometry(true) {
66  // Create lanes
67  int numLanes = myNBEdge->getNumLanes();
68  myLanes.reserve(numLanes);
69  for (int i = 0; i < numLanes; i++) {
70  myLanes.push_back(new GNELane(this, i));
71  myLanes.back()->incRef("GNEEdge::GNEEdge");
72  }
73  // update Lane geometries
74  for (const auto& i : myLanes) {
75  i->updateGeometry();
76  }
77  // update centering boundary without updating grid
78  updateCenteringBoundary(false);
79 }
80 
81 
83  // Delete references to this eddge in lanes
84  for (const auto& lane : myLanes) {
85  lane->decRef("GNEEdge::~GNEEdge");
86  if (lane->unreferenced()) {
87  // show extra information for tests
88  WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in GNEEdge destructor");
89  delete lane;
90  }
91  }
92  // delete references to this eddge in connections
93  for (const auto& connection : myGNEConnections) {
94  connection->decRef("GNEEdge::~GNEEdge");
95  if (connection->unreferenced()) {
96  // show extra information for tests
97  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in GNEEdge destructor");
98  delete connection;
99  }
100  }
101  if (myAmResponsible) {
102  delete myNBEdge;
103  }
104 }
105 
106 
107 void
109  // first check if myUpdateGeometry flag is enabled
110  if (myUpdateGeometry) {
111  // Update geometry of lanes
112  for (const auto& lane : myLanes) {
113  lane->updateGeometry();
114  }
115  // Update geometry of connections
116  for (const auto& connection : myGNEConnections) {
117  connection->updateGeometry();
118  }
119  // Update geometry of additionals children vinculated to this edge
120  for (const auto& childAdditionals : getChildAdditionals()) {
121  childAdditionals->updateGeometry();
122  }
123  // Update geometry of additionals demand elements vinculated to this edge
124  for (const auto& childDemandElements : getChildDemandElements()) {
125  childDemandElements->computePath();
126  childDemandElements->updateGeometry();
127  }
128  // Update geometry of additionals generic datas vinculated to this edge
129  for (const auto& childGenericData : getChildGenericDatas()) {
130  childGenericData->updateGeometry();
131  }
132  }
133  // update vehicle geometry
135  // update vehicle stack labels
137 }
138 
139 
140 Position
142  // currently unused
143  return Position(0, 0);
144 }
145 
146 
148 GNEEdge::getMoveOperation(const double shapeOffset) {
152  // declare a vector for saving geometry points to move
153  std::vector<int> geometryPointsToMove;
154  // if edge is selected, check conditions
156  for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
157  geometryPointsToMove.push_back(i);
158  }
159  }
160  // move entire shape (except extremes)
161  return new GNEMoveOperation(this, myNBEdge->getGeometry());
162  } else {
163  // declare shape to move
164  PositionVector shapeToMove = myNBEdge->getGeometry();
165  // first check if in the given shapeOffset there is a geometry point
166  const Position positionAtOffset = shapeToMove.positionAtOffset2D(shapeOffset);
167  // check if position is valid
168  if (positionAtOffset == Position::INVALID) {
169  return nullptr;
170  } else {
171  // obtain index
172  const int index = myNBEdge->getGeometry().indexOfClosest(positionAtOffset);
173  // declare new index
174  int newIndex = index;
175  // check if we have to create a new index
176  if (positionAtOffset.distanceSquaredTo2D(shapeToMove[index]) > (SNAP_RADIUS * SNAP_RADIUS)) {
177  newIndex = shapeToMove.insertAtClosest(positionAtOffset, true);
178  }
179  // check if attribute carrier is selected
181  // declare a vector for saving geometry points original and to move
182  std::vector<int> geometryPointsToMove;
183  // if edge is selected, check conditions
185  // fill geometry points
186  for (int i = 1; i <= newIndex; i++) {
187  geometryPointsToMove.push_back(i);
188  }
189  // move only a part of edge geometry
190  return new GNEMoveOperation(this, myNBEdge->getGeometry(), geometryPointsToMove, shapeToMove, geometryPointsToMove);
191  } else if (getParentJunctions().back()->isAttributeCarrierSelected()) {
192  for (int i = index; i < (int)shapeToMove.size() - 1; i++) {
193  geometryPointsToMove.push_back(i);
194  }
195  // move only a part of edge geometry
196  return new GNEMoveOperation(this, myNBEdge->getGeometry(), geometryPointsToMove, shapeToMove, geometryPointsToMove);
197  } else {
198  // move as a non-selected edge
199  return new GNEMoveOperation(this, myNBEdge->getGeometry(), {index}, shapeToMove, {newIndex});
200  }
201  } else {
202  // only move clicked edge
203  return new GNEMoveOperation(this, myNBEdge->getGeometry(), {index}, shapeToMove, {newIndex});
204  }
205  }
206  }
207 }
208 
209 
210 void
211 GNEEdge::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
212  // declare shape to move
214  // obtain flags for start and end positions
215  const bool customStartPosition = (myNBEdge->getGeometry().front() != getParentJunctions().front()->getNBNode()->getPosition());
216  const bool customEndPosition = (myNBEdge->getGeometry().back() != getParentJunctions().back()->getNBNode()->getPosition());
217  // get variable for last index
218  const int lastIndex = (int)myNBEdge->getGeometry().size() - 1;
219  // flag to enable/disable remove geometry point
220  bool removeGeometryPoint = true;
221  // obtain index
222  const int index = myNBEdge->getGeometry().indexOfClosest(clickedPosition);
223  // check index
224  if (index == -1) {
225  removeGeometryPoint = false;
226  }
227  // check distance
228  if (shape[index].distanceSquaredTo2D(clickedPosition) > (SNAP_RADIUS * SNAP_RADIUS)) {
229  removeGeometryPoint = false;
230  }
231  // check custom start position
232  if (!customStartPosition && (index == 0)) {
233  removeGeometryPoint = false;
234  }
235  // check custom end position
236  if (!customEndPosition && (index == lastIndex)) {
237  removeGeometryPoint = false;
238  }
239  // check if we can remove geometry point
240  if (removeGeometryPoint) {
241  // check if we're removing first geometry proint
242  if (index == 0) {
243  // commit new geometry start
244  undoList->p_begin("remove first geometry point of " + getTagStr());
245  undoList->p_add(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_START, ""));
246  undoList->p_end();
247  } else if (index == lastIndex) {
248  // commit new geometry end
249  undoList->p_begin("remove last geometry point of " + getTagStr());
250  undoList->p_add(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_END, ""));
251  undoList->p_end();
252  } else {
253  // remove geometry point
254  shape.erase(shape.begin() + index);
255  // get innen shape
256  shape.pop_front();
257  shape.pop_back();
258  // remove double points
260  // commit new shape
261  undoList->p_begin("remove geometry point of " + getTagStr());
262  undoList->p_add(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(shape)));
263  undoList->p_end();
264  }
265  }
266 }
267 
268 
269 bool
271  if (myNBEdge->getGeometry().front() != getParentJunctions().front()->getNBNode()->getPosition()) {
272  return (myNBEdge->getGeometry().front().distanceTo2D(pos) < SNAP_RADIUS);
273  } else {
274  return false;
275  }
276 }
277 
278 
279 bool
281  if (myNBEdge->getGeometry().back() != getParentJunctions().back()->getNBNode()->getPosition()) {
282  return (myNBEdge->getGeometry().back().distanceTo2D(pos) < SNAP_RADIUS);
283  } else {
284  return false;
285  }
286 }
287 
288 
289 void
291  Position delta = junction->getNBNode()->getPosition() - origPos;
293  // geometry endpoint need not equal junction position hence we modify it with delta
294  if (junction == getParentJunctions().front()) {
295  geom[0].add(delta);
296  } else {
297  geom[-1].add(delta);
298  }
299  setGeometry(geom, false);
300 }
301 
302 
303 void
304 GNEEdge::updateCenteringBoundary(const bool updateGrid) {
305  // Remove object from net
306  if (updateGrid) {
308  }
309  // use as boundary the first lane boundary
310  myBoundary = myLanes.front()->getCenteringBoundary();
311  // add lane boundaries
312  for (const auto& lane : myLanes) {
313  myBoundary.add(lane->getCenteringBoundary());
314  }
315  // ensure that geometry points are selectable even if the lane geometry is strange
316  for (const Position& pos : myNBEdge->getGeometry()) {
317  myBoundary.add(pos);
318  }
319  // grow boundary
320  myBoundary.grow(10);
321  // add object into net
322  if (updateGrid) {
323  myNet->addGLObjectIntoGrid(this);
324  }
325 }
326 
327 
328 const std::string
330  return myNBEdge->getStreetName();
331 }
332 
333 
336  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
337  buildPopupHeader(ret, app);
340  // build selection and show parameters menu
343  // build position copy entry
344  buildPositionCopyEntry(ret, false);
345  return ret;
346 }
347 
348 
349 GNEEdge*
351  return myNet->retrieveEdge(getParentJunctions().back(), getParentJunctions().front(), false);
352 }
353 
354 
355 void
357  // check if boundary has to be drawn
358  if (s.drawBoundaries) {
360  }
361  // draw lanes
362  for (const auto& lane : myLanes) {
363  lane->drawGL(s);
364  }
365  // draw child additional
366  for (const auto& additional : getChildAdditionals()) {
367  additional->drawGL(s);
368  }
369  // draw person stops
371  for (const auto& personStopEdge : getChildDemandElements()) {
372  if (personStopEdge->getTagProperty().getTag() == GNE_TAG_PERSONSTOP_EDGE) {
373  personStopEdge->drawGL(s);
374  }
375  }
376  }
377  // draw vehicles
378  const std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesMap = getVehiclesOverEdgeMap();
379  for (const auto& vehicleMap : vehiclesMap) {
380  for (const auto& vehicle : vehicleMap.second) {
381  vehicle->drawGL(s);
382  }
383  }
384  // draw name if isn't being drawn for selecting
385  drawEdgeName(s);
386  // draw dotted contours
387  if (myLanes.size() > 1) {
390  }
391  if (s.drawDottedContour() || (myNet->getViewNet()->getFrontAttributeCarrier() == this)) {
393  }
394  }
395 }
396 
397 
398 NBEdge*
400  return myNBEdge;
401 }
402 
403 
404 Position
405 GNEEdge::getSplitPos(const Position& clickPos) {
406  const PositionVector& geom = myNBEdge->getGeometry();
407  int index = geom.indexOfClosest(clickPos);
408  if (geom[index].distanceTo2D(clickPos) < SNAP_RADIUS) {
409  // split at existing geometry point
410  return geom[index];
411  } else {
412  // split straight between the next two points
413  return geom.positionAtOffset(geom.nearest_offset_to_point2D(clickPos));
414  }
415 }
416 
417 
418 void
420  if ((myNBEdge->getGeometry().front() != getParentJunctions().front()->getNBNode()->getPosition()) && (myNBEdge->getGeometry().front().distanceTo2D(pos) < SNAP_RADIUS)) {
421  undoList->p_begin("remove endpoint");
422  setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
423  undoList->p_end();
424  } else if ((myNBEdge->getGeometry().back() != getParentJunctions().back()->getNBNode()->getPosition()) && (myNBEdge->getGeometry().back().distanceTo2D(pos) < SNAP_RADIUS)) {
425  undoList->p_begin("remove endpoint");
426  setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
427  undoList->p_end();
428  } else {
429  // we need to create new Start/End position over Edge shape, not over clicked position
431  if (offset != GeomHelper::INVALID_OFFSET) {
433  // calculate position over edge shape relative to clicked positino
434  Position newPos = geom.positionAtOffset2D(offset);
435  // snap new position to grid
436  newPos = myNet->getViewNet()->snapToActiveGrid(newPos);
437  undoList->p_begin("set endpoint");
438  int index = geom.indexOfClosest(pos);
439  // check if snap to existing geometry
440  if (geom[index].distanceTo2D(pos) < SNAP_RADIUS) {
441  pos = geom[index];
442  }
443  Position destPos = getParentJunctions().back()->getNBNode()->getPosition();
444  Position sourcePos = getParentJunctions().front()->getNBNode()->getPosition();
445  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
446  setAttribute(GNE_ATTR_SHAPE_END, toString(newPos), undoList);
447  getParentJunctions().back()->invalidateShape();
448  } else {
449  setAttribute(GNE_ATTR_SHAPE_START, toString(newPos), undoList);
450  getParentJunctions().front()->invalidateShape();
451  }
452  /*
453  // possibly existing inner point is no longer needed
454  if (myNBEdge->getInnerGeometry().size() > 0 && getEdgeVertexIndex(pos, false) != -1) {
455  deleteEdgeGeometryPoint(pos, false);
456  }
457  */
458  undoList->p_end();
459  }
460  }
461 }
462 
463 
464 void
466  Position destPos = getParentJunctions().back()->getNBNode()->getPosition();
467  Position sourcePos = getParentJunctions().front()->getNBNode()->getPosition();
468  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
469  setAttribute(GNE_ATTR_SHAPE_END, toString(destPos), undoList);
470  getParentJunctions().back()->invalidateShape();
471  } else {
472  setAttribute(GNE_ATTR_SHAPE_START, toString(sourcePos), undoList);
473  getParentJunctions().front()->invalidateShape();
474  }
475 }
476 
477 
478 void
480  // reset shape start
481  setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
482  getParentJunctions().back()->invalidateShape();
483  // reset shape end
484  setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
485  getParentJunctions().front()->invalidateShape();
486 }
487 
488 void
490  // set new geometry
491  const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
492  if (lefthand) {
493  geom.mirrorX();
494  myNBEdge->mirrorX();
495  }
496  myNBEdge->setGeometry(geom, inner);
497  if (lefthand) {
498  myNBEdge->mirrorX();
499  }
500  // update geometry
501  updateGeometry();
502  // invalidate junction source shape
503  getParentJunctions().front()->invalidateShape();
504  // iterate over first parent junction edges and update geometry
505  for (const auto& edge : getParentJunctions().front()->getGNEIncomingEdges()) {
506  edge->updateGeometry();
507  }
508  for (const auto& edge : getParentJunctions().front()->getGNEOutgoingEdges()) {
509  edge->updateGeometry();
510  }
511  // invalidate junction destiny shape
512  getParentJunctions().back()->invalidateShape();
513  // iterate over second parent junction edges and update geometry
514  for (const auto& edge : getParentJunctions().back()->getGNEIncomingEdges()) {
515  edge->updateGeometry();
516  }
517  for (const auto& edge : getParentJunctions().back()->getGNEOutgoingEdges()) {
518  edge->updateGeometry();
519  }
520 }
521 
522 
523 const Position
525  PositionVector laneShape = myLanes.front()->getLaneShape();
526  laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
527  return laneShape.front();
528 }
529 
530 
531 const Position
533  PositionVector laneShape = myLanes.back()->getLaneShape();
534  laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
535  return laneShape.front();
536 }
537 
538 
539 const Position
541  PositionVector laneShape = myLanes.front()->getLaneShape();
542  laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
543  return laneShape.back();
544 }
545 
546 
547 const Position
549  PositionVector laneShape = myLanes.back()->getLaneShape();
550  laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
551  return laneShape.back();
552 }
553 
554 void
556  // create new and removed unused GNEConnectinos
557  const std::vector<NBEdge::Connection>& connections = myNBEdge->getConnections();
558  // create a vector to keep retrieved and created connections
559  std::vector<GNEConnection*> retrievedConnections;
560  // iterate over NBEdge::Connections of GNEEdge
561  for (const auto& connection : connections) {
562  // retrieve existent GNEConnection, or create it
563  GNEConnection* retrievedGNEConnection = retrieveGNEConnection(connection.fromLane, connection.toEdge, connection.toLane);
564  retrievedGNEConnection->updateLinkState();
565  retrievedConnections.push_back(retrievedGNEConnection);
566  // check if previously this GNEConnections exists, and if true, remove it from myGNEConnections
567  std::vector<GNEConnection*>::iterator retrievedExists = std::find(myGNEConnections.begin(), myGNEConnections.end(), retrievedGNEConnection);
568  if (retrievedExists != myGNEConnections.end()) {
569  myGNEConnections.erase(retrievedExists);
570  } else {
571  // include reference to created GNEConnection
572  retrievedGNEConnection->incRef("GNEEdge::remakeGNEConnections");
573  }
574  // mark it as deprecated
575  retrievedGNEConnection->markConnectionGeometryDeprecated();
576  }
577  // delete non retrieved GNEConnections
578  for (const auto& connection : myGNEConnections) {
579  // decrease reference
580  connection->decRef();
581  // delete GNEConnection if is unreferenced
582  if (connection->unreferenced()) {
583  // remove it from network
584  myNet->addGLObjectIntoGrid(connection);
585  // show extra information for tests
586  WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in rebuildGNEConnections()");
587  delete connection;
588  }
589  }
590  // copy retrieved (existent and created) GNECrossigns to myGNEConnections
591  myGNEConnections = retrievedConnections;
592 }
593 
594 
595 void
597  // Drop all existents connections that aren't referenced anymore
598  for (auto i : myGNEConnections) {
599  // check if connection is selected
600  if (i->isAttributeCarrierSelected()) {
601  i->unselectAttributeCarrier();
602  }
603  // Dec reference of connection
604  i->decRef("GNEEdge::clearGNEConnections");
605  // Delete GNEConnectionToErase if is unreferenced
606  if (i->unreferenced()) {
607  // show extra information for tests
608  WRITE_DEBUG("Deleting unreferenced " + i->getTagStr() + " '" + i->getID() + "' in clearGNEConnections()");
609  delete i;
610  }
611  }
612  myGNEConnections.clear();
613 }
614 
615 
616 int
618  std::vector<GNEAdditional*> routeProbes;
619  for (auto i : getChildAdditionals()) {
620  if (i->getTagProperty().getTag() == routeProbe->getTagProperty().getTag()) {
621  routeProbes.push_back(i);
622  }
623  }
624  // return index of routeProbe in routeProbes vector
625  auto it = std::find(routeProbes.begin(), routeProbes.end(), routeProbe);
626  if (it == routeProbes.end()) {
627  return -1;
628  } else {
629  return (int)(it - routeProbes.begin());
630  }
631 }
632 
633 
634 std::vector<GNECrossing*>
636  std::vector<GNECrossing*> crossings;
637  for (auto i : getParentJunctions().front()->getGNECrossings()) {
638  if (i->checkEdgeBelong(this)) {
639  crossings.push_back(i);
640  }
641  }
642  for (auto i : getParentJunctions().back()->getGNECrossings()) {
643  if (i->checkEdgeBelong(this)) {
644  crossings.push_back(i);
645  }
646  }
647  return crossings;
648 }
649 
650 
651 void
653  // copy edge-specific attributes
655  setAttribute(SUMO_ATTR_TYPE, edgeTemplate.edgeParameters.at(SUMO_ATTR_TYPE), undoList);
658  // copy raw values for lane-specific attributes
659  if (isValid(SUMO_ATTR_SPEED, edgeTemplate.edgeParameters.at(SUMO_ATTR_SPEED))) {
660  setAttribute(SUMO_ATTR_SPEED, edgeTemplate.edgeParameters.at(SUMO_ATTR_SPEED), undoList);
661  }
662  if (isValid(SUMO_ATTR_WIDTH, edgeTemplate.edgeParameters.at(SUMO_ATTR_WIDTH))) {
663  setAttribute(SUMO_ATTR_WIDTH, edgeTemplate.edgeParameters.at(SUMO_ATTR_WIDTH), undoList);
664  }
667  }
668  // copy lane attributes as well
669  for (int i = 0; i < (int)myLanes.size(); i++) {
670  myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, edgeTemplate.laneParameters.at(i).at(SUMO_ATTR_ALLOW), undoList);
671  myLanes[i]->setAttribute(SUMO_ATTR_SPEED, edgeTemplate.laneParameters.at(i).at(SUMO_ATTR_SPEED), undoList);
672  myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, edgeTemplate.laneParameters.at(i).at(SUMO_ATTR_WIDTH), undoList);
673  myLanes[i]->setAttribute(SUMO_ATTR_ENDOFFSET, edgeTemplate.laneParameters.at(i).at(SUMO_ATTR_ENDOFFSET), undoList);
674  }
675 }
676 
677 
678 void
679 GNEEdge::copyEdgeType(const GNEEdgeType *edgeType, GNEUndoList* undoList) {
680  // set type (only for info)
681  setAttribute(SUMO_ATTR_TYPE, edgeType->getAttribute(SUMO_ATTR_ID), undoList);
682  // set num lanes
684  // set speed
686  // set allow (no disallow)
688  // set width
690  // set priority
692  // set parameters
694  // copy lane attributes as well
695  for (int i = 0; i < (int)myLanes.size(); i++) {
696  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_SPEED).size() > 0) {
697  myLanes[i]->setAttribute(SUMO_ATTR_SPEED, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_SPEED), undoList);
698  }
699  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_ALLOW).size() > 0) {
700  myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_ALLOW), undoList);
701  }
702  if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_WIDTH).size() > 0) {
703  myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_WIDTH), undoList);
704  }
705  if (edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS).size() > 0) {
706  myLanes[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
707  }
708  }
709 }
710 
711 
712 std::set<GUIGlID>
714  std::set<GUIGlID> result;
715  for (auto i : myLanes) {
716  result.insert(i->getGlID());
717  }
718  return result;
719 }
720 
721 
722 const std::vector<GNELane*>&
724  return myLanes;
725 }
726 
727 
728 const std::vector<GNEConnection*>&
730  return myGNEConnections;
731 }
732 
733 
734 bool
736  return myWasSplit;
737 }
738 
739 
740 std::string
742  switch (key) {
743  case SUMO_ATTR_ID:
744  return getID();
745  case SUMO_ATTR_FROM:
746  return getParentJunctions().front()->getID();
747  case SUMO_ATTR_TO:
748  return getParentJunctions().back()->getID();
749  case SUMO_ATTR_NUMLANES:
750  return toString(myNBEdge->getNumLanes());
751  case SUMO_ATTR_PRIORITY:
752  return toString(myNBEdge->getPriority());
753  case SUMO_ATTR_LENGTH:
754  return toString(myNBEdge->getFinalLength());
755  case SUMO_ATTR_TYPE:
756  return myNBEdge->getTypeID();
757  case SUMO_ATTR_SHAPE:
761  case SUMO_ATTR_NAME:
762  return myNBEdge->getStreetName();
763  case SUMO_ATTR_ALLOW:
764  return (getVehicleClassNames(myNBEdge->getPermissions()) + (myNBEdge->hasLaneSpecificPermissions() ? " (combined!)" : ""));
765  case SUMO_ATTR_DISALLOW: {
767  }
768  case SUMO_ATTR_SPEED:
770  return "lane specific";
771  } else {
772  return toString(myNBEdge->getSpeed());
773  }
774  case SUMO_ATTR_WIDTH:
776  return "lane specific";
777  } else {
778  return toString(myNBEdge->getLaneWidth());
779  }
780  case SUMO_ATTR_ENDOFFSET:
782  return "lane specific";
783  } else {
784  return toString(myNBEdge->getEndOffset());
785  }
786  case SUMO_ATTR_DISTANCE:
787  return toString(myNBEdge->getDistance());
789  return myConnectionStatus;
791  if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getParentJunctions().front()->getNBNode()->getPosition()) < 2) {
792  return "";
793  } else {
794  return toString(myNBEdge->getGeometry().front());
795  }
796  case GNE_ATTR_SHAPE_END:
797  if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getParentJunctions().back()->getNBNode()->getPosition()) < 2) {
798  return "";
799  } else {
800  return toString(myNBEdge->getGeometry().back());
801  }
802  case GNE_ATTR_BIDIR:
803  return toString(myNBEdge->isBidiRail());
804  case GNE_ATTR_SELECTED:
806  case GNE_ATTR_PARAMETERS:
807  return myNBEdge->getParametersStr();
808  default:
809  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
810  }
811 }
812 
813 
814 std::string
816  std::string result = getAttribute(key);
817  if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
818  result += " " + getVehicleClassNames(SVCAll, true);
819  }
820  return result;
821 }
822 
823 
824 void
825 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
826  switch (key) {
827  case SUMO_ATTR_WIDTH:
828  case SUMO_ATTR_ENDOFFSET:
829  case SUMO_ATTR_SPEED:
830  case SUMO_ATTR_ALLOW:
831  case SUMO_ATTR_DISALLOW: {
832  undoList->p_begin("change " + getTagStr() + " attribute");
833  const std::string origValue = myLanes.at(0)->getAttribute(key); // will have intermediate value of "lane specific"
834  // lane specific attributes need to be changed via lanes to allow undo
835  for (auto it : myLanes) {
836  it->setAttribute(key, value, undoList);
837  }
838  // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
839  undoList->p_add(new GNEChange_Attribute(this, key, value, origValue));
840  undoList->p_end();
841  break;
842  }
843  case SUMO_ATTR_FROM: {
844  undoList->p_begin("change " + getTagStr() + " attribute");
845  // Remove edge from crossings of junction source
846  removeEdgeFromCrossings(getParentJunctions().front(), undoList);
847  // continue changing from junction
848  GNEJunction* originalFirstParentJunction = getParentJunctions().front();
849  getParentJunctions().front()->setLogicValid(false, undoList);
850  undoList->p_add(new GNEChange_Attribute(this, key, value));
851  getParentJunctions().front()->setLogicValid(false, undoList);
852  myNet->retrieveJunction(value)->setLogicValid(false, undoList);
853  setAttribute(GNE_ATTR_SHAPE_START, toString(getParentJunctions().front()->getNBNode()->getPosition()), undoList);
854  getParentJunctions().front()->invalidateShape();
855  undoList->p_end();
856  // update geometries of all implicated junctions
857  originalFirstParentJunction->updateGeometry();
858  getParentJunctions().front()->updateGeometry();
859  getParentJunctions().back()->updateGeometry();
860  break;
861  }
862  case SUMO_ATTR_TO: {
863  undoList->p_begin("change " + getTagStr() + " attribute");
864  // Remove edge from crossings of junction destiny
865  removeEdgeFromCrossings(getParentJunctions().back(), undoList);
866  // continue changing destiny junction
867  GNEJunction* originalSecondParentJunction = getParentJunctions().back();
868  getParentJunctions().back()->setLogicValid(false, undoList);
869  undoList->p_add(new GNEChange_Attribute(this, key, value));
870  getParentJunctions().back()->setLogicValid(false, undoList);
871  myNet->retrieveJunction(value)->setLogicValid(false, undoList);
872  setAttribute(GNE_ATTR_SHAPE_END, toString(getParentJunctions().back()->getNBNode()->getPosition()), undoList);
873  getParentJunctions().back()->invalidateShape();
874  undoList->p_end();
875  // update geometries of all implicated junctions
876  originalSecondParentJunction->updateGeometry();
877  getParentJunctions().back()->updateGeometry();
878  getParentJunctions().front()->updateGeometry();
879  break;
880  }
881  case SUMO_ATTR_ID:
882  case SUMO_ATTR_PRIORITY:
883  case SUMO_ATTR_LENGTH:
884  case SUMO_ATTR_TYPE:
886  case SUMO_ATTR_DISTANCE:
889  case GNE_ATTR_SHAPE_END:
890  case GNE_ATTR_SELECTED:
891  case GNE_ATTR_PARAMETERS:
892  undoList->p_add(new GNEChange_Attribute(this, key, value));
893  break;
894  case SUMO_ATTR_NAME:
895  // user cares about street names. Make sure they appear in the output
897  OptionsCont::getOptions().set("output.street-names", "true");
898  undoList->p_add(new GNEChange_Attribute(this, key, value));
899  break;
900  case SUMO_ATTR_NUMLANES:
901  if (value != getAttribute(key)) {
902  // set num lanes
903  setNumLanes(parse<int>(value), undoList);
904  }
905  break;
906  case SUMO_ATTR_SHAPE:
907  // @note: assumes value of inner geometry!
908  // actually the geometry is already updated (incrementally
909  // during mouse movement). We set the restore point to the end
910  // of the last change-set
911  undoList->p_add(new GNEChange_Attribute(this, key, value));
912  break;
913  case GNE_ATTR_BIDIR:
914  throw InvalidArgument("Attribute of '" + toString(key) + "' cannot be modified");
915  default:
916  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
917  }
918 }
919 
920 
921 bool
922 GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
923  switch (key) {
924  case SUMO_ATTR_ID:
925  return SUMOXMLDefinitions::isValidNetID(value) && (myNet->retrieveEdge(value, false) == nullptr);
926  case SUMO_ATTR_FROM: {
927  // check that is a valid ID and is different of ID of junction destiny
928  if (SUMOXMLDefinitions::isValidNetID(value) && (value != getParentJunctions().back()->getID())) {
929  GNEJunction* junctionFrom = myNet->retrieveJunction(value, false);
930  // check that there isn't already another edge with the same From and To Edge
931  if ((junctionFrom != nullptr) && (myNet->retrieveEdge(junctionFrom, getParentJunctions().back(), false) == nullptr)) {
932  return true;
933  } else {
934  return false;
935  }
936  } else {
937  return false;
938  }
939  }
940  case SUMO_ATTR_TO: {
941  // check that is a valid ID and is different of ID of junction Source
942  if (SUMOXMLDefinitions::isValidNetID(value) && (value != getParentJunctions().front()->getID())) {
943  GNEJunction* junctionTo = myNet->retrieveJunction(value, false);
944  // check that there isn't already another edge with the same From and To Edge
945  if ((junctionTo != nullptr) && (myNet->retrieveEdge(getParentJunctions().front(), junctionTo, false) == nullptr)) {
946  return true;
947  } else {
948  return false;
949  }
950  } else {
951  return false;
952  }
953  }
954  case SUMO_ATTR_SPEED:
955  return canParse<double>(value) && (parse<double>(value) > 0);
956  case SUMO_ATTR_NUMLANES:
957  return canParse<int>(value) && (parse<double>(value) > 0);
958  case SUMO_ATTR_PRIORITY:
959  return canParse<int>(value);
960  case SUMO_ATTR_LENGTH:
961  return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
962  case SUMO_ATTR_ALLOW:
963  case SUMO_ATTR_DISALLOW:
964  return canParseVehicleClasses(value);
965  case SUMO_ATTR_TYPE:
966  return true;
967  case SUMO_ATTR_SHAPE:
968  // empty shapes are allowed
969  return canParse<PositionVector>(value);
972  case SUMO_ATTR_NAME:
973  return true;
974  case SUMO_ATTR_WIDTH:
975  return canParse<double>(value) && ((parse<double>(value) >= -1) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
976  case SUMO_ATTR_ENDOFFSET:
977  return canParse<double>(value) && parse<double>(value) >= 0 && parse<double>(value) < myNBEdge->getLoadedLength();
978  case SUMO_ATTR_DISTANCE:
979  return canParse<double>(value);
980  case GNE_ATTR_SHAPE_START: {
981  if (value.empty()) {
982  return true;
983  } else if (canParse<Position>(value)) {
984  Position shapeStart = parse<Position>(value);
985  return (shapeStart != myNBEdge->getGeometry()[-1]);
986  } else {
987  return false;
988  }
989  }
990  case GNE_ATTR_SHAPE_END: {
991  if (value.empty()) {
992  return true;
993  } else if (canParse<Position>(value)) {
994  Position shapeEnd = parse<Position>(value);
995  return (shapeEnd != myNBEdge->getGeometry()[0]);
996  } else {
997  return false;
998  }
999  }
1000  case GNE_ATTR_BIDIR:
1001  return false;
1002  case GNE_ATTR_SELECTED:
1003  return canParse<bool>(value);
1004  case GNE_ATTR_PARAMETERS:
1005  return Parameterised::areParametersValid(value);
1006  default:
1007  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1008  }
1009 }
1010 
1011 
1012 bool
1014  switch (key) {
1015  case GNE_ATTR_BIDIR:
1016  return false;
1017  default:
1018  return true;
1019  }
1020 }
1021 
1022 
1023 const std::map<std::string, std::string>&
1025  return myNBEdge->getParametersMap();
1026 }
1027 
1028 
1029 void
1031  myAmResponsible = newVal;
1032 }
1033 
1034 
1035 GNELane*
1037  // iterate over all NBEdge lanes
1038  for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1039  // if given VClass is in permissions, return lane
1040  if (myNBEdge->getLanes().at(i).permissions & vClass) {
1041  // return GNELane
1042  return myLanes.at(i);
1043  }
1044  }
1045  // return first lane
1046  return myLanes.front();
1047 }
1048 
1049 
1050 GNELane*
1052  // iterate over all NBEdge lanes
1053  for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1054  // if given VClass isn't in permissions, return lane
1055  if (~(myNBEdge->getLanes().at(i).permissions) & vClass) {
1056  // return GNELane
1057  return myLanes.at(i);
1058  }
1059  }
1060  // return first lane
1061  return myLanes.front();
1062 }
1063 
1064 
1065 void
1067  // get lane vehicles map
1068  const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1069  // iterate over every lane
1070  for (const auto& laneVehicle : laneVehiclesMap) {
1071  // obtain total lenght
1072  double totalLength = 0;
1073  for (const auto& vehicle : laneVehicle.second) {
1074  totalLength += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1075  }
1076  // calculate multiplier for vehicle positions
1077  double multiplier = 1;
1078  const double laneShapeLenght = laneVehicle.first->getLaneShape().length();
1079  if (laneShapeLenght == 0) {
1080  multiplier = 0;
1081  } else if (totalLength > laneShapeLenght) {
1082  multiplier = (laneShapeLenght / totalLength);
1083  }
1084  // declare current lenght
1085  double lenght = 0;
1086  // iterate over vehicles to calculate position and rotations
1087  for (const auto& vehicle : laneVehicle.second) {
1088  vehicle->updateDemandElementSpreadGeometry(laneVehicle.first, lenght * multiplier);
1089  // update lenght
1090  lenght += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1091  }
1092  }
1093 }
1094 
1095 
1096 void
1098  // get lane vehicles map
1099  const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1100  // iterate over laneVehiclesMap and obtain a vector with
1101  for (const auto& vehicleMap : laneVehiclesMap) {
1102  // declare map for sprt vehicles using their departpos+lenght position (StackPosition)
1103  std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosVehicles;
1104  // declare vector of stack demand elements
1105  std::vector<GNEEdge::StackDemandElements> stackedVehicles;
1106  // iterate over vehicles
1107  for (const auto& vehicle : vehicleMap.second) {
1108  // get vehicle's depart pos and lenght
1109  const double departPos = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1110  const double length = vehicle->getAttributeDouble(SUMO_ATTR_LENGTH);
1111  double posOverLane = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1112  // check if we have to adapt posOverLane
1113  if (posOverLane < 0) {
1114  posOverLane += vehicleMap.first->getLaneShape().length();
1115  }
1116  // make a stack position using departPos and length
1117  departPosVehicles.push_back(std::make_pair(StackPosition(departPos, length), vehicle));
1118  // update depart element geometry
1119  vehicle->updateDemandElementGeometry(vehicleMap.first, posOverLane);
1120  // reset vehicle stack label
1121  vehicle->updateDemandElementStackLabel(0);
1122  }
1123 
1124  // sort departPosVehicles
1125  std::sort(departPosVehicles.begin(), departPosVehicles.end());
1126  // iterate over departPosVehicles
1127  for (const auto& departPosVehicle : departPosVehicles) {
1128  // obtain stack position and vehicle
1129  const GNEEdge::StackPosition& vehicleStackPosition = departPosVehicle.first;
1130  GNEDemandElement* vehicle = departPosVehicle.second;
1131  // if stackedVehicles is empty, add a new StackDemandElements
1132  if (stackedVehicles.empty()) {
1133  stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1134  } else if (areStackPositionOverlapped(vehicleStackPosition, stackedVehicles.back().getStackPosition())) {
1135  // add new vehicle to last inserted stackDemandElements
1136  stackedVehicles[stackedVehicles.size() - 1].addDemandElements(vehicle);
1137  } else {
1138  // No overlapping, then add a new StackDemandElements
1139  stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1140  }
1141  }
1142  // iterate over stackedVehicles
1143  for (const auto& vehicle : stackedVehicles) {
1144  // only update vehicles with one or more stack
1145  if (vehicle.getDemandElements().size() > 1) {
1146  // set stack labels
1147  vehicle.getDemandElements().front()->updateDemandElementStackLabel((int)vehicle.getDemandElements().size());
1148  }
1149  }
1150  }
1151 }
1152 
1153 
1154 void
1156  // first check conditions
1157  if ((lane == myLanes.back()) && (s.scale > 8.0) && !myNet->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {
1158  // Obtain exaggeration of the draw
1159  const double exaggeration = s.addSize.getExaggeration(s, this);
1160  // get circle width
1161  bool drawBigGeometryPoints = false;
1163  drawBigGeometryPoints = true;
1164  }
1167  drawBigGeometryPoints = true;
1168  }
1169  double circleWidth = drawBigGeometryPoints ? SNAP_RADIUS * MIN2((double)1, s.laneWidthExaggeration) : 0.5;
1170  double circleWidthSquared = circleWidth * circleWidth;
1171  // obtain color
1172  RGBColor color = s.junctionColorer.getSchemes()[0].getColor(2);
1173  if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
1174  // override with special colors (unless the color scheme is based on selection)
1176  }
1177  GLHelper::setColor(color);
1178  // recognize full transparency and simply don't draw
1179  if (color.alpha() > 0) {
1180  // add edge layer matrix
1181  glPushMatrix();
1182  // translate to front
1183  glTranslated(0, 0, 1);
1184  // draw geometry points expect initial and final
1185  for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
1186  Position pos = myNBEdge->getGeometry()[i];
1187  if (!s.drawForRectangleSelection || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(pos) <= (circleWidthSquared + 2))) {
1188  glPushMatrix();
1189  glTranslated(pos.x(), pos.y(), 0.1);
1190  // resolution of drawn circle depending of the zoom (To improve smothness)
1192  glPopMatrix();
1193  // draw elevation or special symbols (Start, End and Block)
1195  glPushMatrix();
1196  // Translate to geometry point
1197  glTranslated(pos.x(), pos.y(), 0.2);
1198  // draw Z value
1200  glPopMatrix();
1201  }
1202  }
1203  }
1204  // draw line geometry, start and end points if shapeStart or shape end is edited, and depending of drawForRectangleSelection
1205  if (drawBigGeometryPoints) {
1206  if ((myNBEdge->getGeometry().front() != getParentJunctions().front()->getNBNode()->getPosition()) &&
1207  (!s.drawForRectangleSelection || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(myNBEdge->getGeometry().front()) <= (circleWidthSquared + 2)))) {
1208  glPushMatrix();
1209  glTranslated(myNBEdge->getGeometry().front().x(), myNBEdge->getGeometry().front().y(), 0.1);
1210  // resolution of drawn circle depending of the zoom (To improve smothness)
1212  glPopMatrix();
1213  // draw a "s" over last point depending of drawForRectangleSelection
1215  glPushMatrix();
1216  glTranslated(myNBEdge->getGeometry().front().x(), myNBEdge->getGeometry().front().y(), 0.2);
1217  GLHelper::drawText("S", Position(), 0, circleWidth, RGBColor::WHITE);
1218  glPopMatrix();
1219  // draw line between Junction and point
1220  glPushMatrix();
1221  glTranslated(0, 0, 0.1);
1222  glLineWidth(4);
1223  GLHelper::drawLine(myNBEdge->getGeometry().front(), getParentJunctions().front()->getNBNode()->getPosition());
1224  // draw line between begin point of last lane shape and the first edge shape point
1225  GLHelper::drawLine(myNBEdge->getGeometry().front(), myNBEdge->getLanes().back().shape.front());
1226  glPopMatrix();
1227  }
1228  }
1229  if ((myNBEdge->getGeometry().back() != getParentJunctions().back()->getNBNode()->getPosition()) &&
1230  (!s.drawForRectangleSelection || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(myNBEdge->getGeometry().back()) <= (circleWidthSquared + 2)))) {
1231  glPushMatrix();
1232  glTranslated(myNBEdge->getGeometry().back().x(), myNBEdge->getGeometry().back().y(), 0.1);
1233  // resolution of drawn circle depending of the zoom (To improve smothness)
1235  glPopMatrix();
1236  // draw a "e" over last point depending of drawForRectangleSelection
1238  glPushMatrix();
1239  glTranslated(myNBEdge->getGeometry().back().x(), myNBEdge->getGeometry().back().y(), 0.2);
1240  GLHelper::drawText("E", Position(), 0, circleWidth, RGBColor::WHITE);
1241  glPopMatrix();
1242  // draw line between Junction and point
1243  glPushMatrix();
1244  glTranslated(0, 0, 0.1);
1245  glLineWidth(4);
1246  GLHelper::drawLine(myNBEdge->getGeometry().back(), getParentJunctions().back()->getNBNode()->getPosition());
1247  // draw line between last point of first lane shape and the last edge shape point
1248  GLHelper::drawLine(myNBEdge->getGeometry().back(), myNBEdge->getLanes().back().shape.back());
1249  glPopMatrix();
1250  }
1251  }
1252  }
1253  // pop edge layer matrix
1254  glPopMatrix();
1255  }
1256  }
1257 }
1258 
1259 // ===========================================================================
1260 // private
1261 // ===========================================================================
1262 
1263 GNEEdge::StackPosition::StackPosition(const double departPos, const double length) :
1264  tuple(departPos, departPos + length) {
1265 }
1266 
1267 
1268 double
1270  return std::get<0>(*this);
1271 }
1272 
1273 
1274 double
1276  return std::get<1>(*this);
1277 }
1278 
1279 
1281  tuple(stackedPosition, {
1282  demandElement
1283 }) {
1284 }
1285 
1286 
1287 void
1289  std::get<1>(*this).push_back(demandElement);
1290 }
1291 
1292 
1295  return std::get<0>(*this);
1296 }
1297 
1298 
1299 const std::vector<GNEDemandElement*>&
1301  return std::get<1>(*this);
1302 }
1303 
1304 
1305 void
1306 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
1307  switch (key) {
1308  case SUMO_ATTR_ID:
1309  myNet->getAttributeCarriers()->updateID(this, value);
1310  break;
1311  case SUMO_ATTR_FROM:
1312  myNet->changeEdgeEndpoints(this, value, getParentJunctions().back()->getID());
1313  // update this edge of list of outgoings edges of the old first parent junction
1314  getParentJunctions().front()->removeOutgoingGNEEdge(this);
1315  // update first parent junction
1317  // update this edge of list of outgoings edges of the new first parent junction
1318  getParentJunctions().front()->addOutgoingGNEEdge(this);
1319  // update centering boundary and grid
1321  break;
1322  case SUMO_ATTR_TO:
1323  myNet->changeEdgeEndpoints(this, getParentJunctions().front()->getID(), value);
1324  // update this edge of list of incomings edges of the old second parent junction
1325  getParentJunctions().back()->removeIncomingGNEEdge(this);
1326  // update second parent junction
1328  // update this edge of list of incomings edges of the new second parent junction
1329  getParentJunctions().back()->addIncomingGNEEdge(this);
1330  // update centering boundary and grid
1332  break;
1333  case SUMO_ATTR_NUMLANES:
1334  throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
1335  break;
1336  case SUMO_ATTR_PRIORITY:
1337  myNBEdge->myPriority = parse<int>(value);
1338  break;
1339  case SUMO_ATTR_LENGTH:
1340  myNBEdge->setLoadedLength(parse<double>(value));
1341  break;
1342  case SUMO_ATTR_TYPE:
1343  myNBEdge->myType = value;
1344  break;
1345  case SUMO_ATTR_SHAPE:
1346  // set new geometry
1347  setGeometry(parse<PositionVector>(value), true);
1348  // update centering boundary and grid
1350  break;
1351  case SUMO_ATTR_SPREADTYPE:
1353  break;
1354  case SUMO_ATTR_NAME:
1355  myNBEdge->setStreetName(value);
1356  break;
1357  case SUMO_ATTR_SPEED:
1358  myNBEdge->setSpeed(-1, parse<double>(value));
1359  break;
1360  case SUMO_ATTR_WIDTH:
1361  myNBEdge->setLaneWidth(-1, parse<double>(value));
1362  break;
1363  case SUMO_ATTR_ENDOFFSET:
1364  myNBEdge->setEndOffset(-1, parse<double>(value));
1365  break;
1366  case SUMO_ATTR_ALLOW:
1367  break; // no edge value
1368  case SUMO_ATTR_DISALLOW:
1369  break; // no edge value
1370  case SUMO_ATTR_DISTANCE:
1371  myNBEdge->setDistance(parse<double>(value));
1372  break;
1374  myConnectionStatus = value;
1375  if (value == FEATURE_GUESSED) {
1376  WRITE_DEBUG("invalidating (removing) connections of edge '" + getID() + "' due it were guessed");
1379  } else if (value != FEATURE_GUESSED) {
1380  WRITE_DEBUG("declaring connections of edge '" + getID() + "' as loaded (It will not be removed)");
1382  }
1383  break;
1384  case GNE_ATTR_SHAPE_START: {
1385  // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1386  Position newShapeStart;
1387  if (value == "") {
1388  newShapeStart = getParentJunctions().front()->getNBNode()->getPosition();
1389  } else {
1390  newShapeStart = parse<Position>(value);
1391  }
1392  // set shape start position
1393  setShapeStartPos(newShapeStart);
1394  // update centering boundary and grid
1396  break;
1397  }
1398  case GNE_ATTR_SHAPE_END: {
1399  // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destiny position) and set it back to edge
1400  Position newShapeEnd;
1401  if (value == "") {
1402  newShapeEnd = getParentJunctions().back()->getNBNode()->getPosition();
1403  } else {
1404  newShapeEnd = parse<Position>(value);
1405  }
1406  // set shape end position
1407  setShapeEndPos(newShapeEnd);
1408  // update centering boundary and grid
1410  break;
1411  }
1412  case GNE_ATTR_BIDIR:
1413  throw InvalidArgument("Attribute of '" + toString(key) + "' cannot be modified");
1414  case GNE_ATTR_SELECTED:
1415  if (parse<bool>(value)) {
1417  } else {
1419  }
1420  break;
1421  case GNE_ATTR_PARAMETERS:
1422  myNBEdge->setParametersStr(value);
1423  break;
1424  default:
1425  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1426  }
1427 }
1428 
1429 
1430 void
1432  // get start and end points
1433  const Position shapeStart = moveResult.shapeToUpdate.front();
1434  const Position shapeEnd = moveResult.shapeToUpdate.back();
1435  // get innen shape
1436  PositionVector innenShape = moveResult.shapeToUpdate;
1437  innenShape.pop_front();
1438  innenShape.pop_back();
1439  // set shape start
1440  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
1441  setShapeStartPos(shapeStart);
1442  }
1443  // set innen geometry
1444  setGeometry(innenShape, true);
1445  // set shape end
1446  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), ((int)moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
1447  setShapeEndPos(shapeEnd);
1448  }
1449 }
1450 
1451 
1452 void
1453 GNEEdge::commitMoveShape(const GNEMoveResult& moveResult, GNEUndoList* undoList) {
1454  // make sure that newShape isn't empty
1455  if (moveResult.shapeToUpdate.size() > 0) {
1456  // get start and end points
1457  const Position shapeStart = moveResult.shapeToUpdate.front();
1458  const Position shapeEnd = moveResult.shapeToUpdate.back();
1459  // get innen shape
1460  PositionVector innenShape = moveResult.shapeToUpdate;
1461  innenShape.pop_front();
1462  innenShape.pop_back();
1463  // commit new shape
1464  undoList->p_begin("moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
1465  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
1466  undoList->p_add(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_START, toString(shapeStart)));
1467  }
1468  // update shape
1469  undoList->p_add(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(innenShape)));
1470  // check if we have to update shape end
1471  if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), (moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
1472  undoList->p_add(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_END, toString(shapeEnd)));
1473  }
1474  undoList->p_end();
1475  }
1476 }
1477 
1478 
1479 void
1480 GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
1481  // begin undo list
1482  undoList->p_begin("change number of " + toString(SUMO_TAG_LANE) + "s");
1483  // invalidate logic of source/destiny edges
1484  getParentJunctions().front()->setLogicValid(false, undoList);
1485  getParentJunctions().back()->setLogicValid(false, undoList);
1486  // disable update geometry (see #6336)
1487  myUpdateGeometry = false;
1488  const int oldNumLanes = (int)myLanes.size();
1489  for (int i = oldNumLanes; i < numLanes; i++) {
1490  // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
1491  undoList->add(new GNEChange_Lane(this, myNBEdge->getLaneStruct(oldNumLanes - 1)), true);
1492  }
1493  for (int i = (oldNumLanes - 1); i > (numLanes - 1); i--) {
1494  // delete leftmost lane
1495  undoList->add(new GNEChange_Lane(this, myLanes[i], myNBEdge->getLaneStruct(i), false), true);
1496  }
1497  // enable updateGeometry again
1498  myUpdateGeometry = true;
1499  // update geometry of entire edge
1500  updateGeometry();
1501  // end undo list
1502  undoList->p_end();
1503  // update centering boundary and grid
1505 }
1506 
1507 
1508 void
1509 GNEEdge::updateFirstParentJunction(const std::string& value) {
1510  std::vector<GNEJunction*> parentJunctions = getParentJunctions();
1511  parentJunctions[0] = myNet->retrieveJunction(value);
1512  // replace parent junctions
1513  replaceParentElements(this, parentJunctions);
1514 }
1515 
1516 
1517 void
1518 GNEEdge::updateSecondParentJunction(const std::string& value) {
1519  std::vector<GNEJunction*> parentJunctions = getParentJunctions();
1520  parentJunctions[1] = myNet->retrieveJunction(value);
1521  // replace parent junctions
1522  replaceParentElements(this, parentJunctions);
1523 }
1524 
1525 
1526 void
1527 GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections) {
1528  const int index = lane ? lane->getIndex() : myNBEdge->getNumLanes();
1529  // the laneStruct must be created first to ensure we have some geometry
1530  // unless the connections are fully recomputed, existing indices must be shifted
1531  myNBEdge->addLane(index, true, recomputeConnections, !recomputeConnections);
1532  if (lane) {
1533  // restore a previously deleted lane
1534  myLanes.insert(myLanes.begin() + index, lane);
1535 
1536  } else {
1537  // create a new lane by copying leftmost lane
1538  lane = new GNELane(this, index);
1539  myLanes.push_back(lane);
1540  }
1541  lane->incRef("GNEEdge::addLane");
1542  // check if lane is selected
1543  if (lane->isAttributeCarrierSelected()) {
1544  lane->selectAttributeCarrier();
1545  }
1546  // we copy all attributes except shape since this is recomputed from edge shape
1547  myNBEdge->setSpeed(lane->getIndex(), laneAttrs.speed);
1548  myNBEdge->setPermissions(laneAttrs.permissions, lane->getIndex());
1549  myNBEdge->setPreferredVehicleClass(laneAttrs.preferred, lane->getIndex());
1550  myNBEdge->setEndOffset(lane->getIndex(), laneAttrs.endOffset);
1551  myNBEdge->setLaneWidth(lane->getIndex(), laneAttrs.width);
1552  // udate indices
1553  for (int i = 0; i < (int)myLanes.size(); ++i) {
1554  myLanes[i]->setIndex(i);
1555  }
1556  /* while technically correct, this looks ugly
1557  getParentJunctions().front()->invalidateShape();
1558  getParentJunctions().back()->invalidateShape();
1559  */
1560  // Remake connections for this edge and all edges that target this lane
1562  // remake connections of all edges of junction source and destiny
1563  for (auto i : getParentJunctions().front()->getChildEdges()) {
1564  i->remakeGNEConnections();
1565  }
1566  // remake connections of all edges of junction source and destiny
1567  for (auto i : getParentJunctions().back()->getChildEdges()) {
1568  i->remakeGNEConnections();
1569  }
1570  // Update geometry with the new lane
1571  updateGeometry();
1572  // update boundary and grid
1574 }
1575 
1576 
1577 void
1578 GNEEdge::removeLane(GNELane* lane, bool recomputeConnections) {
1579  if (myLanes.size() == 0) {
1580  throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + getTagStr());
1581  }
1582  if (lane == nullptr) {
1583  lane = myLanes.back();
1584  }
1585  // check if lane is selected
1586  if (lane->isAttributeCarrierSelected()) {
1587  lane->unselectAttributeCarrier();
1588  }
1589  // before removing, check that lane isn't being inspected
1592  // Delete lane of edge's container
1593  // unless the connections are fully recomputed, existing indices must be shifted
1594  myNBEdge->deleteLane(lane->getIndex(), recomputeConnections, !recomputeConnections);
1595  lane->decRef("GNEEdge::removeLane");
1596  myLanes.erase(myLanes.begin() + lane->getIndex());
1597  // Delete lane if is unreferenced
1598  if (lane->unreferenced()) {
1599  // show extra information for tests
1600  WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in removeLane()");
1601  delete lane;
1602  }
1603  // udate indices
1604  for (int i = 0; i < (int)myLanes.size(); ++i) {
1605  myLanes[i]->setIndex(i);
1606  }
1607  /* while technically correct, this looks ugly
1608  getParentJunctions().front()->invalidateShape();
1609  getParentJunctions().back()->invalidateShape();
1610  */
1611  // Remake connections of this edge
1613  // remake connections of all edges of junction source and destiny
1614  for (auto i : getParentJunctions().front()->getChildEdges()) {
1615  i->remakeGNEConnections();
1616  }
1617  // remake connections of all edges of junction source and destiny
1618  for (auto i : getParentJunctions().back()->getChildEdges()) {
1619  i->remakeGNEConnections();
1620  }
1621  // Update element
1622  updateGeometry();
1623  // update boundary and grid
1625 }
1626 
1627 
1628 void
1629 GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
1630  // If a new connection was sucesfully created
1632  nbCon.keepClear, nbCon.contPos, nbCon.visibility,
1633  nbCon.speed, nbCon.customLength, nbCon.customShape, nbCon.uncontrolled)) {
1634  // Create or retrieve existent GNEConection
1635  GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
1636  // add it to GNEConnection container
1637  myGNEConnections.push_back(con);
1638  // Add reference
1639  myGNEConnections.back()->incRef("GNEEdge::addConnection");
1640  // select GNEConnection if needed
1641  if (selectAfterCreation) {
1642  con->selectAttributeCarrier();
1643  }
1644  // update geometry
1645  con->updateGeometry();
1646  }
1647  // actually we only do this to force a redraw
1648  updateGeometry();
1649 }
1650 
1651 
1652 void
1654  // check if is a explicit turnaround
1655  if (nbCon.toEdge == myNBEdge->getTurnDestination()) {
1657  }
1658  // remove NBEdge::connection from NBEdge
1660  // remove their associated GNEConnection
1661  GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
1662  if (con != nullptr) {
1663  con->decRef("GNEEdge::removeConnection");
1664  myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), con));
1665  // check if connection is selected
1666  if (con->isAttributeCarrierSelected()) {
1667  con->unselectAttributeCarrier();
1668  }
1669  if (con->unreferenced()) {
1670  // show extra information for tests
1671  WRITE_DEBUG("Deleting unreferenced " + con->getTagStr() + " '" + con->getID() + "' in removeConnection()");
1672  delete con;
1673  // actually we only do this to force a redraw
1674  updateGeometry();
1675  }
1676  }
1677 }
1678 
1679 
1681 GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
1682  for (auto i : myGNEConnections) {
1683  if ((i->getFromLaneIndex() == fromLane) && (i->getEdgeTo()->getNBEdge() == to) && (i->getToLaneIndex() == toLane)) {
1684  return i;
1685  }
1686  }
1687  if (createIfNoExist) {
1688  // create new connection. Will be added to the rTree on first geometry computation
1689  GNEConnection* createdConnection = new GNEConnection(myLanes[fromLane], myNet->retrieveEdge(to->getID())->getLanes()[toLane]);
1690  // show extra information for tests
1691  WRITE_DEBUG("Created " + createdConnection->getTagStr() + " '" + createdConnection->getID() + "' in retrieveGNEConnection()");
1692  // add it into network
1693  myNet->addGLObjectIntoGrid(createdConnection);
1694  return createdConnection;
1695  } else {
1696  return nullptr;
1697  }
1698 }
1699 
1700 
1701 
1702 void
1703 GNEEdge::setMicrosimID(const std::string& newID) {
1705  for (auto i : myLanes) {
1706  i->setMicrosimID(getNBEdge()->getLaneID(i->getIndex()));
1707  }
1708 }
1709 
1710 
1711 bool
1713  for (auto i : myLanes) {
1714  if (i->isRestricted(vclass)) {
1715  return true;
1716  }
1717  }
1718  return false;
1719 }
1720 
1721 
1722 void
1724  // Remove all crossings that contain this edge in parameter "edges"
1725  for (GNECrossing* const i : junction->getGNECrossings()) {
1726  if (i->checkEdgeBelong(this)) {
1727  myNet->deleteCrossing(i, undoList);
1728  }
1729  }
1730 }
1731 
1732 
1733 void
1735  PositionVector modifiedShape = myNBEdge->getGeometry().interpolateZ(
1737  myNBEdge->getToNode()->getPosition().z());
1738  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
1739  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
1740 }
1741 
1742 
1744 GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
1745  const OptionsCont& oc = OptionsCont::getOptions();
1746  // distinguish 3 cases:
1747  // a) if the edge has exactly 3 or 4 points, use these as control points
1748  // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
1749  // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
1750  PositionVector init;
1751 #ifdef DEBUG_SMOOTH_GEOM
1752  if (DEBUGCOND(this)) std::cout << getID()
1753  << " forElevation=" << forElevation
1754  << " fromGeometryLike=" << myNBEdge->getFromNode()->geometryLike()
1755  << " toGeometryLike=" << myNBEdge->getToNode()->geometryLike()
1756  << " smoothShape old=" << old << "\n";
1757 #endif
1758  if (old.size() == 3 || old.size() == 4) {
1759  init = old;
1760  } else if (old.size() > 4 && !forElevation) {
1761  // for elevation, the initial segments are not useful
1762  init.push_back(old[0]);
1763  init.push_back(old[1]);
1764  init.push_back(old[-2]);
1765  init.push_back(old[-1]);
1766  } else if (myNBEdge->getFromNode()->geometryLike() && myNBEdge->getToNode()->geometryLike()) {
1767  PositionVector begShape;
1768  PositionVector endShape;
1769  const EdgeVector& incoming = myNBEdge->getFromNode()->getIncomingEdges();
1770  const EdgeVector& outgoing = myNBEdge->getToNode()->getOutgoingEdges();
1771  if (incoming.size() == 1) {
1772  begShape = incoming[0]->getGeometry();
1773  } else {
1774  assert(incoming.size() == 2);
1775  begShape = myNBEdge->isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
1776  }
1777  if (outgoing.size() == 1) {
1778  endShape = outgoing[0]->getGeometry();
1779  } else {
1780  assert(outgoing.size() == 2);
1781  endShape = myNBEdge->isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
1782  }
1783  const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
1784  if (forElevation) {
1785  // initialize control point elevation for smooth continuation
1786  init.push_back(old[0]);
1787  init.push_back(old.positionAtOffset2D(dist));
1788  init.push_back(old.positionAtOffset2D(old.length2D() - dist));
1789  init.push_back(old[-1]);
1790  double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
1791  double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
1792  // continue incline
1793  init[1].setz(2 * init[0].z() - begZ);
1794  init[2].setz(2 * init[-1].z() - endZ);
1795  } else {
1796  bool ok = true;
1797  const double straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold"));
1798  init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, nullptr, straightThresh);
1799  }
1800 #ifdef DEBUG_SMOOTH_GEOM
1801  if (DEBUGCOND(this)) {
1802  std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
1803  }
1804 #endif
1805  }
1806  if (init.size() == 0) {
1807  return PositionVector::EMPTY;
1808  } else {
1809  const int numPoints = MAX2(oc.getInt("junctions.internal-link-detail"),
1810  int(old.length2D() / oc.getFloat("opendrive.curve-resolution")));
1811  return init.bezier(numPoints);
1812  }
1813 }
1814 
1815 
1816 void
1818  PositionVector modifiedShape = smoothShape(myNBEdge->getGeometry(), false);
1819  if (modifiedShape.size() < 2) {
1820  WRITE_WARNING("Could not compute smooth shape for edge '" + getID() + "'");
1821  } else {
1822  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
1823  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
1824  }
1825 }
1826 
1827 
1828 void
1830  PositionVector elevationBase;
1831  for (const Position& pos : myNBEdge->getGeometry()) {
1832  if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
1833  elevationBase.push_back(pos);
1834  }
1835  }
1836  PositionVector elevation = smoothShape(elevationBase, true);
1837  if (elevation.size() <= 2) {
1838  WRITE_WARNING("Could not compute smooth elevation for edge '" + getID() + "'");
1839  } else {
1840  PositionVector modifiedShape = myNBEdge->getGeometry();
1841  if (modifiedShape.size() < 5) {
1842  modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"), false);
1843  }
1844  const double scale = elevation.length2D() / modifiedShape.length2D();
1845  //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
1846  double seen = 0;
1847  for (int i = 1; i < (int)modifiedShape.size(); ++i) {
1848  seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
1849  modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
1850  }
1851  //std::cout << " mod2=" << modifiedShape << "\n";
1852  PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
1853  setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
1854  }
1855 }
1856 
1857 
1858 void
1860  // remove start position and add it the new position
1862  geom.pop_front();
1863  geom.push_front(pos);
1864  // restore modified shape
1865  setGeometry(geom, false);
1866 }
1867 
1868 
1869 void
1871  // remove end position and add it the new position
1873  geom.pop_back();
1874  geom.push_back(pos);
1875  // restore modified shape
1876  setGeometry(geom, false);
1877 }
1878 
1879 
1880 const std::map<const GNELane*, std::vector<GNEDemandElement*> >
1882  // declare vehicles over edge vector
1883  std::vector<GNEDemandElement*> vehiclesOverEdge;
1884  // declare solution map
1885  std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesOverEdgeMap;
1886  // declare a set of vehicles (to avoid duplicates)
1887  std::set<std::pair<double, GNEDemandElement*> > vehicles;
1888  // first obtain all vehicles of this edge
1889  for (const auto& edgeChild : getChildDemandElements()) {
1890  if (((edgeChild->getTagProperty().getTag() == SUMO_TAG_TRIP) || (edgeChild->getTagProperty().getTag() == SUMO_TAG_FLOW)) &&
1891  (edgeChild->getParentEdges().front() == this)) {
1892  vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
1893  vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
1894  } else if ((edgeChild->getTagProperty().getTag() == SUMO_TAG_ROUTE) && (edgeChild->getParentEdges().front() == this)) {
1895  for (const auto& routeChild : edgeChild->getChildDemandElements()) {
1896  if ((routeChild->getTagProperty().getTag() == SUMO_TAG_VEHICLE) || (routeChild->getTagProperty().getTag() == GNE_TAG_FLOW_ROUTE)) {
1897  vehicles.insert(std::make_pair(routeChild->getAttributeDouble(SUMO_ATTR_DEPART), routeChild));
1898  }
1899  }
1900  } else if ((edgeChild->getTagProperty().getTag() == GNE_TAG_ROUTE_EMBEDDED) && (edgeChild->getParentEdges().front() == this)) {
1901  vehicles.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild->getParentDemandElements().front()));
1902  }
1903  }
1904  // reserve
1905  vehiclesOverEdge.reserve(vehicles.size());
1906  // iterate over vehicles
1907  for (const auto& vehicle : vehicles) {
1908  // add it over vehiclesOverEdge;
1909  vehiclesOverEdge.push_back(vehicle.second);
1910  }
1911  // now split vehicles by lanes
1912  for (const auto& vehicle : vehiclesOverEdge) {
1913  const GNELane* vehicleLane = vehicle->getFirstAllowedVehicleLane();
1914  if (vehicleLane) {
1915  vehiclesOverEdgeMap[vehicleLane].push_back(vehicle);
1916  }
1917  }
1918  return vehiclesOverEdgeMap;
1919 }
1920 
1921 
1922 void
1924  // check if we can draw it
1926  // draw the name and/or the street name
1927  const bool drawStreetName = s.streetName.show && (myNBEdge->getStreetName() != "");
1928  const bool spreadSuperposed = s.spreadSuperposed && myLanes.back()->drawAsRailway(s) && myNBEdge->isBidiRail();
1929  // check conditions
1930  if (s.edgeName.show || drawStreetName || s.edgeValue.show) {
1931  // get first and last lanes
1932  const GNELane* firstLane = myLanes[0];
1933  const GNELane* lastLane = myLanes[myLanes.size() - 1];
1934  // calculate draw position
1935  Position drawPosition = firstLane->getLaneShape().positionAtOffset(firstLane->getLaneShape().length() / (double) 2.);
1936  drawPosition.add(lastLane->getLaneShape().positionAtOffset(lastLane->getLaneShape().length() / (double) 2.));
1937  drawPosition.mul(.5);
1938  if (spreadSuperposed) {
1939  // move name to the right of the edge and towards its beginning
1940  const double dist = 0.6 * s.edgeName.scaledSize(s.scale);
1941  const double shiftA = firstLane->getLaneShape().rotationAtOffset(firstLane->getLaneShape().length() / (double) 2.) - DEG2RAD(135);
1942  const Position shift(dist * cos(shiftA), dist * sin(shiftA));
1943  drawPosition.add(shift);
1944  }
1945  // calculate drawing angle
1946  double drawAngle = firstLane->getLaneShape().rotationDegreeAtOffset(firstLane->getLaneShape().length() / (double) 2.);
1947  drawAngle += 90;
1948  // avoid draw inverted text
1949  if (drawAngle > 90 && drawAngle < 270) {
1950  drawAngle -= 180;
1951  }
1952  // draw edge name
1953  if (s.edgeName.show) {
1954  drawName(drawPosition, s.scale, s.edgeName, drawAngle);
1955  }
1956  // draw street name
1957  if (drawStreetName) {
1958  GLHelper::drawTextSettings(s.streetName, myNBEdge->getStreetName(), drawPosition, s.scale, drawAngle);
1959  }
1960  // draw edge values
1961  if (s.edgeValue.show) {
1962  // get current scheme
1963  const int activeScheme = s.laneColorer.getActive();
1964  // calculate value depending of active scheme
1965  std::string value;
1966  if (activeScheme == 12) {
1967  // edge param, could be non-numerical
1968  value = getNBEdge()->getParameter(s.edgeParam, "");
1969  } else if (activeScheme == 13) {
1970  // lane param, could be non-numerical
1971  value = getNBEdge()->getLaneStruct(lastLane->getIndex()).getParameter(s.laneParam, "");
1972  } else {
1973  // use numerical value value of leftmost lane to hopefully avoid sidewalks, bikelanes etc
1974  const double doubleValue = lastLane->getColorValue(s, activeScheme);
1975  const RGBColor color = s.laneColorer.getScheme().getColor(doubleValue);
1976  value = color.alpha() == 0 ? "" : toString(doubleValue);
1977  }
1978  // check if value is empty
1979  if (value != "") {
1980  GLHelper::drawTextSettings(s.edgeValue, value, drawPosition, s.scale, drawAngle);
1981  }
1982  }
1983  }
1984  }
1985 }
1986 
1987 
1988 bool
1990  if ((vehicleA.beginPosition() == vehicleB.beginPosition()) && (vehicleA.endPosition() == vehicleB.endPosition())) {
1991  return true;
1992  } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
1993  return true;
1994  } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.beginPosition())) {
1995  return true;
1996  } else if ((vehicleA.beginPosition() < vehicleB.endPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
1997  return true;
1998  } else {
1999  return false;
2000  }
2001 }
2002 
2003 
2004 /****************************************************************************/
#define VEHICLE_GAP
Definition: GNEEdge.cpp:44
@ NETWORK_DELETE
mode for deleting network elements
@ NETWORK_MOVE
mode for moving network elements
@ GLO_MAX
empty max
@ GLO_EDGE
an edge
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define DEBUGCOND(PEDID)
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:286
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:34
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.
@ SUMO_TAG_VEHICLE
description of a vehicle
@ GNE_TAG_FLOW_ROUTE
a flow definition using a route instead of a from-to edges route (used in NETEDIT)
@ SUMO_TAG_FLOW
a flow definitio nusing a from-to edges instead of a route (used by router)
@ GNE_TAG_PERSONSTOP_EDGE
@ SUMO_TAG_ROUTE
begin/end of the description of a route
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ GNE_TAG_ROUTE_EMBEDDED
embedded route (used in NETEDIT)
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_TAG_EDGE
begin/end of the description of an edge
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_DISALLOW
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_SPEED
@ GNE_ATTR_SELECTED
element is selected
@ GNE_ATTR_PARAMETERS
parameters "key1=value1|key2=value2|...|keyN=valueN"
@ SUMO_ATTR_PRIORITY
@ SUMO_ATTR_NUMLANES
@ GNE_ATTR_MODIFICATION_STATUS
whether a feature has been loaded,guessed,modified or approved
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_NAME
@ SUMO_ATTR_SPREADTYPE
The information about how to spread the lanes from the given position.
@ SUMO_ATTR_ENDOFFSET
@ GNE_ATTR_SHAPE_END
last coordinate of edge shape
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_DISTANCE
@ GNE_ATTR_BIDIR
whether an edge is part of a bidirectional railway
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_ID
@ GNE_ATTR_SHAPE_START
first coordinate of edge shape
@ SUMO_ATTR_WIDTH
T MIN2(T a, T b)
Definition: StdDefs.h:73
T MAX2(T a, T b)
Definition: StdDefs.h:79
const double SUMO_const_halfLaneWidth
Definition: StdDefs.h:49
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:77
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:299
static void drawBoundary(const Boundary &b)
Draw a boundary (used for debugging)
Definition: GLHelper.cpp:647
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition: GLHelper.cpp:273
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:446
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:347
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:498
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:529
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
friend class GNEChange_Attribute
declare friend class
const std::string & getTagStr() const
get tag assigned to this object in string format
static const std::string FEATURE_GUESSED
feature has been reguessed (may still be unchanged be we can't tell (yet)
const GNETagProperties & getTagProperty() const
get Tag Property assigned to this object
void unselectAttributeCarrier(const bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
GNENet * myNet
pointer to net
void selectAttributeCarrier(const bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
void markConnectionGeometryDeprecated()
check that connection's Geometry has to be updated
void updateGeometry()
update pre-computed geometry information
void updateLinkState()
recompute cached myLinkState
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
Definition: GNECrossing.h:41
bool deleteOnlyGeometryPoints() const
check if only delete geometry points checkbox is enabled
DeleteOptions * getDeleteOptions() const
get delete options
An Element which don't belongs to GNENet but has influency in the simulation.
void updateDemandElementStackLabel(const int stack)
update stack label
Stack demand elements.
Definition: GNEEdge.h:305
const StackPosition & getStackPosition() const
get stack position
Definition: GNEEdge.cpp:1294
const std::vector< GNEDemandElement * > & getDemandElements() const
get demand elements
Definition: GNEEdge.cpp:1300
void addDemandElements(GNEDemandElement *demandElement)
add demand elment to current StackDemandElements
Definition: GNEEdge.cpp:1288
StackDemandElements(const StackPosition stackedPosition, GNEDemandElement *demandElement)
constructor
Definition: GNEEdge.cpp:1280
Stack position (used to stack demand elements over edges)
Definition: GNEEdge.h:291
double beginPosition() const
get begin position
Definition: GNEEdge.cpp:1269
StackPosition(const double departPos, const double length)
constructor
Definition: GNEEdge.cpp:1263
double endPosition() const
get end position
Definition: GNEEdge.cpp:1275
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:49
const Position getFrontDownShapePosition() const
get front down shape position
Definition: GNEEdge.cpp:532
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
Definition: GNEEdge.cpp:304
void drawEdgeName(const GUIVisualizationSettings &s) const
draw edge name
Definition: GNEEdge.cpp:1923
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:1480
void remakeGNEConnections()
remake connections
Definition: GNEEdge.cpp:555
void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)
commit move shape
Definition: GNEEdge.cpp:1453
void setMoveShape(const GNEMoveResult &moveResult)
set move shape
Definition: GNEEdge.cpp:1431
friend class GNEChange_Lane
Friend class.
Definition: GNEEdge.h:52
GNEEdge * getOppositeEdge() const
get opposite edge
Definition: GNEEdge.cpp:350
~GNEEdge()
Destructor.
Definition: GNEEdge.cpp:82
void smooth(GNEUndoList *undoList)
make geometry smooth
Definition: GNEEdge.cpp:1817
void updateGeometry()
update pre-computed geometry information
Definition: GNEEdge.cpp:108
std::string getAttributeForSelection(SumoXMLAttr key) const
method for getting the attribute in the context of object selection
Definition: GNEEdge.cpp:815
void setResponsible(bool newVal)
set responsibility for deleting internal strctures
Definition: GNEEdge.cpp:1030
void copyEdgeType(const GNEEdgeType *edgeType, GNEUndoList *undoList)
copy edge attributes from edgeType
Definition: GNEEdge.cpp:679
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition: GNEEdge.cpp:399
GNEMoveOperation * getMoveOperation(const double shapeOffset)
get move operation for the given shapeOffset
Definition: GNEEdge.cpp:148
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEEdge.cpp:335
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getVehiclesOverEdgeMap() const
get vehicles a that start over this edge
Definition: GNEEdge.cpp:1881
std::set< GUIGlID > getLaneGlIDs() const
returns GLIDs of all lanes
Definition: GNEEdge.cpp:713
const Position getFrontUpShapePosition() const
get front up shape position
Definition: GNEEdge.cpp:524
void setGeometry(PositionVector geom, bool inner)
update edge geometry and inform the lanes
Definition: GNEEdge.cpp:489
void smoothElevation(GNEUndoList *undoList)
smooth elevation with regard to adjoining edges
Definition: GNEEdge.cpp:1829
bool clickedOverShapeEnd(const Position &pos)
return true if user clicked over ShapeEnd
Definition: GNEEdge.cpp:280
void updateVehicleStackLabels()
Definition: GNEEdge.cpp:1097
bool isValid(SumoXMLAttr key, const std::string &value)
Definition: GNEEdge.cpp:922
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList)
remove geometry point in the clicked position
Definition: GNEEdge.cpp:211
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:723
LaneVector myLanes
vector with the lanes of this edge
Definition: GNEEdge.h:272
static const double SNAP_RADIUS
Definition: GNEEdge.h:229
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:1036
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition: GNEEdge.cpp:1653
bool myWasSplit
whether this edge was created from a split
Definition: GNEEdge.h:284
void removeLane(GNELane *lane, bool recomputeConnections)
@briefdecrease the number of lanes by one. argument is only used to increase robustness (assertions)
Definition: GNEEdge.cpp:1578
bool hasRestrictedLane(SUMOVehicleClass vclass) const
check if edge has a restricted lane
Definition: GNEEdge.cpp:1712
void updateSecondParentJunction(const std::string &value)
update last parent junction
Definition: GNEEdge.cpp:1518
PositionVector smoothShape(const PositionVector &shape, bool forElevation)
return smoothed shape
Definition: GNEEdge.cpp:1744
bool wasSplit()
whether this edge was created from a split
Definition: GNEEdge.cpp:735
NBEdge * myNBEdge
the underlying NBEdge
Definition: GNEEdge.h:269
void removeEdgeFromCrossings(GNEJunction *junction, GNEUndoList *undoList)
remove crossing of junction
Definition: GNEEdge.cpp:1723
Position getPositionInView() const
Returns position of hierarchical element in view.
Definition: GNEEdge.cpp:141
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:1527
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:1681
ConnectionVector myGNEConnections
vector with the connections of this edge
Definition: GNEEdge.h:275
void editEndpoint(Position pos, GNEUndoList *undoList)
makes pos the new geometry endpoint at the appropriate end, or remove current existent endpoint
Definition: GNEEdge.cpp:419
void resetBothEndpoint(GNEUndoList *undoList)
restores both endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:479
Position getSplitPos(const Position &clickPos)
Definition: GNEEdge.cpp:405
const std::vector< GNEConnection * > & getGNEConnections() const
returns a reference to the GNEConnection vector
Definition: GNEEdge.cpp:729
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEEdge.cpp:741
void copyTemplate(const GNEInspectorFrame::TemplateEditor::EdgeTemplate &edgeTemplate, GNEUndoList *undoList)
copy edge attributes from edgetemplate
Definition: GNEEdge.cpp:652
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition: GNEEdge.cpp:617
std::string myConnectionStatus
modification status of the connections
Definition: GNEEdge.h:287
const std::string getOptionalName() const
Returns the street name.
Definition: GNEEdge.cpp:329
void clearGNEConnections()
clear current connections
Definition: GNEEdge.cpp:596
bool myUpdateGeometry
@brif flag to enable/disable update geometry of lanes (used mainly by setNumLanes)
Definition: GNEEdge.h:322
const Position getBackDownShapePosition() const
get back down shape position
Definition: GNEEdge.cpp:548
bool areStackPositionOverlapped(const GNEEdge::StackPosition &vehicleA, const GNEEdge::StackPosition &vehicleB) const
check if given stacked positions are overlapped
Definition: GNEEdge.cpp:1989
void updateFirstParentJunction(const std::string &value)
update front parent junction
Definition: GNEEdge.cpp:1509
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition: GNEEdge.cpp:1734
const std::map< std::string, std::string > & getACParametersMap() const
get parameters map
Definition: GNEEdge.cpp:1024
void setShapeStartPos(const Position &pos)
change Shape StartPos
Definition: GNEEdge.cpp:1859
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNEEdge.cpp:825
void setMicrosimID(const std::string &newID)
override to also set lane ids
Definition: GNEEdge.cpp:1703
const Position getBackUpShapePosition() const
get back up shape position
Definition: GNEEdge.cpp:540
void resetEndpoint(const Position &pos, GNEUndoList *undoList)
restores the endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:465
bool isAttributeEnabled(SumoXMLAttr key) const
Definition: GNEEdge.cpp:1013
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEEdge.cpp:356
void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation=false)
adds a connection
Definition: GNEEdge.cpp:1629
void drawEdgeGeometryPoints(const GUIVisualizationSettings &s, const GNELane *lane) const
draw edge geometry points (note: This function is called by GNELane::drawGL(...)
Definition: GNEEdge.cpp:1155
bool clickedOverShapeStart(const Position &pos)
Definition: GNEEdge.cpp:270
std::vector< GNECrossing * > getGNECrossings()
get GNECrossings vinculated with this Edge
Definition: GNEEdge.cpp:635
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:1051
void updateVehicleSpreadGeometries()
Definition: GNEEdge.cpp:1066
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition: GNEEdge.cpp:290
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition: GNEEdge.h:281
GNEEdge(GNENet *net, NBEdge *nbe, bool wasSplit=false, bool loaded=false)
Constructor.
Definition: GNEEdge.cpp:55
void setShapeEndPos(const Position &pos)
change Shape EndPos
Definition: GNEEdge.cpp:1870
const std::vector< GNELaneType * > & getLaneTypes() const
get laneTypes
Definition: GNEEdgeType.cpp:87
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
GNEFrameModuls::HierarchicalElementTree * getHierarchicalElementTree() const
get HierarchicalElementTree modul
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
void updateGeometry()
update pre-computed geometry information (including crossings)
Definition: GNEJunction.cpp:92
NBNode * getNBNode() const
Return net build node.
void setLogicValid(bool valid, GNEUndoList *undoList, const std::string &status=FEATURE_GUESSED)
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:45
const PositionVector & getLaneShape() const
Definition: GNELane.cpp:117
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:733
double getColorValue(const GUIVisualizationSettings &s, int activeScheme) const
return value for lane coloring according to the given scheme
Definition: GNELane.cpp:1235
move operation
move result
std::vector< int > geometryPointsToMove
shape points to move (of shapeToMove)
PositionVector shapeToUpdate
shape to update (edited in moveElement)
void updateID(GNEAttributeCarrier *AC, const std::string newID)
update ID
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:40
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:509
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1411
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1423
GNEEdge * retrieveEdge(const std::string &id, bool failHard=true) const
get edge by id
Definition: GNENet.cpp:1141
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition: GNENet.cpp:2300
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
retrieve all attribute carriers of Net
Definition: GNENet.cpp:130
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition: GNENet.cpp:2236
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:2245
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true) const
get junction by id
Definition: GNENet.cpp:1113
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
const std::string & getID() const
get ID
Boundary myBoundary
object boundary
void decRef(const std::string &debugMsg="")
Decrease reference.
void incRef(const std::string &debugMsg="")
Increarse reference.
bool unreferenced()
check if object ins't referenced
Representation of a RouteProbe in netedit.
Definition: GNERouteProbe.h:31
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
void p_add(GNEChange_Attribute *cmd)
special method, avoid empty changes, always execute
void p_begin(const std::string &description)
Begin undo command sub-group. This begins a new group of commands that are treated as a single comman...
Definition: GNEUndoList.cpp:71
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
Definition: GNEUndoList.cpp:78
const GNEViewNetHelper::DataViewOptions & getDataViewOptions() const
get data view options
Definition: GNEViewNet.cpp:491
const GNEAttributeCarrier * getFrontAttributeCarrier() const
get front attributeCarrier
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:467
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
Definition: GNEViewNet.cpp:479
GNEViewParent * getViewParent() const
get the net object
void removeFromAttributeCarrierInspected(const GNEAttributeCarrier *AC)
remove given AC of list of inspected Attribute Carriers
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:368
bool isAttributeCarrierInspected(const GNEAttributeCarrier *AC) const
check if attribute carrier is being inspected
GNEDeleteFrame * getDeleteFrame() const
get frame for delete elements
GNEInspectorFrame * getInspectorFrame() const
get frame for inspect elements
The popup menu of a globject.
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to copy the cursor position if geo projection is used,...
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0) const
draw name of item
const T getColor(const double value) const
const std::vector< T > & getSchemes() const
Position snapToActiveGrid(const Position &pos, bool snapXY=true) const
Returns a position that is mapped to the closest grid point if the grid is active.
Position getPositionInformation() const
Returns the cursor's x/y position within the network.
Stores the information about how to visualize structures.
bool drawBoundaries
enable or disable draw boundaries
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
GUIVisualizationDetailSettings detailSettings
detail settings
GUIVisualizationSizeSettings addSize
bool drawForPositionSelection
whether drawing is performed for the purpose of selecting objects with a single click
GUIVisualizationTextSettings edgeValue
double laneWidthExaggeration
The lane exaggeration (upscale thickness)
bool drawDottedContour() const
check if dotted contour can be drawn
GUIVisualizationColorSettings colorSettings
color settings
double scale
information about a lane's width (temporary, used for a single view)
bool drawDetail(const double detail, const double exaggeration) const
check if details can be drawn for the given GUIVisualizationDetailSettings and current scale and exxa...
GUIVisualizationTextSettings streetName
GUIColorer laneColorer
The lane colorer.
GUIVisualizationTextSettings edgeName
int getCircleResolution() const
function to calculate circle resolution for all circles drawn in drawGL(...) functions
bool spreadSuperposed
Whether to improve visualisation of superposed (rail) edges.
GUIColorer junctionColorer
The junction colorer.
std::string edgeParam
key for coloring by edge parameter
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:91
void setStreetName(const std::string &name)
sets the street name of this edge
Definition: NBEdge.h:623
void mirrorX()
mirror coordinates along the x-axis
Definition: NBEdge.cpp:552
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
Definition: NBEdge.cpp:3641
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3655
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:3627
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition: NBEdge.h:572
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3597
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:605
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:618
void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices)
add lane
Definition: NBEdge.cpp:3359
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:2196
std::string myType
The type of the edge.
Definition: NBEdge.h:1606
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition: NBEdge.h:803
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition: NBEdge.cpp:713
void setDistance(double distance)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.h:1318
const std::string & getID() const
Definition: NBEdge.h:1423
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:677
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:516
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:589
double getDistance() const
Definition: NBEdge.h:634
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:339
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3491
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:907
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:3006
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:2182
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:490
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:716
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:1318
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1399
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition: NBEdge.cpp:3413
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:2207
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 length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:1066
@ USER
The connection was given by the user.
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:2229
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3336
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:497
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:324
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:964
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1104
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:1340
double getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:630
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3552
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1326
void setLoadedLength(double val)
set loaded length
Definition: NBEdge.cpp:3670
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:569
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3954
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition: NBEdge.cpp:604
int myPriority
The priority of the edge.
Definition: NBEdge.h:1622
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:509
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:259
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:254
const Position & getPosition() const
Definition: NBNode.h:246
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:3192
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:540
const std::string & getID() const
Returns the id.
Definition: Named.h:73
A storage for options typed value containers)
Definition: OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
bool set(const std::string &name, const std::string &value)
Sets the given value for the named option.
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
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:58
static bool areParametersValid(const std::string &value, bool report=false, ParameterisedAttrType attrType=ParameterisedAttrType::STRING, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to a parameters map "key1=value1|key2=value2|....
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"
const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
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".
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value map.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition: Position.h:246
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:282
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:241
double x() const
Returns the x-position.
Definition: Position.h:54
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:124
void mul(double val)
Multiplies both positions with the given value.
Definition: Position.h:104
double z() const
Returns the z-position.
Definition: Position.h:64
double y() const
Returns the y-position.
Definition: Position.h:59
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
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
PositionVector interpolateZ(double zStart, double zEnd) const
returned vector that varies z smoothly over its length
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
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
int indexOfClosest(const Position &p) const
index of the closest position to p
void pop_front()
pop first Position
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
static const RGBColor WHITE
Definition: RGBColor.h:187
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition: RGBColor.h:73
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:145
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
bool hasString(const std::string &str) const
static void drawDottedContourEdge(const DottedContourType type, const GUIVisualizationSettings &s, const GNEEdge *edge, const bool drawFrontExtreme, const bool drawBackExtreme)
draw dotted contour for the given dottedGeometries (used by edges)
std::map< SumoXMLAttr, std::string > edgeParameters
edge parameters
std::vector< std::map< SumoXMLAttr, std::string > > laneParameters
lane parameters
bool showDemandElements() const
check if show demand elements checkbox is enabled
NetworkEditMode networkEditMode
the current Network edit mode
bool isCurrentSupermodeDemand() const
@check if current supermode is Demand
bool editingElevation() const
check if we're editing elevation
bool showDemandElements() const
check if show demand elements checkbox is enabled
RGBColor selectedEdgeColor
edge selection color
static const double geometryPointsText
details for Geometry Points Texts
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
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:188
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:209
int toLane
The lane the connections yields in.
Definition: NBEdge.h:215
double speed
custom speed for connection
Definition: NBEdge.h:239
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:212
KeepClear keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:230
double customLength
custom length for connection
Definition: NBEdge.h:242
bool uncontrolled
check if Connection is uncontrolled
Definition: NBEdge.h:281
PositionVector customShape
custom shape for connection
Definition: NBEdge.h:245
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:227
double contPos
custom position for internal junction on this connection
Definition: NBEdge.h:233
double visibility
custom foe visiblity for connection
Definition: NBEdge.h:236
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:142
double width
This lane's width.
Definition: NBEdge.h:166
double endOffset
This lane's offset to the intersection begin.
Definition: NBEdge.h:159
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition: NBEdge.h:156
double speed
The speed allowed on this lane.
Definition: NBEdge.h:150
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:153