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