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