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