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