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-2026 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
41#include <netedit/GNENet.h>
43#include <netedit/GNEUndoList.h>
47
48#include "GNEConnection.h"
49#include "GNECrossing.h"
50#include "GNEEdge.h"
51#include "GNEEdgeType.h"
52#include "GNELaneType.h"
53#include "GNEEdgeTemplate.h"
54#include "GNELaneTemplate.h"
55
56// ===========================================================================
57// defines
58// ===========================================================================
59
60//#define DEBUG_SMOOTH_GEOM
61//#define DEBUGCOND(obj) (true)
62#define VEHICLE_GAP 1
63#define ENDPOINT_TOLERANCE 2
64
65// ===========================================================================
66// static
67// ===========================================================================
68
71
72// ===========================================================================
73// members methods
74// ===========================================================================
75
76GNEEdge::GNEEdge(GNENet* net, NBEdge* nbe, bool wasSplit, bool loaded):
77 GNENetworkElement(net, nbe->getID(), SUMO_TAG_EDGE),
78 myNBEdge(nbe),
79 myAmResponsible(false),
80 myWasSplit(wasSplit),
81 myConnectionStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED),
82 myMoveElementEdge(new GNEMoveElementEdge(this)),
83 myUpdateGeometry(true) {
84 // set parents
85 setParents<GNEJunction*>({
86 net->getAttributeCarriers()->retrieveJunction(nbe->getFromNode()->getID()),
88 });
89 // Create lanes
90 for (int i = 0; i < myNBEdge->getNumLanes(); i++) {
91 auto lane = new GNELane(this, i);
92 lane->incRef("GNEEdge::GNEEdge");
93 addChildElement(lane);
94 }
95 // update Lane geometries
96 for (const auto& lane : getChildLanes()) {
97 lane->updateGeometry();
98 }
99 // update centering boundary without updating grid
101}
102
103
105 // Delete references to this edge in lanes
106 for (const auto& lane : getChildLanes()) {
107 lane->decRef("GNEEdge::~GNEEdge");
108 if (lane->unreferenced()) {
109 // check if remove it from Attribute Carriers
110 if (myNet->getAttributeCarriers()->getLanes().count(lane) > 0) {
112 }
113 delete lane;
114 }
115 }
116 // delete references to this edge in connections
117 for (const auto& connection : myGNEConnections) {
118 connection->decRef("GNEEdge::~GNEEdge");
119 if (connection->unreferenced()) {
120 // check if remove it from Attribute Carriers
121 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
123 }
124 delete connection;
125 }
126 }
127 if (myAmResponsible) {
128 delete myNBEdge;
129 }
130}
131
132
137
138
141 return myNBEdge;
142}
143
144
145const Parameterised*
147 return myNBEdge;
148}
149
150
151bool
153 if (getFromJunction()->getNBNode()->getPosition() != getToJunction()->getNBNode()->getPosition()) {
154 return true;
155 } else {
156 return false;
157 }
158}
159
160
161std::string
163 return TLF("Parent junctions are in the same position: %, %",
164 toString(getFromJunction()->getNBNode()->getPosition().x()),
165 toString(getFromJunction()->getNBNode()->getPosition().y()));
166}
167
168
169void
171 // first check if myUpdateGeometry flag is enabled
172 if (myUpdateGeometry) {
173 // Update geometry of lanes
174 for (const auto& lane : getChildLanes()) {
175 lane->updateGeometry();
176 }
177 // Update geometry of connections
178 for (const auto& connection : myGNEConnections) {
179 connection->updateGeometry();
180 }
181 // Update geometry of additionals children vinculated to this edge
182 for (const auto& childAdditional : getChildAdditionals()) {
183 childAdditional->updateGeometry();
184 }
185 // Update geometry of additionals demand elements vinculated to this edge
186 for (const auto& childDemandElement : getChildDemandElements()) {
187 childDemandElement->updateGeometry();
188 }
189 // Update geometry of additionals generic datas vinculated to this edge
190 for (const auto& childGenericData : getChildGenericDatas()) {
191 childGenericData->updateGeometry();
192 }
193 // compute geometry of path elements elements vinculated with this edge (depending of showDemandElements)
195 for (const auto& childAdditional : getChildAdditionals()) {
196 childAdditional->computePathElement();
197 }
198 for (const auto& childDemandElement : getChildDemandElements()) {
199 childDemandElement->computePathElement();
200 }
201 for (const auto& childGenericData : getChildGenericDatas()) {
202 childGenericData->computePathElement();
203 }
204 }
205 }
206 // update vehicle geometry
208 // update stack labels
212}
213
214
217 return getChildLanes().front()->getPositionInView();
218}
219
220
221bool
223 // get modes and viewParent (for code legibility)
224 const auto& modes = myNet->getViewNet()->getEditModes();
225 const auto& viewParent = myNet->getViewParent();
226 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
227 // continue depending of current status
228 if (inspectedElements.isInspectingSingleElement()) {
229 // check if starts in this edge
230 if (inspectedElements.getFirstAC()->getTagProperty()->vehicleEdges() &&
231 inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_FROM) &&
232 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_FROM) == getID())) {
233 return true;
234 }
235 } else if (modes.isCurrentSupermodeDemand()) {
236 // get current GNEPlanCreator
237 GNEPlanCreator* planCreator = nullptr;
238 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
239 planCreator = viewParent->getPersonFrame()->getPlanCreator();
240 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
241 planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
242 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
243 planCreator = viewParent->getContainerFrame()->getPlanCreator();
244 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
245 planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
246 }
247 // continue depending of planCreator
248 if (planCreator) {
249 if (planCreator->getPlanParameteres().fromEdge == getID()) {
250 return true;
251 } else if ((planCreator->getPlanParameteres().consecutiveEdges.size() > 0) &&
252 (planCreator->getPlanParameteres().consecutiveEdges.front() == getID())) {
253 return true;
254 }
255 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
256 const auto& selectedEdges = viewParent->getVehicleFrame()->getPathCreator()->getSelectedEdges();
257 // check if this is the first selected edge
258 if ((selectedEdges.size() > 0) && (selectedEdges.front() == this)) {
259 return true;
260 }
261 }
262 } else if (modes.isCurrentSupermodeData()) {
263 // get TAZRelDataFrame
264 const auto& edgeRelDataFrame = viewParent->getEdgeRelDataFrame();
265 if (edgeRelDataFrame->shown()) {
266 // check first Edge
267 if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().empty()) {
268 return false;
269 } else {
270 return edgeRelDataFrame->getPathCreator()->getSelectedEdges().front() == this;
271 }
272 }
273 }
274 // nothing to draw
275 return false;
276}
277
278
279bool
281 // get modes and viewParent (for code legibility)
282 const auto& modes = myNet->getViewNet()->getEditModes();
283 const auto& viewParent = myNet->getViewParent();
284 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
285 // continue depending of current status
286 if (inspectedElements.isInspectingSingleElement()) {
287 // check if starts in this edge
288 if (inspectedElements.getFirstAC()->getTagProperty()->vehicleEdges() &&
289 inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_TO) &&
290 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_TO) == getID())) {
291 return true;
292 }
293 } else if (modes.isCurrentSupermodeDemand()) {
294 // get current GNEPlanCreator
295 GNEPlanCreator* planCreator = nullptr;
296 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
297 planCreator = viewParent->getPersonFrame()->getPlanCreator();
298 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
299 planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
300 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
301 planCreator = viewParent->getContainerFrame()->getPlanCreator();
302 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
303 planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
304 }
305 // continue depending of planCreator
306 if (planCreator) {
307 if (planCreator->getPlanParameteres().toEdge == getID()) {
308 return true;
309 } else if ((planCreator->getPlanParameteres().consecutiveEdges.size() > 1) &&
310 (planCreator->getPlanParameteres().consecutiveEdges.back() == getID())) {
311 return true;
312 }
313 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
314 const auto& selectedEdges = viewParent->getVehicleFrame()->getPathCreator()->getSelectedEdges();
315 // check if this is the last selected edge
316 if ((selectedEdges.size() > 1) && (selectedEdges.back() == this)) {
317 return true;
318 }
319 }
320 } else if (modes.isCurrentSupermodeData()) {
321 // get TAZRelDataFrame
322 const auto& edgeRelDataFrame = viewParent->getEdgeRelDataFrame();
323 if (edgeRelDataFrame->shown()) {
324 // check last Edge
325 if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().empty()) {
326 return false;
327 } else {
328 return edgeRelDataFrame->getPathCreator()->getSelectedEdges().back() == this;
329 }
330 }
331 }
332 // nothing to draw
333 return false;
334}
335
336
337bool
339 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
340 // continue depending of inspected elements
341 if (inspectedElements.isInspectingSingleElement() &&
342 inspectedElements.getFirstAC()->getTagProperty()->getTag() == SUMO_TAG_TAZ) {
343 // check if one of the sourceSink child is placed in this edge
344 for (const auto& sourceSink : getChildTAZSourceSinks()) {
345 if (sourceSink->getParentAdditionals().front() == inspectedElements.getFirstAC()) {
346 return true;
347 }
348 }
349 }
350 if (myNet->getViewNet()->getPopup()) {
351 return myNet->getViewNet()->getPopup()->getGLObject() == this;
352 }
353 return false;
354}
355
356
357bool
359 // get modes and viewParent (for code legibility)
360 const auto& modes = myNet->getViewNet()->getEditModes();
361 const auto& viewParent = myNet->getViewParent();
362 const auto& viewObjectsSelector = myNet->getViewNet()->getViewObjectsSelector();
363 // check if we're selecting edges in additional mode
364 if (modes.isCurrentSupermodeNetwork() && (modes.networkEditMode == NetworkEditMode::NETWORK_ADDITIONAL)) {
365 if (viewParent->getAdditionalFrame()->getViewObjetsSelector()->isNetworkElementSelected(this)) {
366 return true;
367 } else if (viewParent->getAdditionalFrame()->getViewObjetsSelector()->getTag() == myTagProperty->getTag()) {
368 return viewObjectsSelector.getEdgeFront() == this;
369 } else {
370 return false;
371 }
372 }
373 // check if this is the edge under cursor
374 if (viewObjectsSelector.getEdgeFront() != this) {
375 return false;
376 } else {
377 // continue depending of modes
378 if (modes.isCurrentSupermodeDemand()) {
379 // get current plan selector
380 GNEPlanSelector* planSelector = nullptr;
381 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
382 planSelector = viewParent->getPersonFrame()->getPlanSelector();
383 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
384 planSelector = viewParent->getPersonPlanFrame()->getPlanSelector();
385 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
386 planSelector = viewParent->getContainerFrame()->getPlanSelector();
387 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
388 planSelector = viewParent->getContainerPlanFrame()->getPlanSelector();
389 }
390 // continue depending of plan selector
391 if (planSelector && planSelector->markEdges()) {
392 return (viewObjectsSelector.getAttributeCarrierFront()->getTagProperty()->getTag() == SUMO_TAG_LANE);
393 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
394 // get current vehicle template
395 const auto& vehicleTemplate = viewParent->getVehicleFrame()->getVehicleTagSelector()->getCurrentTemplateAC();
396 // check if vehicle can be placed over from-to TAZs
397 if (vehicleTemplate && vehicleTemplate->getTagProperty()->vehicleEdges()) {
398 return (viewObjectsSelector.getAttributeCarrierFront()->getTagProperty()->getTag() == SUMO_TAG_LANE);
399 }
400 }
401 } else if (modes.isCurrentSupermodeData()) {
402 // get frames
403 const auto& edgeDataFrame = viewParent->getEdgeDataFrame();
404 const auto& edgeRelDataFrame = viewParent->getEdgeRelDataFrame();
405 if (edgeDataFrame->shown()) {
406 return true;
407 } else if (edgeRelDataFrame->shown()) {
408 // check edges
409 if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().empty()) {
410 return true;
411 } else if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().size() == 2) {
412 return false;
413 } else if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().front() == this) {
414 return false;
415 } else if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().back() == this) {
416 return false;
417 } else {
418 return true;
419 }
420 }
421
422 }
423 // nothing to draw
424 return false;
425 }
426}
427
428
429bool
431 // first check if we're selecting edges or lanes
433 // get edit modes
434 const auto& editModes = myNet->getViewNet()->getEditModes();
435 // check if we're in delete mode
436 if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE)) {
437 // check lanes
438 for (const auto& lane : getChildLanes()) {
441 return true;
442 }
443 }
444 // check edge
447 return true;
448 }
449 // nothing to draw
450 return false;
451 } else {
452 return false;
453 }
454 } else {
455 return false;
456 }
457}
458
459
460bool
462 // get edit modes
463 const auto& editModes = myNet->getViewNet()->getEditModes();
464 // check if we're in delete mode
465 if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE)) {
466 const auto junction = myNet->getViewNet()->getViewObjectsSelector().getJunctionFront();
468 return ((getFromJunction() == junction) || (getToJunction() == junction));
469 }
470 }
471 return false;
472}
473
474
475bool
477 // first check if we're selecting edges or lanes
479 // get edit modes
480 const auto& editModes = myNet->getViewNet()->getEditModes();
481 // check if we're in select mode
482 if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_SELECT)) {
483 // check lanes
484 for (const auto& lane : getChildLanes()) {
487 return true;
488 }
489 }
490 // check edge
493 return true;
494 }
495 // nothing to draw
496 return false;
497 } else {
498 return false;
499 }
500 } else {
501 return false;
502 }
503}
504
505
506bool
508 // get edit modes
509 const auto& editModes = myNet->getViewNet()->getEditModes();
510 // get move element edge
511 const auto moveElementEdge = dynamic_cast<GNEMoveElementEdge*>(myNet->getViewNet()->getMoveSingleElementValues().getMovedElement());
512 // check if we're in move mode
513 if ((!myNet->getViewNet()->isCurrentlyMovingElements() || (moveElementEdge && (moveElementEdge->getEdge() == this))) && editModes.isCurrentSupermodeNetwork() &&
514 (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE)) {
515 // check if we're editing this network element
517 if (editedNetworkElement) {
518 if (editedNetworkElement == this) {
519 return true;
520 } else {
521 // check lanes
522 for (const auto& lane : getChildLanes()) {
523 if (editedNetworkElement == lane) {
524 return true;
525 }
526 }
527 }
528 } else {
529 // check lanes
530 for (const auto& lane : getChildLanes()) {
533 return true;
534 }
535 }
536 // check edge
539 return true;
540 }
541 }
542 // nothing to draw
543 return false;
544 } else {
545 return false;
546 }
547}
548
549
550bool
552 if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
553 return true;
554 } else if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
555 return true;
556 } else {
557 return false;
558 }
559}
560
561
562bool
564 // get geometry point radius
565 const double geometryPointRadius = getGeometryPointRadius();
566 if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
567 return (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius));
568 } else {
569 return false;
570 }
571}
572
573
574bool
576 // get geometry point radius
577 const double geometryPointRadius = getGeometryPointRadius();
578 if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
579 return (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius));
580 } else {
581 return false;
582 }
583}
584
585
586bool
588 // get geometry point radius
589 const auto geometryPointRadius = getGeometryPointRadius();
590 // first check inner geometry
591 const PositionVector innenShape = myNBEdge->getInnerGeometry();
592 // iterate over geometry point
593 for (const auto& geometryPoint : innenShape) {
594 if (geometryPoint.distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius)) {
595 return true;
596 }
597 }
598 // check start and end shapes
600 return true;
601 } else {
602 return false;
603 }
604}
605
606
607void
609 Position delta = junction->getNBNode()->getPosition() - origPos;
611 // geometry endpoint need not equal junction position hence we modify it with delta
612 if (junction == getFromJunction()) {
613 geom[0].add(delta);
614 } else {
615 geom[-1].add(delta);
616 }
617 setGeometry(geom, false);
618}
619
620
621bool
623 for (const auto& lane : getChildLanes()) {
624 if (lane->isVisible(s)) {
625 return true;
626 }
627 }
628 return false;
629}
630
631
632double
634 return s.addSize.getExaggeration(s, this);
635}
636
637
642
643
644void
645GNEEdge::updateCenteringBoundary(const bool updateGrid) {
646 // Remove object from net
647 if (updateGrid) {
649 }
650 // first add edge boundary
652 // add lane boundaries
653 for (const auto& lane : getChildLanes()) {
654 const auto laneBoundary = lane->getCenteringBoundary();
655 if (laneBoundary.isInitialised()) {
656 myEdgeBoundary.add(laneBoundary);
657 // add additional and demand boundaries
658 for (const auto& additional : lane->getChildAdditionals()) {
659 const auto additionalBoundary = additional->getCenteringBoundary();
660 if (additionalBoundary.isInitialised()) {
661 myEdgeBoundary.add(additional->getCenteringBoundary());
662 }
663 }
664 }
665 }
666 // add additional and demand boundaries
667 for (const auto& additional : getChildAdditionals()) {
668 const auto additionalBoundary = additional->getCenteringBoundary();
669 if (additionalBoundary.isInitialised()) {
670 myEdgeBoundary.add(additionalBoundary);
671 }
672 }
673 // add junction positions
676 // grow boundary
678 // add object into net
679 if (updateGrid) {
681 }
682}
683
684
685const std::string
687 return myNBEdge->getStreetName();
688}
689
690
693 // if we call this function, that's mean that we're clicked over a edge geometry point, then
694 // open the popup dialog of the lane[0] (back)
695 return getChildLanes().back()->getPopUpMenu(app, parent);
696}
697
698
699std::vector<GNEEdge*>
703
704
705void
707 // check drawing boundary selection and size boundary
709 // draw boundary
711 // get detail level from the first lane
712 const auto d = getChildLanes().front()->getDrawingConstants()->getDetail();
713 // calculate layer
714 double layer = GLO_EDGE;
715 if (myDrawInFront) {
716 layer = GLO_FRONTELEMENT;
717 } else if (getChildLanes().front()->getLaneShape().length2D() <= (s.neteditSizeSettings.junctionBubbleRadius * 2)) {
718 layer = GLO_JUNCTION + 1.8;
719 }
720 // check if draw details
722 // draw geometry points
723 drawEdgeGeometryPoints(s, d, layer);
724 // draw edge shape (a red line only visible if lane shape is strange)
725 drawEdgeShape(s, d, layer);
726 // draw edge stopOffset
727 drawLaneStopOffset(s, d, layer);
728 // draw edge name
729 drawEdgeName(s);
730 // draw lock icon
732 // draw dotted contour
734 }
735 // calculate edge contour (always before children)
736 calculateEdgeContour(s, d, layer);
737 // draw lanes
738 for (const auto& lane : getChildLanes()) {
739 lane->drawGL(s);
740 }
741 // draw junctions
743 getToJunction()->drawGL(s);
744 // draw childrens
745 drawChildrens(s);
746 }
747}
748
749
750void
752 // Check if edge can be deleted
754 myNet->deleteEdge(this, myNet->getUndoList(), false);
755 }
756}
757
758
759void
763
764
765NBEdge*
767 return myNBEdge;
768}
769
770
773 // get geometry point radius
774 const double geometryPointRadius = getGeometryPointRadius();
775 const PositionVector& geom = myNBEdge->getGeometry();
776 int index = geom.indexOfClosest(clickPos, true);
777 if (geom[index].distanceSquaredTo2D(clickPos) < (geometryPointRadius * geometryPointRadius)) {
778 // split at existing geometry point
779 return myNet->getViewNet()->snapToActiveGrid(geom[index]);
780 } else {
781 // split straight between the next two points
783 }
784}
785
786
787void
789 // get geometry point radius
790 const double geometryPointRadius = getGeometryPointRadius();
791 if ((myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
792 (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius))) {
793 undoList->begin(this, "remove endpoint");
794 setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
795 undoList->end();
796 } else if ((myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
797 (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius))) {
798 undoList->begin(this, "remove endpoint");
799 setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
800 undoList->end();
801 } else {
802 // we need to create new Start/End position over Edge shape, not over clicked position
804 if (offset != GeomHelper::INVALID_OFFSET) {
806 // calculate position over edge shape relative to clicked position
807 Position newPos = geom.positionAtOffset2D(offset);
808 // snap new position to grid
809 newPos = myNet->getViewNet()->snapToActiveGrid(newPos);
810 undoList->begin(this, "set endpoint");
811 const int index = geom.indexOfClosest(pos, true);
812 const Position destPos = getToJunction()->getNBNode()->getPosition();
813 const Position sourcePos = getFromJunction()->getNBNode()->getPosition();
814 if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
815 // check if snap to existing geometrypoint
816 if (geom[index].distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius)) {
817 newPos = geom[index];
818 // remove existent geometry point to avoid double points
819 myMoveElementEdge->removeGeometryPoint(newPos, undoList);
820 }
821 setAttribute(GNE_ATTR_SHAPE_END, toString(newPos), undoList);
823 } else {
824 // check if snap to existing geometry point
825 if (geom[index].distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius)) {
826 newPos = geom[index];
827 // remove existent geometry point to avoid double points
828 myMoveElementEdge->removeGeometryPoint(newPos, undoList);
829 }
830 setAttribute(GNE_ATTR_SHAPE_START, toString(newPos), undoList);
832 }
833 undoList->end();
834 }
835 }
836}
837
838
839void
842 Position sourcePos = getFromJunction()->getNBNode()->getPosition();
843 if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
844 setAttribute(GNE_ATTR_SHAPE_END, toString(destPos), undoList);
846 } else {
847 setAttribute(GNE_ATTR_SHAPE_START, toString(sourcePos), undoList);
849 }
850}
851
852
853void
855 // reset shape start
856 setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
858 // reset shape end
859 setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
861}
862
863void
865 // set new geometry
866 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
867 if (lefthand) {
868 geom.mirrorX();
869 myNBEdge->mirrorX();
870 }
871 myNBEdge->setGeometry(geom, inner);
872 if (lefthand) {
873 myNBEdge->mirrorX();
874 }
875 // update geometry
877 // invalidate junction source shape
879 // iterate over first parent junction edges and update geometry
880 for (const auto& edge : getFromJunction()->getGNEIncomingEdges()) {
881 edge->updateGeometry();
882 }
883 for (const auto& edge : getFromJunction()->getGNEOutgoingEdges()) {
884 edge->updateGeometry();
885 }
886 // invalidate junction destination shape
888 // iterate over second parent junction edges and update geometry
889 for (const auto& edge : getToJunction()->getGNEIncomingEdges()) {
890 edge->updateGeometry();
891 }
892 for (const auto& edge : getToJunction()->getGNEOutgoingEdges()) {
893 edge->updateGeometry();
894 }
895}
896
897
898const Position
900 PositionVector laneShape = getChildLanes().front()->getLaneShape();
901 laneShape.move2side(getChildLanes().front()->getParentEdge()->getNBEdge()->getLaneWidth(getChildLanes().front()->getIndex()) / 2);
902 return laneShape.front();
903}
904
905
906const Position
908 PositionVector laneShape = getChildLanes().back()->getLaneShape();
909 laneShape.move2side(-1 * getChildLanes().back()->getParentEdge()->getNBEdge()->getLaneWidth(getChildLanes().back()->getIndex()) / 2);
910 return laneShape.front();
911}
912
913
914const Position
916 PositionVector laneShape = getChildLanes().front()->getLaneShape();
917 laneShape.move2side(getChildLanes().front()->getParentEdge()->getNBEdge()->getLaneWidth(getChildLanes().front()->getIndex()) / 2);
918 return laneShape.back();
919}
920
921
922const Position
924 PositionVector laneShape = getChildLanes().back()->getLaneShape();
925 laneShape.move2side(-1 * getChildLanes().back()->getParentEdge()->getNBEdge()->getLaneWidth(getChildLanes().back()->getIndex()) / 2);
926 return laneShape.back();
927}
928
929void
930GNEEdge::remakeGNEConnections(bool junctionsReady) {
931 // create new and removed unused GNEConnections
932 const std::vector<NBEdge::Connection>& connections = myNBEdge->getConnections();
933 // create a vector to keep retrieved and created connections
934 std::vector<GNEConnection*> retrievedConnections;
935 // iterate over NBEdge::Connections of GNEEdge
936 for (const auto& connection : connections) {
937 // retrieve existent GNEConnection, or create it
938 GNEConnection* retrievedGNEConnection = retrieveGNEConnection(connection.fromLane, connection.toEdge, connection.toLane);
939 if (junctionsReady) {
940 retrievedGNEConnection->updateLinkState();
941 }
942 retrievedConnections.push_back(retrievedGNEConnection);
943 // check if previously this GNEConnections exists, and if true, remove it from myGNEConnections
944 std::vector<GNEConnection*>::iterator retrievedExists = std::find(myGNEConnections.begin(), myGNEConnections.end(), retrievedGNEConnection);
945 if (retrievedExists != myGNEConnections.end()) {
946 myGNEConnections.erase(retrievedExists);
947 } else {
948 // include reference to created GNEConnection
949 retrievedGNEConnection->incRef("GNEEdge::remakeGNEConnections");
950 }
951 // mark it as deprecated
952 retrievedGNEConnection->markConnectionGeometryDeprecated();
953 }
954 // delete non retrieved GNEConnections
955 for (const auto& connection : myGNEConnections) {
956 // decrease reference
957 connection->decRef();
958 // remove it from network
959 myNet->removeGLObjectFromGrid(connection);
960 // and from AttributeCarriers
961 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
963 }
964 // delete GNEConnection if is unreferenced
965 if (connection->unreferenced()) {
966 delete connection;
967 }
968 }
969 // copy retrieved (existent and created) GNECrossings to myGNEConnections
970 myGNEConnections = retrievedConnections;
971}
972
973
974void
976 // Drop all existents connections that aren't referenced anymore
977 for (const auto& connection : myGNEConnections) {
978 // check if connection is selected
979 if (connection->isAttributeCarrierSelected()) {
980 connection->unselectAttributeCarrier();
981 }
982 // Dec reference of connection
983 connection->decRef("GNEEdge::clearGNEConnections");
984 // remove it from network
985 myNet->removeGLObjectFromGrid(connection);
986 // and from AttributeCarriers
987 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
989 }
990 // Delete GNEConnectionToErase if is unreferenced
991 if (connection->unreferenced()) {
992 delete connection;
993 }
994 }
995 myGNEConnections.clear();
996}
997
998
999int
1001 std::vector<GNEAdditional*> routeProbes;
1002 for (const auto& additional : getChildAdditionals()) {
1003 if (additional->getTagProperty()->getTag() == routeProbe->getTagProperty()->getTag()) {
1004 routeProbes.push_back(additional);
1005 }
1006 }
1007 // return index of routeProbe in routeProbes vector
1008 auto it = std::find(routeProbes.begin(), routeProbes.end(), routeProbe);
1009 if (it == routeProbes.end()) {
1010 return -1;
1011 } else {
1012 return (int)(it - routeProbes.begin());
1013 }
1014}
1015
1016
1017std::vector<GNECrossing*>
1019 std::vector<GNECrossing*> crossings;
1020 for (auto i : getFromJunction()->getGNECrossings()) {
1021 if (i->checkEdgeBelong(this)) {
1022 crossings.push_back(i);
1023 }
1024 }
1025 for (auto i : getToJunction()->getGNECrossings()) {
1026 if (i->checkEdgeBelong(this)) {
1027 crossings.push_back(i);
1028 }
1029 }
1030 return crossings;
1031}
1032
1033
1034void
1035GNEEdge::copyTemplate(const GNEEdgeTemplate* edgeTemplate, GNEUndoList* undoList) {
1036 // copy edge-specific attributes
1037 for (const auto& attProperty : myTagProperty->getAttributeProperties()) {
1038 if (attProperty->isCopyable() && isValid(attProperty->getAttr(), edgeTemplate->getAttribute(attProperty->getAttr()))) {
1039 setAttribute(attProperty->getAttr(), edgeTemplate->getAttribute(attProperty->getAttr()), undoList);
1040 }
1041 }
1042 // also copy parameters
1044 // copy lane attributes as well
1045 for (int i = 0; i < (int)getChildLanes().size(); i++) {
1046 for (const auto& attProperty : edgeTemplate->getLaneTemplates().at(i)->getTagProperty()->getAttributeProperties()) {
1047 if (attProperty->isCopyable() && getChildLanes()[i]->isValid(attProperty->getAttr(), edgeTemplate->getLaneTemplates().at(i)->getAttribute(attProperty->getAttr()))) {
1048 getChildLanes()[i]->setAttribute(attProperty->getAttr(), edgeTemplate->getLaneTemplates().at(i)->getAttribute(attProperty->getAttr()), undoList);
1049 }
1050 }
1051 // also copy parameters
1052 getChildLanes()[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeTemplate->getLaneTemplates().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
1053 }
1054}
1055
1056
1057void
1058GNEEdge::copyEdgeType(const GNEEdgeType* edgeType, GNEUndoList* undoList) {
1059 const auto tagPropertiesDatabase = myNet->getTagPropertiesDatabase();
1060 // get tag properties
1061 const auto edgeProperties = tagPropertiesDatabase->getTagProperty(SUMO_TAG_EDGE, true);
1062 const auto laneProperties = tagPropertiesDatabase->getTagProperty(SUMO_TAG_LANE, true);
1063 const auto edgeTypeProperties = tagPropertiesDatabase->getTagProperty(SUMO_TAG_TYPE, true);
1064 const auto laneTypeProperties = tagPropertiesDatabase->getTagProperty(SUMO_TAG_LANETYPE, true);
1065 // set type (only for info)
1067 // copy attributes
1068 for (const auto& attrProperty : edgeTypeProperties->getAttributeProperties()) {
1069 if (attrProperty->isCopyable() && edgeProperties->hasAttribute(attrProperty->getAttr())) {
1070 setAttribute(attrProperty->getAttr(), edgeType->getAttribute(attrProperty->getAttr()), undoList);
1071 }
1072 }
1074 // copy lane attributes as well
1075 for (int i = 0; i < (int)getChildLanes().size(); i++) {
1076 for (const auto& attrProperty : laneTypeProperties->getAttributeProperties()) {
1077 if (attrProperty->isCopyable() && laneProperties->hasAttribute(attrProperty->getAttr()) &&
1078 (edgeType->getLaneTypes().at(i)->getAttribute(attrProperty->getAttr()) != laneTypeProperties->getAttributeProperties(attrProperty->getAttr())->getDefaultStringValue())) {
1079 getChildLanes()[i]->setAttribute(attrProperty->getAttr(), edgeType->getLaneTypes().at(i)->getAttribute(attrProperty->getAttr()), undoList);
1080 }
1081 }
1082 if (edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS).size() > 0) {
1083 getChildLanes()[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
1084 }
1085 }
1086}
1087
1088
1089std::set<GUIGlID>
1091 std::set<GUIGlID> result;
1092 for (const auto glID : getChildLanes()) {
1093 result.insert(glID->getGlID());
1094 }
1095 return result;
1096}
1097
1098
1099const std::vector<GNEConnection*>&
1103
1104
1105bool
1107 return myWasSplit;
1108}
1109
1110
1111std::string
1113 switch (key) {
1114 case SUMO_ATTR_ID:
1115 return getMicrosimID();
1116 case SUMO_ATTR_FROM:
1118 return getFromJunction()->getID();
1119 case SUMO_ATTR_TO:
1121 return getToJunction()->getID();
1122 case SUMO_ATTR_NUMLANES:
1123 return toString(myNBEdge->getNumLanes());
1124 case SUMO_ATTR_PRIORITY:
1125 return toString(myNBEdge->getPriority());
1126 case SUMO_ATTR_LENGTH:
1127 return toString(myNBEdge->getFinalLength());
1128 case SUMO_ATTR_TYPE:
1129 return myNBEdge->getTypeID();
1131 return myNBEdge->getRoutingType();
1132 case SUMO_ATTR_SHAPE:
1136 case SUMO_ATTR_NAME:
1137 return myNBEdge->getStreetName();
1138 case SUMO_ATTR_ALLOW:
1139 return (getVehicleClassNames(myNBEdge->getPermissions()) + (myNBEdge->hasLaneSpecificPermissions() ? " (combined!)" : ""));
1140 case SUMO_ATTR_DISALLOW: {
1142 }
1143 case SUMO_ATTR_SPEED:
1145 return "lane specific";
1146 } else {
1147 return toString(myNBEdge->getSpeed());
1148 }
1149 case SUMO_ATTR_FRICTION:
1151 return "lane specific";
1152 } else {
1153 return toString(myNBEdge->getFriction());
1154 }
1155 case SUMO_ATTR_WIDTH:
1157 return "lane specific";
1159 return "default";
1160 } else {
1161 return toString(myNBEdge->getLaneWidth());
1162 }
1165 return "lane specific";
1166 } else {
1167 return toString(myNBEdge->getEndOffset());
1168 }
1169 case SUMO_ATTR_DISTANCE:
1170 return toString(myNBEdge->getDistance());
1172 return myConnectionStatus;
1174 if (getParentJunctions().empty()) {
1175 return "";
1176 } else if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
1177 return "";
1178 } else {
1179 return toString(myNBEdge->getGeometry().front());
1180 }
1181 case GNE_ATTR_SHAPE_END:
1182 if (getParentJunctions().empty()) {
1183 return "";
1184 } else if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
1185 return "";
1186 } else {
1187 return toString(myNBEdge->getGeometry().back());
1188 }
1189 case GNE_ATTR_BIDIR:
1190 return toString(myNBEdge->getBidiEdge() != nullptr);
1196 } else {
1197 return "";
1198 }
1201 default:
1202 return getCommonAttribute(key);
1203 }
1204}
1205
1206
1207double
1211
1212
1217
1218
1221 switch (key) {
1222 case SUMO_ATTR_SHAPE:
1223 return myNBEdge->getInnerGeometry();
1224 default:
1226 }
1227}
1228
1229
1230std::string
1232 std::string result = getAttribute(key);
1233 if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
1234 result += " " + getVehicleClassNames(SVCAll, true);
1235 }
1236 return result;
1237}
1238
1239
1240void
1241GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1242 // get template editor
1244 // check if we have to update template
1245 const bool updateTemplate = templateEditor->getEdgeTemplate() ? (templateEditor->getEdgeTemplate()->getID() == getID()) : false;
1246 switch (key) {
1247 case SUMO_ATTR_WIDTH:
1249 case SUMO_ATTR_SPEED:
1250 case SUMO_ATTR_FRICTION:
1251 case SUMO_ATTR_ALLOW:
1252 case SUMO_ATTR_DISALLOW: {
1253 undoList->begin(this, "change " + getTagStr() + " attribute");
1254 const std::string origValue = getChildLanes().at(0)->getAttribute(key); // will have intermediate value of "lane specific"
1255 // lane specific attributes need to be changed via lanes to allow undo
1256 for (auto it : getChildLanes()) {
1257 it->setAttribute(key, value, undoList);
1258 }
1259 // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
1260 GNEChange_Attribute::changeAttribute(this, key, value, origValue, undoList);
1261 undoList->end();
1262 break;
1263 }
1264 case SUMO_ATTR_FROM: {
1265 if (value != getAttribute(key)) {
1266 undoList->begin(this, "change " + getTagStr() + " attribute");
1267 // Remove edge from crossings of junction source
1269 // continue changing from junction
1270 GNEJunction* originalFirstParentJunction = getFromJunction();
1271 getFromJunction()->setLogicValid(false, undoList);
1272 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1273 getFromJunction()->setLogicValid(false, undoList);
1274 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1275 setAttribute(GNE_ATTR_SHAPE_START, toString(getFromJunction()->getNBNode()->getPosition()), undoList);
1277 undoList->end();
1278 // update geometries of all implicated junctions
1279 originalFirstParentJunction->updateGeometry();
1282 }
1283 break;
1284 }
1285 case SUMO_ATTR_TO: {
1286 if (value != getAttribute(key)) {
1287 undoList->begin(this, "change " + getTagStr() + " attribute");
1288 // Remove edge from crossings of junction destination
1290 // continue changing destination junction
1291 GNEJunction* originalSecondParentJunction = getToJunction();
1292 getToJunction()->setLogicValid(false, undoList);
1293 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1294 getToJunction()->setLogicValid(false, undoList);
1295 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1296 setAttribute(GNE_ATTR_SHAPE_END, toString(getToJunction()->getNBNode()->getPosition()), undoList);
1298 undoList->end();
1299 // update geometries of all implicated junctions
1300 originalSecondParentJunction->updateGeometry();
1303 }
1304 break;
1305 }
1306 case SUMO_ATTR_ID:
1307 case SUMO_ATTR_PRIORITY:
1308 case SUMO_ATTR_LENGTH:
1309 case SUMO_ATTR_TYPE:
1312 case SUMO_ATTR_DISTANCE:
1315 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1316 break;
1318 // special case for stop offset, because affects to stopOffsetExceptions (#15297)
1319 if (canParse<double>(value) && (parse<double>(value) == 0)) {
1321 }
1322 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1323 break;
1325 case GNE_ATTR_SHAPE_END: {
1326 // due to ENDPOINT_TOLERANCE, force change
1327 GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1328 break;
1329 }
1330 case SUMO_ATTR_NAME:
1331 // user cares about street names. Make sure they appear in the output
1333 OptionsCont::getOptions().set("output.street-names", "true");
1334 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1335 break;
1336 case SUMO_ATTR_NUMLANES:
1337 if (value != getAttribute(key)) {
1338 // set num lanes
1339 setNumLanes(parse<int>(value), undoList);
1340 }
1341 break;
1342 case GNE_ATTR_BIDIR:
1343 undoList->begin(this, "change " + getTagStr() + " attribute");
1344 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1345 if (myNBEdge->getTurnDestination(true) != nullptr) {
1347 GNEChange_Attribute::changeAttribute(bidi, key, value, undoList);
1348 if (myNBEdge->getGeometry() != bidi->getNBEdge()->getGeometry().reverse()
1349 && myNBEdge->getGeometry().size() == 2
1350 && bidi->getNBEdge()->getGeometry().size() == 2
1351 && myNBEdge->getBidiEdge() == nullptr) {
1352 // NBEdge::avoidOverlap was already active so we need to reset the
1353 // geometry to its default
1354 resetBothEndpoint(undoList);
1355 bidi->resetBothEndpoint(undoList);
1356 }
1357 }
1358 undoList->end();
1359 break;
1360 case SUMO_ATTR_SHAPE:
1361 // @note: assumes value of inner geometry!
1362 // actually the geometry is already updated (incrementally
1363 // during mouse movement). We set the restore point to the end
1364 // of the last change-set
1365 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1366 break;
1367 default:
1368 setCommonAttribute(key, value, undoList);
1369 break;
1370 }
1371 // update template
1372 if (updateTemplate) {
1373 templateEditor->setEdgeTemplate(this);
1374 }
1375}
1376
1377
1378bool
1379GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
1380 switch (key) {
1381 case SUMO_ATTR_ID:
1382 return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveEdge(value, false) == nullptr);
1383 case SUMO_ATTR_FROM: {
1384 // check that is a valid ID and is different of ID of junction destination
1385 if (value == getFromJunction()->getID()) {
1386 return true;
1387 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getToJunction()->getID())) {
1388 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1389 } else {
1390 return false;
1391 }
1392 }
1393 case SUMO_ATTR_TO: {
1394 // check that is a valid ID and is different of ID of junction Source
1395 if (value == getToJunction()->getID()) {
1396 return true;
1397 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getFromJunction()->getID())) {
1398 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1399 } else {
1400 return false;
1401 }
1402 }
1403 case SUMO_ATTR_SPEED:
1404 return canParse<double>(value) && (parse<double>(value) > 0);
1405 case SUMO_ATTR_FRICTION:
1406 return canParse<double>(value) && (parse<double>(value) > 0);
1407 case SUMO_ATTR_NUMLANES:
1408 return canParse<int>(value) && (parse<double>(value) > 0);
1409 case SUMO_ATTR_PRIORITY:
1410 return canParse<int>(value);
1411 case SUMO_ATTR_LENGTH:
1412 if (value.empty()) {
1413 return true;
1414 } else {
1415 return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
1416 }
1417 case SUMO_ATTR_ALLOW:
1418 case SUMO_ATTR_DISALLOW:
1419 return canParseVehicleClasses(value);
1420 case SUMO_ATTR_TYPE:
1422 return true;
1423 case SUMO_ATTR_SHAPE:
1424 // empty shapes are allowed
1425 return canParse<PositionVector>(value);
1428 case SUMO_ATTR_NAME:
1429 return true;
1430 case SUMO_ATTR_WIDTH:
1431 if (value.empty() || (value == "default")) {
1432 return true;
1433 } else {
1434 return canParse<double>(value) && ((parse<double>(value) >= -1) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
1435 }
1437 return canParse<double>(value) && parse<double>(value) >= 0 && parse<double>(value) < myNBEdge->getLoadedLength();
1438 case SUMO_ATTR_DISTANCE:
1439 if (value.empty()) {
1440 return true;
1441 } else {
1442 return canParse<double>(value);
1443 }
1444 case GNE_ATTR_SHAPE_START: {
1445 if (value.empty()) {
1446 return true;
1447 } else if (canParse<Position>(value)) {
1448 Position shapeStart = parse<Position>(value);
1449 return (shapeStart != myNBEdge->getGeometry()[-1]);
1450 } else {
1451 return false;
1452 }
1453 }
1454 case GNE_ATTR_SHAPE_END: {
1455 if (value.empty()) {
1456 return true;
1457 } else if (canParse<Position>(value)) {
1458 Position shapeEnd = parse<Position>(value);
1459 return (shapeEnd != myNBEdge->getGeometry()[0]);
1460 } else {
1461 return false;
1462 }
1463 }
1464 case GNE_ATTR_BIDIR:
1465 return canParse<bool>(value) && (!parse<bool>(value) || myNBEdge->isBidiEdge(true));
1467 if (value.empty()) {
1468 return true;
1469 } else {
1470 return canParse<double>(value) && (parse<double>(value) >= 0);
1471 }
1473 return canParseVehicleClasses(value);
1474 default:
1475 return isCommonAttributeValid(key, value);
1476 }
1477}
1478
1479
1480bool
1482 switch (key) {
1483 case GNE_ATTR_BIDIR:
1484 return myNBEdge->isBidiEdge(true);
1486 return myNBEdge->myEdgeStopOffset.getOffset() > 0;
1488 return false;
1489 default:
1490 return true;
1491 }
1492}
1493
1494
1495bool
1497 switch (key) {
1498 case SUMO_ATTR_LENGTH:
1499 return !myNBEdge->hasLoadedLength();
1500 case SUMO_ATTR_WIDTH:
1502 return false;
1503 } else {
1505 }
1506 default:
1507 return false;
1508 }
1509}
1510
1511
1512void
1514 myAmResponsible = newVal;
1515}
1516
1517
1518GNELane*
1520 // iterate over all NBEdge lanes
1521 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1522 // if given VClass is in permissions, return lane
1523 if (myNBEdge->getLanes().at(i).permissions & vClass) {
1524 // return GNELane
1525 return getChildLanes().at(i);
1526 }
1527 }
1528 // return first lane
1529 return getChildLanes().front();
1530}
1531
1532
1533GNELane*
1535 // iterate over all NBEdge lanes
1536 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1537 // if given VClass isn't in permissions, return lane
1538 if (~(myNBEdge->getLanes().at(i).permissions) & vClass) {
1539 // return GNELane
1540 return getChildLanes().at(i);
1541 }
1542 }
1543 // return first lane
1544 return getChildLanes().front();
1545}
1546
1547
1548void
1550 // get lane vehicles map
1551 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1552 // iterate over every lane
1553 for (const auto& laneVehicle : laneVehiclesMap) {
1554 // obtain total length
1555 double totalLength = 0;
1556 for (const auto& vehicle : laneVehicle.second) {
1557 totalLength += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1558 }
1559 // calculate multiplier for vehicle positions
1560 double multiplier = 1;
1561 const double laneShapeLength = laneVehicle.first->getLaneShape().length();
1562 if (laneShapeLength == 0) {
1563 multiplier = 0;
1564 } else if (totalLength > laneShapeLength) {
1565 multiplier = (laneShapeLength / totalLength);
1566 }
1567 // declare current length
1568 double length = 0;
1569 // iterate over vehicles to calculate position and rotations
1570 for (const auto& vehicle : laneVehicle.second) {
1571 vehicle->updateDemandElementSpreadGeometry(laneVehicle.first, length * multiplier);
1572 // update length
1573 length += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1574 }
1575 }
1576}
1577
1578
1579void
1581 // get lane vehicles map
1582 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1583 // iterate over laneVehiclesMap and obtain a vector with
1584 for (const auto& vehicleMap : laneVehiclesMap) {
1585 // declare map for sort vehicles using their departpos+length position (StackPosition)
1586 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosVehicles;
1587 // declare vector of stack demand elements
1588 std::vector<GNEEdge::StackDemandElements> stackedVehicles;
1589 // iterate over vehicles
1590 for (const auto& vehicle : vehicleMap.second) {
1591 // get vehicle's depart pos and length
1592 const double departPos = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1593 const double length = vehicle->getAttributeDouble(SUMO_ATTR_LENGTH);
1594 double posOverLane = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1595 // check if we have to adapt posOverLane
1596 if (posOverLane < 0) {
1597 posOverLane += vehicleMap.first->getLaneShape().length();
1598 }
1599 // make a stack position using departPos and length
1600 departPosVehicles.push_back(std::make_pair(StackPosition(departPos, length), vehicle));
1601 // update depart element geometry
1602 vehicle->updateDemandElementGeometry(vehicleMap.first, posOverLane);
1603 // reset vehicle stack label
1604 vehicle->updateDemandElementStackLabel(0);
1605 }
1606
1607 // sort departPosVehicles
1608 std::sort(departPosVehicles.begin(), departPosVehicles.end());
1609 // iterate over departPosVehicles
1610 for (const auto& departPosVehicle : departPosVehicles) {
1611 // obtain stack position and vehicle
1612 const GNEEdge::StackPosition& vehicleStackPosition = departPosVehicle.first;
1613 GNEDemandElement* vehicle = departPosVehicle.second;
1614 // if stackedVehicles is empty, add a new StackDemandElements
1615 if (stackedVehicles.empty()) {
1616 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1617 } else if (areStackPositionOverlapped(vehicleStackPosition, stackedVehicles.back().getStackPosition())) {
1618 // add new vehicle to last inserted stackDemandElements
1619 stackedVehicles[stackedVehicles.size() - 1].addDemandElements(vehicle);
1620 } else {
1621 // No overlapping, then add a new StackDemandElements
1622 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1623 }
1624 }
1625 // iterate over stackedVehicles
1626 for (const auto& vehicle : stackedVehicles) {
1627 // only update vehicles with one or more stack
1628 if (vehicle.getDemandElements().size() > 1) {
1629 // set stack labels
1630 vehicle.getDemandElements().front()->updateDemandElementStackLabel((int)vehicle.getDemandElements().size());
1631 }
1632 }
1633 }
1634}
1635
1636
1637void
1639 // get lane persons map
1640 const std::map<const GNELane*, std::vector<GNEDemandElement*> > lanePersonsMap = getPersonsOverEdgeMap();
1641 // iterate over lanePersonsMap and obtain a vector with
1642 for (const auto& personMap : lanePersonsMap) {
1643 // declare map for sort persons using their departpos+length position (StackPosition)
1644 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosPersons;
1645 // declare vector of stack demand elements
1646 std::vector<GNEEdge::StackDemandElements> stackedPersons;
1647 // iterate over persons
1648 for (const auto& person : personMap.second) {
1649 // get person's depart pos and length
1650 const double departPos = person->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1651 // make a stack position using departPos and length
1652 departPosPersons.push_back(std::make_pair(StackPosition(departPos, 1.8), person));
1653 // update depart element geometry
1654 person->updateDemandElementGeometry(personMap.first, departPos);
1655 // reset person stack label
1656 person->updateDemandElementStackLabel(0);
1657 }
1658
1659 // sort departPosPersons
1660 std::sort(departPosPersons.begin(), departPosPersons.end());
1661 // iterate over departPosPersons
1662 for (const auto& departPosPerson : departPosPersons) {
1663 // obtain stack position and person
1664 const GNEEdge::StackPosition& personStackPosition = departPosPerson.first;
1665 GNEDemandElement* person = departPosPerson.second;
1666 // if stackedPersons is empty, add a new StackDemandElements
1667 if (stackedPersons.empty()) {
1668 stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1669 } else if (areStackPositionOverlapped(personStackPosition, stackedPersons.back().getStackPosition())) {
1670 // add new person to last inserted stackDemandElements
1671 stackedPersons[stackedPersons.size() - 1].addDemandElements(person);
1672 } else {
1673 // No overlapping, then add a new StackDemandElements
1674 stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1675 }
1676 }
1677 // iterate over stackedPersons
1678 for (const auto& person : stackedPersons) {
1679 // only update persons with one or more stack
1680 if (person.getDemandElements().size() > 1) {
1681 // set stack labels
1682 person.getDemandElements().front()->updateDemandElementStackLabel((int)person.getDemandElements().size());
1683 }
1684 }
1685 }
1686}
1687
1688
1689void
1691 // get lane containers map
1692 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneContainersMap = getContainersOverEdgeMap();
1693 // iterate over laneContainersMap and obtain a vector with
1694 for (const auto& containerMap : laneContainersMap) {
1695 // declare map for sort containers using their departpos+length position (StackPosition)
1696 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosContainers;
1697 // declare vector of stack demand elements
1698 std::vector<GNEEdge::StackDemandElements> stackedContainers;
1699 // iterate over containers
1700 for (const auto& container : containerMap.second) {
1701 // get container's depart pos and length
1702 const double departPos = container->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1703 // make a stack position using departPos and length
1704 departPosContainers.push_back(std::make_pair(StackPosition(departPos, 1.8), container));
1705 // update depart element geometry
1706 container->updateDemandElementGeometry(containerMap.first, departPos);
1707 // reset container stack label
1708 container->updateDemandElementStackLabel(0);
1709 }
1710
1711 // sort departPosContainers
1712 std::sort(departPosContainers.begin(), departPosContainers.end());
1713 // iterate over departPosContainers
1714 for (const auto& departPosContainer : departPosContainers) {
1715 // obtain stack position and container
1716 const GNEEdge::StackPosition& containerStackPosition = departPosContainer.first;
1717 GNEDemandElement* container = departPosContainer.second;
1718 // if stackedContainers is empty, add a new StackDemandElements
1719 if (stackedContainers.empty()) {
1720 stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1721 } else if (areStackPositionOverlapped(containerStackPosition, stackedContainers.back().getStackPosition())) {
1722 // add new container to last inserted stackDemandElements
1723 stackedContainers[stackedContainers.size() - 1].addDemandElements(container);
1724 } else {
1725 // No overlapping, then add a new StackDemandElements
1726 stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1727 }
1728 }
1729 // iterate over stackedContainers
1730 for (const auto& container : stackedContainers) {
1731 // only update containers with one or more stack
1732 if (container.getDemandElements().size() > 1) {
1733 // set stack labels
1734 container.getDemandElements().front()->updateDemandElementStackLabel((int)container.getDemandElements().size());
1735 }
1736 }
1737 }
1738}
1739
1740
1741bool
1743 // calculate angle between both junction positions
1744 double edgeAngle = RAD2DEG(getFromJunction()->getPositionInView().angleTo2D(getToJunction()->getPositionInView()));
1745 // adjust to 360 degrees
1746 while (edgeAngle < 0) {
1747 edgeAngle += 360;
1748 }
1749 // fmod round towards zero which is not want we want for negative numbers
1750 edgeAngle = fmod(edgeAngle, 360);
1751 // check angle
1752 return edgeAngle >= 0 && edgeAngle < 180;
1753}
1754
1755
1756bool
1758 // get incoming edges
1759 const auto incomingEdges = getFromJunction()->getGNEIncomingEdges();
1760 // iterate over connections
1761 for (const auto& incomingEdge : incomingEdges) {
1762 for (const auto& connection : incomingEdge->getGNEConnections()) {
1763 if (connection->getEdgeTo() == this) {
1764 return true;
1765 }
1766 }
1767 }
1768 return false;
1769}
1770
1771
1772bool
1774 return (myGNEConnections.size() > 0);
1775}
1776
1777
1778GNEEdge*
1780 for (const auto& outgoingEdge : getParentJunctions().back()->getGNEOutgoingEdges()) {
1781 if (outgoingEdge->getToJunction() == getFromJunction()) {
1782 return outgoingEdge;
1783 }
1784 }
1785 return nullptr;
1786}
1787
1788// ===========================================================================
1789// private
1790// ===========================================================================
1791
1792GNEEdge::StackPosition::StackPosition(const double departPos, const double length) :
1793 pair(departPos, departPos + length) {
1794}
1795
1796
1797double
1799 return first;
1800}
1801
1802
1803double
1805 return second;
1806}
1807
1808
1810 pair(stackedPosition, {
1811 demandElement
1812}) {
1813}
1814
1815
1816void
1818 second.push_back(demandElement);
1819}
1820
1821
1824 return first;
1825}
1826
1827
1828const std::vector<GNEDemandElement*>&
1830 return second;
1831}
1832
1833
1834void
1835GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
1836 switch (key) {
1837 case SUMO_ATTR_ID:
1838 myNet->getAttributeCarriers()->updateEdgeID(this, value);
1839 // enable save demand elements if there are stops
1840 for (const auto& stop : getChildDemandElements()) {
1841 if (stop->getTagProperty()->isVehicleStop()) {
1843 }
1844 }
1845 // also for lanes
1846 for (const auto& lane : getChildLanes()) {
1847 for (const auto& stop : lane->getChildDemandElements()) {
1848 if (stop->getTagProperty()->isVehicleStop()) {
1850 }
1851 }
1852 }
1853 break;
1854 case SUMO_ATTR_FROM:
1855 myNet->changeEdgeEndpoints(this, value, getToJunction()->getID());
1856 // update this edge of list of outgoings edges of the old first parent junction
1858 // update first parent junction
1860 // update this edge of list of outgoings edges of the new first parent junction
1862 // update centering boundary and grid
1864 break;
1865 case SUMO_ATTR_TO:
1866 myNet->changeEdgeEndpoints(this, getFromJunction()->getID(), value);
1867 // update this edge of list of incomings edges of the old second parent junction
1869 // update second parent junction
1871 // update this edge of list of incomings edges of the new second parent junction
1873 // update centering boundary and grid
1875 break;
1876 case SUMO_ATTR_NUMLANES:
1877 throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
1878 case SUMO_ATTR_PRIORITY:
1879 myNBEdge->myPriority = parse<int>(value);
1880 break;
1881 case SUMO_ATTR_LENGTH:
1882 if (value.empty()) {
1884 } else {
1885 myNBEdge->setLoadedLength(parse<double>(value));
1886 }
1887 break;
1888 case SUMO_ATTR_TYPE:
1889 myNBEdge->myType = value;
1890 break;
1892 myNBEdge->myRoutingType = value;
1893 break;
1894 case SUMO_ATTR_SHAPE:
1895 // set new geometry
1896 setGeometry(parse<PositionVector>(value), true);
1897 // update centering boundary and grid
1899 break;
1902 break;
1903 case SUMO_ATTR_NAME:
1904 myNBEdge->setStreetName(value);
1905 break;
1906 case SUMO_ATTR_SPEED:
1907 myNBEdge->setSpeed(-1, parse<double>(value));
1908 break;
1909 case SUMO_ATTR_FRICTION:
1910 myNBEdge->setFriction(-1, parse<double>(value));
1911 break;
1912 case SUMO_ATTR_WIDTH:
1913 if (value.empty() || (value == "default")) {
1915 } else {
1916 myNBEdge->setLaneWidth(-1, parse<double>(value));
1917 }
1918 break;
1920 myNBEdge->setEndOffset(-1, parse<double>(value));
1921 break;
1922 case SUMO_ATTR_ALLOW:
1923 break; // no edge value
1924 case SUMO_ATTR_DISALLOW:
1925 break; // no edge value
1926 case SUMO_ATTR_DISTANCE:
1927 if (value.empty()) {
1928 myNBEdge->setDistance(0.0);
1929 } else {
1930 myNBEdge->setDistance(parse<double>(value));
1931 }
1932 break;
1934 myConnectionStatus = value;
1935 if (value == FEATURE_GUESSED) {
1938 } else if (value != FEATURE_GUESSED) {
1940 }
1941 break;
1942 case GNE_ATTR_SHAPE_START: {
1943 // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1944 Position newShapeStart;
1945 if (value == "") {
1946 newShapeStart = getFromJunction()->getNBNode()->getPosition();
1947 } else {
1948 newShapeStart = parse<Position>(value);
1949 }
1950 // set shape start position
1951 setShapeStartPos(newShapeStart);
1952 // update centering boundary and grid
1954 break;
1955 }
1956 case GNE_ATTR_SHAPE_END: {
1957 // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destination position) and set it back to edge
1958 Position newShapeEnd;
1959 if (value == "") {
1960 newShapeEnd = getToJunction()->getNBNode()->getPosition();
1961 } else {
1962 newShapeEnd = parse<Position>(value);
1963 }
1964 // set shape end position
1965 setShapeEndPos(newShapeEnd);
1966 // update centering boundary and grid
1968 break;
1969 }
1970 case GNE_ATTR_BIDIR:
1971 myNBEdge->setBidi(parse<bool>(value));
1972 break;
1974 if (value.empty()) {
1976 } else {
1977 myNBEdge->myEdgeStopOffset.setOffset(parse<double>(value));
1978 }
1979 break;
1982 break;
1983 default:
1984 setCommonAttribute(key, value);
1985 break;
1986 }
1987 // get template editor
1989 // check if update template (except for modification status)
1990 if (templateEditor->getEdgeTemplate() && (templateEditor->getEdgeTemplate()->getID() == getID()) &&
1993 }
1994 // invalidate demand path calculator
1996}
1997
1998
1999void
2000GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
2001 // begin undo list
2002 undoList->begin(this, "change number of " + toString(SUMO_TAG_LANE) + "s");
2003 // invalidate logic of source/destination edges
2004 getFromJunction()->setLogicValid(false, undoList);
2005 getToJunction()->setLogicValid(false, undoList);
2006 // disable update geometry (see #6336)
2007 myUpdateGeometry = false;
2008 // remove edge from grid
2010 // save old number of lanes
2011 const int oldNumLanes = (int)getChildLanes().size();
2012 // get opposite ID
2013 const auto oppositeID = getChildLanes().back()->getAttribute(GNE_ATTR_OPPOSITE);
2014 if (oppositeID != "") {
2015 // we'll have a different leftmost lane after adding/removing lanes
2017 }
2018 for (int i = oldNumLanes; i < numLanes; i++) {
2019 // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
2020 undoList->add(new GNEChange_Lane(this, myNBEdge->getLaneStruct(oldNumLanes - 1)), true);
2021 }
2022 for (int i = (oldNumLanes - 1); i > (numLanes - 1); i--) {
2023 myNet->deleteLane(getChildLanes().at(i), undoList, false);
2024 }
2025 if (oppositeID != "") {
2027 }
2028 // enable updateGeometry again
2029 myUpdateGeometry = true;
2030 // update geometry of entire edge
2032 // end undo list
2033 undoList->end();
2034 // update centering boundary (without updating RTREE)
2036 // insert edge in grid again
2038}
2039
2040
2041void
2042GNEEdge::updateFirstParentJunction(const std::string& value) {
2043 auto newJunction = myNet->getAttributeCarriers()->retrieveJunction(value);
2044 GNEHierarchicalElement::updateParent(this, 0, newJunction);
2045}
2046
2047
2048void
2049GNEEdge::updateSecondParentJunction(const std::string& value) {
2050 auto newJunction = myNet->getAttributeCarriers()->retrieveJunction(value);
2051 GNEHierarchicalElement::updateParent(this, 1, newJunction);
2052}
2053
2054
2055void
2056GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections) {
2057 const int index = lane ? lane->getIndex() : myNBEdge->getNumLanes();
2058 // the laneStruct must be created first to ensure we have some geometry
2059 // unless the connections are fully recomputed, existing indices must be shifted
2060 myNBEdge->addLane(index, true, recomputeConnections, !recomputeConnections);
2061 if (lane) {
2062 // restore a previously deleted lane
2064 newParentLanes.insert(newParentLanes.begin() + index, lane);
2065 while (getChildLanes().size() > 0) {
2066 removeChild(this, getChildLanes().front());
2067 }
2068 for (const auto newParentLane : newParentLanes) {
2069 insertChild(this, newParentLane);
2070 }
2071 } else {
2072 // create a new lane by copying leftmost lane
2073 lane = new GNELane(this, index);
2075 }
2076 lane->incRef("GNEEdge::addLane");
2077 // add in attributeCarriers
2079 // check if lane is selected
2080 if (lane->isAttributeCarrierSelected()) {
2081 lane->selectAttributeCarrier();
2082 }
2083 // we copy all attributes except shape since this is recomputed from edge shape
2084 myNBEdge->setSpeed(lane->getIndex(), laneAttrs.speed);
2085 myNBEdge->setFriction(lane->getIndex(), laneAttrs.friction);
2086 myNBEdge->setPermissions(laneAttrs.permissions, lane->getIndex());
2088 myNBEdge->setEndOffset(lane->getIndex(), laneAttrs.endOffset);
2089 myNBEdge->setLaneWidth(lane->getIndex(), laneAttrs.width);
2090 // update indices
2091 for (int i = 0; i < (int)getChildLanes().size(); ++i) {
2092 getChildLanes()[i]->setIndex(i);
2093 }
2094 /* while technically correct, this looks ugly
2095 getFromJunction()->invalidateShape();
2096 getToJunction()->invalidateShape();
2097 */
2098 // Remake connections for this edge and all edges that target this lane
2100 // remake connections of all edges of junction source and destination
2101 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2102 fromEdge->remakeGNEConnections();
2103 }
2104 // remake connections of all edges of junction source and destination
2105 for (const auto& toEdge : getToJunction()->getChildEdges()) {
2106 toEdge->remakeGNEConnections();
2107 }
2108 // Update geometry with the new lane
2110 // update boundary and grid
2112}
2113
2114
2115void
2116GNEEdge::removeLane(GNELane* lane, bool recomputeConnections) {
2117 if (getChildLanes().size() == 0) {
2118 throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + getTagStr());
2119 }
2120 if (lane == nullptr) {
2121 lane = getChildLanes().back();
2122 }
2123 // check if lane is selected
2124 if (lane->isAttributeCarrierSelected()) {
2126 }
2127 // before removing, check that lane isn't being inspected
2130 // Delete lane of edge's container
2131 // unless the connections are fully recomputed, existing indices must be shifted
2132 myNBEdge->deleteLane(lane->getIndex(), recomputeConnections, !recomputeConnections);
2133 lane->decRef("GNEEdge::removeLane");
2134 // delete lane from edge
2136 // remove from attributeCarriers
2138 // Delete lane if is unreferenced
2139 if (lane->unreferenced()) {
2140 delete lane;
2141 }
2142 // update indices
2143 for (int i = 0; i < (int)getChildLanes().size(); ++i) {
2144 getChildLanes()[i]->setIndex(i);
2145 }
2146 /* while technically correct, this looks ugly
2147 getFromJunction()->invalidateShape();
2148 getToJunction()->invalidateShape();
2149 */
2150 // Remake connections of this edge
2152 // remake connections of all edges of junction source and destination
2153 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2154 fromEdge->remakeGNEConnections();
2155 }
2156 // remake connections of all edges of junction source and destination
2157 for (const auto& toEdge : getToJunction()->getChildEdges()) {
2158 toEdge->remakeGNEConnections();
2159 }
2160 // Update element
2162 // update boundary and grid
2164}
2165
2166
2167void
2168GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
2169 // If a new connection was successfully created
2171 nbCon.keepClear, nbCon.contPos, nbCon.visibility,
2172 nbCon.speed, nbCon.friction, nbCon.customLength, nbCon.customShape, nbCon.uncontrolled)) {
2173 // Create or retrieve existent GNEConnection
2174 GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
2175 // add it to GNEConnection container
2176 myGNEConnections.push_back(con);
2177 // Add reference
2178 myGNEConnections.back()->incRef("GNEEdge::addConnection");
2179 // select GNEConnection if needed
2180 if (selectAfterCreation) {
2182 }
2183 // update geometry
2184 con->updateGeometry();
2185 }
2186 // actually we only do this to force a redraw
2188}
2189
2190
2191void
2193 // check if is a explicit turnaround
2194 if (nbCon.toEdge == myNBEdge->getTurnDestination()) {
2196 }
2197 // remove NBEdge::connection from NBEdge
2199 // remove their associated GNEConnection
2200 GNEConnection* connection = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
2201 if (connection != nullptr) {
2202 // before removing, check that the connection isn't being inspected
2205 connection->decRef("GNEEdge::removeConnection");
2206 myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), connection));
2207 // check if connection is selected
2208 if (connection->isAttributeCarrierSelected()) {
2209 connection->unselectAttributeCarrier();
2210 }
2211 // remove it from network
2212 myNet->removeGLObjectFromGrid(connection);
2213 // check if remove it from Attribute Carriers
2214 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
2216 }
2217 if (connection->unreferenced()) {
2218 // actually we only do this to force a redraw
2220 }
2221 }
2222}
2223
2224
2226GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
2227 for (const auto& connection : myGNEConnections) {
2228 if ((connection->getFromLaneIndex() == fromLane) && (connection->getEdgeTo()->getNBEdge() == to) && (connection->getToLaneIndex() == toLane)) {
2229 return connection;
2230 }
2231 }
2232 if (createIfNoExist) {
2233 // create new connection. Will be added to the rTree on first geometry computation
2234 GNEConnection* connection = new GNEConnection(getChildLanes()[fromLane], myNet->getAttributeCarriers()->retrieveEdge(to->getID())->getChildLanes()[toLane]);
2235 // add it into network
2236 myNet->addGLObjectIntoGrid(connection);
2237 // add it in attributeCarriers
2239 return connection;
2240 } else {
2241 return nullptr;
2242 }
2243}
2244
2245
2246void
2247GNEEdge::setEdgeID(const std::string& newID) {
2248 setNetworkElementID(newID);
2249 for (const auto& lane : getChildLanes()) {
2250 lane->setNetworkElementID(getNBEdge()->getLaneID(lane->getIndex()));
2251 }
2252}
2253
2254
2255bool
2257 for (const auto& lane : getChildLanes()) {
2258 if (lane->isRestricted(vclass)) {
2259 return true;
2260 }
2261 }
2262 return false;
2263}
2264
2265
2266void
2268 // Remove all crossings that contain this edge in parameter "edges"
2269 for (const auto& crossing : junction->getGNECrossings()) {
2270 if (crossing->checkEdgeBelong(this)) {
2271 myNet->deleteCrossing(crossing, undoList);
2272 }
2273 }
2274}
2275
2276
2277void
2282 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2283 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2284}
2285
2286
2288GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
2289 const auto& neteditOptions = OptionsCont::getOptions();
2290 // distinguish 3 cases:
2291 // a) if the edge has exactly 3 or 4 points, use these as control points
2292 // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
2293 // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
2294 PositionVector init;
2295#ifdef DEBUG_SMOOTH_GEOM
2296 if (DEBUGCOND(this)) std::cout << getID()
2297 << " forElevation=" << forElevation
2298 << " fromGeometryLike=" << myNBEdge->getFromNode()->geometryLike()
2299 << " toGeometryLike=" << myNBEdge->getToNode()->geometryLike()
2300 << " smoothShape old=" << old << "\n";
2301#endif
2302 if (old.size() == 3 || old.size() == 4) {
2303 init = old;
2304 } else if (old.size() > 4 && !forElevation) {
2305 // for elevation, the initial segments are not useful
2306 init.push_back(old[0]);
2307 init.push_back(old[1]);
2308 init.push_back(old[-2]);
2309 init.push_back(old[-1]);
2310 } else if (myNBEdge->getFromNode()->geometryLike() && myNBEdge->getToNode()->geometryLike()) {
2311 PositionVector begShape;
2312 PositionVector endShape;
2313 const EdgeVector& incoming = myNBEdge->getFromNode()->getIncomingEdges();
2314 const EdgeVector& outgoing = myNBEdge->getToNode()->getOutgoingEdges();
2315 if (incoming.size() == 1) {
2316 begShape = incoming[0]->getGeometry();
2317 } else {
2318 assert(incoming.size() == 2);
2319 begShape = myNBEdge->isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
2320 }
2321 if (outgoing.size() == 1) {
2322 endShape = outgoing[0]->getGeometry();
2323 } else {
2324 assert(outgoing.size() == 2);
2325 endShape = myNBEdge->isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
2326 }
2327 const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
2328 if (forElevation) {
2329 // initialize control point elevation for smooth continuation
2330 init.push_back(old[0]);
2331 init.push_back(old.positionAtOffset2D(dist));
2332 init.push_back(old.positionAtOffset2D(old.length2D() - dist));
2333 init.push_back(old[-1]);
2334 double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
2335 double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
2336 // continue incline
2337 init[1].setz(2 * init[0].z() - begZ);
2338 init[2].setz(2 * init[-1].z() - endZ);
2339 } else {
2340 bool ok = true;
2341 const double straightThresh = DEG2RAD(neteditOptions.getFloat("opendrive-output.straight-threshold"));
2342 init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, nullptr, straightThresh);
2343 }
2344#ifdef DEBUG_SMOOTH_GEOM
2345 if (DEBUGCOND(this)) {
2346 std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
2347 }
2348#endif
2349 }
2350 if (init.size() == 0) {
2351 return PositionVector::EMPTY;
2352 } else {
2353 const int numPoints = MAX2(neteditOptions.getInt("junctions.internal-link-detail"),
2354 int(old.length2D() / neteditOptions.getFloat("opendrive.curve-resolution")));
2355 return init.bezier(numPoints);
2356 }
2357}
2358
2359
2360void
2362 PositionVector modifiedShape = smoothShape(myNBEdge->getGeometry(), false);
2363 if (modifiedShape.size() < 2) {
2364 WRITE_WARNINGF(TL("Could not compute smooth shape for edge '%'"), getID());
2365 } else {
2366 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2367 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2368 }
2369}
2370
2371
2372void
2374 PositionVector elevationBase;
2375 for (const Position& pos : myNBEdge->getGeometry()) {
2376 if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
2377 elevationBase.push_back(pos);
2378 }
2379 }
2380 PositionVector elevation = smoothShape(elevationBase, true);
2381 if (elevation.size() <= 2) {
2382 WRITE_WARNINGF(TL("Could not compute smooth elevation for edge '%'"), getID());
2383 } else {
2384 PositionVector modifiedShape = myNBEdge->getGeometry();
2385 if (modifiedShape.size() < 5) {
2386 modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"), false);
2387 }
2388 const double scale = elevation.length2D() / modifiedShape.length2D();
2389 //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
2390 double seen = 0;
2391 for (int i = 1; i < (int)modifiedShape.size(); ++i) {
2392 seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
2393 modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
2394 }
2395 //std::cout << " mod2=" << modifiedShape << "\n";
2396 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2397 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2398 }
2399}
2400
2401
2402void
2404 // remove start position and add it the new position
2406 geom.pop_front();
2407 geom.push_front(pos);
2408 // restore modified shape
2409 setGeometry(geom, false);
2410}
2411
2412
2413void
2415 // remove end position and add it the new position
2417 geom.pop_back();
2418 geom.push_back(pos);
2419 // restore modified shape
2420 setGeometry(geom, false);
2421}
2422
2423
2424const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2426 // declare vehicles over edge vector
2427 std::vector<GNEDemandElement*> vehiclesOverEdge;
2428 // declare solution map
2429 std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesOverEdgeMap;
2430 // declare a set of vehicles (to avoid duplicates)
2431 std::set<std::pair<double, GNEDemandElement*> > vehicles;
2432 // first obtain all vehicles of this edge
2433 for (const auto& edgeChild : getChildDemandElements()) {
2434 if (((edgeChild->getTagProperty()->getTag() == SUMO_TAG_TRIP) || (edgeChild->getTagProperty()->getTag() == SUMO_TAG_FLOW)) &&
2435 (edgeChild->getParentEdges().front() == this)) {
2436 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2437 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2438 } else if ((edgeChild->getTagProperty()->getTag() == SUMO_TAG_ROUTE) && (edgeChild->getParentEdges().front() == this)) {
2439 for (const auto& routeChild : edgeChild->getChildDemandElements()) {
2440 if (routeChild->getTagProperty()->vehicleRoute()) {
2441 vehicles.insert(std::make_pair(routeChild->getAttributeDouble(SUMO_ATTR_DEPART), routeChild));
2442 }
2443 }
2444 } else if ((edgeChild->getTagProperty()->getTag() == GNE_TAG_ROUTE_EMBEDDED) && (edgeChild->getParentEdges().front() == this) && (edgeChild->getParentDemandElements().size() > 0)) {
2445 vehicles.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild->getParentDemandElements().front()));
2446 }
2447 }
2448 // reserve
2449 vehiclesOverEdge.reserve(vehicles.size());
2450 // iterate over vehicles
2451 for (const auto& vehicle : vehicles) {
2452 // add it over vehiclesOverEdge;
2453 vehiclesOverEdge.push_back(vehicle.second);
2454 }
2455 // now split vehicles by lanes
2456 for (const auto& vehicle : vehiclesOverEdge) {
2457 const GNELane* vehicleLane = vehicle->getFirstPathLane();
2458 if (vehicleLane) {
2459 vehiclesOverEdgeMap[vehicleLane].push_back(vehicle);
2460 }
2461 }
2462 return vehiclesOverEdgeMap;
2463}
2464
2465
2466const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2468 // declare persons over edge vector
2469 std::vector<GNEDemandElement*> personsOverEdge;
2470 // declare solution map
2471 std::map<const GNELane*, std::vector<GNEDemandElement*> > personsOverEdgeMap;
2472 // declare a set of persons (to avoid duplicates)
2473 std::set<std::pair<double, GNEDemandElement*> > persons;
2474 // first obtain all persons of this edge
2475 for (const auto& edgeChild : getChildDemandElements()) {
2476 if (edgeChild->getTagProperty()->isPlanPerson() && (edgeChild->getParentDemandElements().size() > 0)) {
2477 persons.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2478 }
2479 }
2480 // reserve
2481 personsOverEdge.reserve(persons.size());
2482 // iterate over persons
2483 for (const auto& person : persons) {
2484 // add it over personsOverEdge;
2485 personsOverEdge.push_back(person.second);
2486 }
2487 // now split persons by lanes
2488 for (const auto& person : personsOverEdge) {
2489 const GNELane* personLane = person->getFirstPathLane();
2490 if (personLane) {
2491 personsOverEdgeMap[personLane].push_back(person);
2492 }
2493 }
2494 return personsOverEdgeMap;
2495}
2496
2497
2498
2499const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2501 // declare containers over edge vector
2502 std::vector<GNEDemandElement*> containersOverEdge;
2503 // declare solution map
2504 std::map<const GNELane*, std::vector<GNEDemandElement*> > containersOverEdgeMap;
2505 // declare a set of containers (to avoid duplicates)
2506 std::set<std::pair<double, GNEDemandElement*> > containers;
2507 // first obtain all containers of this edge
2508 for (const auto& edgeChild : getChildDemandElements()) {
2509 if (edgeChild->getTagProperty()->isPlanContainer() && (edgeChild->getParentDemandElements().size() > 0)) {
2510 containers.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2511 }
2512 }
2513 // reserve
2514 containersOverEdge.reserve(containers.size());
2515 // iterate over containers
2516 for (const auto& container : containers) {
2517 // add it over containersOverEdge;
2518 containersOverEdge.push_back(container.second);
2519 }
2520 // now split containers by lanes
2521 for (const auto& container : containersOverEdge) {
2522 const GNELane* containerLane = container->getFirstPathLane();
2523 if (containerLane) {
2524 containersOverEdgeMap[containerLane].push_back(container);
2525 }
2526 }
2527 return containersOverEdgeMap;
2528}
2529
2530
2531void
2533 // first check conditions
2535 // check if draw geometry points
2536 const bool bigGeometryPoints = drawBigGeometryPoints();
2537 // Obtain exaggeration of the draw
2538 const double exaggeration = getExaggeration(s);
2539 // get geometry point radius
2540 const double geometryPointRadius = getGeometryPointRadius();
2541 // obtain geometry point color
2542 RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2543 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2544 // override with special colors (unless the color scheme is based on selection)
2545 geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2546 }
2547 // draw geometry points except initial and final
2548 for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
2549 // obtain geometry point
2550 const auto geometryPointPos = myNBEdge->getGeometry()[i];
2551 // push geometry point drawing matrix
2553 // set color
2554 GLHelper::setColor(geometryPointColor);
2555 // move geometry point geometryPointPos
2556 glTranslated(geometryPointPos.x(), geometryPointPos.y(), bigGeometryPoints ? GLO_GEOMETRYPOINT : GLO_LANE + 1);
2557 // draw filled circle (resolution of drawn circle depending of the zoom, to improve smoothness)
2558 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius);
2559 // draw elevation or special symbols (Start, End and Block)
2561 // Translate to top
2562 glTranslated(0, 0, 0.2);
2563 // draw Z value
2564 GLHelper::drawText(toString(geometryPointPos.z()), Position(), 0, s.edgeValue.scaledSize(s.scale) / 2, s.edgeValue.color);
2565 }
2566 // pop geometry point drawing matrix
2568 }
2569 // draw start and end points
2570 if (bigGeometryPoints) {
2571 drawStartGeometryPoint(s, d, geometryPointRadius, layer, exaggeration);
2572 drawEndGeometryPoint(s, d, geometryPointRadius, layer, exaggeration);
2573 }
2574 // draw dotted contour geometry points
2577 }
2578}
2579
2580
2581void
2583 const double geometryPointRadius, const double layer, const double exaggeration) const {
2584 // check detail level
2586 // get first geometry point
2587 const auto& startGeometryPointPos = myNBEdge->getGeometry().front();
2588 // get flags
2589 const bool startPosEdited = (startGeometryPointPos != getParentJunctions().front()->getPositionInView());
2591 // check drawing conditions
2592 if (startPosEdited || forceDraw) {
2593 // calculate angle betwen first and second geometry point
2594 const double angle = RAD2DEG(startGeometryPointPos.angleTo2D(myNBEdge->getGeometry()[1])) * -1;
2595 // get selected geometry points
2596 const auto selectedGeometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(this);
2597 // override with special colors (unless the color scheme is based on selection)
2598 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2600 } else {
2601 GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2602 }
2603 // push drawing matrix
2605 // move to point position
2606 glTranslated(startGeometryPointPos.x(), startGeometryPointPos.y(), GLO_GEOMETRYPOINT);
2607 // resolution of drawn circle depending of detail
2608 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2609 // pop drawing matrix
2611 // draw a "s" over last point depending of detail level
2613 // push drawing matrix
2615 // move top
2616 glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2617 // draw S
2618 GLHelper::drawText("S", startGeometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2619 // pop drawing matrix
2621 // check if draw line between junctions
2622 if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.front() == 0)) {
2623 // set base color
2625 // push drawing matrix
2627 // draw line between geometry point and from junction
2628 const PositionVector lineA = {startGeometryPointPos, getFromJunction()->getNBNode()->getPosition()};
2629 GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2630 // draw line between begin point of last lane shape and the first edge shape point
2631 const PositionVector lineB = {startGeometryPointPos, myNBEdge->getLanes().back().shape.front()};
2632 GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2633 // pop drawing matrix
2635 }
2636 }
2637 // draw dotted contour geometry points
2639 geometryPointRadius, exaggeration);
2640 }
2641 }
2642}
2643
2644
2645void
2647 const double geometryPointRadius, const double layer, const double exaggeration) const {
2648 // check detail level
2650 // get first geometry point
2651 const auto& geometryPointPos = myNBEdge->getGeometry().back();
2652 // get flags
2653 const bool endPosEdited = (geometryPointPos != getParentJunctions().back()->getPositionInView());
2655 // check drawing conditions
2656 if (endPosEdited || forceDraw) {
2657 // calculate angle last and previous geometry point
2658 const double angle = RAD2DEG(geometryPointPos.angleTo2D(myNBEdge->getGeometry()[-2])) * -1;
2659 // get selected geometry points
2660 const auto selectedGeometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(this);
2661 // override with special colors (unless the color scheme is based on selection)
2662 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2664 } else {
2665 GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2666 }
2667 // push drawing matrix
2669 // move to point position
2670 glTranslated(geometryPointPos.x(), geometryPointPos.y(), GLO_GEOMETRYPOINT);
2671 // resolution of drawn circle depending of detail
2672 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2673 // pop drawing matrix
2675 // draw a "s" over last point depending of detail level
2677 // push drawing matrix
2679 // move top
2680 glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2681 // draw S
2682 GLHelper::drawText("E", geometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2683 // pop drawing matrix
2685 // check if draw line between junctions
2686 if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.back() == ((int)myNBEdge->getGeometry().size() - 1))) {
2687 // set base color
2689 // push drawing matrix
2691 // draw line between geometry point and from junction
2692 const PositionVector lineA = {geometryPointPos, getToJunction()->getNBNode()->getPosition()};
2693 GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2694 // draw line between begin point of last lane shape and the first edge shape point
2695 const PositionVector lineB = {geometryPointPos, myNBEdge->getLanes().back().shape.back()};
2696 GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2697 // pop drawing matrix
2699 }
2700 }
2701 // draw dotted contour geometry points
2703 geometryPointRadius, exaggeration);
2704 }
2705 }
2706}
2707
2708
2709void
2711 // draw the name and/or the street name
2712 const bool drawStreetName = s.streetName.show(this) && (myNBEdge->getStreetName() != "");
2713 const bool spreadSuperposed = s.spreadSuperposed && myNBEdge->getBidiEdge() != nullptr;
2714 // check conditions
2715 if (s.edgeName.show(this) || drawStreetName || s.edgeValue.show(this)) {
2716 // get first and last lanes
2717 const GNELane* firstLane = getChildLanes()[0];
2718 const GNELane* lastLane = getChildLanes()[getChildLanes().size() - 1];
2719 // calculate draw position
2720 Position drawPosition = firstLane->getLaneShape().positionAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2721 drawPosition.add(lastLane->getLaneShape().positionAtOffset(lastLane->getLaneShape().length() / (double) 2.));
2722 drawPosition.mul(.5);
2723 if (spreadSuperposed) {
2724 // move name to the right of the edge and towards its beginning
2725 const double dist = 0.6 * s.edgeName.scaledSize(s.scale);
2726 const double shiftA = firstLane->getLaneShape().rotationAtOffset(firstLane->getLaneShape().length() / (double) 2.) - DEG2RAD(135);
2727 const Position shift(dist * cos(shiftA), dist * sin(shiftA));
2728 drawPosition.add(shift);
2729 }
2730 // calculate drawing angle
2731 double drawAngle = firstLane->getLaneShape().rotationDegreeAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2732 drawAngle += 90;
2733 // avoid draw inverted text
2734 if (drawAngle > 90 && drawAngle < 270) {
2735 drawAngle -= 180;
2736 }
2737 // draw edge name
2738 if (s.edgeName.show(this)) {
2739 drawName(drawPosition, s.scale, s.edgeName, drawAngle);
2740 }
2741 // draw street name
2742 if (drawStreetName) {
2743 GLHelper::drawTextSettings(s.streetName, myNBEdge->getStreetName(), drawPosition, s.scale, drawAngle);
2744 }
2745 // draw edge values
2746 if (s.edgeValue.show(this)) {
2747 // get current scheme
2748 const int activeScheme = s.laneColorer.getActive();
2749 // calculate value depending of active scheme
2750 std::string value;
2751 if (activeScheme == 12) {
2752 // edge param, could be non-numerical
2753 value = getNBEdge()->getParameter(s.edgeParam, "");
2754 } else if (activeScheme == 13) {
2755 // lane param, could be non-numerical
2756 value = getNBEdge()->getLaneStruct(lastLane->getIndex()).getParameter(s.laneParam, "");
2757 } else {
2758 // use numerical value value of leftmost lane to hopefully avoid sidewalks, bikelanes etc
2759 const double doubleValue = lastLane->getColorValue(s, activeScheme);
2760 const RGBColor color = s.laneColorer.getScheme().getColor(doubleValue);
2761 value = color.alpha() == 0 ? "" : toString(doubleValue);
2762 }
2763 // check if value is empty
2764 if (value != "") {
2765 GLHelper::drawTextSettings(s.edgeValue, value, drawPosition, s.scale, drawAngle);
2766 }
2767 }
2768 }
2769}
2770
2771
2772void
2774 // draw geometry only if we'rent in drawForObjectUnderCursor mode
2776 // Push stopOffset matrix
2778 // translate to front (note: Special case)
2779 drawInLayer(layer + 1);
2781 for (const auto& lane : getChildLanes()) {
2782 lane->drawLaneStopOffset(s);
2783 }
2784 }
2785 // Push stopOffset matrix
2787 }
2788}
2789
2790
2791void
2793 // draw child additional
2794 for (const auto& additional : getChildAdditionals()) {
2795 if (!additional->getTagProperty()->isListedElement()) {
2796 additional->drawGL(s);
2797 }
2798 }
2799 // draw person stops
2801 for (const auto& stopEdge : getChildDemandElements()) {
2802 if ((stopEdge->getTagProperty()->getTag() == GNE_TAG_STOPPERSON_EDGE) || (stopEdge->getTagProperty()->getTag() == GNE_TAG_STOPCONTAINER_EDGE)) {
2803 stopEdge->drawGL(s);
2804 }
2805 }
2806 }
2807 // draw vehicles
2808 const std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesMap = getVehiclesOverEdgeMap();
2809 for (const auto& vehicleMap : vehiclesMap) {
2810 for (const auto& vehicle : vehicleMap.second) {
2811 vehicle->drawGL(s);
2812 }
2813 }
2814 // draw TAZ elements
2815 drawTAZElements(s);
2816}
2817
2818
2819void
2821 // if we're selecting using a boundary, first don't calculate contour bt check if edge boundary is within selection boundary
2823 // simply add object in ViewObjectsHandler with full boundary
2824 gViewObjectsHandler.selectObject(s, this, layer, false, nullptr);
2825 } else {
2826 // get geometry point radius
2827 const auto geometryPointRadius = getGeometryPointRadius();
2828 // check if edit extrems
2829 const bool forceDrawExtrems = myNet->getViewParent()->getMoveFrame()->getNetworkMoveOptions()->getForceDrawGeometryPoints();
2830 const bool firstExtrem = forceDrawExtrems || (myNBEdge->getGeometry().front() != getParentJunctions().front()->getPositionInView());
2831 const bool lastExtrem = forceDrawExtrems || (myNBEdge->getGeometry().back() != getParentJunctions().back()->getPositionInView());
2832 // check if we're in move mode
2834 // calculate contour
2835 myNetworkElementContour.calculateContourEdge(s, d, this, this, layer, true, true);
2836 // calculate edge geometry points
2837 myNetworkElementContour.calculateContourEdgeGeometryPoints(s, d, this, geometryPointRadius, moveMode, firstExtrem, lastExtrem);
2838 }
2839}
2840
2841
2842void
2844 // first check if draw TAZ Elements is enabled
2846 if (getChildTAZSourceSinks().size() > 0) {
2847 // check if TAZ Source/sink is selected
2848 bool selected = false;
2849 for (const auto& TAZSourceSink : getChildTAZSourceSinks()) {
2850 if (TAZSourceSink->isAttributeCarrierSelected()) {
2851 selected = true;
2852 }
2853 }
2854 // iterate over lanes
2855 for (const auto& lane : getChildLanes()) {
2856 // Push layer matrix
2858 // translate to front (note: Special case)
2859 if (myDrawInFront) {
2860 glTranslated(0, 0, GLO_FRONTELEMENT);
2861 } else if (lane->getLaneShape().length2D() <= (s.neteditSizeSettings.junctionBubbleRadius * 2)) {
2863 } else {
2865 }
2866 // move to front
2867 glTranslated(0, 0, 0.1);
2868 // set color
2869 if (selected) {
2871 } else {
2873 }
2874 // draw as box lines
2876 lane->getDrawingConstants()->getDrawingWidth());
2877 // Pop layer matrix
2879 }
2880 /*
2881 // check if curently we're inspecting a TAZ Source/Sink
2882 for (const auto& TAZSourceSink : TAZSourceSinks) {
2883 if (myNet->getViewNet()->isAttributeCarrierInspected(TAZSourceSink)) {
2884 drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::INSPECT, this, true, true);
2885 } else if (TAZSourceSink == markAC) {
2886 drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::FRONT, this, true, true);
2887 }
2888 }
2889 */
2890 }
2891 }
2892}
2893
2894
2895void
2897 // avoid draw for railways
2898 if ((d <= GUIVisualizationSettings::Detail::LaneDetails) && !getChildLanes().front()->getDrawingConstants()->drawAsRailway() &&
2900 // push draw matrix
2902 // translate to front depending of big points
2903 if (drawBigGeometryPoints()) {
2904 glTranslated(0, 0, GLO_GEOMETRYPOINT - 1);
2905 } else {
2906 glTranslated(0, 0, layer);
2907 }
2908 // obtain color
2909 RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2910 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2911 // override with special colors (unless the color scheme is based on selection)
2912 geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2913 }
2914 // never draw when at full transparency
2915 if (geometryPointColor.alpha() != 0) {
2916 // set color
2917 GLHelper::setColor(geometryPointColor);
2918 // iterate over NBEdge geometry
2919 for (int i = 1; i < (int)myNBEdge->getGeometry().size(); i++) {
2920 // calculate line between previous and current geometry point
2921 PositionVector line = {myNBEdge->getGeometry()[i - 1], myNBEdge->getGeometry()[i]};
2922 line.move2side(0.2);
2923 // draw box line
2924 GLHelper::drawBoxLine(line[1], RAD2DEG(line[0].angleTo2D(line[1])) - 90, line[0].distanceTo2D(line[1]), .1);
2925 }
2926 }
2927 // pop draw matrix
2929 }
2930}
2931
2932
2933bool
2935 // get edit modes
2936 const auto& editModes = myNet->getViewNet()->getEditModes();
2937 // continue depending of conditions
2938 if (!editModes.isCurrentSupermodeNetwork()) {
2939 return false;
2940 } else if (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) {
2941 return true;
2942 } else if ((editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE) &&
2944 return true;
2945 } else {
2946 return false;
2947 }
2948}
2949
2950
2951bool
2953 if ((vehicleA.beginPosition() == vehicleB.beginPosition()) && (vehicleA.endPosition() == vehicleB.endPosition())) {
2954 return true;
2955 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2956 return true;
2957 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.beginPosition())) {
2958 return true;
2959 } else if ((vehicleA.beginPosition() < vehicleB.endPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2960 return true;
2961 } else {
2962 return false;
2963 }
2964}
2965
2966
2967double
2971
2972/****************************************************************************/
#define VEHICLE_GAP
Definition GNEEdge.cpp:62
std::vector< ChildType > GNEHierarchicalContainerChildren
#define ENDPOINT_TOLERANCE
@ 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:287
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
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
@ SUMO_ATTR_ROUTINGTYPE
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:49
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
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
double getCommonAttributeDouble(SumoXMLAttr key) const
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(......
const std::string getID() const override
get ID (all Attribute Carriers have one)
PositionVector getCommonAttributePositionVector(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
Position getCommonAttributePosition(SumoXMLAttr key) const
const GNETagProperties * getTagProperty() const
get tagProperty associated with this Attribute Carrier
GNENet * myNet
pointer to net
bool isCommonAttributeValid(SumoXMLAttr key, const std::string &value) const
std::string getCommonAttribute(SumoXMLAttr key) 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 updateGeometry() override
update pre-computed geometry information
void markConnectionGeometryDeprecated()
check that connection's Geometry has to be updated
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 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
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 bool forceCalculation=false) const
calculate contour for first geometry point
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:412
const StackPosition & getStackPosition() const
get stack position
Definition GNEEdge.cpp:1823
const std::vector< GNEDemandElement * > & getDemandElements() const
get demand elements
Definition GNEEdge.cpp:1829
void addDemandElements(GNEDemandElement *demandElement)
add demand elment to current StackDemandElements
Definition GNEEdge.cpp:1817
StackDemandElements(const StackPosition stackedPosition, GNEDemandElement *demandElement)
constructor
Definition GNEEdge.cpp:1809
Stack position (used to stack demand elements over edges)
Definition GNEEdge.h:398
double beginPosition() const
get begin position
Definition GNEEdge.cpp:1798
StackPosition(const double departPos, const double length)
constructor
Definition GNEEdge.cpp:1792
double endPosition() const
get end position
Definition GNEEdge.cpp:1804
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:2532
double getAttributeDouble(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1208
const Position getFrontDownShapePosition() const
get front down shape position
Definition GNEEdge.cpp:907
Boundary myEdgeBoundary
edge boundary
Definition GNEEdge.h:432
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
Definition GNEEdge.cpp:645
void drawEdgeName(const GUIVisualizationSettings &s) const
draw edge name
Definition GNEEdge.cpp:2710
bool isConvexAngle() const
check if edge makes a convex angle [0 - 180) degrees
Definition GNEEdge.cpp:1742
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:2000
bool isNetworkElementValid() const override
check if current network element is valid to be written into XML
Definition GNEEdge.cpp:152
std::string getAttributeForSelection(SumoXMLAttr key) const override
method for getting the attribute in the context of object selection
Definition GNEEdge.cpp:1231
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getPersonsOverEdgeMap() const
get persons a that start over this edge
Definition GNEEdge.cpp:2467
PositionVector getAttributePositionVector(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1220
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getContainersOverEdgeMap() const
get containers a that start over this edge
Definition GNEEdge.cpp:2500
bool hasPredecessors() const
check if this edge has predecessors (note: only for vehicles, this function ignore walking areas!...
Definition GNEEdge.cpp:1757
friend class GNEChange_Lane
Friend class.
Definition GNEEdge.h:54
void updateGLObject() override
update GLObject (geometry, ID, etc.)
Definition GNEEdge.cpp:760
~GNEEdge()
Destructor.
Definition GNEEdge.cpp:104
void smooth(GNEUndoList *undoList)
make geometry smooth
Definition GNEEdge.cpp:2361
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList) override
Definition GNEEdge.cpp:1241
double getGeometryPointRadius() const
get geometry point radius
Definition GNEEdge.cpp:2968
void setResponsible(bool newVal)
set responsibility for deleting internal structures
Definition GNEEdge.cpp:1513
void copyEdgeType(const GNEEdgeType *edgeType, GNEUndoList *undoList)
copy edge attributes from edgeType
Definition GNEEdge.cpp:1058
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition GNEEdge.cpp:766
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent) override
Returns an own popup-menu.
Definition GNEEdge.cpp:692
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getVehiclesOverEdgeMap() const
get vehicles a that start over this edge
Definition GNEEdge.cpp:2425
std::set< GUIGlID > getLaneGlIDs() const
returns GLIDs of all lanes
Definition GNEEdge.cpp:1090
GNEEdge * getReverseEdge() const
get reverse edge (if exist)
Definition GNEEdge.cpp:1779
const Position getFrontUpShapePosition() const
get front up shape position
Definition GNEEdge.cpp:899
void setGeometry(PositionVector geom, bool inner)
update edge geometry and inform the lanes
Definition GNEEdge.cpp:864
void smoothElevation(GNEUndoList *undoList)
smooth elevation with regard to adjoining edges
Definition GNEEdge.cpp:2373
bool clickedOverGeometryPoint(const Position &pos) const
return true if user clicked over a Geometry Point
Definition GNEEdge.cpp:587
bool clickedOverShapeEnd(const Position &pos) const
return true if user clicked over ShapeEnd
Definition GNEEdge.cpp:575
void updateVehicleStackLabels()
Definition GNEEdge.cpp:1580
void remakeGNEConnections(bool junctionsReady=false)
remake connections
Definition GNEEdge.cpp:930
bool isAttributeComputed(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1496
void calculateEdgeContour(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
calculate contours
Definition GNEEdge.cpp:2820
static const double SNAP_RADIUS
Definition GNEEdge.h:321
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:1519
bool hasCustomEndPoints() const
Definition GNEEdge.cpp:551
void updatePersonStackLabels()
Definition GNEEdge.cpp:1638
void setEdgeID(const std::string &newID)
set edge ID
Definition GNEEdge.cpp:2247
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition GNEEdge.cpp:2192
void drawChildrens(const GUIVisualizationSettings &s) const
draw children
Definition GNEEdge.cpp:2792
bool hasSuccessors() const
check if this edge has successors (note: only for vehicles, this function ignore walking areas!...
Definition GNEEdge.cpp:1773
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:2582
GNEMoveElementEdge * myMoveElementEdge
move element edge
Definition GNEEdge.h:429
bool drawBigGeometryPoints() const
check if draw big geometry points
Definition GNEEdge.cpp:2934
bool myWasSplit
whether this edge was created from a split
Definition GNEEdge.h:391
void removeLane(GNELane *lane, bool recomputeConnections)
@briefdecrease the number of lanes by one. argument is only used to increase robustness (assertions)
Definition GNEEdge.cpp:2116
GNEMoveElement * getMoveElement() const override
methods to retrieve the elements linked to this edge
Definition GNEEdge.cpp:134
bool hasRestrictedLane(SUMOVehicleClass vclass) const
check if edge has a restricted lane
Definition GNEEdge.cpp:2256
static const double SNAP_RADIUS_SQUARED
Definition GNEEdge.h:324
void updateSecondParentJunction(const std::string &value)
update last parent junction
Definition GNEEdge.cpp:2049
bool isVisible(const GUIVisualizationSettings &s) const override
check if object is visible (Currently used only in netedit)
Definition GNEEdge.cpp:622
const std::string getOptionalName() const override
Returns the street name.
Definition GNEEdge.cpp:686
std::vector< GNEEdge * > getOppositeEdges() const
get opposite edges
Definition GNEEdge.cpp:700
PositionVector smoothShape(const PositionVector &shape, bool forElevation)
return smoothed shape
Definition GNEEdge.cpp:2288
bool checkDrawSelectContour() const override
check if draw select contour (blue)
Definition GNEEdge.cpp:476
GNEJunction * getFromJunction() const
get from Junction (only used to increase readability)
Definition GNEEdge.h:87
bool wasSplit()
whether this edge was created from a split
Definition GNEEdge.cpp:1106
NBEdge * myNBEdge
the underlying NBEdge
Definition GNEEdge.h:379
void copyTemplate(const GNEEdgeTemplate *edgeTemplate, GNEUndoList *undoList)
copy edge attributes from edgetemplate
Definition GNEEdge.cpp:1035
void removeEdgeFromCrossings(GNEJunction *junction, GNEUndoList *undoList)
remove crossing of junction
Definition GNEEdge.cpp:2267
bool checkDrawMoveContour() const override
check if draw move contour (red)
Definition GNEEdge.cpp:507
Position getPositionInView() const
Returns position of hierarchical element in view.
Definition GNEEdge.cpp:216
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:2056
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:2226
Position getAttributePosition(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1214
bool checkDrawToContour() const override
check if draw from contour (magenta)
Definition GNEEdge.cpp:280
ConnectionVector myGNEConnections
vector with the connections of this edge
Definition GNEEdge.h:382
void editEndpoint(Position pos, GNEUndoList *undoList)
makes pos the new geometry endpoint at the appropriate end, or remove current existent endpoint
Definition GNEEdge.cpp:788
void resetBothEndpoint(GNEUndoList *undoList)
restores both endpoint to the junction position at the appropriate end
Definition GNEEdge.cpp:854
Position getSplitPos(const Position &clickPos)
Definition GNEEdge.cpp:772
void drawGL(const GUIVisualizationSettings &s) const override
Draws the object.
Definition GNEEdge.cpp:706
const std::vector< GNEConnection * > & getGNEConnections() const
returns a reference to the GNEConnection vector
Definition GNEEdge.cpp:1100
bool isValid(SumoXMLAttr key, const std::string &value) override
Definition GNEEdge.cpp:1379
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition GNEEdge.cpp:1000
bool checkDrawRelatedContour() const override
check if draw related contour (cyan)
Definition GNEEdge.cpp:338
std::string myConnectionStatus
modification status of the connections
Definition GNEEdge.h:394
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:2646
double getExaggeration(const GUIVisualizationSettings &s) const override
return exaggeration associated with this GLObject
Definition GNEEdge.cpp:633
bool checkDrawDeleteContour() const override
check if draw delete contour (pink/white)
Definition GNEEdge.cpp:430
Boundary getCenteringBoundary() const override
Returns the boundary to which the view shall be centered in order to show the object.
Definition GNEEdge.cpp:639
void clearGNEConnections()
clear current connections
Definition GNEEdge.cpp:975
bool myUpdateGeometry
flag to enable/disable update geometry of lanes (used mainly by setNumLanes)
Definition GNEEdge.h:435
const Position getBackDownShapePosition() const
get back down shape position
Definition GNEEdge.cpp:923
bool areStackPositionOverlapped(const GNEEdge::StackPosition &vehicleA, const GNEEdge::StackPosition &vehicleB) const
check if given stacked positions are overlapped
Definition GNEEdge.cpp:2952
bool checkDrawDeleteContourSmall() const override
check if draw delete contour small (pink/white)
Definition GNEEdge.cpp:461
void updateFirstParentJunction(const std::string &value)
update front parent junction
Definition GNEEdge.cpp:2042
void updateGeometry() override
update pre-computed geometry information
Definition GNEEdge.cpp:170
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition GNEEdge.cpp:2278
void updateContainerStackLabels()
Definition GNEEdge.cpp:1690
bool clickedOverShapeStart(const Position &pos) const
return true if user clicked over ShapeStart
Definition GNEEdge.cpp:563
void deleteGLObject() override
delete element
Definition GNEEdge.cpp:751
void setShapeStartPos(const Position &pos)
change Shape StartPos
Definition GNEEdge.cpp:2403
GNEJunction * getToJunction() const
get from Junction (only used to increase readability)
Definition GNEEdge.h:92
const Position getBackUpShapePosition() const
get back up shape position
Definition GNEEdge.cpp:915
void resetEndpoint(const Position &pos, GNEUndoList *undoList)
restores the endpoint to the junction position at the appropriate end
Definition GNEEdge.cpp:840
bool isAttributeEnabled(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1481
void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation=false)
adds a connection
Definition GNEEdge.cpp:2168
void drawLaneStopOffset(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
draw edgeStopOffset
Definition GNEEdge.cpp:2773
void drawTAZElements(const GUIVisualizationSettings &s) const
draw TAZElements
Definition GNEEdge.cpp:2843
void drawEdgeShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
draw edge shape (only one line)
Definition GNEEdge.cpp:2896
std::vector< GNECrossing * > getGNECrossings()
get GNECrossings vinculated with this Edge
Definition GNEEdge.cpp:1018
bool checkDrawFromContour() const override
check if draw from contour (green)
Definition GNEEdge.cpp:222
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:1534
Parameterised * getParameters() override
get parameters associated with this edge
Definition GNEEdge.cpp:140
void updateVehicleSpreadGeometries()
Definition GNEEdge.cpp:1549
bool checkDrawOverContour() const override
check if draw over contour (orange)
Definition GNEEdge.cpp:358
std::string getAttribute(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1112
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition GNEEdge.cpp:608
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition GNEEdge.h:388
GNEEdge(GNENet *net, NBEdge *nbe, bool wasSplit=false, bool loaded=false)
Constructor.
Definition GNEEdge.cpp:76
void setShapeEndPos(const Position &pos)
change Shape EndPos
Definition GNEEdge.cpp:2414
std::string getNetworkElementProblem() const override
return a string with the current network element problem
Definition GNEEdge.cpp:162
const std::vector< GNELaneTemplate * > & getLaneTemplates() const
get vector with the lane templates of this edge
std::string getAttribute(SumoXMLAttr key) const override
std::string getAttribute(SumoXMLAttr key) const override
const std::vector< GNELaneType * > & getLaneTypes() const
get laneTypes
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() override
update pre-computed geometry information (including crossings)
Boundary getCenteringBoundary() const override
Returns the boundary to which the view shall be centered in order to show the object.
void removeOutgoingGNEEdge(GNEEdge *edge)
remove outgoing GNEEdge
void removeIncomingGNEEdge(GNEEdge *edge)
remove incoming GNEEdge
void drawGL(const GUIVisualizationSettings &s) const override
Draws 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
const PositionVector & getLaneShape() const
get elements shape
Definition GNELane.cpp:232
double getColorValue(const GUIVisualizationSettings &s, int activeScheme) const override
return value for lane coloring according to the given scheme
Definition GNELane.cpp:1557
int getIndex() const
returns the index of the lane
Definition GNELane.cpp:624
void setIndex(int index)
Definition GNELane.cpp:630
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList) override
remove geometry point in the clicked position
bool getForceDrawGeometryPoints() const
check if option "force draw geometry points" is enabled
NetworkMoveOptions * getNetworkMoveOptions() const
get network mode options
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
void requireSaveDemandElements()
inform that demand elements has to be saved
void deleteEdge(GNEEdge *edge, GNEUndoList *undoList, bool recomputeConnections)
removes edge
Definition GNENet.cpp:485
void deleteLane(GNELane *lane, GNEUndoList *undoList, bool recomputeConnections)
removes lane
Definition GNENet.cpp:664
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition GNENet.cpp:721
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1449
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1459
GNENetHelper::SavingStatus * getSavingStatus() const
get saving status
Definition GNENet.cpp:186
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:198
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition GNENet.cpp:2220
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition GNENet.cpp:174
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition GNENet.cpp:2193
const GNETagPropertiesDatabase * getTagPropertiesDatabase() const
get tag properties database (used for simplify code)
Definition GNENet.cpp:162
GNEViewParent * getViewParent() const
get view parent (used for simplify code)
Definition GNENet.cpp:150
GNEUndoList * getUndoList() const
get undo list(used for simplify code)
Definition GNENet.cpp:156
GNEViewNet * getViewNet() const
get view net (used for simplify code)
Definition GNENet.cpp:144
bool checkDrawingBoundarySelection() const
GNEContour myNetworkElementContour
network element contour
GNEHierarchicalElement * getHierarchicalElement() override
methods to retrieve the elements linked to this network element
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::MoveSingleElementModul & getMoveSingleElementValues() const
get move single element values
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
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)
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)
GUIGLObjectPopupMenu * getPopup() const
ge the current popup-menu
bool selectObject(const GUIVisualizationSettings &s, const GUIGlObject *GLObject, const double layer, const bool checkDuplicated, const GNESegment *segment)
const Triangle & getSelectionTriangle() const
get selection triangle
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:593
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
Definition NBEdge.cpp:4518
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition NBEdge.cpp:4541
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:4504
StopOffset myEdgeStopOffset
A vClass specific stop offset - assumed of length 0 (unspecified) or 1. For the latter case the int i...
Definition NBEdge.h:1823
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:4456
bool hasLaneSpecificFriction() const
whether lanes differ in friction
Definition NBEdge.cpp:2486
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:1451
void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices)
add lane
Definition NBEdge.cpp:4193
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition NBEdge.cpp:2476
std::string myType
The type of the edge.
Definition NBEdge.h:1760
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:1021
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::string & getRoutingType() const
return whether this edge should be a bidi edge
Definition NBEdge.h:1446
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:1551
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:4327
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition NBEdge.cpp:1015
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition NBEdge.cpp:3808
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition NBEdge.cpp:2462
bool isBidiEdge(bool checkPotential=false) const
whether this edge is part of a bidirectional edge pair
Definition NBEdge.cpp:784
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:4472
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:1471
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition NBEdge.cpp:1552
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition NBEdge.cpp:4248
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition NBEdge.cpp:2496
std::string getLaneID(int lane) const
get lane ID
Definition NBEdge.cpp:4179
@ 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:1209
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition NBEdge.cpp:2518
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:1537
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition NBEdge.h:545
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:4170
std::string myRoutingType
The routing type of the edge.
Definition NBEdge.h:1865
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:1465
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:4410
void setLoadedLength(double val)
set loaded length
Definition NBEdge.cpp:4556
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition NBEdge.cpp:613
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition NBEdge.cpp:4892
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition NBEdge.cpp:660
int myPriority
The priority of the edge.
Definition NBEdge.h:1779
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:4073
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition NBNode.cpp:4027
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:618
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.
An upper class for objects with additional parameters.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
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
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 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:60
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
GNEMoveElement * getMovedElement() const
get moved element
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