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