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-2024 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#include <config.h>
22
23#include <netedit/GNENet.h>
24#include <netedit/GNEUndoList.h>
25#include <netedit/GNEViewNet.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//#define DEBUG_SMOOTH_GEOM
58//#define DEBUGCOND(obj) (true)
59#define VEHICLE_GAP 1
60#define ENDPOINT_TOLERANCE 2
61
62// ===========================================================================
63// static
64// ===========================================================================
67
68// ===========================================================================
69// members methods
70// ===========================================================================
71
72GNEEdge::GNEEdge(GNENet* net, NBEdge* nbe, bool wasSplit, bool loaded):
73 GNENetworkElement(net, nbe->getID(), GLO_EDGE, SUMO_TAG_EDGE, GUIIconSubSys::getIcon(GUIIcon::EDGE), {
76},
77{}, {}, {}, {}, {}),
78myNBEdge(nbe),
79myLanes(0),
80myAmResponsible(false),
81myWasSplit(wasSplit),
82myConnectionStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED),
83myUpdateGeometry(true) {
84 // Create lanes
85 int numLanes = myNBEdge->getNumLanes();
86 myLanes.reserve(numLanes);
87 for (int i = 0; i < numLanes; i++) {
88 myLanes.push_back(new GNELane(this, i));
89 myLanes.back()->incRef("GNEEdge::GNEEdge");
90 }
91 // update Lane geometries
92 for (const auto& lane : myLanes) {
93 lane->updateGeometry();
94 }
95 // update centering boundary without updating grid
96 updateCenteringBoundary(false);
97}
98
99
101 // Delete references to this edge in lanes
102 for (const auto& lane : myLanes) {
103 lane->decRef("GNEEdge::~GNEEdge");
104 if (lane->unreferenced()) {
105 // check if remove it from Attribute Carriers
106 if (myNet->getAttributeCarriers()->getLanes().count(lane) > 0) {
108 }
109 // show extra information for tests
110 WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in GNEEdge destructor");
111 delete lane;
112 }
113 }
114 // delete references to this edge in connections
115 for (const auto& connection : myGNEConnections) {
116 connection->decRef("GNEEdge::~GNEEdge");
117 if (connection->unreferenced()) {
118 // check if remove it from Attribute Carriers
119 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
121 }
122 // show extra information for tests
123 WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in GNEEdge destructor");
124 delete connection;
125 }
126 }
127 if (myAmResponsible) {
128 delete myNBEdge;
129 }
130}
131
132
133bool
135 if (getFromJunction()->getNBNode()->getPosition() != getToJunction()->getNBNode()->getPosition()) {
136 return true;
137 } else {
138 return false;
139 }
140}
141
142
143std::string
145 return TLF("Parent junctions are in the same position: %, %",
146 toString(getFromJunction()->getNBNode()->getPosition().x()),
147 toString(getFromJunction()->getNBNode()->getPosition().y()));
148}
149
150
151void
153 // first check if myUpdateGeometry flag is enabled
154 if (myUpdateGeometry) {
155 // Update geometry of lanes
156 for (const auto& lane : myLanes) {
157 lane->updateGeometry();
158 }
159 // Update geometry of connections
160 for (const auto& connection : myGNEConnections) {
161 connection->updateGeometry();
162 }
163 // Update geometry of additionals children vinculated to this edge
164 for (const auto& childAdditional : getChildAdditionals()) {
165 childAdditional->updateGeometry();
166 }
167 // Update geometry of additionals demand elements vinculated to this edge
168 for (const auto& childDemandElement : getChildDemandElements()) {
169 childDemandElement->updateGeometry();
170 }
171 // Update geometry of additionals generic datas vinculated to this edge
172 for (const auto& childGenericData : getChildGenericDatas()) {
173 childGenericData->updateGeometry();
174 }
175 // compute geometry of path elements elements vinculated with this edge (depending of showDemandElements)
177 for (const auto& childAdditional : getChildAdditionals()) {
178 childAdditional->computePathElement();
179 }
180 for (const auto& childDemandElement : getChildDemandElements()) {
181 childDemandElement->computePathElement();
182 }
183 for (const auto& childGenericData : getChildGenericDatas()) {
184 childGenericData->computePathElement();
185 }
186 }
187 }
188 // update vehicle geometry
190 // update stack labels
194}
195
196
199 return myLanes.front()->getPositionInView();
200}
201
202
203bool
205 // get modes and viewParent (for code legibility)
206 const auto& modes = myNet->getViewNet()->getEditModes();
207 const auto& viewParent = myNet->getViewNet()->getViewParent();
208 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
209 // continue depending of current status
210 if (inspectedElements.isInspectingSingleElement()) {
211 // check if starts in this edge
212 if (inspectedElements.getFirstAC()->getTagProperty().vehicleEdges() &&
213 inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_FROM) &&
214 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_FROM) == getID())) {
215 return true;
216 }
217 } else if (modes.isCurrentSupermodeDemand()) {
218 // get current GNEPlanCreator
219 GNEPlanCreator* planCreator = nullptr;
220 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
221 planCreator = viewParent->getPersonFrame()->getPlanCreator();
222 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
223 planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
224 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
225 planCreator = viewParent->getContainerFrame()->getPlanCreator();
226 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
227 planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
228 }
229 // continue depending of planCreator
230 if (planCreator) {
231 if (planCreator->getPlanParameteres().fromEdge == getID()) {
232 return true;
233 }
234 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
235 const auto& selectedEdges = viewParent->getVehicleFrame()->getPathCreator()->getSelectedEdges();
236 // check if this is the first selected edge
237 if ((selectedEdges.size() > 0) && (selectedEdges.front() == this)) {
238 return true;
239 }
240 }
241 } else if (modes.isCurrentSupermodeData()) {
242 // get TAZRelDataFrame
243 const auto& edgeRelDataFrame = viewParent->getEdgeRelDataFrame();
244 if (edgeRelDataFrame->shown()) {
245 // check first Edge
246 if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().empty()) {
247 return false;
248 } else {
249 return edgeRelDataFrame->getPathCreator()->getSelectedEdges().front() == this;
250 }
251 }
252 }
253 // nothing to draw
254 return false;
255}
256
257
258bool
260 // get modes and viewParent (for code legibility)
261 const auto& modes = myNet->getViewNet()->getEditModes();
262 const auto& viewParent = myNet->getViewNet()->getViewParent();
263 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
264 // continue depending of current status
265 if (inspectedElements.isInspectingSingleElement()) {
266 // check if starts in this edge
267 if (inspectedElements.getFirstAC()->getTagProperty().vehicleEdges() &&
268 inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_TO) &&
269 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_TO) == getID())) {
270 return true;
271 }
272 } else if (modes.isCurrentSupermodeDemand()) {
273 // get current GNEPlanCreator
274 GNEPlanCreator* planCreator = nullptr;
275 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
276 planCreator = viewParent->getPersonFrame()->getPlanCreator();
277 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
278 planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
279 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
280 planCreator = viewParent->getContainerFrame()->getPlanCreator();
281 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
282 planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
283 }
284 // continue depending of planCreator
285 if (planCreator) {
286 if (planCreator->getPlanParameteres().toEdge == getID()) {
287 return true;
288 }
289 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
290 const auto& selectedEdges = viewParent->getVehicleFrame()->getPathCreator()->getSelectedEdges();
291 // check if this is the last selected edge
292 if ((selectedEdges.size() > 1) && (selectedEdges.back() == this)) {
293 return true;
294 }
295 }
296 } else if (modes.isCurrentSupermodeData()) {
297 // get TAZRelDataFrame
298 const auto& edgeRelDataFrame = viewParent->getEdgeRelDataFrame();
299 if (edgeRelDataFrame->shown()) {
300 // check last Edge
301 if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().empty()) {
302 return false;
303 } else {
304 return edgeRelDataFrame->getPathCreator()->getSelectedEdges().back() == this;
305 }
306 }
307 }
308 // nothing to draw
309 return false;
310}
311
312
313bool
315 return false;
316}
317
318
319bool
321 const auto& viewObjectsSelector = myNet->getViewNet()->getViewObjectsSelector();
322 // first check if this is the edge under cursor
323 if (viewObjectsSelector.getEdgeFront() != this) {
324 return false;
325 } else {
326 // get modes and viewParent (for code legibility)
327 const auto& modes = myNet->getViewNet()->getEditModes();
328 const auto& viewParent = myNet->getViewNet()->getViewParent();
329 if (modes.isCurrentSupermodeDemand()) {
330 // get current plan selector
331 GNEPlanSelector* planSelector = nullptr;
332 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
333 planSelector = viewParent->getPersonFrame()->getPlanSelector();
334 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
335 planSelector = viewParent->getPersonPlanFrame()->getPlanSelector();
336 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
337 planSelector = viewParent->getContainerFrame()->getPlanSelector();
338 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
339 planSelector = viewParent->getContainerPlanFrame()->getPlanSelector();
340 }
341 // continue depending of plan selector
342 if (planSelector && planSelector->markEdges()) {
343 return (viewObjectsSelector.getAttributeCarrierFront()->getTagProperty().getTag() == SUMO_TAG_LANE);
344 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
345 // get current vehicle template
346 const auto& vehicleTemplate = viewParent->getVehicleFrame()->getVehicleTagSelector()->getCurrentTemplateAC();
347 // check if vehicle can be placed over from-to TAZs
348 if (vehicleTemplate && vehicleTemplate->getTagProperty().vehicleEdges()) {
349 return (viewObjectsSelector.getAttributeCarrierFront()->getTagProperty().getTag() == SUMO_TAG_LANE);
350 }
351 }
352 } else if (modes.isCurrentSupermodeData()) {
353 // get frames
354 const auto& edgeDataFrame = viewParent->getEdgeDataFrame();
355 const auto& edgeRelDataFrame = viewParent->getEdgeRelDataFrame();
356 if (edgeDataFrame->shown()) {
357 return true;
358 } else if (edgeRelDataFrame->shown()) {
359 // check edges
360 if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().empty()) {
361 return true;
362 } else if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().size() == 2) {
363 return false;
364 } else if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().front() == this) {
365 return false;
366 } else if (edgeRelDataFrame->getPathCreator()->getSelectedEdges().back() == this) {
367 return false;
368 } else {
369 return true;
370 }
371 }
372 }
373 // nothing to draw
374 return false;
375 }
376}
377
378
379bool
381 // first check if we're selecting edges or lanes
383 // get edit modes
384 const auto& editModes = myNet->getViewNet()->getEditModes();
385 // check if we're in delete mode
386 if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE)) {
387 // check lanes
388 for (const auto& lane : myLanes) {
391 return true;
392 }
393 }
394 // check edge
397 return true;
398 }
399 // nothing to draw
400 return false;
401 } else {
402 return false;
403 }
404 } else {
405 return false;
406 }
407}
408
409
410bool
412 // first check if we're selecting edges or lanes
414 // get edit modes
415 const auto& editModes = myNet->getViewNet()->getEditModes();
416 // check if we're in select mode
417 if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_SELECT)) {
418 // check lanes
419 for (const auto& lane : myLanes) {
422 return true;
423 }
424 }
425 // check edge
428 return true;
429 }
430 // nothing to draw
431 return false;
432 } else {
433 return false;
434 }
435 } else {
436 return false;
437 }
438}
439
440
441bool
443 // get edit modes
444 const auto& editModes = myNet->getViewNet()->getEditModes();
445 // check if we're in move mode
446 if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&
447 (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE)) {
448 // check if we're editing this network element
450 if (editedNetworkElement) {
451 if (editedNetworkElement == this) {
452 return true;
453 } else {
454 // check lanes
455 for (const auto& lane : myLanes) {
456 if (editedNetworkElement == lane) {
457 return true;
458 }
459 }
460 }
461 } else {
462 // check lanes
463 for (const auto& lane : myLanes) {
466 return true;
467 }
468 }
469 // check edge
472 return true;
473 }
474 }
475 // nothing to draw
476 return false;
477 } else {
478 return false;
479 }
480}
481
482
485 // get geometry point radius
486 const double geometryPointRadius = getGeometryPointRadius();
487 // check if edge is selected
489 // check if both junctions are selected
498 // special case: when only a single edge is selected, move all shape points (including custom end points)
500 } else {
501 // synchronized movement of a single point
502 return processNoneJunctionSelected(geometryPointRadius);
503 }
504 } else {
505 // calculate move shape operation (because there are only an edge selected)
506 return calculateMoveShapeOperation(this, myNBEdge->getGeometry(), false);
507 }
508 } else {
509 // calculate move shape operation
510 return calculateMoveShapeOperation(this, myNBEdge->getGeometry(), false);
511 }
512}
513
514
515void
516GNEEdge::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
517 // get geometry point radius
518 const double geometryPointRadius = getGeometryPointRadius();
519 // declare shape to move
521 // obtain flags for start and end positions
522 const bool customStartPosition = (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE);
523 const bool customEndPosition = (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE);
524 // get variable for last index
525 const int lastIndex = (int)myNBEdge->getGeometry().size() - 1;
526 // flag to enable/disable remove geometry point
527 bool removeGeometryPoint = true;
528 // obtain index
529 const int index = myNBEdge->getGeometry().indexOfClosest(clickedPosition, true);
530 // check index
531 if (index == -1) {
532 removeGeometryPoint = false;
533 }
534 // check distance
535 if (shape[index].distanceSquaredTo2D(clickedPosition) > (geometryPointRadius * geometryPointRadius)) {
536 removeGeometryPoint = false;
537 }
538 // check custom start position
539 if (!customStartPosition && (index == 0)) {
540 removeGeometryPoint = false;
541 }
542 // check custom end position
543 if (!customEndPosition && (index == lastIndex)) {
544 removeGeometryPoint = false;
545 }
546 // check if we can remove geometry point
548 // check if we're removing first geometry proint
549 if (index == 0) {
550 // commit new geometry start
551 undoList->begin(this, "remove first geometry point of " + getTagStr());
553 undoList->end();
554 } else if (index == lastIndex) {
555 // commit new geometry end
556 undoList->begin(this, "remove last geometry point of " + getTagStr());
558 undoList->end();
559 } else {
560 // remove geometry point
561 shape.erase(shape.begin() + index);
562 // get innen shape
563 shape.pop_front();
564 shape.pop_back();
565 // remove double points
566 shape.removeDoublePoints((geometryPointRadius * geometryPointRadius));
567 // commit new shape
568 undoList->begin(this, "remove geometry point of " + getTagStr());
570 undoList->end();
571 }
572 }
573}
574
575
576bool
578 if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
579 return true;
580 } else if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
581 return true;
582 } else {
583 return false;
584 }
585}
586
587
588bool
590 // get geometry point radius
591 const double geometryPointRadius = getGeometryPointRadius();
592 if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
593 return (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius));
594 } else {
595 return false;
596 }
597}
598
599
600bool
602 // get geometry point radius
603 const double geometryPointRadius = getGeometryPointRadius();
604 if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
605 return (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius));
606 } else {
607 return false;
608 }
609}
610
611
612bool
614 // get geometry point radius
615 const auto geometryPointRadius = getGeometryPointRadius();
616 // first check inner geometry
617 const PositionVector innenShape = myNBEdge->getInnerGeometry();
618 // iterate over geometry point
619 for (const auto& geometryPoint : innenShape) {
620 if (geometryPoint.distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius)) {
621 return true;
622 }
623 }
624 // check start and end shapes
626 return true;
627 } else {
628 return false;
629 }
630}
631
632
633void
635 Position delta = junction->getNBNode()->getPosition() - origPos;
637 // geometry endpoint need not equal junction position hence we modify it with delta
638 if (junction == getFromJunction()) {
639 geom[0].add(delta);
640 } else {
641 geom[-1].add(delta);
642 }
643 setGeometry(geom, false);
644}
645
646
647double
649 return s.addSize.getExaggeration(s, this);
650}
651
652
657
658
659void
660GNEEdge::updateCenteringBoundary(const bool updateGrid) {
661 // Remove object from net
662 if (updateGrid) {
664 }
665 // first add edge boundary
667 // add lane boundaries
668 for (const auto& lane : myLanes) {
669 const auto laneBoundary = lane->getCenteringBoundary();
670 if (laneBoundary.isInitialised()) {
671 myEdgeBoundary.add(laneBoundary);
672 // add additional and demand boundaries
673 for (const auto& additional : lane->getChildAdditionals()) {
674 const auto additionalBoundary = additional->getCenteringBoundary();
675 if (additionalBoundary.isInitialised()) {
676 myEdgeBoundary.add(additional->getCenteringBoundary());
677 }
678 }
679 }
680 }
681 // add additional and demand boundaries
682 for (const auto& additional : getChildAdditionals()) {
683 const auto additionalBoundary = additional->getCenteringBoundary();
684 if (additionalBoundary.isInitialised()) {
685 myEdgeBoundary.add(additionalBoundary);
686 }
687 }
688 // add junction positions
691 // grow boundary
693 // add object into net
694 if (updateGrid) {
696 }
697}
698
699
700const std::string
702 return myNBEdge->getStreetName();
703}
704
705
708 // if we call this function, that's mean that we're clicked over a edge geometry point, then
709 // open the popup dialog of the lane[0] (back)
710 return myLanes.back()->getPopUpMenu(app, parent);
711}
712
713
714std::vector<GNEEdge*>
718
719
720void
722 // check drawing boundary selection and size boundary
724 // draw boundary
726 // get detail level from the first lane
727 const auto d = myLanes.front()->getDrawingConstants()->getDetail();
728 // calculate layer
729 double layer = GLO_EDGE;
730 if (myDrawInFront) {
731 layer = GLO_FRONTELEMENT;
732 } else if (myLanes.front()->getLaneShape().length2D() <= (s.neteditSizeSettings.junctionBubbleRadius * 2)) {
733 layer = GLO_JUNCTION + 1.8;
734 }
735 // check if draw details
737 // draw geometry points
738 drawEdgeGeometryPoints(s, d, layer);
739 // draw edge shape (a red line only visible if lane shape is strange)
740 drawEdgeShape(s, d, layer);
741 // draw edge stopOffset
742 drawLaneStopOffset(s, d, layer);
743 // draw edge name
744 drawEdgeName(s);
745 // draw lock icon
747 // draw dotted contour
749 }
750 // calculate edge contour (always before children)
751 calculateEdgeContour(s, d, layer);
752 // draw lanes
753 for (const auto& lane : myLanes) {
754 lane->drawGL(s);
755 }
756 // draw junctions
758 getToJunction()->drawGL(s);
759 // draw childrens
760 drawChildrens(s);
761 }
762}
763
764
765void
767 // Check if edge can be deleted
769 myNet->deleteEdge(this, myNet->getViewNet()->getUndoList(), false);
770 }
771}
772
773
774void
778
779
780NBEdge*
782 return myNBEdge;
783}
784
785
788 // get geometry point radius
789 const double geometryPointRadius = getGeometryPointRadius();
790 const PositionVector& geom = myNBEdge->getGeometry();
791 int index = geom.indexOfClosest(clickPos, true);
792 if (geom[index].distanceSquaredTo2D(clickPos) < (geometryPointRadius * geometryPointRadius)) {
793 // split at existing geometry point
794 return myNet->getViewNet()->snapToActiveGrid(geom[index]);
795 } else {
796 // split straight between the next two points
798 }
799}
800
801
802void
804 // get geometry point radius
805 const double geometryPointRadius = getGeometryPointRadius();
806 if ((myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
807 (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius))) {
808 undoList->begin(this, "remove endpoint");
809 setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
810 undoList->end();
811 } else if ((myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
812 (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius))) {
813 undoList->begin(this, "remove endpoint");
814 setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
815 undoList->end();
816 } else {
817 // we need to create new Start/End position over Edge shape, not over clicked position
819 if (offset != GeomHelper::INVALID_OFFSET) {
821 // calculate position over edge shape relative to clicked position
822 Position newPos = geom.positionAtOffset2D(offset);
823 // snap new position to grid
824 newPos = myNet->getViewNet()->snapToActiveGrid(newPos);
825 undoList->begin(this, "set endpoint");
826 const int index = geom.indexOfClosest(pos, true);
827 const Position destPos = getToJunction()->getNBNode()->getPosition();
828 const Position sourcePos = getFromJunction()->getNBNode()->getPosition();
829 if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
830 // check if snap to existing geometrypoint
831 if (geom[index].distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius)) {
832 newPos = geom[index];
833 // remove existent geometry point to avoid double points
834 removeGeometryPoint(newPos, undoList);
835 }
836 setAttribute(GNE_ATTR_SHAPE_END, toString(newPos), undoList);
838 } else {
839 // check if snap to existing geometry point
840 if (geom[index].distanceSquaredTo2D(pos) < (geometryPointRadius * geometryPointRadius)) {
841 newPos = geom[index];
842 // remove existent geometry point to avoid double points
843 removeGeometryPoint(newPos, undoList);
844 }
845 setAttribute(GNE_ATTR_SHAPE_START, toString(newPos), undoList);
847 }
848 undoList->end();
849 }
850 }
851}
852
853
854void
857 Position sourcePos = getFromJunction()->getNBNode()->getPosition();
858 if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
859 setAttribute(GNE_ATTR_SHAPE_END, toString(destPos), undoList);
861 } else {
862 setAttribute(GNE_ATTR_SHAPE_START, toString(sourcePos), undoList);
864 }
865}
866
867
868void
870 // reset shape start
871 setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
873 // reset shape end
874 setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
876}
877
878void
880 // set new geometry
881 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
882 if (lefthand) {
883 geom.mirrorX();
884 myNBEdge->mirrorX();
885 }
886 myNBEdge->setGeometry(geom, inner);
887 if (lefthand) {
888 myNBEdge->mirrorX();
889 }
890 // update geometry
892 // invalidate junction source shape
894 // iterate over first parent junction edges and update geometry
895 for (const auto& edge : getFromJunction()->getGNEIncomingEdges()) {
896 edge->updateGeometry();
897 }
898 for (const auto& edge : getFromJunction()->getGNEOutgoingEdges()) {
899 edge->updateGeometry();
900 }
901 // invalidate junction destination shape
903 // iterate over second parent junction edges and update geometry
904 for (const auto& edge : getToJunction()->getGNEIncomingEdges()) {
905 edge->updateGeometry();
906 }
907 for (const auto& edge : getToJunction()->getGNEOutgoingEdges()) {
908 edge->updateGeometry();
909 }
910}
911
912
913const Position
915 PositionVector laneShape = myLanes.front()->getLaneShape();
916 laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
917 return laneShape.front();
918}
919
920
921const Position
923 PositionVector laneShape = myLanes.back()->getLaneShape();
924 laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
925 return laneShape.front();
926}
927
928
929const Position
931 PositionVector laneShape = myLanes.front()->getLaneShape();
932 laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
933 return laneShape.back();
934}
935
936
937const Position
939 PositionVector laneShape = myLanes.back()->getLaneShape();
940 laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
941 return laneShape.back();
942}
943
944void
945GNEEdge::remakeGNEConnections(bool junctionsReady) {
946 // create new and removed unused GNEConnections
947 const std::vector<NBEdge::Connection>& connections = myNBEdge->getConnections();
948 // create a vector to keep retrieved and created connections
949 std::vector<GNEConnection*> retrievedConnections;
950 // iterate over NBEdge::Connections of GNEEdge
951 for (const auto& connection : connections) {
952 // retrieve existent GNEConnection, or create it
953 GNEConnection* retrievedGNEConnection = retrieveGNEConnection(connection.fromLane, connection.toEdge, connection.toLane);
954 if (junctionsReady) {
955 retrievedGNEConnection->updateLinkState();
956 }
957 retrievedConnections.push_back(retrievedGNEConnection);
958 // check if previously this GNEConnections exists, and if true, remove it from myGNEConnections
959 std::vector<GNEConnection*>::iterator retrievedExists = std::find(myGNEConnections.begin(), myGNEConnections.end(), retrievedGNEConnection);
960 if (retrievedExists != myGNEConnections.end()) {
961 myGNEConnections.erase(retrievedExists);
962 } else {
963 // include reference to created GNEConnection
964 retrievedGNEConnection->incRef("GNEEdge::remakeGNEConnections");
965 }
966 // mark it as deprecated
967 retrievedGNEConnection->markConnectionGeometryDeprecated();
968 }
969 // delete non retrieved GNEConnections
970 for (const auto& connection : myGNEConnections) {
971 // decrease reference
972 connection->decRef();
973 // remove it from network
974 myNet->removeGLObjectFromGrid(connection);
975 // and from AttributeCarriers
976 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
978 }
979 // delete GNEConnection if is unreferenced
980 if (connection->unreferenced()) {
981
982 // show extra information for tests
983 WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in rebuildGNEConnections()");
984 delete connection;
985 }
986 }
987 // copy retrieved (existent and created) GNECrossings to myGNEConnections
988 myGNEConnections = retrievedConnections;
989}
990
991
992void
994 // Drop all existents connections that aren't referenced anymore
995 for (const auto& connection : myGNEConnections) {
996 // check if connection is selected
997 if (connection->isAttributeCarrierSelected()) {
998 connection->unselectAttributeCarrier();
999 }
1000 // Dec reference of connection
1001 connection->decRef("GNEEdge::clearGNEConnections");
1002 // remove it from network
1003 myNet->removeGLObjectFromGrid(connection);
1004 // and from AttributeCarriers
1005 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
1007 }
1008 // Delete GNEConnectionToErase if is unreferenced
1009 if (connection->unreferenced()) {
1010 // show extra information for tests
1011 WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in clearGNEConnections()");
1012 delete connection;
1013 }
1014 }
1015 myGNEConnections.clear();
1016}
1017
1018
1019int
1021 std::vector<GNEAdditional*> routeProbes;
1022 for (auto i : getChildAdditionals()) {
1023 if (i->getTagProperty().getTag() == routeProbe->getTagProperty().getTag()) {
1024 routeProbes.push_back(i);
1025 }
1026 }
1027 // return index of routeProbe in routeProbes vector
1028 auto it = std::find(routeProbes.begin(), routeProbes.end(), routeProbe);
1029 if (it == routeProbes.end()) {
1030 return -1;
1031 } else {
1032 return (int)(it - routeProbes.begin());
1033 }
1034}
1035
1036
1037std::vector<GNECrossing*>
1039 std::vector<GNECrossing*> crossings;
1040 for (auto i : getFromJunction()->getGNECrossings()) {
1041 if (i->checkEdgeBelong(this)) {
1042 crossings.push_back(i);
1043 }
1044 }
1045 for (auto i : getToJunction()->getGNECrossings()) {
1046 if (i->checkEdgeBelong(this)) {
1047 crossings.push_back(i);
1048 }
1049 }
1050 return crossings;
1051}
1052
1053
1054void
1055GNEEdge::copyTemplate(const GNEEdgeTemplate* edgeTemplate, GNEUndoList* undoList) {
1056 // copy edge-specific attributes
1057 for (const auto& attProperty : myTagProperty) {
1058 if (attProperty.isCopyable() && isValid(attProperty.getAttr(), edgeTemplate->getAttribute(attProperty.getAttr()))) {
1059 setAttribute(attProperty.getAttr(), edgeTemplate->getAttribute(attProperty.getAttr()), undoList);
1060 }
1061 }
1062 // also copy parameters
1064 // copy lane attributes as well
1065 for (int i = 0; i < (int)myLanes.size(); i++) {
1066 for (const auto& attProperty : edgeTemplate->getLaneTemplates().at(i)->getTagProperty()) {
1067 if (attProperty.isCopyable() && myLanes[i]->isValid(attProperty.getAttr(), edgeTemplate->getLaneTemplates().at(i)->getAttribute(attProperty.getAttr()))) {
1068 myLanes[i]->setAttribute(attProperty.getAttr(), edgeTemplate->getLaneTemplates().at(i)->getAttribute(attProperty.getAttr()), undoList);
1069 }
1070 }
1071 // also copy parameters
1072 myLanes[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeTemplate->getLaneTemplates().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
1073 }
1074}
1075
1076
1077void
1078GNEEdge::copyEdgeType(const GNEEdgeType* edgeType, GNEUndoList* undoList) {
1079 // get tag properties
1080 const auto& edgeProperties = getTagProperty(SUMO_TAG_EDGE);
1081 const auto& laneProperties = getTagProperty(SUMO_TAG_LANE);
1082 const auto& edgeTypeProperties = getTagProperty(SUMO_TAG_TYPE);
1083 const auto& laneTypeProperties = getTagProperty(SUMO_TAG_LANETYPE);
1084 // set type (only for info)
1086 // copy attributes
1087 for (const auto& attrProperty : edgeTypeProperties) {
1088 if (attrProperty.isCopyable() && edgeProperties.hasAttribute(attrProperty.getAttr())) {
1089 setAttribute(attrProperty.getAttr(), edgeType->getAttribute(attrProperty.getAttr()), undoList);
1090 }
1091 }
1093 // copy lane attributes as well
1094 for (int i = 0; i < (int)myLanes.size(); i++) {
1095 for (const auto& attrProperty : laneTypeProperties) {
1096 if (attrProperty.isCopyable() && laneProperties.hasAttribute(attrProperty.getAttr()) && (edgeType->getLaneTypes().at(i)->getAttribute(attrProperty.getAttr()) != laneTypeProperties.getAttributeProperties(attrProperty.getAttr()).getDefaultValue())) {
1097 myLanes[i]->setAttribute(attrProperty.getAttr(), edgeType->getLaneTypes().at(i)->getAttribute(attrProperty.getAttr()), undoList);
1098 }
1099 }
1100 if (edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS).size() > 0) {
1101 myLanes[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
1102 }
1103 }
1104}
1105
1106
1107std::set<GUIGlID>
1109 std::set<GUIGlID> result;
1110 for (auto i : myLanes) {
1111 result.insert(i->getGlID());
1112 }
1113 return result;
1114}
1115
1116
1117const std::vector<GNELane*>&
1119 return myLanes;
1120}
1121
1122
1123const std::vector<GNEConnection*>&
1127
1128
1129bool
1131 return myWasSplit;
1132}
1133
1134
1135std::string
1137 switch (key) {
1138 case SUMO_ATTR_ID:
1139 return getMicrosimID();
1140 case SUMO_ATTR_FROM:
1142 return getFromJunction()->getID();
1143 case SUMO_ATTR_TO:
1145 return getToJunction()->getID();
1146 case SUMO_ATTR_NUMLANES:
1147 return toString(myNBEdge->getNumLanes());
1148 case SUMO_ATTR_PRIORITY:
1149 return toString(myNBEdge->getPriority());
1150 case SUMO_ATTR_LENGTH:
1151 return toString(myNBEdge->getFinalLength());
1152 case SUMO_ATTR_TYPE:
1153 return myNBEdge->getTypeID();
1154 case SUMO_ATTR_SHAPE:
1158 case SUMO_ATTR_NAME:
1159 return myNBEdge->getStreetName();
1160 case SUMO_ATTR_ALLOW:
1161 return (getVehicleClassNames(myNBEdge->getPermissions()) + (myNBEdge->hasLaneSpecificPermissions() ? " (combined!)" : ""));
1162 case SUMO_ATTR_DISALLOW: {
1164 }
1165 case SUMO_ATTR_SPEED:
1167 return "lane specific";
1168 } else {
1169 return toString(myNBEdge->getSpeed());
1170 }
1171 case SUMO_ATTR_FRICTION:
1173 return "lane specific";
1174 } else {
1175 return toString(myNBEdge->getFriction());
1176 }
1177 case SUMO_ATTR_WIDTH:
1179 return "lane specific";
1181 return "default";
1182 } else {
1183 return toString(myNBEdge->getLaneWidth());
1184 }
1187 return "lane specific";
1188 } else {
1189 return toString(myNBEdge->getEndOffset());
1190 }
1191 case SUMO_ATTR_DISTANCE:
1192 return toString(myNBEdge->getDistance());
1194 return myConnectionStatus;
1196 if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
1197 return "";
1198 } else {
1199 return toString(myNBEdge->getGeometry().front());
1200 }
1201 case GNE_ATTR_SHAPE_END:
1202 if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
1203 return "";
1204 } else {
1205 return toString(myNBEdge->getGeometry().back());
1206 }
1207 case GNE_ATTR_BIDIR:
1208 return toString(myNBEdge->getBidiEdge() != nullptr);
1214 } else {
1215 return "";
1216 }
1220 return myNBEdge->getParametersStr();
1221 default:
1222 return getCommonAttribute(key);
1223 }
1224}
1225
1226
1229 switch (key) {
1230 case SUMO_ATTR_SHAPE:
1231 return myNBEdge->getInnerGeometry();
1232 default:
1233 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1234 }
1235}
1236
1237
1238std::string
1240 std::string result = getAttribute(key);
1241 if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
1242 result += " " + getVehicleClassNames(SVCAll, true);
1243 }
1244 return result;
1245}
1246
1247
1248void
1249GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1250 // get template editor
1252 // check if we have to update template
1253 const bool updateTemplate = templateEditor->getEdgeTemplate() ? (templateEditor->getEdgeTemplate()->getID() == getID()) : false;
1254 switch (key) {
1255 case SUMO_ATTR_WIDTH:
1257 case SUMO_ATTR_SPEED:
1258 case SUMO_ATTR_FRICTION:
1259 case SUMO_ATTR_ALLOW:
1260 case SUMO_ATTR_DISALLOW: {
1261 undoList->begin(this, "change " + getTagStr() + " attribute");
1262 const std::string origValue = myLanes.at(0)->getAttribute(key); // will have intermediate value of "lane specific"
1263 // lane specific attributes need to be changed via lanes to allow undo
1264 for (auto it : myLanes) {
1265 it->setAttribute(key, value, undoList);
1266 }
1267 // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
1268 GNEChange_Attribute::changeAttribute(this, key, value, origValue, undoList);
1269 undoList->end();
1270 break;
1271 }
1272 case SUMO_ATTR_FROM: {
1273 if (value != getAttribute(key)) {
1274 undoList->begin(this, "change " + getTagStr() + " attribute");
1275 // Remove edge from crossings of junction source
1277 // continue changing from junction
1278 GNEJunction* originalFirstParentJunction = getFromJunction();
1279 getFromJunction()->setLogicValid(false, undoList);
1280 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1281 getFromJunction()->setLogicValid(false, undoList);
1282 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1283 setAttribute(GNE_ATTR_SHAPE_START, toString(getFromJunction()->getNBNode()->getPosition()), undoList);
1285 undoList->end();
1286 // update geometries of all implicated junctions
1287 originalFirstParentJunction->updateGeometry();
1290 }
1291 break;
1292 }
1293 case SUMO_ATTR_TO: {
1294 if (value != getAttribute(key)) {
1295 undoList->begin(this, "change " + getTagStr() + " attribute");
1296 // Remove edge from crossings of junction destination
1298 // continue changing destination junction
1299 GNEJunction* originalSecondParentJunction = getToJunction();
1300 getToJunction()->setLogicValid(false, undoList);
1301 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1302 getToJunction()->setLogicValid(false, undoList);
1303 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1304 setAttribute(GNE_ATTR_SHAPE_END, toString(getToJunction()->getNBNode()->getPosition()), undoList);
1306 undoList->end();
1307 // update geometries of all implicated junctions
1308 originalSecondParentJunction->updateGeometry();
1311 }
1312 break;
1313 }
1314 case SUMO_ATTR_ID:
1315 case SUMO_ATTR_PRIORITY:
1316 case SUMO_ATTR_LENGTH:
1317 case SUMO_ATTR_TYPE:
1319 case SUMO_ATTR_DISTANCE:
1323 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1324 break;
1326 // special case for stop offset, because affects to stopOffsetExceptions (#15297)
1327 if (canParse<double>(value) && (parse<double>(value) == 0)) {
1329 }
1330 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1331 break;
1333 case GNE_ATTR_SHAPE_END: {
1334 // due to ENDPOINT_TOLERANCE, force change
1335 GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1336 break;
1337 }
1338 case SUMO_ATTR_NAME:
1339 // user cares about street names. Make sure they appear in the output
1341 OptionsCont::getOptions().set("output.street-names", "true");
1342 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1343 break;
1344 case SUMO_ATTR_NUMLANES:
1345 if (value != getAttribute(key)) {
1346 // set num lanes
1347 setNumLanes(parse<int>(value), undoList);
1348 }
1349 break;
1350 case GNE_ATTR_BIDIR:
1351 undoList->begin(this, "change " + getTagStr() + " attribute");
1352 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1353 if (myNBEdge->getTurnDestination(true) != nullptr) {
1355 GNEChange_Attribute::changeAttribute(bidi, key, value, undoList);
1356 if (myNBEdge->getGeometry() != bidi->getNBEdge()->getGeometry().reverse()
1357 && myNBEdge->getGeometry().size() == 2
1358 && bidi->getNBEdge()->getGeometry().size() == 2
1359 && myNBEdge->getBidiEdge() == nullptr) {
1360 // NBEdge::avoidOverlap was already active so we need to reset the
1361 // geometry to its default
1362 resetBothEndpoint(undoList);
1363 bidi->resetBothEndpoint(undoList);
1364 }
1365 }
1366 undoList->end();
1367 break;
1368 case SUMO_ATTR_SHAPE:
1369 // @note: assumes value of inner geometry!
1370 // actually the geometry is already updated (incrementally
1371 // during mouse movement). We set the restore point to the end
1372 // of the last change-set
1373 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1374 break;
1375 default:
1376 setCommonAttribute(key, value, undoList);
1377 break;
1378 }
1379 // update template
1380 if (updateTemplate) {
1381 templateEditor->setEdgeTemplate(this);
1382 }
1383}
1384
1385
1386bool
1387GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
1388 switch (key) {
1389 case SUMO_ATTR_ID:
1390 return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveEdge(value, false) == nullptr);
1391 case SUMO_ATTR_FROM: {
1392 // check that is a valid ID and is different of ID of junction destination
1393 if (value == getFromJunction()->getID()) {
1394 return true;
1395 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getToJunction()->getID())) {
1396 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1397 } else {
1398 return false;
1399 }
1400 }
1401 case SUMO_ATTR_TO: {
1402 // check that is a valid ID and is different of ID of junction Source
1403 if (value == getToJunction()->getID()) {
1404 return true;
1405 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getFromJunction()->getID())) {
1406 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1407 } else {
1408 return false;
1409 }
1410 }
1411 case SUMO_ATTR_SPEED:
1412 return canParse<double>(value) && (parse<double>(value) > 0);
1413 case SUMO_ATTR_FRICTION:
1414 return canParse<double>(value) && (parse<double>(value) > 0);
1415 case SUMO_ATTR_NUMLANES:
1416 return canParse<int>(value) && (parse<double>(value) > 0);
1417 case SUMO_ATTR_PRIORITY:
1418 return canParse<int>(value);
1419 case SUMO_ATTR_LENGTH:
1420 if (value.empty()) {
1421 return true;
1422 } else {
1423 return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
1424 }
1425 case SUMO_ATTR_ALLOW:
1426 case SUMO_ATTR_DISALLOW:
1427 return canParseVehicleClasses(value);
1428 case SUMO_ATTR_TYPE:
1429 return true;
1430 case SUMO_ATTR_SHAPE:
1431 // empty shapes are allowed
1432 return canParse<PositionVector>(value);
1435 case SUMO_ATTR_NAME:
1436 return true;
1437 case SUMO_ATTR_WIDTH:
1438 if (value.empty() || (value == "default")) {
1439 return true;
1440 } else {
1441 return canParse<double>(value) && ((parse<double>(value) >= -1) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
1442 }
1444 return canParse<double>(value) && parse<double>(value) >= 0 && parse<double>(value) < myNBEdge->getLoadedLength();
1445 case SUMO_ATTR_DISTANCE:
1446 if (value.empty()) {
1447 return true;
1448 } else {
1449 return canParse<double>(value);
1450 }
1451 case GNE_ATTR_SHAPE_START: {
1452 if (value.empty()) {
1453 return true;
1454 } else if (canParse<Position>(value)) {
1455 Position shapeStart = parse<Position>(value);
1456 return (shapeStart != myNBEdge->getGeometry()[-1]);
1457 } else {
1458 return false;
1459 }
1460 }
1461 case GNE_ATTR_SHAPE_END: {
1462 if (value.empty()) {
1463 return true;
1464 } else if (canParse<Position>(value)) {
1465 Position shapeEnd = parse<Position>(value);
1466 return (shapeEnd != myNBEdge->getGeometry()[0]);
1467 } else {
1468 return false;
1469 }
1470 }
1471 case GNE_ATTR_BIDIR:
1472 return canParse<bool>(value) && (!parse<bool>(value) || myNBEdge->isBidiEdge(true));
1474 if (value.empty()) {
1475 return true;
1476 } else {
1477 return canParse<double>(value) && (parse<double>(value) >= 0);
1478 }
1480 return canParseVehicleClasses(value);
1483 default:
1484 return isCommonValid(key, value);
1485 }
1486}
1487
1488
1489bool
1491 switch (key) {
1492 case GNE_ATTR_BIDIR:
1493 return myNBEdge->isBidiEdge(true);
1495 return myNBEdge->myEdgeStopOffset.getOffset() > 0;
1497 return false;
1498 default:
1499 return true;
1500 }
1501}
1502
1503
1504bool
1506 switch (key) {
1507 case SUMO_ATTR_LENGTH:
1508 return !myNBEdge->hasLoadedLength();
1509 case SUMO_ATTR_WIDTH:
1511 return false;
1512 } else {
1514 }
1515 default:
1516 return false;
1517 }
1518}
1519
1520
1521const Parameterised::Map&
1525
1526
1527void
1529 myAmResponsible = newVal;
1530}
1531
1532
1533GNELane*
1535 // iterate over all NBEdge lanes
1536 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1537 // if given VClass is in permissions, return lane
1538 if (myNBEdge->getLanes().at(i).permissions & vClass) {
1539 // return GNELane
1540 return myLanes.at(i);
1541 }
1542 }
1543 // return first lane
1544 return myLanes.front();
1545}
1546
1547
1548GNELane*
1550 // iterate over all NBEdge lanes
1551 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1552 // if given VClass isn't in permissions, return lane
1553 if (~(myNBEdge->getLanes().at(i).permissions) & vClass) {
1554 // return GNELane
1555 return myLanes.at(i);
1556 }
1557 }
1558 // return first lane
1559 return myLanes.front();
1560}
1561
1562
1563void
1565 // get lane vehicles map
1566 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1567 // iterate over every lane
1568 for (const auto& laneVehicle : laneVehiclesMap) {
1569 // obtain total length
1570 double totalLength = 0;
1571 for (const auto& vehicle : laneVehicle.second) {
1572 totalLength += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1573 }
1574 // calculate multiplier for vehicle positions
1575 double multiplier = 1;
1576 const double laneShapeLength = laneVehicle.first->getLaneShape().length();
1577 if (laneShapeLength == 0) {
1578 multiplier = 0;
1579 } else if (totalLength > laneShapeLength) {
1580 multiplier = (laneShapeLength / totalLength);
1581 }
1582 // declare current length
1583 double length = 0;
1584 // iterate over vehicles to calculate position and rotations
1585 for (const auto& vehicle : laneVehicle.second) {
1586 vehicle->updateDemandElementSpreadGeometry(laneVehicle.first, length * multiplier);
1587 // update length
1588 length += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1589 }
1590 }
1591}
1592
1593
1594void
1596 // get lane vehicles map
1597 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1598 // iterate over laneVehiclesMap and obtain a vector with
1599 for (const auto& vehicleMap : laneVehiclesMap) {
1600 // declare map for sort vehicles using their departpos+length position (StackPosition)
1601 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosVehicles;
1602 // declare vector of stack demand elements
1603 std::vector<GNEEdge::StackDemandElements> stackedVehicles;
1604 // iterate over vehicles
1605 for (const auto& vehicle : vehicleMap.second) {
1606 // get vehicle's depart pos and length
1607 const double departPos = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1608 const double length = vehicle->getAttributeDouble(SUMO_ATTR_LENGTH);
1609 double posOverLane = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1610 // check if we have to adapt posOverLane
1611 if (posOverLane < 0) {
1612 posOverLane += vehicleMap.first->getLaneShape().length();
1613 }
1614 // make a stack position using departPos and length
1615 departPosVehicles.push_back(std::make_pair(StackPosition(departPos, length), vehicle));
1616 // update depart element geometry
1617 vehicle->updateDemandElementGeometry(vehicleMap.first, posOverLane);
1618 // reset vehicle stack label
1619 vehicle->updateDemandElementStackLabel(0);
1620 }
1621
1622 // sort departPosVehicles
1623 std::sort(departPosVehicles.begin(), departPosVehicles.end());
1624 // iterate over departPosVehicles
1625 for (const auto& departPosVehicle : departPosVehicles) {
1626 // obtain stack position and vehicle
1627 const GNEEdge::StackPosition& vehicleStackPosition = departPosVehicle.first;
1628 GNEDemandElement* vehicle = departPosVehicle.second;
1629 // if stackedVehicles is empty, add a new StackDemandElements
1630 if (stackedVehicles.empty()) {
1631 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1632 } else if (areStackPositionOverlapped(vehicleStackPosition, stackedVehicles.back().getStackPosition())) {
1633 // add new vehicle to last inserted stackDemandElements
1634 stackedVehicles[stackedVehicles.size() - 1].addDemandElements(vehicle);
1635 } else {
1636 // No overlapping, then add a new StackDemandElements
1637 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1638 }
1639 }
1640 // iterate over stackedVehicles
1641 for (const auto& vehicle : stackedVehicles) {
1642 // only update vehicles with one or more stack
1643 if (vehicle.getDemandElements().size() > 1) {
1644 // set stack labels
1645 vehicle.getDemandElements().front()->updateDemandElementStackLabel((int)vehicle.getDemandElements().size());
1646 }
1647 }
1648 }
1649}
1650
1651
1652void
1654 // get lane persons map
1655 const std::map<const GNELane*, std::vector<GNEDemandElement*> > lanePersonsMap = getPersonsOverEdgeMap();
1656 // iterate over lanePersonsMap and obtain a vector with
1657 for (const auto& personMap : lanePersonsMap) {
1658 // declare map for sort persons using their departpos+length position (StackPosition)
1659 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosPersons;
1660 // declare vector of stack demand elements
1661 std::vector<GNEEdge::StackDemandElements> stackedPersons;
1662 // iterate over persons
1663 for (const auto& person : personMap.second) {
1664 // get person's depart pos and length
1665 const double departPos = person->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1666 // make a stack position using departPos and length
1667 departPosPersons.push_back(std::make_pair(StackPosition(departPos, 1.8), person));
1668 // update depart element geometry
1669 person->updateDemandElementGeometry(personMap.first, departPos);
1670 // reset person stack label
1671 person->updateDemandElementStackLabel(0);
1672 }
1673
1674 // sort departPosPersons
1675 std::sort(departPosPersons.begin(), departPosPersons.end());
1676 // iterate over departPosPersons
1677 for (const auto& departPosPerson : departPosPersons) {
1678 // obtain stack position and person
1679 const GNEEdge::StackPosition& personStackPosition = departPosPerson.first;
1680 GNEDemandElement* person = departPosPerson.second;
1681 // if stackedPersons is empty, add a new StackDemandElements
1682 if (stackedPersons.empty()) {
1683 stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1684 } else if (areStackPositionOverlapped(personStackPosition, stackedPersons.back().getStackPosition())) {
1685 // add new person to last inserted stackDemandElements
1686 stackedPersons[stackedPersons.size() - 1].addDemandElements(person);
1687 } else {
1688 // No overlapping, then add a new StackDemandElements
1689 stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1690 }
1691 }
1692 // iterate over stackedPersons
1693 for (const auto& person : stackedPersons) {
1694 // only update persons with one or more stack
1695 if (person.getDemandElements().size() > 1) {
1696 // set stack labels
1697 person.getDemandElements().front()->updateDemandElementStackLabel((int)person.getDemandElements().size());
1698 }
1699 }
1700 }
1701}
1702
1703
1704void
1706 // get lane containers map
1707 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneContainersMap = getContainersOverEdgeMap();
1708 // iterate over laneContainersMap and obtain a vector with
1709 for (const auto& containerMap : laneContainersMap) {
1710 // declare map for sort containers using their departpos+length position (StackPosition)
1711 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosContainers;
1712 // declare vector of stack demand elements
1713 std::vector<GNEEdge::StackDemandElements> stackedContainers;
1714 // iterate over containers
1715 for (const auto& container : containerMap.second) {
1716 // get container's depart pos and length
1717 const double departPos = container->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1718 // make a stack position using departPos and length
1719 departPosContainers.push_back(std::make_pair(StackPosition(departPos, 1.8), container));
1720 // update depart element geometry
1721 container->updateDemandElementGeometry(containerMap.first, departPos);
1722 // reset container stack label
1723 container->updateDemandElementStackLabel(0);
1724 }
1725
1726 // sort departPosContainers
1727 std::sort(departPosContainers.begin(), departPosContainers.end());
1728 // iterate over departPosContainers
1729 for (const auto& departPosContainer : departPosContainers) {
1730 // obtain stack position and container
1731 const GNEEdge::StackPosition& containerStackPosition = departPosContainer.first;
1732 GNEDemandElement* container = departPosContainer.second;
1733 // if stackedContainers is empty, add a new StackDemandElements
1734 if (stackedContainers.empty()) {
1735 stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1736 } else if (areStackPositionOverlapped(containerStackPosition, stackedContainers.back().getStackPosition())) {
1737 // add new container to last inserted stackDemandElements
1738 stackedContainers[stackedContainers.size() - 1].addDemandElements(container);
1739 } else {
1740 // No overlapping, then add a new StackDemandElements
1741 stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1742 }
1743 }
1744 // iterate over stackedContainers
1745 for (const auto& container : stackedContainers) {
1746 // only update containers with one or more stack
1747 if (container.getDemandElements().size() > 1) {
1748 // set stack labels
1749 container.getDemandElements().front()->updateDemandElementStackLabel((int)container.getDemandElements().size());
1750 }
1751 }
1752 }
1753}
1754
1755
1756bool
1758 // calculate angle between both junction positions
1759 double edgeAngle = RAD2DEG(getFromJunction()->getPositionInView().angleTo2D(getToJunction()->getPositionInView()));
1760 // adjust to 360 degrees
1761 while (edgeAngle < 0) {
1762 edgeAngle += 360;
1763 }
1764 // fmod round towards zero which is not want we want for negative numbers
1765 edgeAngle = fmod(edgeAngle, 360);
1766 // check angle
1767 return edgeAngle >= 0 && edgeAngle < 180;
1768}
1769
1770
1771bool
1773 // get incoming edges
1774 const auto incomingEdges = getFromJunction()->getGNEIncomingEdges();
1775 // iterate over connections
1776 for (const auto& incomingEdge : incomingEdges) {
1777 for (const auto& connection : incomingEdge->getGNEConnections()) {
1778 if (connection->getEdgeTo() == this) {
1779 return true;
1780 }
1781 }
1782 }
1783 return false;
1784}
1785
1786
1787bool
1789 return (myGNEConnections.size() > 0);
1790}
1791
1792
1793GNEEdge*
1795 for (const auto& outgoingEdge : getParentJunctions().back()->getGNEOutgoingEdges()) {
1796 if (outgoingEdge->getToJunction() == getFromJunction()) {
1797 return outgoingEdge;
1798 }
1799 }
1800 return nullptr;
1801}
1802
1803// ===========================================================================
1804// private
1805// ===========================================================================
1806
1807GNEEdge::StackPosition::StackPosition(const double departPos, const double length) :
1808 pair(departPos, departPos + length) {
1809}
1810
1811
1812double
1814 return first;
1815}
1816
1817
1818double
1820 return second;
1821}
1822
1823
1825 pair(stackedPosition, {
1826 demandElement
1827}) {
1828}
1829
1830
1831void
1833 second.push_back(demandElement);
1834}
1835
1836
1839 return first;
1840}
1841
1842
1843const std::vector<GNEDemandElement*>&
1845 return second;
1846}
1847
1848
1849void
1850GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
1851 switch (key) {
1852 case SUMO_ATTR_ID:
1853 myNet->getAttributeCarriers()->updateEdgeID(this, value);
1854 // enable save demand elements if there are stops
1855 for (const auto& stop : getChildDemandElements()) {
1856 if (stop->getTagProperty().isVehicleStop()) {
1858 }
1859 }
1860 // also for lanes
1861 for (const auto& lane : myLanes) {
1862 for (const auto& stop : lane->getChildDemandElements()) {
1863 if (stop->getTagProperty().isVehicleStop()) {
1865 }
1866 }
1867 }
1868 break;
1869 case SUMO_ATTR_FROM:
1870 myNet->changeEdgeEndpoints(this, value, getToJunction()->getID());
1871 // update this edge of list of outgoings edges of the old first parent junction
1873 // update first parent junction
1875 // update this edge of list of outgoings edges of the new first parent junction
1877 // update centering boundary and grid
1879 break;
1880 case SUMO_ATTR_TO:
1881 myNet->changeEdgeEndpoints(this, getFromJunction()->getID(), value);
1882 // update this edge of list of incomings edges of the old second parent junction
1884 // update second parent junction
1886 // update this edge of list of incomings edges of the new second parent junction
1888 // update centering boundary and grid
1890 break;
1891 case SUMO_ATTR_NUMLANES:
1892 throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
1893 case SUMO_ATTR_PRIORITY:
1894 myNBEdge->myPriority = parse<int>(value);
1895 break;
1896 case SUMO_ATTR_LENGTH:
1897 if (value.empty()) {
1899 } else {
1900 myNBEdge->setLoadedLength(parse<double>(value));
1901 }
1902 break;
1903 case SUMO_ATTR_TYPE:
1904 myNBEdge->myType = value;
1905 break;
1906 case SUMO_ATTR_SHAPE:
1907 // set new geometry
1908 setGeometry(parse<PositionVector>(value), true);
1909 // update centering boundary and grid
1911 break;
1914 break;
1915 case SUMO_ATTR_NAME:
1916 myNBEdge->setStreetName(value);
1917 break;
1918 case SUMO_ATTR_SPEED:
1919 myNBEdge->setSpeed(-1, parse<double>(value));
1920 break;
1921 case SUMO_ATTR_FRICTION:
1922 myNBEdge->setFriction(-1, parse<double>(value));
1923 break;
1924 case SUMO_ATTR_WIDTH:
1925 if (value.empty() || (value == "default")) {
1927 } else {
1928 myNBEdge->setLaneWidth(-1, parse<double>(value));
1929 }
1930 break;
1932 myNBEdge->setEndOffset(-1, parse<double>(value));
1933 break;
1934 case SUMO_ATTR_ALLOW:
1935 break; // no edge value
1936 case SUMO_ATTR_DISALLOW:
1937 break; // no edge value
1938 case SUMO_ATTR_DISTANCE:
1939 if (value.empty()) {
1940 myNBEdge->setDistance(0.0);
1941 } else {
1942 myNBEdge->setDistance(parse<double>(value));
1943 }
1944 break;
1946 myConnectionStatus = value;
1947 if (value == FEATURE_GUESSED) {
1948 WRITE_DEBUG("invalidating (removing) connections of edge '" + getID() + "' due it were guessed");
1951 } else if (value != FEATURE_GUESSED) {
1952 WRITE_DEBUG("declaring connections of edge '" + getID() + "' as loaded (It will not be removed)");
1954 }
1955 break;
1956 case GNE_ATTR_SHAPE_START: {
1957 // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1958 Position newShapeStart;
1959 if (value == "") {
1960 newShapeStart = getFromJunction()->getNBNode()->getPosition();
1961 } else {
1962 newShapeStart = parse<Position>(value);
1963 }
1964 // set shape start position
1965 setShapeStartPos(newShapeStart);
1966 // update centering boundary and grid
1968 break;
1969 }
1970 case GNE_ATTR_SHAPE_END: {
1971 // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destination position) and set it back to edge
1972 Position newShapeEnd;
1973 if (value == "") {
1974 newShapeEnd = getToJunction()->getNBNode()->getPosition();
1975 } else {
1976 newShapeEnd = parse<Position>(value);
1977 }
1978 // set shape end position
1979 setShapeEndPos(newShapeEnd);
1980 // update centering boundary and grid
1982 break;
1983 }
1984 case GNE_ATTR_BIDIR:
1985 myNBEdge->setBidi(parse<bool>(value));
1986 break;
1988 if (value.empty()) {
1990 } else {
1991 myNBEdge->myEdgeStopOffset.setOffset(parse<double>(value));
1992 }
1993 break;
1996 break;
1998 myNBEdge->setParametersStr(value);
1999 break;
2000 default:
2001 setCommonAttribute(key, value);
2002 break;
2003 }
2004 // get template editor
2006 // check if update template (except for modification status)
2007 if (templateEditor->getEdgeTemplate() && (templateEditor->getEdgeTemplate()->getID() == getID()) &&
2010 }
2011 // invalidate demand path calculator
2013}
2014
2015
2016void
2018 // get start and end points
2019 const Position shapeStart = moveResult.shapeToUpdate.front();
2020 const Position shapeEnd = moveResult.shapeToUpdate.back();
2021 // get innen shape
2022 PositionVector innenShape = moveResult.shapeToUpdate;
2023 innenShape.pop_front();
2024 innenShape.pop_back();
2025 // set shape start
2026 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
2027 setShapeStartPos(shapeStart);
2028 }
2029 // set innen geometry
2030 setGeometry(innenShape, true);
2031 // set shape end
2032 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), ((int)moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
2033 setShapeEndPos(shapeEnd);
2034 }
2035}
2036
2037
2038void
2040 // make sure that newShape isn't empty
2041 if (moveResult.shapeToUpdate.size() > 1) {
2042 // get innen shape
2043 PositionVector innenShapeToUpdate = moveResult.shapeToUpdate;
2044 innenShapeToUpdate.pop_front();
2045 innenShapeToUpdate.pop_back();
2046 // commit new shape
2047 undoList->begin(this, "moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
2048 // update start position
2049 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
2051 }
2052 // check if update shape
2053 if (innenShapeToUpdate.size() > 0) {
2054 GNEChange_Attribute::changeAttribute(this, SUMO_ATTR_SHAPE, toString(innenShapeToUpdate), undoList);
2055 }
2056 // update end position
2057 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), ((int)moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
2059 }
2060 undoList->end();
2061 }
2062}
2063
2064
2065void
2066GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
2067 // begin undo list
2068 undoList->begin(this, "change number of " + toString(SUMO_TAG_LANE) + "s");
2069 // invalidate logic of source/destination edges
2070 getFromJunction()->setLogicValid(false, undoList);
2071 getToJunction()->setLogicValid(false, undoList);
2072 // disable update geometry (see #6336)
2073 myUpdateGeometry = false;
2074 // remove edge from grid
2076 // save old number of lanes
2077 const int oldNumLanes = (int)myLanes.size();
2078 // get opposite ID
2079 const auto oppositeID = myLanes.back()->getAttribute(GNE_ATTR_OPPOSITE);
2080 if (oppositeID != "") {
2081 // we'll have a different leftmost lane after adding/removing lanes
2083 }
2084 for (int i = oldNumLanes; i < numLanes; i++) {
2085 // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
2086 undoList->add(new GNEChange_Lane(this, myNBEdge->getLaneStruct(oldNumLanes - 1)), true);
2087 }
2088 for (int i = (oldNumLanes - 1); i > (numLanes - 1); i--) {
2089 // delete leftmost lane
2090 undoList->add(new GNEChange_Lane(this, myLanes[i], myNBEdge->getLaneStruct(i), false), true);
2091 }
2092 if (oppositeID != "") {
2093 GNEChange_Attribute::changeAttribute(myLanes.back(), GNE_ATTR_OPPOSITE, oppositeID, undoList);
2094 }
2095 // enable updateGeometry again
2096 myUpdateGeometry = true;
2097 // update geometry of entire edge
2099 // end undo list
2100 undoList->end();
2101 // update centering boundary (without updating RTREE)
2103 // insert edge in grid again
2105}
2106
2107
2108void
2109GNEEdge::updateFirstParentJunction(const std::string& value) {
2110 std::vector<GNEJunction*> parentJunctions = getParentJunctions();
2111 parentJunctions[0] = myNet->getAttributeCarriers()->retrieveJunction(value);
2112 // replace parent junctions
2113 replaceParentElements(this, parentJunctions);
2114}
2115
2116
2117void
2118GNEEdge::updateSecondParentJunction(const std::string& value) {
2119 std::vector<GNEJunction*> parentJunctions = getParentJunctions();
2120 parentJunctions[1] = myNet->getAttributeCarriers()->retrieveJunction(value);
2121 // replace parent junctions
2122 replaceParentElements(this, parentJunctions);
2123}
2124
2125
2126void
2127GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections) {
2128 const int index = lane ? lane->getIndex() : myNBEdge->getNumLanes();
2129 // the laneStruct must be created first to ensure we have some geometry
2130 // unless the connections are fully recomputed, existing indices must be shifted
2131 myNBEdge->addLane(index, true, recomputeConnections, !recomputeConnections);
2132 if (lane) {
2133 // restore a previously deleted lane
2134 myLanes.insert(myLanes.begin() + index, lane);
2135 } else {
2136 // create a new lane by copying leftmost lane
2137 lane = new GNELane(this, index);
2138 myLanes.push_back(lane);
2139 }
2140 lane->incRef("GNEEdge::addLane");
2141 // add in attributeCarriers
2143 // check if lane is selected
2144 if (lane->isAttributeCarrierSelected()) {
2145 lane->selectAttributeCarrier();
2146 }
2147 // we copy all attributes except shape since this is recomputed from edge shape
2148 myNBEdge->setSpeed(lane->getIndex(), laneAttrs.speed);
2149 myNBEdge->setFriction(lane->getIndex(), laneAttrs.friction);
2150 myNBEdge->setPermissions(laneAttrs.permissions, lane->getIndex());
2152 myNBEdge->setEndOffset(lane->getIndex(), laneAttrs.endOffset);
2153 myNBEdge->setLaneWidth(lane->getIndex(), laneAttrs.width);
2154 // update indices
2155 for (int i = 0; i < (int)myLanes.size(); ++i) {
2156 myLanes[i]->setIndex(i);
2157 }
2158 /* while technically correct, this looks ugly
2159 getFromJunction()->invalidateShape();
2160 getToJunction()->invalidateShape();
2161 */
2162 // Remake connections for this edge and all edges that target this lane
2164 // remake connections of all edges of junction source and destination
2165 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2166 fromEdge->remakeGNEConnections();
2167 }
2168 // remake connections of all edges of junction source and destination
2169 for (const auto& toEdge : getToJunction()->getChildEdges()) {
2170 toEdge->remakeGNEConnections();
2171 }
2172 // Update geometry with the new lane
2174 // update boundary and grid
2176}
2177
2178
2179void
2180GNEEdge::removeLane(GNELane* lane, bool recomputeConnections) {
2181 if (myLanes.size() == 0) {
2182 throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + getTagStr());
2183 }
2184 if (lane == nullptr) {
2185 lane = myLanes.back();
2186 }
2187 // check if lane is selected
2188 if (lane->isAttributeCarrierSelected()) {
2190 }
2191 // before removing, check that lane isn't being inspected
2194 // Delete lane of edge's container
2195 // unless the connections are fully recomputed, existing indices must be shifted
2196 myNBEdge->deleteLane(lane->getIndex(), recomputeConnections, !recomputeConnections);
2197 lane->decRef("GNEEdge::removeLane");
2198 myLanes.erase(myLanes.begin() + lane->getIndex());
2199 // remove from attributeCarriers
2201 // Delete lane if is unreferenced
2202 if (lane->unreferenced()) {
2203 // show extra information for tests
2204 WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in removeLane()");
2205 delete lane;
2206 }
2207 // update indices
2208 for (int i = 0; i < (int)myLanes.size(); ++i) {
2209 myLanes[i]->setIndex(i);
2210 }
2211 /* while technically correct, this looks ugly
2212 getFromJunction()->invalidateShape();
2213 getToJunction()->invalidateShape();
2214 */
2215 // Remake connections of this edge
2217 // remake connections of all edges of junction source and destination
2218 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2219 fromEdge->remakeGNEConnections();
2220 }
2221 // remake connections of all edges of junction source and destination
2222 for (const auto& toEdge : getToJunction()->getChildEdges()) {
2223 toEdge->remakeGNEConnections();
2224 }
2225 // Update element
2227 // update boundary and grid
2229}
2230
2231
2232void
2233GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
2234 // If a new connection was successfully created
2236 nbCon.keepClear, nbCon.contPos, nbCon.visibility,
2237 nbCon.speed, nbCon.friction, nbCon.customLength, nbCon.customShape, nbCon.uncontrolled)) {
2238 // Create or retrieve existent GNEConnection
2239 GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
2240 // add it to GNEConnection container
2241 myGNEConnections.push_back(con);
2242 // Add reference
2243 myGNEConnections.back()->incRef("GNEEdge::addConnection");
2244 // select GNEConnection if needed
2245 if (selectAfterCreation) {
2247 }
2248 // update geometry
2249 con->updateGeometry();
2250 }
2251 // actually we only do this to force a redraw
2253}
2254
2255
2256void
2258 // check if is a explicit turnaround
2259 if (nbCon.toEdge == myNBEdge->getTurnDestination()) {
2261 }
2262 // remove NBEdge::connection from NBEdge
2264 // remove their associated GNEConnection
2265 GNEConnection* connection = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
2266 if (connection != nullptr) {
2267 // before removing, check that the connection isn't being inspected
2270 connection->decRef("GNEEdge::removeConnection");
2271 myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), connection));
2272 // check if connection is selected
2273 if (connection->isAttributeCarrierSelected()) {
2274 connection->unselectAttributeCarrier();
2275 }
2276 // remove it from network
2277 myNet->removeGLObjectFromGrid(connection);
2278 // check if remove it from Attribute Carriers
2279 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
2281 }
2282 if (connection->unreferenced()) {
2283 // show extra information for tests
2284 WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in removeConnection()");
2285 // actually we only do this to force a redraw
2287 }
2288 }
2289}
2290
2291
2293GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
2294 for (const auto& connection : myGNEConnections) {
2295 if ((connection->getFromLaneIndex() == fromLane) && (connection->getEdgeTo()->getNBEdge() == to) && (connection->getToLaneIndex() == toLane)) {
2296 return connection;
2297 }
2298 }
2299 if (createIfNoExist) {
2300 // create new connection. Will be added to the rTree on first geometry computation
2301 GNEConnection* connection = new GNEConnection(myLanes[fromLane], myNet->getAttributeCarriers()->retrieveEdge(to->getID())->getLanes()[toLane]);
2302 // show extra information for tests
2303 WRITE_DEBUG("Created " + connection->getTagStr() + " '" + connection->getID() + "' in retrieveGNEConnection()");
2304 // add it into network
2305 myNet->addGLObjectIntoGrid(connection);
2306 // add it in attributeCarriers
2308 return connection;
2309 } else {
2310 return nullptr;
2311 }
2312}
2313
2314
2315void
2316GNEEdge::setEdgeID(const std::string& newID) {
2317 setNetworkElementID(newID);
2318 for (const auto& lane : myLanes) {
2319 lane->setNetworkElementID(getNBEdge()->getLaneID(lane->getIndex()));
2320 }
2321}
2322
2323
2324bool
2326 for (const auto& lane : myLanes) {
2327 if (lane->isRestricted(vclass)) {
2328 return true;
2329 }
2330 }
2331 return false;
2332}
2333
2334
2335void
2337 // Remove all crossings that contain this edge in parameter "edges"
2338 for (const auto& crossing : junction->getGNECrossings()) {
2339 if (crossing->checkEdgeBelong(this)) {
2340 myNet->deleteCrossing(crossing, undoList);
2341 }
2342 }
2343}
2344
2345
2346void
2351 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2352 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2353}
2354
2355
2357GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
2358 const auto& neteditOptions = OptionsCont::getOptions();
2359 // distinguish 3 cases:
2360 // a) if the edge has exactly 3 or 4 points, use these as control points
2361 // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
2362 // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
2363 PositionVector init;
2364#ifdef DEBUG_SMOOTH_GEOM
2365 if (DEBUGCOND(this)) std::cout << getID()
2366 << " forElevation=" << forElevation
2367 << " fromGeometryLike=" << myNBEdge->getFromNode()->geometryLike()
2368 << " toGeometryLike=" << myNBEdge->getToNode()->geometryLike()
2369 << " smoothShape old=" << old << "\n";
2370#endif
2371 if (old.size() == 3 || old.size() == 4) {
2372 init = old;
2373 } else if (old.size() > 4 && !forElevation) {
2374 // for elevation, the initial segments are not useful
2375 init.push_back(old[0]);
2376 init.push_back(old[1]);
2377 init.push_back(old[-2]);
2378 init.push_back(old[-1]);
2379 } else if (myNBEdge->getFromNode()->geometryLike() && myNBEdge->getToNode()->geometryLike()) {
2380 PositionVector begShape;
2381 PositionVector endShape;
2382 const EdgeVector& incoming = myNBEdge->getFromNode()->getIncomingEdges();
2383 const EdgeVector& outgoing = myNBEdge->getToNode()->getOutgoingEdges();
2384 if (incoming.size() == 1) {
2385 begShape = incoming[0]->getGeometry();
2386 } else {
2387 assert(incoming.size() == 2);
2388 begShape = myNBEdge->isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
2389 }
2390 if (outgoing.size() == 1) {
2391 endShape = outgoing[0]->getGeometry();
2392 } else {
2393 assert(outgoing.size() == 2);
2394 endShape = myNBEdge->isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
2395 }
2396 const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
2397 if (forElevation) {
2398 // initialize control point elevation for smooth continuation
2399 init.push_back(old[0]);
2400 init.push_back(old.positionAtOffset2D(dist));
2401 init.push_back(old.positionAtOffset2D(old.length2D() - dist));
2402 init.push_back(old[-1]);
2403 double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
2404 double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
2405 // continue incline
2406 init[1].setz(2 * init[0].z() - begZ);
2407 init[2].setz(2 * init[-1].z() - endZ);
2408 } else {
2409 bool ok = true;
2410 const double straightThresh = DEG2RAD(neteditOptions.getFloat("opendrive-output.straight-threshold"));
2411 init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, nullptr, straightThresh);
2412 }
2413#ifdef DEBUG_SMOOTH_GEOM
2414 if (DEBUGCOND(this)) {
2415 std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
2416 }
2417#endif
2418 }
2419 if (init.size() == 0) {
2420 return PositionVector::EMPTY;
2421 } else {
2422 const int numPoints = MAX2(neteditOptions.getInt("junctions.internal-link-detail"),
2423 int(old.length2D() / neteditOptions.getFloat("opendrive.curve-resolution")));
2424 return init.bezier(numPoints);
2425 }
2426}
2427
2428
2429void
2431 PositionVector modifiedShape = smoothShape(myNBEdge->getGeometry(), false);
2432 if (modifiedShape.size() < 2) {
2433 WRITE_WARNINGF(TL("Could not compute smooth shape for edge '%'"), getID());
2434 } else {
2435 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2436 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2437 }
2438}
2439
2440
2441void
2443 PositionVector elevationBase;
2444 for (const Position& pos : myNBEdge->getGeometry()) {
2445 if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
2446 elevationBase.push_back(pos);
2447 }
2448 }
2449 PositionVector elevation = smoothShape(elevationBase, true);
2450 if (elevation.size() <= 2) {
2451 WRITE_WARNINGF(TL("Could not compute smooth elevation for edge '%'"), getID());
2452 } else {
2453 PositionVector modifiedShape = myNBEdge->getGeometry();
2454 if (modifiedShape.size() < 5) {
2455 modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"), false);
2456 }
2457 const double scale = elevation.length2D() / modifiedShape.length2D();
2458 //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
2459 double seen = 0;
2460 for (int i = 1; i < (int)modifiedShape.size(); ++i) {
2461 seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
2462 modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
2463 }
2464 //std::cout << " mod2=" << modifiedShape << "\n";
2465 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2466 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2467 }
2468}
2469
2470
2471void
2473 // remove start position and add it the new position
2475 geom.pop_front();
2476 geom.push_front(pos);
2477 // restore modified shape
2478 setGeometry(geom, false);
2479}
2480
2481
2482void
2484 // remove end position and add it the new position
2486 geom.pop_back();
2487 geom.push_back(pos);
2488 // restore modified shape
2489 setGeometry(geom, false);
2490}
2491
2492
2493const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2495 // declare vehicles over edge vector
2496 std::vector<GNEDemandElement*> vehiclesOverEdge;
2497 // declare solution map
2498 std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesOverEdgeMap;
2499 // declare a set of vehicles (to avoid duplicates)
2500 std::set<std::pair<double, GNEDemandElement*> > vehicles;
2501 // first obtain all vehicles of this edge
2502 for (const auto& edgeChild : getChildDemandElements()) {
2503 if (((edgeChild->getTagProperty().getTag() == SUMO_TAG_TRIP) || (edgeChild->getTagProperty().getTag() == SUMO_TAG_FLOW)) &&
2504 (edgeChild->getParentEdges().front() == this)) {
2505 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2506 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2507 } else if ((edgeChild->getTagProperty().getTag() == SUMO_TAG_ROUTE) && (edgeChild->getParentEdges().front() == this)) {
2508 for (const auto& routeChild : edgeChild->getChildDemandElements()) {
2509 if (routeChild->getTagProperty().vehicleRoute()) {
2510 vehicles.insert(std::make_pair(routeChild->getAttributeDouble(SUMO_ATTR_DEPART), routeChild));
2511 }
2512 }
2513 } else if ((edgeChild->getTagProperty().getTag() == GNE_TAG_ROUTE_EMBEDDED) && (edgeChild->getParentEdges().front() == this)) {
2514 vehicles.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild->getParentDemandElements().front()));
2515 }
2516 }
2517 // reserve
2518 vehiclesOverEdge.reserve(vehicles.size());
2519 // iterate over vehicles
2520 for (const auto& vehicle : vehicles) {
2521 // add it over vehiclesOverEdge;
2522 vehiclesOverEdge.push_back(vehicle.second);
2523 }
2524 // now split vehicles by lanes
2525 for (const auto& vehicle : vehiclesOverEdge) {
2526 const GNELane* vehicleLane = vehicle->getFirstPathLane();
2527 if (vehicleLane) {
2528 vehiclesOverEdgeMap[vehicleLane].push_back(vehicle);
2529 }
2530 }
2531 return vehiclesOverEdgeMap;
2532}
2533
2534
2535const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2537 // declare persons over edge vector
2538 std::vector<GNEDemandElement*> personsOverEdge;
2539 // declare solution map
2540 std::map<const GNELane*, std::vector<GNEDemandElement*> > personsOverEdgeMap;
2541 // declare a set of persons (to avoid duplicates)
2542 std::set<std::pair<double, GNEDemandElement*> > persons;
2543 // first obtain all persons of this edge
2544 for (const auto& edgeChild : getChildDemandElements()) {
2545 if (edgeChild->getTagProperty().isPlanPerson()) {
2546 persons.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2547 }
2548 }
2549 // reserve
2550 personsOverEdge.reserve(persons.size());
2551 // iterate over persons
2552 for (const auto& person : persons) {
2553 // add it over personsOverEdge;
2554 personsOverEdge.push_back(person.second);
2555 }
2556 // now split persons by lanes
2557 for (const auto& person : personsOverEdge) {
2558 const GNELane* personLane = person->getFirstPathLane();
2559 if (personLane) {
2560 personsOverEdgeMap[personLane].push_back(person);
2561 }
2562 }
2563 return personsOverEdgeMap;
2564}
2565
2566
2567
2568const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2570 // declare containers over edge vector
2571 std::vector<GNEDemandElement*> containersOverEdge;
2572 // declare solution map
2573 std::map<const GNELane*, std::vector<GNEDemandElement*> > containersOverEdgeMap;
2574 // declare a set of containers (to avoid duplicates)
2575 std::set<std::pair<double, GNEDemandElement*> > containers;
2576 // first obtain all containers of this edge
2577 for (const auto& edgeChild : getChildDemandElements()) {
2578 if (edgeChild->getTagProperty().isPlanContainer()) {
2579 containers.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2580 }
2581 }
2582 // reserve
2583 containersOverEdge.reserve(containers.size());
2584 // iterate over containers
2585 for (const auto& container : containers) {
2586 // add it over containersOverEdge;
2587 containersOverEdge.push_back(container.second);
2588 }
2589 // now split containers by lanes
2590 for (const auto& container : containersOverEdge) {
2591 const GNELane* containerLane = container->getFirstPathLane();
2592 if (containerLane) {
2593 containersOverEdgeMap[containerLane].push_back(container);
2594 }
2595 }
2596 return containersOverEdgeMap;
2597}
2598
2599
2600void
2602 // first check conditions
2604 // check if draw geometry points
2605 const bool bigGeometryPoints = drawBigGeometryPoints();
2606 // Obtain exaggeration of the draw
2607 const double exaggeration = getExaggeration(s);
2608 // get geometry point radius
2609 const double geometryPointRadius = getGeometryPointRadius();
2610 // obtain geometry point color
2611 RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2612 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2613 // override with special colors (unless the color scheme is based on selection)
2614 geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2615 }
2616 // draw geometry points except initial and final
2617 for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
2618 // obtain geometry point
2619 const auto geometryPointPos = myNBEdge->getGeometry()[i];
2620 // push geometry point drawing matrix
2622 // set color
2623 GLHelper::setColor(geometryPointColor);
2624 // move geometry point geometryPointPos
2625 glTranslated(geometryPointPos.x(), geometryPointPos.y(), bigGeometryPoints ? GLO_GEOMETRYPOINT : GLO_LANE + 1);
2626 // draw filled circle (resolution of drawn circle depending of the zoom, to improve smoothness)
2627 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius);
2628 // draw elevation or special symbols (Start, End and Block)
2630 // Translate to top
2631 glTranslated(0, 0, 0.2);
2632 // draw Z value
2633 GLHelper::drawText(toString(geometryPointPos.z()), Position(), 0, s.edgeValue.scaledSize(s.scale) / 2, s.edgeValue.color);
2634 }
2635 // pop geometry point drawing matrix
2637 }
2638 // draw start and end points
2639 if (bigGeometryPoints) {
2640 drawStartGeometryPoint(s, d, geometryPointRadius, layer, exaggeration);
2641 drawEndGeometryPoint(s, d, geometryPointRadius, layer, exaggeration);
2642 }
2643 // draw dotted contour geometry points
2646 }
2647}
2648
2649
2650void
2652 const double geometryPointRadius, const double layer, const double exaggeration) const {
2653 // check detail level
2655 // get first geometry point
2656 const auto& startGeometryPointPos = myNBEdge->getGeometry().front();
2657 // get flags
2658 const bool startPosEdited = (startGeometryPointPos != getParentJunctions().front()->getPositionInView());
2660 // check drawing conditions
2661 if (startPosEdited || forceDraw) {
2662 // calculate angle betwen first and second geometry point
2663 const double angle = RAD2DEG(startGeometryPointPos.angleTo2D(myNBEdge->getGeometry()[1])) * -1;
2664 // get selected geometry points
2665 const auto selectedGeometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(this);
2666 // override with special colors (unless the color scheme is based on selection)
2667 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2669 } else {
2670 GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2671 }
2672 // push drawing matrix
2674 // move to point position
2675 glTranslated(startGeometryPointPos.x(), startGeometryPointPos.y(), GLO_GEOMETRYPOINT);
2676 // resolution of drawn circle depending of detail
2677 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2678 // pop drawing matrix
2680 // draw a "s" over last point depending of detail level
2682 // push drawing matrix
2684 // move top
2685 glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2686 // draw S
2687 GLHelper::drawText("S", startGeometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2688 // pop drawing matrix
2690 // check if draw line between junctions
2691 if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.front() == 0)) {
2692 // set base color
2694 // push drawing matrix
2696 // draw line between geometry point and from junction
2697 const PositionVector lineA = {startGeometryPointPos, getFromJunction()->getNBNode()->getPosition()};
2698 GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2699 // draw line between begin point of last lane shape and the first edge shape point
2700 const PositionVector lineB = {startGeometryPointPos, myNBEdge->getLanes().back().shape.front()};
2701 GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2702 // pop drawing matrix
2704 }
2705 }
2706 // draw dotted contour geometry points
2708 geometryPointRadius, exaggeration);
2709 }
2710 }
2711}
2712
2713
2714void
2716 const double layer, const double geometryPointRadius, const double exaggeration) const {
2717 // check detail level
2719 // get first geometry point
2720 const auto& geometryPointPos = myNBEdge->getGeometry().back();
2721 // get flags
2722 const bool endPosEdited = (geometryPointPos != getParentJunctions().back()->getPositionInView());
2724 // check drawing conditions
2725 if (endPosEdited || forceDraw) {
2726 // calculate angle last and previous geometry point
2727 const double angle = RAD2DEG(geometryPointPos.angleTo2D(myNBEdge->getGeometry()[-2])) * -1;
2728 // get selected geometry points
2729 const auto selectedGeometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(this);
2730 // override with special colors (unless the color scheme is based on selection)
2731 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2733 } else {
2734 GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2735 }
2736 // push drawing matrix
2738 // move to point position
2739 glTranslated(geometryPointPos.x(), geometryPointPos.y(), GLO_GEOMETRYPOINT);
2740 // resolution of drawn circle depending of detail
2741 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2742 // pop drawing matrix
2744 // draw a "s" over last point depending of detail level
2746 // push drawing matrix
2748 // move top
2749 glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2750 // draw S
2751 GLHelper::drawText("E", geometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2752 // pop drawing matrix
2754 // check if draw line between junctions
2755 if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.back() == ((int)myNBEdge->getGeometry().size() - 1))) {
2756 // set base color
2758 // push drawing matrix
2760 // draw line between geometry point and from junction
2761 const PositionVector lineA = {geometryPointPos, getToJunction()->getNBNode()->getPosition()};
2762 GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2763 // draw line between begin point of last lane shape and the first edge shape point
2764 const PositionVector lineB = {geometryPointPos, myNBEdge->getLanes().back().shape.back()};
2765 GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2766 // pop drawing matrix
2768 }
2769 }
2770 // draw dotted contour geometry points
2772 geometryPointRadius, exaggeration);
2773 }
2774 }
2775}
2776
2777
2778void
2780 // draw the name and/or the street name
2781 const bool drawStreetName = s.streetName.show(this) && (myNBEdge->getStreetName() != "");
2782 const bool spreadSuperposed = s.spreadSuperposed && myNBEdge->getBidiEdge() != nullptr;
2783 // check conditions
2784 if (s.edgeName.show(this) || drawStreetName || s.edgeValue.show(this)) {
2785 // get first and last lanes
2786 const GNELane* firstLane = myLanes[0];
2787 const GNELane* lastLane = myLanes[myLanes.size() - 1];
2788 // calculate draw position
2789 Position drawPosition = firstLane->getLaneShape().positionAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2790 drawPosition.add(lastLane->getLaneShape().positionAtOffset(lastLane->getLaneShape().length() / (double) 2.));
2791 drawPosition.mul(.5);
2792 if (spreadSuperposed) {
2793 // move name to the right of the edge and towards its beginning
2794 const double dist = 0.6 * s.edgeName.scaledSize(s.scale);
2795 const double shiftA = firstLane->getLaneShape().rotationAtOffset(firstLane->getLaneShape().length() / (double) 2.) - DEG2RAD(135);
2796 const Position shift(dist * cos(shiftA), dist * sin(shiftA));
2797 drawPosition.add(shift);
2798 }
2799 // calculate drawing angle
2800 double drawAngle = firstLane->getLaneShape().rotationDegreeAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2801 drawAngle += 90;
2802 // avoid draw inverted text
2803 if (drawAngle > 90 && drawAngle < 270) {
2804 drawAngle -= 180;
2805 }
2806 // draw edge name
2807 if (s.edgeName.show(this)) {
2808 drawName(drawPosition, s.scale, s.edgeName, drawAngle);
2809 }
2810 // draw street name
2811 if (drawStreetName) {
2812 GLHelper::drawTextSettings(s.streetName, myNBEdge->getStreetName(), drawPosition, s.scale, drawAngle);
2813 }
2814 // draw edge values
2815 if (s.edgeValue.show(this)) {
2816 // get current scheme
2817 const int activeScheme = s.laneColorer.getActive();
2818 // calculate value depending of active scheme
2819 std::string value;
2820 if (activeScheme == 12) {
2821 // edge param, could be non-numerical
2822 value = getNBEdge()->getParameter(s.edgeParam, "");
2823 } else if (activeScheme == 13) {
2824 // lane param, could be non-numerical
2825 value = getNBEdge()->getLaneStruct(lastLane->getIndex()).getParameter(s.laneParam, "");
2826 } else {
2827 // use numerical value value of leftmost lane to hopefully avoid sidewalks, bikelanes etc
2828 const double doubleValue = lastLane->getColorValue(s, activeScheme);
2829 const RGBColor color = s.laneColorer.getScheme().getColor(doubleValue);
2830 value = color.alpha() == 0 ? "" : toString(doubleValue);
2831 }
2832 // check if value is empty
2833 if (value != "") {
2834 GLHelper::drawTextSettings(s.edgeValue, value, drawPosition, s.scale, drawAngle);
2835 }
2836 }
2837 }
2838}
2839
2840
2841void
2843 // draw geometry only if we'rent in drawForObjectUnderCursor mode
2845 // Push stopOffset matrix
2847 // translate to front (note: Special case)
2848 drawInLayer(layer + 1);
2850 for (const auto& lane : getLanes()) {
2851 lane->drawLaneStopOffset(s);
2852 }
2853 }
2854 // Push stopOffset matrix
2856 }
2857}
2858
2859
2860void
2862 // draw child additional
2863 for (const auto& additional : getChildAdditionals()) {
2864 additional->drawGL(s);
2865 }
2866 // draw person stops
2868 for (const auto& stopEdge : getChildDemandElements()) {
2869 if ((stopEdge->getTagProperty().getTag() == GNE_TAG_STOPPERSON_EDGE) || (stopEdge->getTagProperty().getTag() == GNE_TAG_STOPCONTAINER_EDGE)) {
2870 stopEdge->drawGL(s);
2871 }
2872 }
2873 }
2874 // draw vehicles
2875 const std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesMap = getVehiclesOverEdgeMap();
2876 for (const auto& vehicleMap : vehiclesMap) {
2877 for (const auto& vehicle : vehicleMap.second) {
2878 vehicle->drawGL(s);
2879 }
2880 }
2881 // draw TAZ elements
2882 drawTAZElements(s);
2883}
2884
2885
2886void
2888 // if we're selecting using a boundary, first don't calculate contour bt check if edge boundary is within selection boundary
2890 // simply add object in ViewObjectsHandler with full boundary
2891 gViewObjectsHandler.selectObject(this, layer, false, true, nullptr);
2892 } else {
2893 // get geometry point radius
2894 const auto geometryPointRadius = getGeometryPointRadius();
2895 // check if edit extrems
2897 const bool firstExtrem = forceDrawExtrems || (myNBEdge->getGeometry().front() != getParentJunctions().front()->getPositionInView());
2898 const bool lastExtrem = forceDrawExtrems || (myNBEdge->getGeometry().back() != getParentJunctions().back()->getPositionInView());
2899 // check if we're in move mode
2901 // calculate contour
2902 myNetworkElementContour.calculateContourEdge(s, d, this, this, layer, true, true);
2903 // calculate edge geometry points
2904 myNetworkElementContour.calculateContourEdgeGeometryPoints(s, d, this, geometryPointRadius, moveMode, firstExtrem, lastExtrem);
2905 }
2906}
2907
2908
2909void
2911 // first check if draw TAZ Elements is enabled
2913 std::vector<GNEAdditional*> TAZSourceSinks;
2914 // get all TAZ source/sinks vinculated with this edge
2915 for (const auto& additional : getChildAdditionals()) {
2916 if ((additional->getTagProperty().getTag() == SUMO_TAG_TAZSOURCE) ||
2917 (additional->getTagProperty().getTag() == SUMO_TAG_TAZSINK)) {
2918 TAZSourceSinks.push_back(additional);
2919 }
2920 }
2921 if (TAZSourceSinks.size() > 0) {
2922 // check if TAZ Source/sink is selected
2923 bool selected = false;
2924 for (const auto& TAZSourceSink : TAZSourceSinks) {
2925 if (TAZSourceSink->isAttributeCarrierSelected()) {
2926 selected = true;
2927 }
2928 }
2929 // iterate over lanes
2930 for (const auto& lane : myLanes) {
2931 // Push layer matrix
2933 // translate to front (note: Special case)
2934 if (myDrawInFront) {
2935 glTranslated(0, 0, GLO_FRONTELEMENT);
2936 } else if (lane->getLaneShape().length2D() <= (s.neteditSizeSettings.junctionBubbleRadius * 2)) {
2938 } else {
2940 }
2941 // move to front
2942 glTranslated(0, 0, 0.1);
2943 // set color
2944 if (selected) {
2946 } else {
2948 }
2949 // draw as box lines
2951 lane->getDrawingConstants()->getDrawingWidth());
2952 // Pop layer matrix
2954 }
2955 /*
2956 // check if curently we're inspecting a TAZ Source/Sink
2957 for (const auto& TAZSourceSink : TAZSourceSinks) {
2958 if (myNet->getViewNet()->isAttributeCarrierInspected(TAZSourceSink)) {
2959 drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::INSPECT, this, true, true);
2960 } else if (TAZSourceSink == markAC) {
2961 drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::FRONT, this, true, true);
2962 }
2963 }
2964 */
2965 }
2966 }
2967}
2968
2969
2970void
2972 // avoid draw for railways
2973 if ((d <= GUIVisualizationSettings::Detail::LaneDetails) && !myLanes.front()->getDrawingConstants()->drawAsRailway() &&
2975 // push draw matrix
2977 // translate to front depending of big points
2978 if (drawBigGeometryPoints()) {
2979 glTranslated(0, 0, GLO_GEOMETRYPOINT - 1);
2980 } else {
2981 glTranslated(0, 0, layer);
2982 }
2983 // obtain color
2984 RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2985 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2986 // override with special colors (unless the color scheme is based on selection)
2987 geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2988 }
2989 // set color
2990 GLHelper::setColor(geometryPointColor);
2991 // iterate over NBEdge geometry
2992 for (int i = 1; i < (int)myNBEdge->getGeometry().size(); i++) {
2993 // calculate line between previous and current geometry point
2994 PositionVector line = {myNBEdge->getGeometry()[i - 1], myNBEdge->getGeometry()[i]};
2995 line.move2side(0.2);
2996 // draw box line
2997 GLHelper::drawBoxLine(line[1], RAD2DEG(line[0].angleTo2D(line[1])) - 90, line[0].distanceTo2D(line[1]), .1);
2998 }
2999 // pop draw matrix
3001 }
3002}
3003
3004
3005bool
3007 // get edit modes
3008 const auto& editModes = myNet->getViewNet()->getEditModes();
3009 // continue depending of conditions
3010 if (!editModes.isCurrentSupermodeNetwork()) {
3011 return false;
3012 } else if (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) {
3013 return true;
3014 } else if ((editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE) &&
3016 return true;
3017 } else {
3018 return false;
3019 }
3020}
3021
3022
3023bool
3025 if ((vehicleA.beginPosition() == vehicleB.beginPosition()) && (vehicleA.endPosition() == vehicleB.endPosition())) {
3026 return true;
3027 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
3028 return true;
3029 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.beginPosition())) {
3030 return true;
3031 } else if ((vehicleA.beginPosition() < vehicleB.endPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
3032 return true;
3033 } else {
3034 return false;
3035 }
3036}
3037
3038
3040GNEEdge::processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
3041 // calculate squared snapRadius
3042 const double squaredSnapRadius = (snapRadius * snapRadius);
3043 // declare shape to move
3044 PositionVector shapeToMove = originalShape;
3045 // obtain nearest index
3046 const int nearestIndex = originalShape.indexOfClosest(mousePosition);
3047 // obtain nearest position
3048 const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
3049 // generate indexes
3050 std::vector<int> indexes;
3051 // check conditions
3052 if (nearestIndex == -1) {
3053 return nullptr;
3054 } else if (nearestPosition == Position::INVALID) {
3055 // special case for extremes
3056 if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3057 for (int i = 1; i <= nearestIndex; i++) {
3058 indexes.push_back(i);
3059 }
3060 // move extrem without creating new geometry point
3061 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3062 } else {
3063 return nullptr;
3064 }
3065 } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3066 for (int i = 1; i <= nearestIndex; i++) {
3067 indexes.push_back(i);
3068 }
3069 // move geometry point without creating new geometry point
3070 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3071 } else {
3072 // create new geometry point and keep new index (if we clicked near of shape)
3073 const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
3074 for (int i = 1; i <= newIndex; i++) {
3075 indexes.push_back(i);
3076 }
3077 // move after setting new geometry point in shapeToMove
3078 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3079 }
3080}
3081
3082
3084GNEEdge::processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
3085 // calculate squared snapRadius
3086 const double squaredSnapRadius = (snapRadius * snapRadius);
3087 // declare shape to move
3088 PositionVector shapeToMove = originalShape;
3089 // obtain nearest index
3090 const int nearestIndex = originalShape.indexOfClosest(mousePosition);
3091 // obtain nearest position
3092 const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
3093 // generate indexes
3094 std::vector<int> indexes;
3095 // check conditions
3096 if (nearestIndex == -1) {
3097 return nullptr;
3098 } else if (nearestPosition == Position::INVALID) {
3099 // special case for extremes
3100 if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3101 for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
3102 indexes.push_back(i);
3103 }
3104 // move extrem without creating new geometry point
3105 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3106 } else {
3107 return nullptr;
3108 }
3109 } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3110 for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
3111 indexes.push_back(i);
3112 }
3113 // move geometry point without creating new geometry point
3114 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3115 } else {
3116 // create new geometry point and keep new index (if we clicked near of shape)
3117 const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
3118 for (int i = newIndex; i < ((int)originalShape.size() - 1); i++) {
3119 indexes.push_back(i);
3120 }
3121 // move after setting new geometry point in shapeToMove
3122 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3123 }
3124}
3125
3126
3129 std::vector<int> geometryPointsToMove;
3130 for (int i = 0; i < (int)myNBEdge->getGeometry().size(); i++) {
3131 geometryPointsToMove.push_back(i);
3132 }
3133 // move entire shape (including extremes)
3134 return new GNEMoveOperation(this, myNBEdge->getGeometry(), geometryPointsToMove, myNBEdge->getGeometry(), geometryPointsToMove);
3135}
3136
3137
3140 // get move multiple element values
3141 const auto& moveMultipleElementValues = myNet->getViewNet()->getMoveMultipleElementValues();
3142 // declare shape to move
3143 PositionVector shapeToMove = myNBEdge->getGeometry();
3144 // first check if kept offset is larger than geometry
3145 if (shapeToMove.length2D() < moveMultipleElementValues.getEdgeOffset()) {
3146 return nullptr;
3147 }
3148 // declare offset
3149 double offset = 0;
3150 // set offset depending of convex angle
3151 if (isConvexAngle()) {
3152 offset = moveMultipleElementValues.getEdgeOffset();
3153 } else {
3154 offset = shapeToMove.length2D() - moveMultipleElementValues.getEdgeOffset();
3155 }
3156 // obtain offset position
3157 const Position offsetPosition = myNBEdge->getGeometry().positionAtOffset2D(offset);
3158 // obtain nearest index to offset position
3159 const int nearestIndex = myNBEdge->getGeometry().indexOfClosest(offsetPosition);
3160 // check conditions
3161 if ((nearestIndex == -1) || (offsetPosition == Position::INVALID)) {
3162 return nullptr;
3163 } else if (offsetPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= (snapRadius * snapRadius)) {
3164 // move geometry point without creating new geometry point
3165 return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {nearestIndex});
3166 } else {
3167 // create new geometry point and keep new index (if we clicked near of shape)
3168 const int newIndex = shapeToMove.insertAtClosest(offsetPosition, true);
3169 // move after setting new geometry point in shapeToMove
3170 return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {newIndex});
3171 }
3172}
3173
3174
3175double
3179
3180
3181/****************************************************************************/
#define ENDPOINT_TOLERANCE
Definition GNEEdge.cpp:60
#define VEHICLE_GAP
Definition GNEEdge.cpp:59
@ NETWORK_DELETE
mode for deleting network elements
@ NETWORK_MOVE
mode for moving network elements
@ 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
GUIIcon
An enumeration of icons used by the gui applications.
Definition GUIIcons.h:33
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define RAD2DEG(x)
Definition GeomHelper.h:36
#define DEBUGCOND(PED)
#define WRITE_DEBUG(msg)
Definition MsgHandler.h:306
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define TL(string)
Definition MsgHandler.h:315
#define TLF(string,...)
Definition MsgHandler.h:317
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_TAZSINK
a sink within a district (connection road)
@ 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
begin/end of the description of a route
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_TYPE
type (edge)
@ SUMO_TAG_TAZSOURCE
a source within a district (connection road)
@ 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:76
T MAX2(T a, T b)
Definition StdDefs.h:82
const double SUMO_const_halfLaneWidth
Definition StdDefs.h:49
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:78
bool isInitialised() const
check if Boundary is Initialised
Definition Boundary.cpp:259
Boundary & grow(double by)
extends the boundary by the given amount
Definition Boundary.cpp:343
bool contains2D(const Boundary &b) const
return true if this boundary contains the given boundary (only X-Y)
Definition Boundary.cpp:232
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:961
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:751
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:782
const std::string getID() const
get ID (all Attribute Carriers have one)
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
void selectAttributeCarrier()
select attribute carrier using GUIGlobalSelection
bool myDrawInFront
boolean to check if drawn this AC over other elements
bool mySelected
boolean to check if this AC is selected (more quickly as checking GUIGlObjectStorage)
static const std::string True
true value in string format (used for comparing boolean values in getAttribute(......
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)
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
bool isCommonValid(SumoXMLAttr key, const std::string &value)
void drawInLayer(const double typeOrLayer, const double extraOffset=0) const
draw element in the given layer, or in front if corresponding flag is enabled
GNENet * myNet
pointer to net
static const std::string False
true value in string format(used for comparing boolean values in getAttribute(...))
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 markConnectionGeometryDeprecated()
check that connection's Geometry has to be updated
void updateGeometry()
update pre-computed geometry information
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 calculateContourFirstGeometryPoint(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const PositionVector &shape, const double layer, const double radius, const double scale) const
calculate contour for first geometry point
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
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:402
const StackPosition & getStackPosition() const
get stack position
Definition GNEEdge.cpp:1838
const std::vector< GNEDemandElement * > & getDemandElements() const
get demand elements
Definition GNEEdge.cpp:1844
void addDemandElements(GNEDemandElement *demandElement)
add demand elment to current StackDemandElements
Definition GNEEdge.cpp:1832
StackDemandElements(const StackPosition stackedPosition, GNEDemandElement *demandElement)
constructor
Definition GNEEdge.cpp:1824
Stack position (used to stack demand elements over edges)
Definition GNEEdge.h:388
double beginPosition() const
get begin position
Definition GNEEdge.cpp:1813
StackPosition(const double departPos, const double length)
constructor
Definition GNEEdge.cpp:1807
double endPosition() const
get end position
Definition GNEEdge.cpp:1819
A road/street connecting two junctions (netedit-version)
Definition GNEEdge.h:53
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:2601
const Position getFrontDownShapePosition() const
get front down shape position
Definition GNEEdge.cpp:922
Boundary myEdgeBoundary
edge boundary
Definition GNEEdge.h:419
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
Definition GNEEdge.cpp:660
void drawEdgeName(const GUIVisualizationSettings &s) const
draw edge name
Definition GNEEdge.cpp:2779
bool isConvexAngle() const
check if edge makes a convex angle [0 - 180) degrees
Definition GNEEdge.cpp:1757
bool checkDrawRelatedContour() const
check if draw related contour (cyan)
Definition GNEEdge.cpp:314
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:2066
std::string getNetworkElementProblem() const
return a string with the current network element problem
Definition GNEEdge.cpp:144
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getPersonsOverEdgeMap() const
get persons a that start over this edge
Definition GNEEdge.cpp:2536
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getContainersOverEdgeMap() const
get containers a that start over this edge
Definition GNEEdge.cpp:2569
void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)
commit move shape
Definition GNEEdge.cpp:2039
bool hasPredecessors() const
check if this edge has predecessors (note: only for vehicles, this function ignore walking areas!...
Definition GNEEdge.cpp:1772
void setMoveShape(const GNEMoveResult &moveResult)
set move shape
Definition GNEEdge.cpp:2017
bool checkDrawMoveContour() const
check if draw move contour (red)
Definition GNEEdge.cpp:442
friend class GNEChange_Lane
Friend class.
Definition GNEEdge.h:56
bool checkDrawOverContour() const
check if draw over contour (orange)
Definition GNEEdge.cpp:320
~GNEEdge()
Destructor.
Definition GNEEdge.cpp:100
void smooth(GNEUndoList *undoList)
make geometry smooth
Definition GNEEdge.cpp:2430
void updateGeometry()
update pre-computed geometry information
Definition GNEEdge.cpp:152
double getGeometryPointRadius() const
get geometry point radius
Definition GNEEdge.cpp:3176
GNEMoveOperation * getMoveOperation()
get move operation
Definition GNEEdge.cpp:484
std::string getAttributeForSelection(SumoXMLAttr key) const
method for getting the attribute in the context of object selection
Definition GNEEdge.cpp:1239
void setResponsible(bool newVal)
set responsibility for deleting internal structures
Definition GNEEdge.cpp:1528
void copyEdgeType(const GNEEdgeType *edgeType, GNEUndoList *undoList)
copy edge attributes from edgeType
Definition GNEEdge.cpp:1078
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition GNEEdge.cpp:781
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition GNEEdge.cpp:707
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getVehiclesOverEdgeMap() const
get vehicles a that start over this edge
Definition GNEEdge.cpp:2494
std::set< GUIGlID > getLaneGlIDs() const
returns GLIDs of all lanes
Definition GNEEdge.cpp:1108
GNEEdge * getReverseEdge() const
get reverse edge (if exist)
Definition GNEEdge.cpp:1794
const Position getFrontUpShapePosition() const
get front up shape position
Definition GNEEdge.cpp:914
void setGeometry(PositionVector geom, bool inner)
update edge geometry and inform the lanes
Definition GNEEdge.cpp:879
void smoothElevation(GNEUndoList *undoList)
smooth elevation with regard to adjoining edges
Definition GNEEdge.cpp:2442
bool clickedOverGeometryPoint(const Position &pos) const
return true if user clicked over a Geometry Point
Definition GNEEdge.cpp:613
bool clickedOverShapeEnd(const Position &pos) const
return true if user clicked over ShapeEnd
Definition GNEEdge.cpp:601
void updateVehicleStackLabels()
Definition GNEEdge.cpp:1595
bool isValid(SumoXMLAttr key, const std::string &value)
Definition GNEEdge.cpp:1387
void remakeGNEConnections(bool junctionsReady=false)
remake connections
Definition GNEEdge.cpp:945
GNEMoveOperation * processMoveBothJunctionSelected()
process moving edge when both junctions are selected
Definition GNEEdge.cpp:3128
void calculateEdgeContour(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
calculate contours
Definition GNEEdge.cpp:2887
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList)
remove geometry point in the clicked position
Definition GNEEdge.cpp:516
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition GNEEdge.cpp:1118
LaneVector myLanes
vector with the lanes of this edge
Definition GNEEdge.h:369
static const double SNAP_RADIUS
Definition GNEEdge.h:308
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:1534
bool hasCustomEndPoints() const
Definition GNEEdge.cpp:577
void updatePersonStackLabels()
Definition GNEEdge.cpp:1653
void setEdgeID(const std::string &newID)
set edge ID
Definition GNEEdge.cpp:2316
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition GNEEdge.cpp:2257
void drawChildrens(const GUIVisualizationSettings &s) const
draw children
Definition GNEEdge.cpp:2861
bool hasSuccessors() const
check if this edge has successors (note: only for vehicles, this function ignore walking areas!...
Definition GNEEdge.cpp:1788
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:2651
bool isAttributeComputed(SumoXMLAttr key) const
Definition GNEEdge.cpp:1505
bool drawBigGeometryPoints() const
check if draw big geometry points
Definition GNEEdge.cpp:3006
bool myWasSplit
whether this edge was created from a split
Definition GNEEdge.h:381
void removeLane(GNELane *lane, bool recomputeConnections)
@briefdecrease the number of lanes by one. argument is only used to increase robustness (assertions)
Definition GNEEdge.cpp:2180
bool checkDrawSelectContour() const
check if draw select contour (blue)
Definition GNEEdge.cpp:411
double getExaggeration(const GUIVisualizationSettings &s) const
return exaggeration associated with this GLObject
Definition GNEEdge.cpp:648
bool hasRestrictedLane(SUMOVehicleClass vclass) const
check if edge has a restricted lane
Definition GNEEdge.cpp:2325
static const double SNAP_RADIUS_SQUARED
Definition GNEEdge.h:311
void updateSecondParentJunction(const std::string &value)
update last parent junction
Definition GNEEdge.cpp:2118
std::vector< GNEEdge * > getOppositeEdges() const
get opposite edges
Definition GNEEdge.cpp:715
PositionVector smoothShape(const PositionVector &shape, bool forElevation)
return smoothed shape
Definition GNEEdge.cpp:2357
GNEJunction * getFromJunction() const
get from Junction (only used to increase readability)
Definition GNEEdge.h:77
bool wasSplit()
whether this edge was created from a split
Definition GNEEdge.cpp:1130
NBEdge * myNBEdge
the underlying NBEdge
Definition GNEEdge.h:366
void copyTemplate(const GNEEdgeTemplate *edgeTemplate, GNEUndoList *undoList)
copy edge attributes from edgetemplate
Definition GNEEdge.cpp:1055
void removeEdgeFromCrossings(GNEJunction *junction, GNEUndoList *undoList)
remove crossing of junction
Definition GNEEdge.cpp:2336
Position getPositionInView() const
Returns position of hierarchical element in view.
Definition GNEEdge.cpp:198
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:2127
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:2293
ConnectionVector myGNEConnections
vector with the connections of this edge
Definition GNEEdge.h:372
void editEndpoint(Position pos, GNEUndoList *undoList)
makes pos the new geometry endpoint at the appropriate end, or remove current existent endpoint
Definition GNEEdge.cpp:803
void resetBothEndpoint(GNEUndoList *undoList)
restores both endpoint to the junction position at the appropriate end
Definition GNEEdge.cpp:869
Position getSplitPos(const Position &clickPos)
Definition GNEEdge.cpp:787
const std::vector< GNEConnection * > & getGNEConnections() const
returns a reference to the GNEConnection vector
Definition GNEEdge.cpp:1124
std::string getAttribute(SumoXMLAttr key) const
Definition GNEEdge.cpp:1136
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition GNEEdge.cpp:1020
bool checkDrawFromContour() const
check if draw from contour (green)
Definition GNEEdge.cpp:204
std::string myConnectionStatus
modification status of the connections
Definition GNEEdge.h:384
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:2715
bool checkDrawDeleteContour() const
check if draw delete contour (pink/white)
Definition GNEEdge.cpp:380
void deleteGLObject()
delete element
Definition GNEEdge.cpp:766
const std::string getOptionalName() const
Returns the street name.
Definition GNEEdge.cpp:701
void clearGNEConnections()
clear current connections
Definition GNEEdge.cpp:993
bool myUpdateGeometry
flag to enable/disable update geometry of lanes (used mainly by setNumLanes)
Definition GNEEdge.h:422
const Position getBackDownShapePosition() const
get back down shape position
Definition GNEEdge.cpp:938
bool areStackPositionOverlapped(const GNEEdge::StackPosition &vehicleA, const GNEEdge::StackPosition &vehicleB) const
check if given stacked positions are overlapped
Definition GNEEdge.cpp:3024
void updateFirstParentJunction(const std::string &value)
update front parent junction
Definition GNEEdge.cpp:2109
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition GNEEdge.cpp:2347
void updateContainerStackLabels()
Definition GNEEdge.cpp:1705
bool checkDrawToContour() const
check if draw from contour (magenta)
Definition GNEEdge.cpp:259
bool clickedOverShapeStart(const Position &pos) const
return true if user clicked over ShapeStart
Definition GNEEdge.cpp:589
bool isNetworkElementValid() const
check if current network element is valid to be written into XML
Definition GNEEdge.cpp:134
void setShapeStartPos(const Position &pos)
change Shape StartPos
Definition GNEEdge.cpp:2472
GNEJunction * getToJunction() const
get from Junction (only used to increase readability)
Definition GNEEdge.h:82
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition GNEEdge.cpp:1249
const Position getBackUpShapePosition() const
get back up shape position
Definition GNEEdge.cpp:930
void resetEndpoint(const Position &pos, GNEUndoList *undoList)
restores the endpoint to the junction position at the appropriate end
Definition GNEEdge.cpp:855
bool isAttributeEnabled(SumoXMLAttr key) const
Definition GNEEdge.cpp:1490
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition GNEEdge.cpp:721
void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation=false)
adds a connection
Definition GNEEdge.cpp:2233
GNEMoveOperation * processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only from junction is selected
Definition GNEEdge.cpp:3040
GNEMoveOperation * processNoneJunctionSelected(const double snapRadius)
process moving edge when none junction are selected
Definition GNEEdge.cpp:3139
PositionVector getAttributePositionVector(SumoXMLAttr key) const
Definition GNEEdge.cpp:1228
void drawLaneStopOffset(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
draw edgeStopOffset
Definition GNEEdge.cpp:2842
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition GNEEdge.cpp:654
const Parameterised::Map & getACParametersMap() const
get parameters map
Definition GNEEdge.cpp:1522
void drawTAZElements(const GUIVisualizationSettings &s) const
draw TAZElements
Definition GNEEdge.cpp:2910
void drawEdgeShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
draw edge shape (only one line)
Definition GNEEdge.cpp:2971
std::vector< GNECrossing * > getGNECrossings()
get GNECrossings vinculated with this Edge
Definition GNEEdge.cpp:1038
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:1549
void updateVehicleSpreadGeometries()
Definition GNEEdge.cpp:1564
GNEMoveOperation * processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only to junction is selected
Definition GNEEdge.cpp:3084
void updateGLObject()
update GLObject (geometry, ID, etc.)
Definition GNEEdge.cpp:775
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition GNEEdge.cpp:634
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition GNEEdge.h:378
GNEEdge(GNENet *net, NBEdge *nbe, bool wasSplit=false, bool loaded=false)
Constructor.
Definition GNEEdge.cpp:72
void setShapeEndPos(const Position &pos)
change Shape EndPos
Definition GNEEdge.cpp:2483
std::string getAttribute(SumoXMLAttr key) const
const std::vector< GNELaneTemplate * > & getLaneTemplates() const
get vector with the lane templates of this edge
const std::vector< GNELaneType * > & getLaneTypes() const
get laneTypes
std::string getAttribute(SumoXMLAttr key) const
void removeCurrentEditedAttributeCarrier(const GNEAttributeCarrier *HE)
if given AttributeCarrier is the same of myHE, set it as nullptr
const std::vector< GNEJunction * > & getParentJunctions() const
get parent junctions
const std::vector< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
const std::vector< GNEEdge * > & getChildEdges() const
get child edges
const std::vector< GNEAdditional * > & getChildAdditionals() const
return child additionals
void replaceParentElements(T *elementChild, const U &newParents)
replace parent elements
const std::vector< GNEGenericData * > & getChildGenericDatas() const
return child generic data 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()
update pre-computed geometry information (including crossings)
void removeOutgoingGNEEdge(GNEEdge *edge)
remove outgoing GNEEdge
void removeIncomingGNEEdge(GNEEdge *edge)
remove incoming GNEEdge
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show 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
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition GNELane.h:46
const PositionVector & getLaneShape() const
get elements shape
Definition GNELane.cpp:214
int getIndex() const
returns the index of the lane
Definition GNELane.cpp:620
void setIndex(int index)
Definition GNELane.cpp:626
double getColorValue(const GUIVisualizationSettings &s, int activeScheme) const
return value for lane coloring according to the given scheme
Definition GNELane.cpp:1563
GNEMoveOperation * calculateMoveShapeOperation(const GUIGlObject *obj, const PositionVector originalShape, const bool maintainShapeClosed)
calculate move shape operation
bool getForceDrawGeometryPoints() const
force draw geometry points
NetworkModeOptions * getNetworkModeOptions() const
get network mode options
move operation
move result
std::vector< int > geometryPointsToMove
shape points to move (of shapeToMove)
PositionVector shapeToUpdate
shape to update (edited in moveElement)
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
int getNumberOfSelectedEdges() const
get number of selected edges
void requireSaveDemandElements()
inform that demand elements has to be saved
A NBNetBuilder extended by visualisation and editing capabilities.
Definition GNENet.h:42
void deleteEdge(GNEEdge *edge, GNEUndoList *undoList, bool recomputeConnections)
removes edge
Definition GNENet.cpp:433
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition GNENet.cpp:658
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1390
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1400
GNENetHelper::SavingStatus * getSavingStatus() const
get saving status
Definition GNENet.cpp:133
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:145
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition GNENet.cpp:2187
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition GNENet.cpp:127
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition GNENet.cpp:2154
GNEViewNet * getViewNet() const
get view net
Definition GNENet.cpp:2163
bool checkDrawingBoundarySelection() const
GNEContour myNetworkElementContour
network element contour
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
Representation of a RouteProbe in netedit.
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
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
const GUIGlObject * getGUIGlObjectFront() const
get front GUIGLObject or a pointer to nullptr
bool isCurrentlyMovingElements() const
check if an element is being moved
const GNEViewNetHelper::DataViewOptions & getDataViewOptions() const
get data view options
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
const GNEViewNetHelper::EditNetworkElementShapes & getEditNetworkElementShapes() const
get Edit Shape module
GNEViewNetHelper::InspectedElements & getInspectedElements()
get inspected elements
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
GNEViewParent * getViewParent() const
get the net object
bool checkOverLockedElement(const GUIGlObject *GLObject, const bool isSelected) const
check if given element is locked (used for drawing select and delete contour)
bool checkSelectEdges() const
check if select edges (toggle using button or shift)
GNEUndoList * getUndoList() const
get the undoList object
const GNEViewNetHelper::MoveMultipleElementModul & getMoveMultipleElementValues() const
get move multiple element values
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.
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)
virtual Position getPositionInformation() const
Returns the cursor's x/y position within the network.
const Boundary & getSelectionBoundary() const
get selection boundary
bool selectObject(const GUIGlObject *GLObject, const double layer, const bool checkDuplicated, const bool fullBoundary, const GNESegment *segment)
const std::vector< int > & getSelectedGeometryPoints(const GUIGlObject *GLObject) const
get geometry points for the given glObject
const GUIGlObject * markedFirstGeometryPoint
marked first geometry point (used for moving/delete geometry points)
Stores the information about how to visualize structures.
GUIVisualizationSizeSettings addSize
GUIVisualizationTextSettings edgeValue
double laneWidthExaggeration
The lane exaggeration (upscale thickness)
GUIVisualizationColorSettings colorSettings
color settings
GUIVisualizationDottedContourSettings dottedContourSettings
dotted contour settings
double scale
information about a lane's width (temporary, used for a single view)
GUIVisualizationTextSettings streetName
bool drawForViewObjectsHandler
whether drawing is performed for the purpose of selecting objects in view using ViewObjectsHandler
GUIColorer laneColorer
The lane colorer.
GUIVisualizationTextSettings edgeName
Setting bundles for optional drawing names with size and color.
bool checkDrawEdge(const Boundary &b) const
check if draw edge
bool spreadSuperposed
Whether to improve visualisation of superposed (rail) edges.
GUIColorer junctionColorer
The junction colorer.
std::string edgeParam
key for coloring by edge parameter
GUIVisualizationNeteditSizeSettings neteditSizeSettings
netedit size settings
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
Definition GeomHelper.h:50
The representation of a single edge during network building.
Definition NBEdge.h:92
void setStreetName(const std::string &name)
sets the street name of this edge
Definition NBEdge.h:674
void mirrorX()
mirror coordinates along the x-axis
Definition NBEdge.cpp:570
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
Definition NBEdge.cpp:4356
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition NBEdge.cpp:4379
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition NBEdge.h:1041
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:4342
StopOffset myEdgeStopOffset
A vClass specific stop offset - assumed of length 0 (unspecified) or 1. For the latter case the int i...
Definition NBEdge.h:1800
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition NBEdge.h:602
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition NBEdge.cpp:4294
bool hasLaneSpecificFriction() const
whether lanes differ in friction
Definition NBEdge.cpp:2461
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition NBEdge.h:642
NBNode * getToNode() const
Returns the destination node of the edge.
Definition NBEdge.h:546
Lane & getLaneStruct(int lane)
Definition NBEdge.h:1428
void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices)
add lane
Definition NBEdge.cpp:4031
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition NBEdge.cpp:2451
std::string myType
The type of the edge.
Definition NBEdge.h:1737
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition NBEdge.h:783
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition NBEdge.cpp:998
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition NBEdge.h:612
void setDistance(double distance)
set kilometrage at start of edge (negative value implies couting down along the edge)
Definition NBEdge.h:1413
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition NBEdge.h:730
double getSpeed() const
Returns the speed allowed on this edge.
Definition NBEdge.h:619
const std::string & getID() const
Definition NBEdge.h:1528
double getDistance() const
get distance
Definition NBEdge.h:679
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:4165
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition NBEdge.cpp:992
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition NBEdge.cpp:3665
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition NBEdge.cpp:2437
bool isBidiEdge(bool checkPotential=false) const
whether this edge is part of a bidirectional edge pair
Definition NBEdge.cpp:761
void setBidi(bool isBidi)
mark this edge as a bidi edge
Definition NBEdge.h:1418
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:520
void setFriction(int lane, double friction)
set lane specific friction (negative lane implies set for all lanes)
Definition NBEdge.cpp:4310
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:1448
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition NBEdge.cpp:1529
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition NBEdge.cpp:4086
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition NBEdge.cpp:2471
std::string getLaneID(int lane) const
get lane ID
Definition NBEdge.cpp:4017
@ USER
The connection was given by the user.
double getFriction() const
Returns the friction on this edge.
Definition NBEdge.h:626
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:1186
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition NBEdge.cpp:2493
const std::string & getTypeID() const
get ID of type
Definition NBEdge.h:1181
const std::string & getStreetName() const
Returns the street name of this edge.
Definition NBEdge.h:669
const NBEdge * getBidiEdge() const
Definition NBEdge.h:1514
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition NBEdge.h:539
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:4008
int getPriority() const
Returns the priority of the edge.
Definition NBEdge.h:527
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:1442
double getEndOffset() const
Returns the offset to the destination node.
Definition NBEdge.h:689
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition NBEdge.cpp:4248
void setLoadedLength(double val)
set loaded length
Definition NBEdge.cpp:4394
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition NBEdge.cpp:590
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition NBEdge.cpp:4715
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition NBEdge.cpp:637
int myPriority
The priority of the edge.
Definition NBEdge.h:1756
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:3882
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition NBNode.cpp:3836
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:575
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.
static bool areParametersValid(const std::string &value, bool report=false, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to a parameters map "key1=value1|key2=value2|....
std::map< std::string, std::string > Map
parameters map
void setParametersStr(const std::string &paramsString, const std::string kvsep="=", const std::string sep="|")
set the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN"
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
std::string getParametersStr(const std::string kvsep="=", const std::string sep="|") const
Returns the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN".
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition Position.h:281
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:322
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition Position.h:276
void add(const Position &pos)
Adds the given position to this one.
Definition Position.h:132
void mul(double val)
Multiplies position with the given value.
Definition Position.h:105
double z() const
Returns the z-position.
Definition Position.h:65
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
int insertAtClosest(const Position &p, bool interpolateZ)
inserts p between the two closest positions
void push_front(const Position &p)
insert in front a Position
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false, int beginOffset=0, int endOffset=0, bool resample=false)
Removes positions if too near.
void pop_front()
pop first Position
PositionVector reverse() const
reverse position vector
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
static const RGBColor BLUE
Definition RGBColor.h:187
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition RGBColor.cpp:92
static const RGBColor ORANGE
Definition RGBColor.h:191
static const RGBColor CYAN
Definition RGBColor.h:189
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
bool hasString(const std::string &str) const
bool showDemandElements() const
check if show demand elements checkbox is enabled
NetworkEditMode networkEditMode
the current Network edit mode
bool isCurrentSupermodeNetwork() const
@check if current supermode is Network
GNENetworkElement * getEditedNetworkElement() const
pointer to edited network element
static void drawLockIcon(const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, GUIGlObjectType type, const Position position, const double exaggeration, const double size=0.5, const double offsetx=0, const double offsety=0)
draw lock icon
bool isMovingSelectedEdge() const
flag for moving edge
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