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