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 (junctionsReady) {
947 retrievedGNEConnection->updateLinkState();
948 }
949 retrievedConnections.push_back(retrievedGNEConnection);
950 // check if previously this GNEConnections exists, and if true, remove it from myGNEConnections
951 std::vector<GNEConnection*>::iterator retrievedExists = std::find(myGNEConnections.begin(), myGNEConnections.end(), retrievedGNEConnection);
952 if (retrievedExists != myGNEConnections.end()) {
953 myGNEConnections.erase(retrievedExists);
954 } else {
955 // include reference to created GNEConnection
956 retrievedGNEConnection->incRef("GNEEdge::remakeGNEConnections");
957 }
958 // mark it as deprecated
959 retrievedGNEConnection->markConnectionGeometryDeprecated();
960 }
961 // delete non retrieved GNEConnections
962 for (const auto& connection : myGNEConnections) {
963 // decrease reference
964 connection->decRef();
965 // remove it from network
966 myNet->removeGLObjectFromGrid(connection);
967 // and from AttributeCarriers
968 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
970 }
971 // delete GNEConnection if is unreferenced
972 if (connection->unreferenced()) {
973 delete connection;
974 }
975 }
976 // copy retrieved (existent and created) GNECrossings to myGNEConnections
977 myGNEConnections = retrievedConnections;
978}
979
980
981void
983 // Drop all existents connections that aren't referenced anymore
984 for (const auto& connection : myGNEConnections) {
985 // check if connection is selected
986 if (connection->isAttributeCarrierSelected()) {
987 connection->unselectAttributeCarrier();
988 }
989 // Dec reference of connection
990 connection->decRef("GNEEdge::clearGNEConnections");
991 // remove it from network
992 myNet->removeGLObjectFromGrid(connection);
993 // and from AttributeCarriers
994 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
996 }
997 // Delete GNEConnectionToErase if is unreferenced
998 if (connection->unreferenced()) {
999 delete connection;
1000 }
1001 }
1002 myGNEConnections.clear();
1003}
1004
1005
1006int
1008 std::vector<GNEAdditional*> routeProbes;
1009 for (const auto& additional : getChildAdditionals()) {
1010 if (additional->getTagProperty()->getTag() == routeProbe->getTagProperty()->getTag()) {
1011 routeProbes.push_back(additional);
1012 }
1013 }
1014 // return index of routeProbe in routeProbes vector
1015 auto it = std::find(routeProbes.begin(), routeProbes.end(), routeProbe);
1016 if (it == routeProbes.end()) {
1017 return -1;
1018 } else {
1019 return (int)(it - routeProbes.begin());
1020 }
1021}
1022
1023
1024std::vector<GNECrossing*>
1026 std::vector<GNECrossing*> crossings;
1027 for (auto i : getFromJunction()->getGNECrossings()) {
1028 if (i->checkEdgeBelong(this)) {
1029 crossings.push_back(i);
1030 }
1031 }
1032 for (auto i : getToJunction()->getGNECrossings()) {
1033 if (i->checkEdgeBelong(this)) {
1034 crossings.push_back(i);
1035 }
1036 }
1037 return crossings;
1038}
1039
1040
1041void
1042GNEEdge::copyTemplate(const GNEEdgeTemplate* edgeTemplate, GNEUndoList* undoList) {
1043 // copy edge-specific attributes
1044 for (const auto& attProperty : myTagProperty->getAttributeProperties()) {
1045 if (attProperty->isCopyable() && isValid(attProperty->getAttr(), edgeTemplate->getAttribute(attProperty->getAttr()))) {
1046 setAttribute(attProperty->getAttr(), edgeTemplate->getAttribute(attProperty->getAttr()), undoList);
1047 }
1048 }
1049 // also copy parameters
1051 // copy lane attributes as well
1052 for (int i = 0; i < (int)getChildLanes().size(); i++) {
1053 for (const auto& attProperty : edgeTemplate->getLaneTemplates().at(i)->getTagProperty()->getAttributeProperties()) {
1054 if (attProperty->isCopyable() && getChildLanes()[i]->isValid(attProperty->getAttr(), edgeTemplate->getLaneTemplates().at(i)->getAttribute(attProperty->getAttr()))) {
1055 getChildLanes()[i]->setAttribute(attProperty->getAttr(), edgeTemplate->getLaneTemplates().at(i)->getAttribute(attProperty->getAttr()), undoList);
1056 }
1057 }
1058 // also copy parameters
1059 getChildLanes()[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeTemplate->getLaneTemplates().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
1060 }
1061}
1062
1063
1064void
1065GNEEdge::copyEdgeType(const GNEEdgeType* edgeType, GNEUndoList* undoList) {
1066 const auto tagPropertiesDatabase = myNet->getTagPropertiesDatabase();
1067 // get tag properties
1068 const auto edgeProperties = tagPropertiesDatabase->getTagProperty(SUMO_TAG_EDGE, true);
1069 const auto laneProperties = tagPropertiesDatabase->getTagProperty(SUMO_TAG_LANE, true);
1070 const auto edgeTypeProperties = tagPropertiesDatabase->getTagProperty(SUMO_TAG_TYPE, true);
1071 const auto laneTypeProperties = tagPropertiesDatabase->getTagProperty(SUMO_TAG_LANETYPE, true);
1072 // set type (only for info)
1074 // copy attributes
1075 for (const auto& attrProperty : edgeTypeProperties->getAttributeProperties()) {
1076 if (attrProperty->isCopyable() && edgeProperties->hasAttribute(attrProperty->getAttr())) {
1077 setAttribute(attrProperty->getAttr(), edgeType->getAttribute(attrProperty->getAttr()), undoList);
1078 }
1079 }
1081 // copy lane attributes as well
1082 for (int i = 0; i < (int)getChildLanes().size(); i++) {
1083 for (const auto& attrProperty : laneTypeProperties->getAttributeProperties()) {
1084 if (attrProperty->isCopyable() && laneProperties->hasAttribute(attrProperty->getAttr()) &&
1085 (edgeType->getLaneTypes().at(i)->getAttribute(attrProperty->getAttr()) != laneTypeProperties->getAttributeProperties(attrProperty->getAttr())->getDefaultStringValue())) {
1086 getChildLanes()[i]->setAttribute(attrProperty->getAttr(), edgeType->getLaneTypes().at(i)->getAttribute(attrProperty->getAttr()), undoList);
1087 }
1088 }
1089 if (edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS).size() > 0) {
1090 getChildLanes()[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
1091 }
1092 }
1093}
1094
1095
1096std::set<GUIGlID>
1098 std::set<GUIGlID> result;
1099 for (const auto glID : getChildLanes()) {
1100 result.insert(glID->getGlID());
1101 }
1102 return result;
1103}
1104
1105
1106const std::vector<GNEConnection*>&
1110
1111
1112bool
1114 return myWasSplit;
1115}
1116
1117
1118std::string
1120 switch (key) {
1121 case SUMO_ATTR_ID:
1122 return getMicrosimID();
1123 case SUMO_ATTR_FROM:
1125 return getFromJunction()->getID();
1126 case SUMO_ATTR_TO:
1128 return getToJunction()->getID();
1129 case SUMO_ATTR_NUMLANES:
1130 return toString(myNBEdge->getNumLanes());
1131 case SUMO_ATTR_PRIORITY:
1132 return toString(myNBEdge->getPriority());
1133 case SUMO_ATTR_LENGTH:
1134 return toString(myNBEdge->getFinalLength());
1135 case SUMO_ATTR_TYPE:
1136 return myNBEdge->getTypeID();
1138 return myNBEdge->getRoutingType();
1139 case SUMO_ATTR_SHAPE:
1143 case SUMO_ATTR_NAME:
1144 return myNBEdge->getStreetName();
1145 case SUMO_ATTR_ALLOW:
1146 return (getVehicleClassNames(myNBEdge->getPermissions()) + (myNBEdge->hasLaneSpecificPermissions() ? " (combined!)" : ""));
1147 case SUMO_ATTR_DISALLOW: {
1149 }
1150 case SUMO_ATTR_SPEED:
1152 return "lane specific";
1153 } else {
1154 return toString(myNBEdge->getSpeed());
1155 }
1156 case SUMO_ATTR_FRICTION:
1158 return "lane specific";
1159 } else {
1160 return toString(myNBEdge->getFriction());
1161 }
1162 case SUMO_ATTR_WIDTH:
1164 return "lane specific";
1166 return "default";
1167 } else {
1168 return toString(myNBEdge->getLaneWidth());
1169 }
1172 return "lane specific";
1173 } else {
1174 return toString(myNBEdge->getEndOffset());
1175 }
1176 case SUMO_ATTR_DISTANCE:
1177 return toString(myNBEdge->getDistance());
1179 return myConnectionStatus;
1181 if (getParentJunctions().empty()) {
1182 return "";
1183 } else if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
1184 return "";
1185 } else {
1186 return toString(myNBEdge->getGeometry().front());
1187 }
1188 case GNE_ATTR_SHAPE_END:
1189 if (getParentJunctions().empty()) {
1190 return "";
1191 } else if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
1192 return "";
1193 } else {
1194 return toString(myNBEdge->getGeometry().back());
1195 }
1196 case GNE_ATTR_BIDIR:
1197 return toString(myNBEdge->getBidiEdge() != nullptr);
1203 } else {
1204 return "";
1205 }
1208 default:
1209 return getCommonAttribute(key);
1210 }
1211}
1212
1213
1214double
1218
1219
1224
1225
1228 switch (key) {
1229 case SUMO_ATTR_SHAPE:
1230 return myNBEdge->getInnerGeometry();
1231 default:
1233 }
1234}
1235
1236
1237std::string
1239 std::string result = getAttribute(key);
1240 if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
1241 result += " " + getVehicleClassNames(SVCAll, true);
1242 }
1243 return result;
1244}
1245
1246
1247void
1248GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1249 // get template editor
1251 // check if we have to update template
1252 const bool updateTemplate = templateEditor->getEdgeTemplate() ? (templateEditor->getEdgeTemplate()->getID() == getID()) : false;
1253 switch (key) {
1254 case SUMO_ATTR_WIDTH:
1256 case SUMO_ATTR_SPEED:
1257 case SUMO_ATTR_FRICTION:
1258 case SUMO_ATTR_ALLOW:
1259 case SUMO_ATTR_DISALLOW: {
1260 undoList->begin(this, "change " + getTagStr() + " attribute");
1261 const std::string origValue = getChildLanes().at(0)->getAttribute(key); // will have intermediate value of "lane specific"
1262 // lane specific attributes need to be changed via lanes to allow undo
1263 for (auto it : getChildLanes()) {
1264 it->setAttribute(key, value, undoList);
1265 }
1266 // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
1267 GNEChange_Attribute::changeAttribute(this, key, value, origValue, undoList);
1268 undoList->end();
1269 break;
1270 }
1271 case SUMO_ATTR_FROM: {
1272 if (value != getAttribute(key)) {
1273 undoList->begin(this, "change " + getTagStr() + " attribute");
1274 // Remove edge from crossings of junction source
1276 // continue changing from junction
1277 GNEJunction* originalFirstParentJunction = getFromJunction();
1278 getFromJunction()->setLogicValid(false, undoList);
1279 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1280 getFromJunction()->setLogicValid(false, undoList);
1281 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1282 setAttribute(GNE_ATTR_SHAPE_START, toString(getFromJunction()->getNBNode()->getPosition()), undoList);
1284 undoList->end();
1285 // update geometries of all implicated junctions
1286 originalFirstParentJunction->updateGeometry();
1289 }
1290 break;
1291 }
1292 case SUMO_ATTR_TO: {
1293 if (value != getAttribute(key)) {
1294 undoList->begin(this, "change " + getTagStr() + " attribute");
1295 // Remove edge from crossings of junction destination
1297 // continue changing destination junction
1298 GNEJunction* originalSecondParentJunction = getToJunction();
1299 getToJunction()->setLogicValid(false, undoList);
1300 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1301 getToJunction()->setLogicValid(false, undoList);
1302 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1303 setAttribute(GNE_ATTR_SHAPE_END, toString(getToJunction()->getNBNode()->getPosition()), undoList);
1305 undoList->end();
1306 // update geometries of all implicated junctions
1307 originalSecondParentJunction->updateGeometry();
1310 }
1311 break;
1312 }
1313 case SUMO_ATTR_ID:
1314 case SUMO_ATTR_PRIORITY:
1315 case SUMO_ATTR_LENGTH:
1316 case SUMO_ATTR_TYPE:
1319 case SUMO_ATTR_DISTANCE:
1322 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1323 break;
1325 // special case for stop offset, because affects to stopOffsetExceptions (#15297)
1326 if (canParse<double>(value) && (parse<double>(value) == 0)) {
1328 }
1329 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1330 break;
1332 case GNE_ATTR_SHAPE_END: {
1333 // due to ENDPOINT_TOLERANCE, force change
1334 GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1335 break;
1336 }
1337 case SUMO_ATTR_NAME:
1338 // user cares about street names. Make sure they appear in the output
1340 OptionsCont::getOptions().set("output.street-names", "true");
1341 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1342 break;
1343 case SUMO_ATTR_NUMLANES:
1344 if (value != getAttribute(key)) {
1345 // set num lanes
1346 setNumLanes(parse<int>(value), undoList);
1347 }
1348 break;
1349 case GNE_ATTR_BIDIR:
1350 undoList->begin(this, "change " + getTagStr() + " attribute");
1351 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1352 if (myNBEdge->getTurnDestination(true) != nullptr) {
1354 GNEChange_Attribute::changeAttribute(bidi, key, value, undoList);
1355 if (myNBEdge->getGeometry() != bidi->getNBEdge()->getGeometry().reverse()
1356 && myNBEdge->getGeometry().size() == 2
1357 && bidi->getNBEdge()->getGeometry().size() == 2
1358 && myNBEdge->getBidiEdge() == nullptr) {
1359 // NBEdge::avoidOverlap was already active so we need to reset the
1360 // geometry to its default
1361 resetBothEndpoint(undoList);
1362 bidi->resetBothEndpoint(undoList);
1363 }
1364 }
1365 undoList->end();
1366 break;
1367 case SUMO_ATTR_SHAPE:
1368 // @note: assumes value of inner geometry!
1369 // actually the geometry is already updated (incrementally
1370 // during mouse movement). We set the restore point to the end
1371 // of the last change-set
1372 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1373 break;
1374 default:
1375 setCommonAttribute(key, value, undoList);
1376 break;
1377 }
1378 // update template
1379 if (updateTemplate) {
1380 templateEditor->setEdgeTemplate(this);
1381 }
1382}
1383
1384
1385bool
1386GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
1387 switch (key) {
1388 case SUMO_ATTR_ID:
1389 return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveEdge(value, false) == nullptr);
1390 case SUMO_ATTR_FROM: {
1391 // check that is a valid ID and is different of ID of junction destination
1392 if (value == getFromJunction()->getID()) {
1393 return true;
1394 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getToJunction()->getID())) {
1395 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1396 } else {
1397 return false;
1398 }
1399 }
1400 case SUMO_ATTR_TO: {
1401 // check that is a valid ID and is different of ID of junction Source
1402 if (value == getToJunction()->getID()) {
1403 return true;
1404 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getFromJunction()->getID())) {
1405 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1406 } else {
1407 return false;
1408 }
1409 }
1410 case SUMO_ATTR_SPEED:
1411 return canParse<double>(value) && (parse<double>(value) > 0);
1412 case SUMO_ATTR_FRICTION:
1413 return canParse<double>(value) && (parse<double>(value) > 0);
1414 case SUMO_ATTR_NUMLANES:
1415 return canParse<int>(value) && (parse<double>(value) > 0);
1416 case SUMO_ATTR_PRIORITY:
1417 return canParse<int>(value);
1418 case SUMO_ATTR_LENGTH:
1419 if (value.empty()) {
1420 return true;
1421 } else {
1422 return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
1423 }
1424 case SUMO_ATTR_ALLOW:
1425 case SUMO_ATTR_DISALLOW:
1426 return canParseVehicleClasses(value);
1427 case SUMO_ATTR_TYPE:
1429 return true;
1430 case SUMO_ATTR_SHAPE:
1431 // empty shapes are allowed
1432 return canParse<PositionVector>(value);
1435 case SUMO_ATTR_NAME:
1436 return true;
1437 case SUMO_ATTR_WIDTH:
1438 if (value.empty() || (value == "default")) {
1439 return true;
1440 } else {
1441 return canParse<double>(value) && ((parse<double>(value) >= -1) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
1442 }
1444 return canParse<double>(value) && parse<double>(value) >= 0 && parse<double>(value) < myNBEdge->getLoadedLength();
1445 case SUMO_ATTR_DISTANCE:
1446 if (value.empty()) {
1447 return true;
1448 } else {
1449 return canParse<double>(value);
1450 }
1451 case GNE_ATTR_SHAPE_START: {
1452 if (value.empty()) {
1453 return true;
1454 } else if (canParse<Position>(value)) {
1455 Position shapeStart = parse<Position>(value);
1456 return (shapeStart != myNBEdge->getGeometry()[-1]);
1457 } else {
1458 return false;
1459 }
1460 }
1461 case GNE_ATTR_SHAPE_END: {
1462 if (value.empty()) {
1463 return true;
1464 } else if (canParse<Position>(value)) {
1465 Position shapeEnd = parse<Position>(value);
1466 return (shapeEnd != myNBEdge->getGeometry()[0]);
1467 } else {
1468 return false;
1469 }
1470 }
1471 case GNE_ATTR_BIDIR:
1472 return canParse<bool>(value) && (!parse<bool>(value) || myNBEdge->isBidiEdge(true));
1474 if (value.empty()) {
1475 return true;
1476 } else {
1477 return canParse<double>(value) && (parse<double>(value) >= 0);
1478 }
1480 return canParseVehicleClasses(value);
1481 default:
1482 return isCommonAttributeValid(key, value);
1483 }
1484}
1485
1486
1487bool
1489 switch (key) {
1490 case GNE_ATTR_BIDIR:
1491 return myNBEdge->isBidiEdge(true);
1493 return myNBEdge->myEdgeStopOffset.getOffset() > 0;
1495 return false;
1496 default:
1497 return true;
1498 }
1499}
1500
1501
1502bool
1504 switch (key) {
1505 case SUMO_ATTR_LENGTH:
1506 return !myNBEdge->hasLoadedLength();
1507 case SUMO_ATTR_WIDTH:
1509 return false;
1510 } else {
1512 }
1513 default:
1514 return false;
1515 }
1516}
1517
1518
1519void
1521 myAmResponsible = newVal;
1522}
1523
1524
1525GNELane*
1527 // iterate over all NBEdge lanes
1528 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1529 // if given VClass is in permissions, return lane
1530 if (myNBEdge->getLanes().at(i).permissions & vClass) {
1531 // return GNELane
1532 return getChildLanes().at(i);
1533 }
1534 }
1535 // return first lane
1536 return getChildLanes().front();
1537}
1538
1539
1540GNELane*
1542 // iterate over all NBEdge lanes
1543 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1544 // if given VClass isn't in permissions, return lane
1545 if (~(myNBEdge->getLanes().at(i).permissions) & vClass) {
1546 // return GNELane
1547 return getChildLanes().at(i);
1548 }
1549 }
1550 // return first lane
1551 return getChildLanes().front();
1552}
1553
1554
1555void
1557 // get lane vehicles map
1558 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1559 // iterate over every lane
1560 for (const auto& laneVehicle : laneVehiclesMap) {
1561 // obtain total length
1562 double totalLength = 0;
1563 for (const auto& vehicle : laneVehicle.second) {
1564 totalLength += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1565 }
1566 // calculate multiplier for vehicle positions
1567 double multiplier = 1;
1568 const double laneShapeLength = laneVehicle.first->getLaneShape().length();
1569 if (laneShapeLength == 0) {
1570 multiplier = 0;
1571 } else if (totalLength > laneShapeLength) {
1572 multiplier = (laneShapeLength / totalLength);
1573 }
1574 // declare current length
1575 double length = 0;
1576 // iterate over vehicles to calculate position and rotations
1577 for (const auto& vehicle : laneVehicle.second) {
1578 vehicle->updateDemandElementSpreadGeometry(laneVehicle.first, length * multiplier);
1579 // update length
1580 length += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1581 }
1582 }
1583}
1584
1585
1586void
1588 // get lane vehicles map
1589 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1590 // iterate over laneVehiclesMap and obtain a vector with
1591 for (const auto& vehicleMap : laneVehiclesMap) {
1592 // declare map for sort vehicles using their departpos+length position (StackPosition)
1593 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosVehicles;
1594 // declare vector of stack demand elements
1595 std::vector<GNEEdge::StackDemandElements> stackedVehicles;
1596 // iterate over vehicles
1597 for (const auto& vehicle : vehicleMap.second) {
1598 // get vehicle's depart pos and length
1599 const double departPos = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1600 const double length = vehicle->getAttributeDouble(SUMO_ATTR_LENGTH);
1601 double posOverLane = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1602 // check if we have to adapt posOverLane
1603 if (posOverLane < 0) {
1604 posOverLane += vehicleMap.first->getLaneShape().length();
1605 }
1606 // make a stack position using departPos and length
1607 departPosVehicles.push_back(std::make_pair(StackPosition(departPos, length), vehicle));
1608 // update depart element geometry
1609 vehicle->updateDemandElementGeometry(vehicleMap.first, posOverLane);
1610 // reset vehicle stack label
1611 vehicle->updateDemandElementStackLabel(0);
1612 }
1613
1614 // sort departPosVehicles
1615 std::sort(departPosVehicles.begin(), departPosVehicles.end());
1616 // iterate over departPosVehicles
1617 for (const auto& departPosVehicle : departPosVehicles) {
1618 // obtain stack position and vehicle
1619 const GNEEdge::StackPosition& vehicleStackPosition = departPosVehicle.first;
1620 GNEDemandElement* vehicle = departPosVehicle.second;
1621 // if stackedVehicles is empty, add a new StackDemandElements
1622 if (stackedVehicles.empty()) {
1623 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1624 } else if (areStackPositionOverlapped(vehicleStackPosition, stackedVehicles.back().getStackPosition())) {
1625 // add new vehicle to last inserted stackDemandElements
1626 stackedVehicles[stackedVehicles.size() - 1].addDemandElements(vehicle);
1627 } else {
1628 // No overlapping, then add a new StackDemandElements
1629 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1630 }
1631 }
1632 // iterate over stackedVehicles
1633 for (const auto& vehicle : stackedVehicles) {
1634 // only update vehicles with one or more stack
1635 if (vehicle.getDemandElements().size() > 1) {
1636 // set stack labels
1637 vehicle.getDemandElements().front()->updateDemandElementStackLabel((int)vehicle.getDemandElements().size());
1638 }
1639 }
1640 }
1641}
1642
1643
1644void
1646 // get lane persons map
1647 const std::map<const GNELane*, std::vector<GNEDemandElement*> > lanePersonsMap = getPersonsOverEdgeMap();
1648 // iterate over lanePersonsMap and obtain a vector with
1649 for (const auto& personMap : lanePersonsMap) {
1650 // declare map for sort persons using their departpos+length position (StackPosition)
1651 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosPersons;
1652 // declare vector of stack demand elements
1653 std::vector<GNEEdge::StackDemandElements> stackedPersons;
1654 // iterate over persons
1655 for (const auto& person : personMap.second) {
1656 // get person's depart pos and length
1657 const double departPos = person->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1658 // make a stack position using departPos and length
1659 departPosPersons.push_back(std::make_pair(StackPosition(departPos, 1.8), person));
1660 // update depart element geometry
1661 person->updateDemandElementGeometry(personMap.first, departPos);
1662 // reset person stack label
1663 person->updateDemandElementStackLabel(0);
1664 }
1665
1666 // sort departPosPersons
1667 std::sort(departPosPersons.begin(), departPosPersons.end());
1668 // iterate over departPosPersons
1669 for (const auto& departPosPerson : departPosPersons) {
1670 // obtain stack position and person
1671 const GNEEdge::StackPosition& personStackPosition = departPosPerson.first;
1672 GNEDemandElement* person = departPosPerson.second;
1673 // if stackedPersons is empty, add a new StackDemandElements
1674 if (stackedPersons.empty()) {
1675 stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1676 } else if (areStackPositionOverlapped(personStackPosition, stackedPersons.back().getStackPosition())) {
1677 // add new person to last inserted stackDemandElements
1678 stackedPersons[stackedPersons.size() - 1].addDemandElements(person);
1679 } else {
1680 // No overlapping, then add a new StackDemandElements
1681 stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1682 }
1683 }
1684 // iterate over stackedPersons
1685 for (const auto& person : stackedPersons) {
1686 // only update persons with one or more stack
1687 if (person.getDemandElements().size() > 1) {
1688 // set stack labels
1689 person.getDemandElements().front()->updateDemandElementStackLabel((int)person.getDemandElements().size());
1690 }
1691 }
1692 }
1693}
1694
1695
1696void
1698 // get lane containers map
1699 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneContainersMap = getContainersOverEdgeMap();
1700 // iterate over laneContainersMap and obtain a vector with
1701 for (const auto& containerMap : laneContainersMap) {
1702 // declare map for sort containers using their departpos+length position (StackPosition)
1703 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosContainers;
1704 // declare vector of stack demand elements
1705 std::vector<GNEEdge::StackDemandElements> stackedContainers;
1706 // iterate over containers
1707 for (const auto& container : containerMap.second) {
1708 // get container's depart pos and length
1709 const double departPos = container->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1710 // make a stack position using departPos and length
1711 departPosContainers.push_back(std::make_pair(StackPosition(departPos, 1.8), container));
1712 // update depart element geometry
1713 container->updateDemandElementGeometry(containerMap.first, departPos);
1714 // reset container stack label
1715 container->updateDemandElementStackLabel(0);
1716 }
1717
1718 // sort departPosContainers
1719 std::sort(departPosContainers.begin(), departPosContainers.end());
1720 // iterate over departPosContainers
1721 for (const auto& departPosContainer : departPosContainers) {
1722 // obtain stack position and container
1723 const GNEEdge::StackPosition& containerStackPosition = departPosContainer.first;
1724 GNEDemandElement* container = departPosContainer.second;
1725 // if stackedContainers is empty, add a new StackDemandElements
1726 if (stackedContainers.empty()) {
1727 stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1728 } else if (areStackPositionOverlapped(containerStackPosition, stackedContainers.back().getStackPosition())) {
1729 // add new container to last inserted stackDemandElements
1730 stackedContainers[stackedContainers.size() - 1].addDemandElements(container);
1731 } else {
1732 // No overlapping, then add a new StackDemandElements
1733 stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1734 }
1735 }
1736 // iterate over stackedContainers
1737 for (const auto& container : stackedContainers) {
1738 // only update containers with one or more stack
1739 if (container.getDemandElements().size() > 1) {
1740 // set stack labels
1741 container.getDemandElements().front()->updateDemandElementStackLabel((int)container.getDemandElements().size());
1742 }
1743 }
1744 }
1745}
1746
1747
1748bool
1750 // calculate angle between both junction positions
1751 double edgeAngle = RAD2DEG(getFromJunction()->getPositionInView().angleTo2D(getToJunction()->getPositionInView()));
1752 // adjust to 360 degrees
1753 while (edgeAngle < 0) {
1754 edgeAngle += 360;
1755 }
1756 // fmod round towards zero which is not want we want for negative numbers
1757 edgeAngle = fmod(edgeAngle, 360);
1758 // check angle
1759 return edgeAngle >= 0 && edgeAngle < 180;
1760}
1761
1762
1763bool
1765 // get incoming edges
1766 const auto incomingEdges = getFromJunction()->getGNEIncomingEdges();
1767 // iterate over connections
1768 for (const auto& incomingEdge : incomingEdges) {
1769 for (const auto& connection : incomingEdge->getGNEConnections()) {
1770 if (connection->getEdgeTo() == this) {
1771 return true;
1772 }
1773 }
1774 }
1775 return false;
1776}
1777
1778
1779bool
1781 return (myGNEConnections.size() > 0);
1782}
1783
1784
1785GNEEdge*
1787 for (const auto& outgoingEdge : getParentJunctions().back()->getGNEOutgoingEdges()) {
1788 if (outgoingEdge->getToJunction() == getFromJunction()) {
1789 return outgoingEdge;
1790 }
1791 }
1792 return nullptr;
1793}
1794
1795// ===========================================================================
1796// private
1797// ===========================================================================
1798
1799GNEEdge::StackPosition::StackPosition(const double departPos, const double length) :
1800 pair(departPos, departPos + length) {
1801}
1802
1803
1804double
1806 return first;
1807}
1808
1809
1810double
1812 return second;
1813}
1814
1815
1817 pair(stackedPosition, {
1818 demandElement
1819}) {
1820}
1821
1822
1823void
1825 second.push_back(demandElement);
1826}
1827
1828
1831 return first;
1832}
1833
1834
1835const std::vector<GNEDemandElement*>&
1837 return second;
1838}
1839
1840
1841void
1842GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
1843 switch (key) {
1844 case SUMO_ATTR_ID:
1845 myNet->getAttributeCarriers()->updateEdgeID(this, value);
1846 // enable save demand elements if there are stops
1847 for (const auto& stop : getChildDemandElements()) {
1848 if (stop->getTagProperty()->isVehicleStop()) {
1850 }
1851 }
1852 // also for lanes
1853 for (const auto& lane : getChildLanes()) {
1854 for (const auto& stop : lane->getChildDemandElements()) {
1855 if (stop->getTagProperty()->isVehicleStop()) {
1857 }
1858 }
1859 }
1860 break;
1861 case SUMO_ATTR_FROM:
1862 myNet->changeEdgeEndpoints(this, value, getToJunction()->getID());
1863 // update this edge of list of outgoings edges of the old first parent junction
1865 // update first parent junction
1867 // update this edge of list of outgoings edges of the new first parent junction
1869 // update centering boundary and grid
1871 break;
1872 case SUMO_ATTR_TO:
1873 myNet->changeEdgeEndpoints(this, getFromJunction()->getID(), value);
1874 // update this edge of list of incomings edges of the old second parent junction
1876 // update second parent junction
1878 // update this edge of list of incomings edges of the new second parent junction
1880 // update centering boundary and grid
1882 break;
1883 case SUMO_ATTR_NUMLANES:
1884 throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
1885 case SUMO_ATTR_PRIORITY:
1886 myNBEdge->myPriority = parse<int>(value);
1887 break;
1888 case SUMO_ATTR_LENGTH:
1889 if (value.empty()) {
1891 } else {
1892 myNBEdge->setLoadedLength(parse<double>(value));
1893 }
1894 break;
1895 case SUMO_ATTR_TYPE:
1896 myNBEdge->myType = value;
1897 break;
1899 myNBEdge->myRoutingType = value;
1900 break;
1901 case SUMO_ATTR_SHAPE:
1902 // set new geometry
1903 setGeometry(parse<PositionVector>(value), true);
1904 // update centering boundary and grid
1906 break;
1909 break;
1910 case SUMO_ATTR_NAME:
1911 myNBEdge->setStreetName(value);
1912 break;
1913 case SUMO_ATTR_SPEED:
1914 myNBEdge->setSpeed(-1, parse<double>(value));
1915 break;
1916 case SUMO_ATTR_FRICTION:
1917 myNBEdge->setFriction(-1, parse<double>(value));
1918 break;
1919 case SUMO_ATTR_WIDTH:
1920 if (value.empty() || (value == "default")) {
1922 } else {
1923 myNBEdge->setLaneWidth(-1, parse<double>(value));
1924 }
1925 break;
1927 myNBEdge->setEndOffset(-1, parse<double>(value));
1928 break;
1929 case SUMO_ATTR_ALLOW:
1930 break; // no edge value
1931 case SUMO_ATTR_DISALLOW:
1932 break; // no edge value
1933 case SUMO_ATTR_DISTANCE:
1934 if (value.empty()) {
1935 myNBEdge->setDistance(0.0);
1936 } else {
1937 myNBEdge->setDistance(parse<double>(value));
1938 }
1939 break;
1941 myConnectionStatus = value;
1942 if (value == FEATURE_GUESSED) {
1945 } else if (value != FEATURE_GUESSED) {
1947 }
1948 break;
1949 case GNE_ATTR_SHAPE_START: {
1950 // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1951 Position newShapeStart;
1952 if (value == "") {
1953 newShapeStart = getFromJunction()->getNBNode()->getPosition();
1954 } else {
1955 newShapeStart = parse<Position>(value);
1956 }
1957 // set shape start position
1958 setShapeStartPos(newShapeStart);
1959 // update centering boundary and grid
1961 break;
1962 }
1963 case GNE_ATTR_SHAPE_END: {
1964 // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destination position) and set it back to edge
1965 Position newShapeEnd;
1966 if (value == "") {
1967 newShapeEnd = getToJunction()->getNBNode()->getPosition();
1968 } else {
1969 newShapeEnd = parse<Position>(value);
1970 }
1971 // set shape end position
1972 setShapeEndPos(newShapeEnd);
1973 // update centering boundary and grid
1975 break;
1976 }
1977 case GNE_ATTR_BIDIR:
1978 myNBEdge->setBidi(parse<bool>(value));
1979 break;
1981 if (value.empty()) {
1983 } else {
1984 myNBEdge->myEdgeStopOffset.setOffset(parse<double>(value));
1985 }
1986 break;
1989 break;
1990 default:
1991 setCommonAttribute(key, value);
1992 break;
1993 }
1994 // get template editor
1996 // check if update template (except for modification status)
1997 if (templateEditor->getEdgeTemplate() && (templateEditor->getEdgeTemplate()->getID() == getID()) &&
2000 }
2001 // invalidate demand path calculator
2003}
2004
2005
2006void
2007GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
2008 // begin undo list
2009 undoList->begin(this, "change number of " + toString(SUMO_TAG_LANE) + "s");
2010 // invalidate logic of source/destination edges
2011 getFromJunction()->setLogicValid(false, undoList);
2012 getToJunction()->setLogicValid(false, undoList);
2013 // disable update geometry (see #6336)
2014 myUpdateGeometry = false;
2015 // remove edge from grid
2017 // save old number of lanes
2018 const int oldNumLanes = (int)getChildLanes().size();
2019 // get opposite ID
2020 const auto oppositeID = getChildLanes().back()->getAttribute(GNE_ATTR_OPPOSITE);
2021 if (oppositeID != "") {
2022 // we'll have a different leftmost lane after adding/removing lanes
2024 }
2025 for (int i = oldNumLanes; i < numLanes; i++) {
2026 // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
2027 undoList->add(new GNEChange_Lane(this, myNBEdge->getLaneStruct(oldNumLanes - 1)), true);
2028 }
2029 for (int i = (oldNumLanes - 1); i > (numLanes - 1); i--) {
2030 myNet->deleteLane(getChildLanes().at(i), undoList, false);
2031 }
2032 if (oppositeID != "") {
2034 }
2035 // enable updateGeometry again
2036 myUpdateGeometry = true;
2037 // update geometry of entire edge
2039 // end undo list
2040 undoList->end();
2041 // update centering boundary (without updating RTREE)
2043 // insert edge in grid again
2045}
2046
2047
2048void
2049GNEEdge::updateFirstParentJunction(const std::string& value) {
2050 auto newJunction = myNet->getAttributeCarriers()->retrieveJunction(value);
2051 GNEHierarchicalElement::updateParent(this, 0, newJunction);
2052}
2053
2054
2055void
2056GNEEdge::updateSecondParentJunction(const std::string& value) {
2057 auto newJunction = myNet->getAttributeCarriers()->retrieveJunction(value);
2058 GNEHierarchicalElement::updateParent(this, 1, newJunction);
2059}
2060
2061
2062void
2063GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections) {
2064 const int index = lane ? lane->getIndex() : myNBEdge->getNumLanes();
2065 // the laneStruct must be created first to ensure we have some geometry
2066 // unless the connections are fully recomputed, existing indices must be shifted
2067 myNBEdge->addLane(index, true, recomputeConnections, !recomputeConnections);
2068 if (lane) {
2069 // restore a previously deleted lane
2071 newParentLanes.insert(newParentLanes.begin() + index, lane);
2072 while (getChildLanes().size() > 0) {
2073 removeChild(this, getChildLanes().front());
2074 }
2075 for (const auto newParentLane : newParentLanes) {
2076 insertChild(this, newParentLane);
2077 }
2078 } else {
2079 // create a new lane by copying leftmost lane
2080 lane = new GNELane(this, index);
2082 }
2083 lane->incRef("GNEEdge::addLane");
2084 // add in attributeCarriers
2086 // check if lane is selected
2087 if (lane->isAttributeCarrierSelected()) {
2088 lane->selectAttributeCarrier();
2089 }
2090 // we copy all attributes except shape since this is recomputed from edge shape
2091 myNBEdge->setSpeed(lane->getIndex(), laneAttrs.speed);
2092 myNBEdge->setFriction(lane->getIndex(), laneAttrs.friction);
2093 myNBEdge->setPermissions(laneAttrs.permissions, lane->getIndex());
2095 myNBEdge->setEndOffset(lane->getIndex(), laneAttrs.endOffset);
2096 myNBEdge->setLaneWidth(lane->getIndex(), laneAttrs.width);
2097 // update indices
2098 for (int i = 0; i < (int)getChildLanes().size(); ++i) {
2099 getChildLanes()[i]->setIndex(i);
2100 }
2101 /* while technically correct, this looks ugly
2102 getFromJunction()->invalidateShape();
2103 getToJunction()->invalidateShape();
2104 */
2105 // Remake connections for this edge and all edges that target this lane
2107 // remake connections of all edges of junction source and destination
2108 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2109 fromEdge->remakeGNEConnections();
2110 }
2111 // remake connections of all edges of junction source and destination
2112 for (const auto& toEdge : getToJunction()->getChildEdges()) {
2113 toEdge->remakeGNEConnections();
2114 }
2115 // Update geometry with the new lane
2117 // update boundary and grid
2119}
2120
2121
2122void
2123GNEEdge::removeLane(GNELane* lane, bool recomputeConnections) {
2124 if (getChildLanes().size() == 0) {
2125 throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + getTagStr());
2126 }
2127 if (lane == nullptr) {
2128 lane = getChildLanes().back();
2129 }
2130 // check if lane is selected
2131 if (lane->isAttributeCarrierSelected()) {
2133 }
2134 // before removing, check that lane isn't being inspected
2137 // Delete lane of edge's container
2138 // unless the connections are fully recomputed, existing indices must be shifted
2139 myNBEdge->deleteLane(lane->getIndex(), recomputeConnections, !recomputeConnections);
2140 lane->decRef("GNEEdge::removeLane");
2141 // delete lane from edge
2143 // remove from attributeCarriers
2145 // Delete lane if is unreferenced
2146 if (lane->unreferenced()) {
2147 delete lane;
2148 }
2149 // update indices
2150 for (int i = 0; i < (int)getChildLanes().size(); ++i) {
2151 getChildLanes()[i]->setIndex(i);
2152 }
2153 /* while technically correct, this looks ugly
2154 getFromJunction()->invalidateShape();
2155 getToJunction()->invalidateShape();
2156 */
2157 // Remake connections of this edge
2159 // remake connections of all edges of junction source and destination
2160 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2161 fromEdge->remakeGNEConnections();
2162 }
2163 // remake connections of all edges of junction source and destination
2164 for (const auto& toEdge : getToJunction()->getChildEdges()) {
2165 toEdge->remakeGNEConnections();
2166 }
2167 // Update element
2169 // update boundary and grid
2171}
2172
2173
2174void
2175GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
2176 // If a new connection was successfully created
2178 nbCon.keepClear, nbCon.contPos, nbCon.visibility,
2179 nbCon.speed, nbCon.friction, nbCon.customLength, nbCon.customShape, nbCon.uncontrolled)) {
2180 // Create or retrieve existent GNEConnection
2181 GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
2182 // add it to GNEConnection container
2183 myGNEConnections.push_back(con);
2184 // Add reference
2185 myGNEConnections.back()->incRef("GNEEdge::addConnection");
2186 // select GNEConnection if needed
2187 if (selectAfterCreation) {
2189 }
2190 // update geometry
2191 con->updateGeometry();
2192 }
2193 // actually we only do this to force a redraw
2195}
2196
2197
2198void
2200 // check if is a explicit turnaround
2201 if (nbCon.toEdge == myNBEdge->getTurnDestination()) {
2203 }
2204 // remove NBEdge::connection from NBEdge
2206 // remove their associated GNEConnection
2207 GNEConnection* connection = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
2208 if (connection != nullptr) {
2209 // before removing, check that the connection isn't being inspected
2212 connection->decRef("GNEEdge::removeConnection");
2213 myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), connection));
2214 // check if connection is selected
2215 if (connection->isAttributeCarrierSelected()) {
2216 connection->unselectAttributeCarrier();
2217 }
2218 // remove it from network
2219 myNet->removeGLObjectFromGrid(connection);
2220 // check if remove it from Attribute Carriers
2221 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
2223 }
2224 if (connection->unreferenced()) {
2225 // actually we only do this to force a redraw
2227 }
2228 }
2229}
2230
2231
2233GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
2234 for (const auto& connection : myGNEConnections) {
2235 if ((connection->getFromLaneIndex() == fromLane) && (connection->getEdgeTo()->getNBEdge() == to) && (connection->getToLaneIndex() == toLane)) {
2236 return connection;
2237 }
2238 }
2239 if (createIfNoExist) {
2240 // create new connection. Will be added to the rTree on first geometry computation
2241 GNEConnection* connection = new GNEConnection(getChildLanes()[fromLane], myNet->getAttributeCarriers()->retrieveEdge(to->getID())->getChildLanes()[toLane]);
2242 // add it into network
2243 myNet->addGLObjectIntoGrid(connection);
2244 // add it in attributeCarriers
2246 return connection;
2247 } else {
2248 return nullptr;
2249 }
2250}
2251
2252
2253void
2254GNEEdge::setEdgeID(const std::string& newID) {
2255 setNetworkElementID(newID);
2256 for (const auto& lane : getChildLanes()) {
2257 lane->setNetworkElementID(getNBEdge()->getLaneID(lane->getIndex()));
2258 }
2259}
2260
2261
2262bool
2264 for (const auto& lane : getChildLanes()) {
2265 if (lane->isRestricted(vclass)) {
2266 return true;
2267 }
2268 }
2269 return false;
2270}
2271
2272
2273void
2275 // Remove all crossings that contain this edge in parameter "edges"
2276 for (const auto& crossing : junction->getGNECrossings()) {
2277 if (crossing->checkEdgeBelong(this)) {
2278 myNet->deleteCrossing(crossing, undoList);
2279 }
2280 }
2281}
2282
2283
2284void
2289 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2290 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2291}
2292
2293
2295GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
2296 const auto& neteditOptions = OptionsCont::getOptions();
2297 // distinguish 3 cases:
2298 // a) if the edge has exactly 3 or 4 points, use these as control points
2299 // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
2300 // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
2301 PositionVector init;
2302#ifdef DEBUG_SMOOTH_GEOM
2303 if (DEBUGCOND(this)) std::cout << getID()
2304 << " forElevation=" << forElevation
2305 << " fromGeometryLike=" << myNBEdge->getFromNode()->geometryLike()
2306 << " toGeometryLike=" << myNBEdge->getToNode()->geometryLike()
2307 << " smoothShape old=" << old << "\n";
2308#endif
2309 if (old.size() == 3 || old.size() == 4) {
2310 init = old;
2311 } else if (old.size() > 4 && !forElevation) {
2312 // for elevation, the initial segments are not useful
2313 init.push_back(old[0]);
2314 init.push_back(old[1]);
2315 init.push_back(old[-2]);
2316 init.push_back(old[-1]);
2317 } else if (myNBEdge->getFromNode()->geometryLike() && myNBEdge->getToNode()->geometryLike()) {
2318 PositionVector begShape;
2319 PositionVector endShape;
2320 const EdgeVector& incoming = myNBEdge->getFromNode()->getIncomingEdges();
2321 const EdgeVector& outgoing = myNBEdge->getToNode()->getOutgoingEdges();
2322 if (incoming.size() == 1) {
2323 begShape = incoming[0]->getGeometry();
2324 } else {
2325 assert(incoming.size() == 2);
2326 begShape = myNBEdge->isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
2327 }
2328 if (outgoing.size() == 1) {
2329 endShape = outgoing[0]->getGeometry();
2330 } else {
2331 assert(outgoing.size() == 2);
2332 endShape = myNBEdge->isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
2333 }
2334 const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
2335 if (forElevation) {
2336 // initialize control point elevation for smooth continuation
2337 init.push_back(old[0]);
2338 init.push_back(old.positionAtOffset2D(dist));
2339 init.push_back(old.positionAtOffset2D(old.length2D() - dist));
2340 init.push_back(old[-1]);
2341 double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
2342 double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
2343 // continue incline
2344 init[1].setz(2 * init[0].z() - begZ);
2345 init[2].setz(2 * init[-1].z() - endZ);
2346 } else {
2347 bool ok = true;
2348 const double straightThresh = DEG2RAD(neteditOptions.getFloat("opendrive-output.straight-threshold"));
2349 init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, nullptr, straightThresh);
2350 }
2351#ifdef DEBUG_SMOOTH_GEOM
2352 if (DEBUGCOND(this)) {
2353 std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
2354 }
2355#endif
2356 }
2357 if (init.size() == 0) {
2358 return PositionVector::EMPTY;
2359 } else {
2360 const int numPoints = MAX2(neteditOptions.getInt("junctions.internal-link-detail"),
2361 int(old.length2D() / neteditOptions.getFloat("opendrive.curve-resolution")));
2362 return init.bezier(numPoints);
2363 }
2364}
2365
2366
2367void
2369 PositionVector modifiedShape = smoothShape(myNBEdge->getGeometry(), false);
2370 if (modifiedShape.size() < 2) {
2371 WRITE_WARNINGF(TL("Could not compute smooth shape for edge '%'"), getID());
2372 } else {
2373 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2374 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2375 }
2376}
2377
2378
2379void
2381 PositionVector elevationBase;
2382 for (const Position& pos : myNBEdge->getGeometry()) {
2383 if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
2384 elevationBase.push_back(pos);
2385 }
2386 }
2387 PositionVector elevation = smoothShape(elevationBase, true);
2388 if (elevation.size() <= 2) {
2389 WRITE_WARNINGF(TL("Could not compute smooth elevation for edge '%'"), getID());
2390 } else {
2391 PositionVector modifiedShape = myNBEdge->getGeometry();
2392 if (modifiedShape.size() < 5) {
2393 modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"), false);
2394 }
2395 const double scale = elevation.length2D() / modifiedShape.length2D();
2396 //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
2397 double seen = 0;
2398 for (int i = 1; i < (int)modifiedShape.size(); ++i) {
2399 seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
2400 modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
2401 }
2402 //std::cout << " mod2=" << modifiedShape << "\n";
2403 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2404 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2405 }
2406}
2407
2408
2409void
2411 // remove start position and add it the new position
2413 geom.pop_front();
2414 geom.push_front(pos);
2415 // restore modified shape
2416 setGeometry(geom, false);
2417}
2418
2419
2420void
2422 // remove end position and add it the new position
2424 geom.pop_back();
2425 geom.push_back(pos);
2426 // restore modified shape
2427 setGeometry(geom, false);
2428}
2429
2430
2431const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2433 // declare vehicles over edge vector
2434 std::vector<GNEDemandElement*> vehiclesOverEdge;
2435 // declare solution map
2436 std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesOverEdgeMap;
2437 // declare a set of vehicles (to avoid duplicates)
2438 std::set<std::pair<double, GNEDemandElement*> > vehicles;
2439 // first obtain all vehicles of this edge
2440 for (const auto& edgeChild : getChildDemandElements()) {
2441 if (((edgeChild->getTagProperty()->getTag() == SUMO_TAG_TRIP) || (edgeChild->getTagProperty()->getTag() == SUMO_TAG_FLOW)) &&
2442 (edgeChild->getParentEdges().front() == this)) {
2443 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2444 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2445 } else if ((edgeChild->getTagProperty()->getTag() == SUMO_TAG_ROUTE) && (edgeChild->getParentEdges().front() == this)) {
2446 for (const auto& routeChild : edgeChild->getChildDemandElements()) {
2447 if (routeChild->getTagProperty()->vehicleRoute()) {
2448 vehicles.insert(std::make_pair(routeChild->getAttributeDouble(SUMO_ATTR_DEPART), routeChild));
2449 }
2450 }
2451 } else if ((edgeChild->getTagProperty()->getTag() == GNE_TAG_ROUTE_EMBEDDED) && (edgeChild->getParentEdges().front() == this) && (edgeChild->getParentDemandElements().size() > 0)) {
2452 vehicles.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild->getParentDemandElements().front()));
2453 }
2454 }
2455 // reserve
2456 vehiclesOverEdge.reserve(vehicles.size());
2457 // iterate over vehicles
2458 for (const auto& vehicle : vehicles) {
2459 // add it over vehiclesOverEdge;
2460 vehiclesOverEdge.push_back(vehicle.second);
2461 }
2462 // now split vehicles by lanes
2463 for (const auto& vehicle : vehiclesOverEdge) {
2464 const GNELane* vehicleLane = vehicle->getFirstPathLane();
2465 if (vehicleLane) {
2466 vehiclesOverEdgeMap[vehicleLane].push_back(vehicle);
2467 }
2468 }
2469 return vehiclesOverEdgeMap;
2470}
2471
2472
2473const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2475 // declare persons over edge vector
2476 std::vector<GNEDemandElement*> personsOverEdge;
2477 // declare solution map
2478 std::map<const GNELane*, std::vector<GNEDemandElement*> > personsOverEdgeMap;
2479 // declare a set of persons (to avoid duplicates)
2480 std::set<std::pair<double, GNEDemandElement*> > persons;
2481 // first obtain all persons of this edge
2482 for (const auto& edgeChild : getChildDemandElements()) {
2483 if (edgeChild->getTagProperty()->isPlanPerson() && (edgeChild->getParentDemandElements().size() > 0)) {
2484 persons.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2485 }
2486 }
2487 // reserve
2488 personsOverEdge.reserve(persons.size());
2489 // iterate over persons
2490 for (const auto& person : persons) {
2491 // add it over personsOverEdge;
2492 personsOverEdge.push_back(person.second);
2493 }
2494 // now split persons by lanes
2495 for (const auto& person : personsOverEdge) {
2496 const GNELane* personLane = person->getFirstPathLane();
2497 if (personLane) {
2498 personsOverEdgeMap[personLane].push_back(person);
2499 }
2500 }
2501 return personsOverEdgeMap;
2502}
2503
2504
2505
2506const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2508 // declare containers over edge vector
2509 std::vector<GNEDemandElement*> containersOverEdge;
2510 // declare solution map
2511 std::map<const GNELane*, std::vector<GNEDemandElement*> > containersOverEdgeMap;
2512 // declare a set of containers (to avoid duplicates)
2513 std::set<std::pair<double, GNEDemandElement*> > containers;
2514 // first obtain all containers of this edge
2515 for (const auto& edgeChild : getChildDemandElements()) {
2516 if (edgeChild->getTagProperty()->isPlanContainer() && (edgeChild->getParentDemandElements().size() > 0)) {
2517 containers.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2518 }
2519 }
2520 // reserve
2521 containersOverEdge.reserve(containers.size());
2522 // iterate over containers
2523 for (const auto& container : containers) {
2524 // add it over containersOverEdge;
2525 containersOverEdge.push_back(container.second);
2526 }
2527 // now split containers by lanes
2528 for (const auto& container : containersOverEdge) {
2529 const GNELane* containerLane = container->getFirstPathLane();
2530 if (containerLane) {
2531 containersOverEdgeMap[containerLane].push_back(container);
2532 }
2533 }
2534 return containersOverEdgeMap;
2535}
2536
2537
2538void
2540 // first check conditions
2542 // check if draw geometry points
2543 const bool bigGeometryPoints = drawBigGeometryPoints();
2544 // Obtain exaggeration of the draw
2545 const double exaggeration = getExaggeration(s);
2546 // get geometry point radius
2547 const double geometryPointRadius = getGeometryPointRadius();
2548 // obtain geometry point color
2549 RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2550 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2551 // override with special colors (unless the color scheme is based on selection)
2552 geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2553 }
2554 // draw geometry points except initial and final
2555 for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
2556 // obtain geometry point
2557 const auto geometryPointPos = myNBEdge->getGeometry()[i];
2558 // push geometry point drawing matrix
2560 // set color
2561 GLHelper::setColor(geometryPointColor);
2562 // move geometry point geometryPointPos
2563 glTranslated(geometryPointPos.x(), geometryPointPos.y(), bigGeometryPoints ? GLO_GEOMETRYPOINT : GLO_LANE + 1);
2564 // draw filled circle (resolution of drawn circle depending of the zoom, to improve smoothness)
2565 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius);
2566 // draw elevation or special symbols (Start, End and Block)
2568 // Translate to top
2569 glTranslated(0, 0, 0.2);
2570 // draw Z value
2571 GLHelper::drawText(toString(geometryPointPos.z()), Position(), 0, s.edgeValue.scaledSize(s.scale) / 2, s.edgeValue.color);
2572 }
2573 // pop geometry point drawing matrix
2575 }
2576 // draw start and end points
2577 if (bigGeometryPoints) {
2578 drawStartGeometryPoint(s, d, geometryPointRadius, layer, exaggeration);
2579 drawEndGeometryPoint(s, d, geometryPointRadius, layer, exaggeration);
2580 }
2581 // draw dotted contour geometry points
2584 }
2585}
2586
2587
2588void
2590 const double geometryPointRadius, const double layer, const double exaggeration) const {
2591 // check detail level
2593 // get first geometry point
2594 const auto& startGeometryPointPos = myNBEdge->getGeometry().front();
2595 // get flags
2596 const bool startPosEdited = (startGeometryPointPos != getParentJunctions().front()->getPositionInView());
2598 // check drawing conditions
2599 if (startPosEdited || forceDraw) {
2600 // calculate angle betwen first and second geometry point
2601 const double angle = RAD2DEG(startGeometryPointPos.angleTo2D(myNBEdge->getGeometry()[1])) * -1;
2602 // get selected geometry points
2603 const auto selectedGeometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(this);
2604 // override with special colors (unless the color scheme is based on selection)
2605 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2607 } else {
2608 GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2609 }
2610 // push drawing matrix
2612 // move to point position
2613 glTranslated(startGeometryPointPos.x(), startGeometryPointPos.y(), GLO_GEOMETRYPOINT);
2614 // resolution of drawn circle depending of detail
2615 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2616 // pop drawing matrix
2618 // draw a "s" over last point depending of detail level
2620 // push drawing matrix
2622 // move top
2623 glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2624 // draw S
2625 GLHelper::drawText("S", startGeometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2626 // pop drawing matrix
2628 // check if draw line between junctions
2629 if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.front() == 0)) {
2630 // set base color
2632 // push drawing matrix
2634 // draw line between geometry point and from junction
2635 const PositionVector lineA = {startGeometryPointPos, getFromJunction()->getNBNode()->getPosition()};
2636 GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2637 // draw line between begin point of last lane shape and the first edge shape point
2638 const PositionVector lineB = {startGeometryPointPos, myNBEdge->getLanes().back().shape.front()};
2639 GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2640 // pop drawing matrix
2642 }
2643 }
2644 // draw dotted contour geometry points
2646 geometryPointRadius, exaggeration);
2647 }
2648 }
2649}
2650
2651
2652void
2654 const double geometryPointRadius, const double layer, const double exaggeration) const {
2655 // check detail level
2657 // get first geometry point
2658 const auto& geometryPointPos = myNBEdge->getGeometry().back();
2659 // get flags
2660 const bool endPosEdited = (geometryPointPos != getParentJunctions().back()->getPositionInView());
2662 // check drawing conditions
2663 if (endPosEdited || forceDraw) {
2664 // calculate angle last and previous geometry point
2665 const double angle = RAD2DEG(geometryPointPos.angleTo2D(myNBEdge->getGeometry()[-2])) * -1;
2666 // get selected geometry points
2667 const auto selectedGeometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(this);
2668 // override with special colors (unless the color scheme is based on selection)
2669 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2671 } else {
2672 GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2673 }
2674 // push drawing matrix
2676 // move to point position
2677 glTranslated(geometryPointPos.x(), geometryPointPos.y(), GLO_GEOMETRYPOINT);
2678 // resolution of drawn circle depending of detail
2679 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2680 // pop drawing matrix
2682 // draw a "s" over last point depending of detail level
2684 // push drawing matrix
2686 // move top
2687 glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2688 // draw S
2689 GLHelper::drawText("E", geometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2690 // pop drawing matrix
2692 // check if draw line between junctions
2693 if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.back() == ((int)myNBEdge->getGeometry().size() - 1))) {
2694 // set base color
2696 // push drawing matrix
2698 // draw line between geometry point and from junction
2699 const PositionVector lineA = {geometryPointPos, getToJunction()->getNBNode()->getPosition()};
2700 GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2701 // draw line between begin point of last lane shape and the first edge shape point
2702 const PositionVector lineB = {geometryPointPos, myNBEdge->getLanes().back().shape.back()};
2703 GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2704 // pop drawing matrix
2706 }
2707 }
2708 // draw dotted contour geometry points
2710 geometryPointRadius, exaggeration);
2711 }
2712 }
2713}
2714
2715
2716void
2718 // draw the name and/or the street name
2719 const bool drawStreetName = s.streetName.show(this) && (myNBEdge->getStreetName() != "");
2720 const bool spreadSuperposed = s.spreadSuperposed && myNBEdge->getBidiEdge() != nullptr;
2721 // check conditions
2722 if (s.edgeName.show(this) || drawStreetName || s.edgeValue.show(this)) {
2723 // get first and last lanes
2724 const GNELane* firstLane = getChildLanes()[0];
2725 const GNELane* lastLane = getChildLanes()[getChildLanes().size() - 1];
2726 // calculate draw position
2727 Position drawPosition = firstLane->getLaneShape().positionAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2728 drawPosition.add(lastLane->getLaneShape().positionAtOffset(lastLane->getLaneShape().length() / (double) 2.));
2729 drawPosition.mul(.5);
2730 if (spreadSuperposed) {
2731 // move name to the right of the edge and towards its beginning
2732 const double dist = 0.6 * s.edgeName.scaledSize(s.scale);
2733 const double shiftA = firstLane->getLaneShape().rotationAtOffset(firstLane->getLaneShape().length() / (double) 2.) - DEG2RAD(135);
2734 const Position shift(dist * cos(shiftA), dist * sin(shiftA));
2735 drawPosition.add(shift);
2736 }
2737 // calculate drawing angle
2738 double drawAngle = firstLane->getLaneShape().rotationDegreeAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2739 drawAngle += 90;
2740 // avoid draw inverted text
2741 if (drawAngle > 90 && drawAngle < 270) {
2742 drawAngle -= 180;
2743 }
2744 // draw edge name
2745 if (s.edgeName.show(this)) {
2746 drawName(drawPosition, s.scale, s.edgeName, drawAngle);
2747 }
2748 // draw street name
2749 if (drawStreetName) {
2750 GLHelper::drawTextSettings(s.streetName, myNBEdge->getStreetName(), drawPosition, s.scale, drawAngle);
2751 }
2752 // draw edge values
2753 if (s.edgeValue.show(this)) {
2754 // get current scheme
2755 const int activeScheme = s.laneColorer.getActive();
2756 // calculate value depending of active scheme
2757 std::string value;
2758 if (activeScheme == 12) {
2759 // edge param, could be non-numerical
2760 value = getNBEdge()->getParameter(s.edgeParam, "");
2761 } else if (activeScheme == 13) {
2762 // lane param, could be non-numerical
2763 value = getNBEdge()->getLaneStruct(lastLane->getIndex()).getParameter(s.laneParam, "");
2764 } else {
2765 // use numerical value value of leftmost lane to hopefully avoid sidewalks, bikelanes etc
2766 const double doubleValue = lastLane->getColorValue(s, activeScheme);
2767 const RGBColor color = s.laneColorer.getScheme().getColor(doubleValue);
2768 value = color.alpha() == 0 ? "" : toString(doubleValue);
2769 }
2770 // check if value is empty
2771 if (value != "") {
2772 GLHelper::drawTextSettings(s.edgeValue, value, drawPosition, s.scale, drawAngle);
2773 }
2774 }
2775 }
2776}
2777
2778
2779void
2781 // draw geometry only if we'rent in drawForObjectUnderCursor mode
2783 // Push stopOffset matrix
2785 // translate to front (note: Special case)
2786 drawInLayer(layer + 1);
2788 for (const auto& lane : getChildLanes()) {
2789 lane->drawLaneStopOffset(s);
2790 }
2791 }
2792 // Push stopOffset matrix
2794 }
2795}
2796
2797
2798void
2800 // draw child additional
2801 for (const auto& additional : getChildAdditionals()) {
2802 if (!additional->getTagProperty()->isListedElement()) {
2803 additional->drawGL(s);
2804 }
2805 }
2806 // draw person stops
2808 for (const auto& stopEdge : getChildDemandElements()) {
2809 if ((stopEdge->getTagProperty()->getTag() == GNE_TAG_STOPPERSON_EDGE) || (stopEdge->getTagProperty()->getTag() == GNE_TAG_STOPCONTAINER_EDGE)) {
2810 stopEdge->drawGL(s);
2811 }
2812 }
2813 }
2814 // draw vehicles
2815 const std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesMap = getVehiclesOverEdgeMap();
2816 for (const auto& vehicleMap : vehiclesMap) {
2817 for (const auto& vehicle : vehicleMap.second) {
2818 vehicle->drawGL(s);
2819 }
2820 }
2821 // draw TAZ elements
2822 drawTAZElements(s);
2823}
2824
2825
2826void
2828 // if we're selecting using a boundary, first don't calculate contour bt check if edge boundary is within selection boundary
2830 // simply add object in ViewObjectsHandler with full boundary
2831 gViewObjectsHandler.selectObject(s, this, layer, false, nullptr);
2832 } else {
2833 // get geometry point radius
2834 const auto geometryPointRadius = getGeometryPointRadius();
2835 // check if edit extrems
2836 const bool forceDrawExtrems = myNet->getViewParent()->getMoveFrame()->getNetworkMoveOptions()->getForceDrawGeometryPoints();
2837 const bool firstExtrem = forceDrawExtrems || (myNBEdge->getGeometry().front() != getParentJunctions().front()->getPositionInView());
2838 const bool lastExtrem = forceDrawExtrems || (myNBEdge->getGeometry().back() != getParentJunctions().back()->getPositionInView());
2839 // check if we're in move mode
2841 // calculate contour
2842 myNetworkElementContour.calculateContourEdge(s, d, this, this, layer, true, true);
2843 // calculate edge geometry points
2844 myNetworkElementContour.calculateContourEdgeGeometryPoints(s, d, this, geometryPointRadius, moveMode, firstExtrem, lastExtrem);
2845 }
2846}
2847
2848
2849void
2851 // first check if draw TAZ Elements is enabled
2853 if (getChildTAZSourceSinks().size() > 0) {
2854 // check if TAZ Source/sink is selected
2855 bool selected = false;
2856 for (const auto& TAZSourceSink : getChildTAZSourceSinks()) {
2857 if (TAZSourceSink->isAttributeCarrierSelected()) {
2858 selected = true;
2859 }
2860 }
2861 // iterate over lanes
2862 for (const auto& lane : getChildLanes()) {
2863 // Push layer matrix
2865 // translate to front (note: Special case)
2866 if (myDrawInFront) {
2867 glTranslated(0, 0, GLO_FRONTELEMENT);
2868 } else if (lane->getLaneShape().length2D() <= (s.neteditSizeSettings.junctionBubbleRadius * 2)) {
2870 } else {
2872 }
2873 // move to front
2874 glTranslated(0, 0, 0.1);
2875 // set color
2876 if (selected) {
2878 } else {
2880 }
2881 // draw as box lines
2883 lane->getDrawingConstants()->getDrawingWidth());
2884 // Pop layer matrix
2886 }
2887 /*
2888 // check if curently we're inspecting a TAZ Source/Sink
2889 for (const auto& TAZSourceSink : TAZSourceSinks) {
2890 if (myNet->getViewNet()->isAttributeCarrierInspected(TAZSourceSink)) {
2891 drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::INSPECT, this, true, true);
2892 } else if (TAZSourceSink == markAC) {
2893 drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::FRONT, this, true, true);
2894 }
2895 }
2896 */
2897 }
2898 }
2899}
2900
2901
2902void
2904 // avoid draw for railways
2905 if ((d <= GUIVisualizationSettings::Detail::LaneDetails) && !getChildLanes().front()->getDrawingConstants()->drawAsRailway() &&
2907 // push draw matrix
2909 // translate to front depending of big points
2910 if (drawBigGeometryPoints()) {
2911 glTranslated(0, 0, GLO_GEOMETRYPOINT - 1);
2912 } else {
2913 glTranslated(0, 0, layer);
2914 }
2915 // obtain color
2916 RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2917 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2918 // override with special colors (unless the color scheme is based on selection)
2919 geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2920 }
2921 // never draw when at full transparency
2922 if (geometryPointColor.alpha() != 0) {
2923 // set color
2924 GLHelper::setColor(geometryPointColor);
2925 // iterate over NBEdge geometry
2926 for (int i = 1; i < (int)myNBEdge->getGeometry().size(); i++) {
2927 // calculate line between previous and current geometry point
2928 PositionVector line = {myNBEdge->getGeometry()[i - 1], myNBEdge->getGeometry()[i]};
2929 line.move2side(0.2);
2930 // draw box line
2931 GLHelper::drawBoxLine(line[1], RAD2DEG(line[0].angleTo2D(line[1])) - 90, line[0].distanceTo2D(line[1]), .1);
2932 }
2933 }
2934 // pop draw matrix
2936 }
2937}
2938
2939
2940bool
2942 // get edit modes
2943 const auto& editModes = myNet->getViewNet()->getEditModes();
2944 // continue depending of conditions
2945 if (!editModes.isCurrentSupermodeNetwork()) {
2946 return false;
2947 } else if (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) {
2948 return true;
2949 } else if ((editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE) &&
2951 return true;
2952 } else {
2953 return false;
2954 }
2955}
2956
2957
2958bool
2960 if ((vehicleA.beginPosition() == vehicleB.beginPosition()) && (vehicleA.endPosition() == vehicleB.endPosition())) {
2961 return true;
2962 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2963 return true;
2964 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.beginPosition())) {
2965 return true;
2966 } else if ((vehicleA.beginPosition() < vehicleB.endPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2967 return true;
2968 } else {
2969 return false;
2970 }
2971}
2972
2973
2974double
2978
2979/****************************************************************************/
#define VEHICLE_GAP
Definition GNEEdge.cpp:62
std::vector< ChildType > GNEHierarchicalContainerChildren
#define ENDPOINT_TOLERANCE
@ NETWORK_DELETE
mode for deleting network elements
@ NETWORK_MOVE
mode for moving network elements
@ NETWORK_ADDITIONAL
Mode for editing additionals.
@ NETWORK_SELECT
mode for selecting network elements
@ DEMAND_PERSONPLAN
Mode for editing person plan.
@ DEMAND_CONTAINER
Mode for editing container.
@ DEMAND_PERSON
Mode for editing person.
@ DEMAND_VEHICLE
Mode for editing vehicles.
@ DEMAND_CONTAINERPLAN
Mode for editing container plan.
@ GLO_JUNCTION
a junction
@ GLO_FRONTELEMENT
front element (used in netedit)
@ GLO_LANE
a lane
@ GLO_GEOMETRYPOINT
geometry point (used in netedit)
@ GLO_EDGE
an edge
GUIViewObjectsHandler gViewObjectsHandler
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define RAD2DEG(x)
Definition GeomHelper.h:36
#define DEBUGCOND(PED)
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition NBCont.h:42
const SVCPermissions SVCAll
all VClasses are allowed
SVCPermissions invertPermissions(SVCPermissions permissions)
negate the given permissions and ensure that only relevant bits are set
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
bool canParseVehicleClasses(const std::string &classes)
Checks whether the given string contains only known vehicle classes.
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SUMO_TAG_TAZ
a traffic assignment zone
@ GNE_TAG_STOPCONTAINER_EDGE
@ SUMO_TAG_LANETYPE
lane type
@ SUMO_TAG_FLOW
a flow definition using from and to edges or a route
@ SUMO_TAG_ROUTE
description of a route
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_TYPE
type (edge)
@ GNE_TAG_ROUTE_EMBEDDED
embedded route
@ GNE_TAG_STOPPERSON_EDGE
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_TAG_EDGE
begin/end of the description of an edge
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_DISALLOW
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_FROM_JUNCTION
@ SUMO_ATTR_SPEED
@ GNE_ATTR_STOPOFFSET
stop offset (virtual, used by edge and lanes)
@ GNE_ATTR_OPPOSITE
to busStop (used by personPlans)
@ SUMO_ATTR_TO_JUNCTION
@ GNE_ATTR_PARAMETERS
parameters "key1=value1|key2=value2|...|keyN=valueN"
@ SUMO_ATTR_PRIORITY
@ GNE_ATTR_STOPOEXCEPTION
stop exceptions (virtual, used by edge and lanes)
@ SUMO_ATTR_NUMLANES
@ GNE_ATTR_MODIFICATION_STATUS
whether a feature has been loaded,guessed,modified or approved
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_NAME
@ SUMO_ATTR_SPREADTYPE
The information about how to spread the lanes from the given position.
@ GNE_ATTR_IS_ROUNDABOUT
@ SUMO_ATTR_ENDOFFSET
@ GNE_ATTR_SHAPE_END
last coordinate of edge shape
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_DISTANCE
@ GNE_ATTR_BIDIR
whether an edge is part of a bidirectional railway
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_ID
@ GNE_ATTR_SHAPE_START
first coordinate of edge shape
@ SUMO_ATTR_WIDTH
@ SUMO_ATTR_FRICTION
@ SUMO_ATTR_ROUTINGTYPE
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
const double SUMO_const_halfLaneWidth
Definition StdDefs.h:53
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:75
Boundary & grow(double by)
extends the boundary by the given amount
Definition Boundary.cpp:340
std::vector< std::string > consecutiveEdges
consecutive edges
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:649
static void popMatrix()
pop matrix
Definition GLHelper.cpp:131
static void drawBoundary(const GUIVisualizationSettings &s, const Boundary &b)
Draw a boundary (used for debugging)
Definition GLHelper.cpp:952
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition GLHelper.cpp:296
static void drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius)
Draws a filled circle around (0,0) depending of level of detail.
Definition GLHelper.cpp:534
static void pushMatrix()
push matrix
Definition GLHelper.cpp:118
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition GLHelper.cpp:742
static void drawTextSettings(const GUIVisualizationTextSettings &settings, const std::string &text, const Position &pos, const double scale, const double angle=0, const double layer=2048, const int align=0)
Definition GLHelper.cpp:773
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
double getCommonAttributeDouble(SumoXMLAttr key) const
bool myDrawInFront
boolean to check if drawn this AC over other elements
bool mySelected
boolean to check if this AC is selected (more quickly as checking GUIGlObjectStorage)
static const std::string FALSE_STR
true value in string format(used for comparing boolean values in getAttribute(...))
static const std::string TRUE_STR
true value in string format (used for comparing boolean values in getAttribute(......
const std::string getID() const override
get ID (all Attribute Carriers have one)
PositionVector getCommonAttributePositionVector(SumoXMLAttr key) const
void unselectAttributeCarrier()
unselect attribute carrier using GUIGlobalSelection
void setCommonAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
const std::string & getTagStr() const
get tag assigned to this object in string format
static const std::string FEATURE_GUESSED
feature has been reguessed (may still be unchanged be we can't tell (yet)
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
void drawInLayer(const double typeOrLayer, const double extraOffset=0) const
draw element in the given layer, or in front if corresponding flag is enabled
Position getCommonAttributePosition(SumoXMLAttr key) const
const GNETagProperties * getTagProperty() const
get tagProperty associated with this Attribute Carrier
GNENet * myNet
pointer to net
bool isCommonAttributeValid(SumoXMLAttr key, const std::string &value) const
std::string getCommonAttribute(SumoXMLAttr key) const
const GNETagProperties * myTagProperty
reference to tagProperty associated with this attribute carrier
static void changeAttribute(GNEAttributeCarrier *AC, SumoXMLAttr key, const std::string &value, GNEUndoList *undoList, const bool force=false)
change attribute
void updateGeometry() override
update pre-computed geometry information
void markConnectionGeometryDeprecated()
check that connection's Geometry has to be updated
void updateLinkState()
recompute cached myLinkState
void drawDottedContourGeometryPoints(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, const PositionVector &shape, const double radius, const double scale, const double lineWidth) const
draw dotted contour for geometry points
void calculateContourEdgeGeometryPoints(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEEdge *edge, const double radius, const bool calculatePosOverShape, const bool firstExtrem, const bool lastExtrem) const
calculate contour for edge geometry points
void calculateContourEdge(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEEdge *edge, const GUIGlObject *elementToRegister, const double layer, const bool closeFirstExtrem, const bool closeLastExtrem) const
calculate contour edge
void calculateContourFirstGeometryPoint(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const PositionVector &shape, const double layer, const double radius, const double scale, const bool forceCalculation=false) const
calculate contour for first geometry point
bool drawDottedContours(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, const double lineWidth, const bool addOffset) const
draw dotted contours (basics, select, delete, inspect...)
bool deleteOnlyGeometryPoints() const
check if only delete geometry points checkbox is enabled
struct for saving subordinated elements (Junction->Edge->Lane->(Additional | DemandElement)
ProtectElements * getProtectElements() const
get protect elements modul
DeleteOptions * getDeleteOptions() const
get delete options modul
void updateDemandElementStackLabel(const int stack)
update stack label
Stack demand elements.
Definition GNEEdge.h:412
const StackPosition & getStackPosition() const
get stack position
Definition GNEEdge.cpp:1830
const std::vector< GNEDemandElement * > & getDemandElements() const
get demand elements
Definition GNEEdge.cpp:1836
void addDemandElements(GNEDemandElement *demandElement)
add demand elment to current StackDemandElements
Definition GNEEdge.cpp:1824
StackDemandElements(const StackPosition stackedPosition, GNEDemandElement *demandElement)
constructor
Definition GNEEdge.cpp:1816
Stack position (used to stack demand elements over edges)
Definition GNEEdge.h:398
double beginPosition() const
get begin position
Definition GNEEdge.cpp:1805
StackPosition(const double departPos, const double length)
constructor
Definition GNEEdge.cpp:1799
double endPosition() const
get end position
Definition GNEEdge.cpp:1811
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:2539
double getAttributeDouble(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1215
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:2717
bool isConvexAngle() const
check if edge makes a convex angle [0 - 180) degrees
Definition GNEEdge.cpp:1749
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:2007
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:1238
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getPersonsOverEdgeMap() const
get persons a that start over this edge
Definition GNEEdge.cpp:2474
PositionVector getAttributePositionVector(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1227
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getContainersOverEdgeMap() const
get containers a that start over this edge
Definition GNEEdge.cpp:2507
bool hasPredecessors() const
check if this edge has predecessors (note: only for vehicles, this function ignore walking areas!...
Definition GNEEdge.cpp:1764
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:2368
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList) override
Definition GNEEdge.cpp:1248
double getGeometryPointRadius() const
get geometry point radius
Definition GNEEdge.cpp:2975
void setResponsible(bool newVal)
set responsibility for deleting internal structures
Definition GNEEdge.cpp:1520
void copyEdgeType(const GNEEdgeType *edgeType, GNEUndoList *undoList)
copy edge attributes from edgeType
Definition GNEEdge.cpp:1065
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:2432
std::set< GUIGlID > getLaneGlIDs() const
returns GLIDs of all lanes
Definition GNEEdge.cpp:1097
GNEEdge * getReverseEdge() const
get reverse edge (if exist)
Definition GNEEdge.cpp:1786
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:2380
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:1587
void remakeGNEConnections(bool junctionsReady=false)
remake connections
Definition GNEEdge.cpp:937
bool isAttributeComputed(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1503
void calculateEdgeContour(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
calculate contours
Definition GNEEdge.cpp:2827
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:1526
bool hasCustomEndPoints() const
Definition GNEEdge.cpp:558
void updatePersonStackLabels()
Definition GNEEdge.cpp:1645
void setEdgeID(const std::string &newID)
set edge ID
Definition GNEEdge.cpp:2254
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition GNEEdge.cpp:2199
void drawChildrens(const GUIVisualizationSettings &s) const
draw children
Definition GNEEdge.cpp:2799
bool hasSuccessors() const
check if this edge has successors (note: only for vehicles, this function ignore walking areas!...
Definition GNEEdge.cpp:1780
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:2589
GNEMoveElementEdge * myMoveElementEdge
move element edge
Definition GNEEdge.h:429
bool drawBigGeometryPoints() const
check if draw big geometry points
Definition GNEEdge.cpp:2941
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:2123
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:2263
static const double SNAP_RADIUS_SQUARED
Definition GNEEdge.h:324
void updateSecondParentJunction(const std::string &value)
update last parent junction
Definition GNEEdge.cpp:2056
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:2295
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:1113
NBEdge * myNBEdge
the underlying NBEdge
Definition GNEEdge.h:379
void copyTemplate(const GNEEdgeTemplate *edgeTemplate, GNEUndoList *undoList)
copy edge attributes from edgetemplate
Definition GNEEdge.cpp:1042
void removeEdgeFromCrossings(GNEJunction *junction, GNEUndoList *undoList)
remove crossing of junction
Definition GNEEdge.cpp:2274
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:2063
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:2233
Position getAttributePosition(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1221
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:1107
bool isValid(SumoXMLAttr key, const std::string &value) override
Definition GNEEdge.cpp:1386
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition GNEEdge.cpp:1007
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:2653
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:982
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:2959
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:2049
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:2285
void updateContainerStackLabels()
Definition GNEEdge.cpp:1697
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:2410
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:1488
void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation=false)
adds a connection
Definition GNEEdge.cpp:2175
void drawLaneStopOffset(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
draw edgeStopOffset
Definition GNEEdge.cpp:2780
void drawTAZElements(const GUIVisualizationSettings &s) const
draw TAZElements
Definition GNEEdge.cpp:2850
void drawEdgeShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
draw edge shape (only one line)
Definition GNEEdge.cpp:2903
std::vector< GNECrossing * > getGNECrossings()
get GNECrossings vinculated with this Edge
Definition GNEEdge.cpp:1025
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:1541
Parameterised * getParameters() override
get parameters associated with this edge
Definition GNEEdge.cpp:147
void updateVehicleSpreadGeometries()
Definition GNEEdge.cpp:1556
bool checkDrawOverContour() const override
check if draw over contour (orange)
Definition GNEEdge.cpp:365
std::string getAttribute(SumoXMLAttr key) const override
Definition GNEEdge.cpp:1119
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:2421
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:1557
int getIndex() const
returns the index of the lane
Definition GNELane.cpp:624
void setIndex(int index)
Definition GNELane.cpp:630
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList) override
remove geometry point in the clicked position
bool getForceDrawGeometryPoints() const
check if option "force draw geometry points" is enabled
NetworkMoveOptions * getNetworkMoveOptions() const
get network mode options
std::vector< GNEEdge * > retrieveEdges(GNEJunction *from, GNEJunction *to) const
get all edges by from and to GNEJunction
const std::unordered_map< const GUIGlObject *, GNEConnection * > & getConnections() const
get connections
void insertLane(GNELane *lane)
insert lane in container
void deleteConnection(GNEConnection *connection)
delete connection from container
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
void insertConnection(GNEConnection *connection)
insert connection in container
void updateEdgeID(GNEEdge *edge, const std::string &newID)
update edge ID in container
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
const std::unordered_map< const GUIGlObject *, GNELane * > & getLanes() const
get lanes
void deleteLane(GNELane *lane)
delete lane from container
void requireSaveDemandElements()
inform that demand elements has to be saved
void deleteEdge(GNEEdge *edge, GNEUndoList *undoList, bool recomputeConnections)
removes edge
Definition GNENet.cpp:485
void deleteLane(GNELane *lane, GNEUndoList *undoList, bool recomputeConnections)
removes lane
Definition GNENet.cpp:664
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition GNENet.cpp:721
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1449
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1459
GNENetHelper::SavingStatus * getSavingStatus() const
get saving status
Definition GNENet.cpp:186
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:198
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition GNENet.cpp: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:4518
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition NBEdge.cpp:4541
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition NBEdge.h:1047
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
Definition NBEdge.cpp:4504
StopOffset myEdgeStopOffset
A vClass specific stop offset - assumed of length 0 (unspecified) or 1. For the latter case the int i...
Definition NBEdge.h:1823
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition NBEdge.h:608
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition NBEdge.cpp:4456
bool hasLaneSpecificFriction() const
whether lanes differ in friction
Definition NBEdge.cpp:2486
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition NBEdge.h:648
NBNode * getToNode() const
Returns the destination node of the edge.
Definition NBEdge.h:552
Lane & getLaneStruct(int lane)
Definition NBEdge.h:1451
void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices)
add lane
Definition NBEdge.cpp:4193
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition NBEdge.cpp:2476
std::string myType
The type of the edge.
Definition NBEdge.h:1760
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition NBEdge.h:789
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition NBEdge.cpp:1021
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition NBEdge.h:618
void setDistance(double distance)
set kilometrage at start of edge (negative value implies couting down along the edge)
Definition NBEdge.h:1425
const std::string & getRoutingType() const
return whether this edge should be a bidi edge
Definition NBEdge.h:1446
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition NBEdge.h:736
double getSpeed() const
Returns the speed allowed on this edge.
Definition NBEdge.h:625
const std::string & getID() const
Definition NBEdge.h:1551
double getDistance() const
get distance
Definition NBEdge.h:685
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition NBEdge.h:364
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition NBEdge.cpp:4327
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition NBEdge.cpp:1015
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition NBEdge.cpp:3808
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition NBEdge.cpp:2462
bool isBidiEdge(bool checkPotential=false) const
whether this edge is part of a bidirectional edge pair
Definition NBEdge.cpp:784
void setBidi(bool isBidi)
mark this edge as a bidi edge
Definition NBEdge.h:1430
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:526
void setFriction(int lane, double friction)
set lane specific friction (negative lane implies set for all lanes)
Definition NBEdge.cpp:4472
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false, const bool keepPossibleTurns=false)
Removes the specified connection(s)
Definition NBEdge.cpp:1471
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition NBEdge.cpp:1552
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition NBEdge.cpp:4248
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition NBEdge.cpp:2496
std::string getLaneID(int lane) const
get lane ID
Definition NBEdge.cpp:4179
@ USER
The connection was given by the user.
double getFriction() const
Returns the friction on this edge.
Definition NBEdge.h:632
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double friction=UNSPECIFIED_FRICTION, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection to a certain lane of a certain edge.
Definition NBEdge.cpp:1209
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition NBEdge.cpp:2518
const std::string & getTypeID() const
get ID of type
Definition NBEdge.h:1187
const std::string & getStreetName() const
Returns the street name of this edge.
Definition NBEdge.h:675
const NBEdge * getBidiEdge() const
Definition NBEdge.h:1537
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition NBEdge.h:545
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:4170
std::string myRoutingType
The routing type of the edge.
Definition NBEdge.h:1865
int getPriority() const
Returns the priority of the edge.
Definition NBEdge.h:533
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition NBEdge.h:346
void declareConnectionsAsLoaded(EdgeBuildingStep step=EdgeBuildingStep::LANES2LANES_USER)
declares connections as fully loaded. This is needed to avoid recomputing connections if an edge has ...
Definition NBEdge.h:1465
double getEndOffset() const
Returns the offset to the destination node.
Definition NBEdge.h:695
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition NBEdge.cpp:4410
void setLoadedLength(double val)
set loaded length
Definition NBEdge.cpp:4556
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition NBEdge.cpp:613
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition NBEdge.cpp:4892
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition NBEdge.cpp:660
int myPriority
The priority of the edge.
Definition NBEdge.h:1779
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition NBNode.h:268
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition NBNode.h:273
const Position & getPosition() const
Definition NBNode.h:260
bool isRoundabout() const
return whether this node is part of a roundabout
Definition NBNode.cpp:4073
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition NBNode.cpp:4027
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, bool &ok, NBNode *recordError=0, double straightThresh=DEG2RAD(5), int shapeFlag=0)
get bezier control points
Definition NBNode.cpp:618
const std::string & getID() const
Returns the id.
Definition Named.h: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:194
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition RGBColor.cpp:92
static const RGBColor ORANGE
Definition RGBColor.h:198
static const RGBColor CYAN
Definition RGBColor.h:196
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition RGBColor.cpp:200
static StringBijection< LaneSpreadFunction > LaneSpreadFunctions
lane spread functions
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
void setOffset(const double offset)
set offset
bool isDefined() const
check if stopOffset was defined
SVCPermissions getPermissions() const
get permissions
void setExceptions(const std::string permissions)
set exceptions (used in netedit)
std::string getExceptions() const
get exceptions (used in netedit)
double getOffset() const
get offset
const std::string & getString(const T key) const
get string
bool hasString(const std::string &str) const
check if the given string exist
bool isBoundaryFullWithin(const Boundary &boundary) const
check if the given position is FULL within this triangle
Definition Triangle.cpp:60
bool showDemandElements() const
check if show demand elements checkbox is enabled
NetworkEditMode networkEditMode
the current Network edit mode
bool isCurrentSupermodeNetwork() const
@check if current supermode is Network
GNENetworkElement * getEditedNetworkElement() const
pointer to edited network element
static void drawLockIcon(const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, GUIGlObjectType type, const Position position, const double exaggeration, const double size=0.5, const double offsetx=0, const double offsety=0)
draw lock icon
GNEMoveElement * getMovedElement() const
get moved element
bool editingElevation() const
check if we're editing elevation
bool showDemandElements() const
check if show demand elements checkbox is enabled
bool showTAZElements() const
check if show TAZ Elements
RGBColor selectedEdgeColor
edge selection color
static const double segmentWidthSmall
width of small dotted contour segments
static const double segmentWidth
width of dotted contour segments
static const double junctionBubbleRadius
junction bubble radius
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
bool show(const GUIGlObject *o) const
whether to show the text
double scaledSize(double scale, double constFactor=0.1) const
get scale size
A structure which describes a connection between edges or lanes.
Definition NBEdge.h:201
int fromLane
The lane the connections starts at.
Definition NBEdge.h:210
int toLane
The lane the connections yields in.
Definition NBEdge.h:216
double speed
custom speed for connection
Definition NBEdge.h:240
NBEdge * toEdge
The edge the connections yields in.
Definition NBEdge.h:213
KeepClear keepClear
whether the junction must be kept clear when using this connection
Definition NBEdge.h:231
double customLength
custom length for connection
Definition NBEdge.h:246
bool uncontrolled
check if Connection is uncontrolled
Definition NBEdge.h:298
PositionVector customShape
custom shape for connection
Definition NBEdge.h:249
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition NBEdge.h:228
double contPos
custom position for internal junction on this connection
Definition NBEdge.h:234
double visibility
custom foe visiblity for connection
Definition NBEdge.h:237
An (internal) definition of a single lane of an edge.
Definition NBEdge.h:143
double width
This lane's width.
Definition NBEdge.h:176
double endOffset
This lane's offset to the intersection begin.
Definition NBEdge.h:169
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition NBEdge.h:160
double speed
The speed allowed on this lane.
Definition NBEdge.h:151
double friction
The friction on this lane.
Definition NBEdge.h:154
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition NBEdge.h:157