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 (myNet->getViewNet()->getFrontAttributeCarrier() == this) {
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 }
1219 case GNE_ATTR_SELECTED:
1222 return myNBEdge->getParametersStr();
1223 default:
1224 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1225 }
1226}
1227
1228
1231 switch (key) {
1232 case SUMO_ATTR_SHAPE:
1233 return myNBEdge->getInnerGeometry();
1234 default:
1235 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1236 }
1237}
1238
1239
1240std::string
1242 std::string result = getAttribute(key);
1243 if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
1244 result += " " + getVehicleClassNames(SVCAll, true);
1245 }
1246 return result;
1247}
1248
1249
1250void
1251GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1252 // get template editor
1254 // check if we have to update template
1255 const bool updateTemplate = templateEditor->getEdgeTemplate() ? (templateEditor->getEdgeTemplate()->getID() == getID()) : false;
1256 switch (key) {
1257 case SUMO_ATTR_WIDTH:
1259 case SUMO_ATTR_SPEED:
1260 case SUMO_ATTR_FRICTION:
1261 case SUMO_ATTR_ALLOW:
1262 case SUMO_ATTR_DISALLOW: {
1263 undoList->begin(this, "change " + getTagStr() + " attribute");
1264 const std::string origValue = myLanes.at(0)->getAttribute(key); // will have intermediate value of "lane specific"
1265 // lane specific attributes need to be changed via lanes to allow undo
1266 for (auto it : myLanes) {
1267 it->setAttribute(key, value, undoList);
1268 }
1269 // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
1270 GNEChange_Attribute::changeAttribute(this, key, value, origValue, undoList);
1271 undoList->end();
1272 break;
1273 }
1274 case SUMO_ATTR_FROM: {
1275 if (value != getAttribute(key)) {
1276 undoList->begin(this, "change " + getTagStr() + " attribute");
1277 // Remove edge from crossings of junction source
1279 // continue changing from junction
1280 GNEJunction* originalFirstParentJunction = getFromJunction();
1281 getFromJunction()->setLogicValid(false, undoList);
1282 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1283 getFromJunction()->setLogicValid(false, undoList);
1284 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1285 setAttribute(GNE_ATTR_SHAPE_START, toString(getFromJunction()->getNBNode()->getPosition()), undoList);
1287 undoList->end();
1288 // update geometries of all implicated junctions
1289 originalFirstParentJunction->updateGeometry();
1292 }
1293 break;
1294 }
1295 case SUMO_ATTR_TO: {
1296 if (value != getAttribute(key)) {
1297 undoList->begin(this, "change " + getTagStr() + " attribute");
1298 // Remove edge from crossings of junction destination
1300 // continue changing destination junction
1301 GNEJunction* originalSecondParentJunction = getToJunction();
1302 getToJunction()->setLogicValid(false, undoList);
1303 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1304 getToJunction()->setLogicValid(false, undoList);
1305 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1306 setAttribute(GNE_ATTR_SHAPE_END, toString(getToJunction()->getNBNode()->getPosition()), undoList);
1308 undoList->end();
1309 // update geometries of all implicated junctions
1310 originalSecondParentJunction->updateGeometry();
1313 }
1314 break;
1315 }
1316 case SUMO_ATTR_ID:
1317 case SUMO_ATTR_PRIORITY:
1318 case SUMO_ATTR_LENGTH:
1319 case SUMO_ATTR_TYPE:
1321 case SUMO_ATTR_DISTANCE:
1323 case GNE_ATTR_SELECTED:
1326 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1327 break;
1329 // special case for stop offset, because affects to stopOffsetExceptions (#15297)
1330 if (canParse<double>(value) && (parse<double>(value) == 0)) {
1332 }
1333 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1334 break;
1336 case GNE_ATTR_SHAPE_END: {
1337 // due to ENDPOINT_TOLERANCE, force change
1338 GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1339 break;
1340 }
1341 case SUMO_ATTR_NAME:
1342 // user cares about street names. Make sure they appear in the output
1344 OptionsCont::getOptions().set("output.street-names", "true");
1345 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1346 break;
1347 case SUMO_ATTR_NUMLANES:
1348 if (value != getAttribute(key)) {
1349 // set num lanes
1350 setNumLanes(parse<int>(value), undoList);
1351 }
1352 break;
1353 case GNE_ATTR_BIDIR:
1354 undoList->begin(this, "change " + getTagStr() + " attribute");
1355 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1356 if (myNBEdge->getTurnDestination(true) != nullptr) {
1358 GNEChange_Attribute::changeAttribute(bidi, key, value, undoList);
1359 if (myNBEdge->getGeometry() != bidi->getNBEdge()->getGeometry().reverse()
1360 && myNBEdge->getGeometry().size() == 2
1361 && bidi->getNBEdge()->getGeometry().size() == 2
1362 && myNBEdge->getBidiEdge() == nullptr) {
1363 // NBEdge::avoidOverlap was already active so we need to reset the
1364 // geometry to its default
1365 resetBothEndpoint(undoList);
1366 bidi->resetBothEndpoint(undoList);
1367 }
1368 }
1369 undoList->end();
1370 break;
1371 case SUMO_ATTR_SHAPE:
1372 // @note: assumes value of inner geometry!
1373 // actually the geometry is already updated (incrementally
1374 // during mouse movement). We set the restore point to the end
1375 // of the last change-set
1376 GNEChange_Attribute::changeAttribute(this, key, value, undoList);
1377 break;
1378 default:
1379 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1380 }
1381 // update template
1382 if (updateTemplate) {
1383 templateEditor->setEdgeTemplate(this);
1384 }
1385}
1386
1387
1388bool
1389GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
1390 switch (key) {
1391 case SUMO_ATTR_ID:
1392 return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveEdge(value, false) == nullptr);
1393 case SUMO_ATTR_FROM: {
1394 // check that is a valid ID and is different of ID of junction destination
1395 if (value == getFromJunction()->getID()) {
1396 return true;
1397 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getToJunction()->getID())) {
1398 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1399 } else {
1400 return false;
1401 }
1402 }
1403 case SUMO_ATTR_TO: {
1404 // check that is a valid ID and is different of ID of junction Source
1405 if (value == getToJunction()->getID()) {
1406 return true;
1407 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getFromJunction()->getID())) {
1408 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1409 } else {
1410 return false;
1411 }
1412 }
1413 case SUMO_ATTR_SPEED:
1414 return canParse<double>(value) && (parse<double>(value) > 0);
1415 case SUMO_ATTR_FRICTION:
1416 return canParse<double>(value) && (parse<double>(value) > 0);
1417 case SUMO_ATTR_NUMLANES:
1418 return canParse<int>(value) && (parse<double>(value) > 0);
1419 case SUMO_ATTR_PRIORITY:
1420 return canParse<int>(value);
1421 case SUMO_ATTR_LENGTH:
1422 if (value.empty()) {
1423 return true;
1424 } else {
1425 return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
1426 }
1427 case SUMO_ATTR_ALLOW:
1428 case SUMO_ATTR_DISALLOW:
1429 return canParseVehicleClasses(value);
1430 case SUMO_ATTR_TYPE:
1431 return true;
1432 case SUMO_ATTR_SHAPE:
1433 // empty shapes are allowed
1434 return canParse<PositionVector>(value);
1437 case SUMO_ATTR_NAME:
1438 return true;
1439 case SUMO_ATTR_WIDTH:
1440 if (value.empty() || (value == "default")) {
1441 return true;
1442 } else {
1443 return canParse<double>(value) && ((parse<double>(value) >= -1) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
1444 }
1446 return canParse<double>(value) && parse<double>(value) >= 0 && parse<double>(value) < myNBEdge->getLoadedLength();
1447 case SUMO_ATTR_DISTANCE:
1448 if (value.empty()) {
1449 return true;
1450 } else {
1451 return canParse<double>(value);
1452 }
1453 case GNE_ATTR_SHAPE_START: {
1454 if (value.empty()) {
1455 return true;
1456 } else if (canParse<Position>(value)) {
1457 Position shapeStart = parse<Position>(value);
1458 return (shapeStart != myNBEdge->getGeometry()[-1]);
1459 } else {
1460 return false;
1461 }
1462 }
1463 case GNE_ATTR_SHAPE_END: {
1464 if (value.empty()) {
1465 return true;
1466 } else if (canParse<Position>(value)) {
1467 Position shapeEnd = parse<Position>(value);
1468 return (shapeEnd != myNBEdge->getGeometry()[0]);
1469 } else {
1470 return false;
1471 }
1472 }
1473 case GNE_ATTR_BIDIR:
1474 return canParse<bool>(value) && (!parse<bool>(value) || myNBEdge->isBidiEdge(true));
1476 if (value.empty()) {
1477 return true;
1478 } else {
1479 return canParse<double>(value) && (parse<double>(value) >= 0);
1480 }
1482 return canParseVehicleClasses(value);
1483 case GNE_ATTR_SELECTED:
1484 return canParse<bool>(value);
1487 default:
1488 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1489 }
1490}
1491
1492
1493bool
1495 switch (key) {
1496 case GNE_ATTR_BIDIR:
1497 return myNBEdge->isBidiEdge(true);
1499 return myNBEdge->myEdgeStopOffset.getOffset() > 0;
1501 return false;
1502 default:
1503 return true;
1504 }
1505}
1506
1507
1508bool
1510 switch (key) {
1511 case SUMO_ATTR_LENGTH:
1512 return !myNBEdge->hasLoadedLength();
1513 case SUMO_ATTR_WIDTH:
1515 return false;
1516 } else {
1518 }
1519 default:
1520 return false;
1521 }
1522}
1523
1524
1525const Parameterised::Map&
1529
1530
1531void
1533 myAmResponsible = newVal;
1534}
1535
1536
1537GNELane*
1539 // iterate over all NBEdge lanes
1540 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1541 // if given VClass is in permissions, return lane
1542 if (myNBEdge->getLanes().at(i).permissions & vClass) {
1543 // return GNELane
1544 return myLanes.at(i);
1545 }
1546 }
1547 // return first lane
1548 return myLanes.front();
1549}
1550
1551
1552GNELane*
1554 // iterate over all NBEdge lanes
1555 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1556 // if given VClass isn't in permissions, return lane
1557 if (~(myNBEdge->getLanes().at(i).permissions) & vClass) {
1558 // return GNELane
1559 return myLanes.at(i);
1560 }
1561 }
1562 // return first lane
1563 return myLanes.front();
1564}
1565
1566
1567void
1569 // get lane vehicles map
1570 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1571 // iterate over every lane
1572 for (const auto& laneVehicle : laneVehiclesMap) {
1573 // obtain total length
1574 double totalLength = 0;
1575 for (const auto& vehicle : laneVehicle.second) {
1576 totalLength += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1577 }
1578 // calculate multiplier for vehicle positions
1579 double multiplier = 1;
1580 const double laneShapeLength = laneVehicle.first->getLaneShape().length();
1581 if (laneShapeLength == 0) {
1582 multiplier = 0;
1583 } else if (totalLength > laneShapeLength) {
1584 multiplier = (laneShapeLength / totalLength);
1585 }
1586 // declare current length
1587 double length = 0;
1588 // iterate over vehicles to calculate position and rotations
1589 for (const auto& vehicle : laneVehicle.second) {
1590 vehicle->updateDemandElementSpreadGeometry(laneVehicle.first, length * multiplier);
1591 // update length
1592 length += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1593 }
1594 }
1595}
1596
1597
1598void
1600 // get lane vehicles map
1601 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1602 // iterate over laneVehiclesMap and obtain a vector with
1603 for (const auto& vehicleMap : laneVehiclesMap) {
1604 // declare map for sort vehicles using their departpos+length position (StackPosition)
1605 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosVehicles;
1606 // declare vector of stack demand elements
1607 std::vector<GNEEdge::StackDemandElements> stackedVehicles;
1608 // iterate over vehicles
1609 for (const auto& vehicle : vehicleMap.second) {
1610 // get vehicle's depart pos and length
1611 const double departPos = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1612 const double length = vehicle->getAttributeDouble(SUMO_ATTR_LENGTH);
1613 double posOverLane = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1614 // check if we have to adapt posOverLane
1615 if (posOverLane < 0) {
1616 posOverLane += vehicleMap.first->getLaneShape().length();
1617 }
1618 // make a stack position using departPos and length
1619 departPosVehicles.push_back(std::make_pair(StackPosition(departPos, length), vehicle));
1620 // update depart element geometry
1621 vehicle->updateDemandElementGeometry(vehicleMap.first, posOverLane);
1622 // reset vehicle stack label
1623 vehicle->updateDemandElementStackLabel(0);
1624 }
1625
1626 // sort departPosVehicles
1627 std::sort(departPosVehicles.begin(), departPosVehicles.end());
1628 // iterate over departPosVehicles
1629 for (const auto& departPosVehicle : departPosVehicles) {
1630 // obtain stack position and vehicle
1631 const GNEEdge::StackPosition& vehicleStackPosition = departPosVehicle.first;
1632 GNEDemandElement* vehicle = departPosVehicle.second;
1633 // if stackedVehicles is empty, add a new StackDemandElements
1634 if (stackedVehicles.empty()) {
1635 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1636 } else if (areStackPositionOverlapped(vehicleStackPosition, stackedVehicles.back().getStackPosition())) {
1637 // add new vehicle to last inserted stackDemandElements
1638 stackedVehicles[stackedVehicles.size() - 1].addDemandElements(vehicle);
1639 } else {
1640 // No overlapping, then add a new StackDemandElements
1641 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1642 }
1643 }
1644 // iterate over stackedVehicles
1645 for (const auto& vehicle : stackedVehicles) {
1646 // only update vehicles with one or more stack
1647 if (vehicle.getDemandElements().size() > 1) {
1648 // set stack labels
1649 vehicle.getDemandElements().front()->updateDemandElementStackLabel((int)vehicle.getDemandElements().size());
1650 }
1651 }
1652 }
1653}
1654
1655
1656void
1658 // get lane persons map
1659 const std::map<const GNELane*, std::vector<GNEDemandElement*> > lanePersonsMap = getPersonsOverEdgeMap();
1660 // iterate over lanePersonsMap and obtain a vector with
1661 for (const auto& personMap : lanePersonsMap) {
1662 // declare map for sort persons using their departpos+length position (StackPosition)
1663 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosPersons;
1664 // declare vector of stack demand elements
1665 std::vector<GNEEdge::StackDemandElements> stackedPersons;
1666 // iterate over persons
1667 for (const auto& person : personMap.second) {
1668 // get person's depart pos and length
1669 const double departPos = person->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1670 // make a stack position using departPos and length
1671 departPosPersons.push_back(std::make_pair(StackPosition(departPos, 1.8), person));
1672 // update depart element geometry
1673 person->updateDemandElementGeometry(personMap.first, departPos);
1674 // reset person stack label
1675 person->updateDemandElementStackLabel(0);
1676 }
1677
1678 // sort departPosPersons
1679 std::sort(departPosPersons.begin(), departPosPersons.end());
1680 // iterate over departPosPersons
1681 for (const auto& departPosPerson : departPosPersons) {
1682 // obtain stack position and person
1683 const GNEEdge::StackPosition& personStackPosition = departPosPerson.first;
1684 GNEDemandElement* person = departPosPerson.second;
1685 // if stackedPersons is empty, add a new StackDemandElements
1686 if (stackedPersons.empty()) {
1687 stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1688 } else if (areStackPositionOverlapped(personStackPosition, stackedPersons.back().getStackPosition())) {
1689 // add new person to last inserted stackDemandElements
1690 stackedPersons[stackedPersons.size() - 1].addDemandElements(person);
1691 } else {
1692 // No overlapping, then add a new StackDemandElements
1693 stackedPersons.push_back(GNEEdge::StackDemandElements(personStackPosition, person));
1694 }
1695 }
1696 // iterate over stackedPersons
1697 for (const auto& person : stackedPersons) {
1698 // only update persons with one or more stack
1699 if (person.getDemandElements().size() > 1) {
1700 // set stack labels
1701 person.getDemandElements().front()->updateDemandElementStackLabel((int)person.getDemandElements().size());
1702 }
1703 }
1704 }
1705}
1706
1707
1708void
1710 // get lane containers map
1711 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneContainersMap = getContainersOverEdgeMap();
1712 // iterate over laneContainersMap and obtain a vector with
1713 for (const auto& containerMap : laneContainersMap) {
1714 // declare map for sort containers using their departpos+length position (StackPosition)
1715 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosContainers;
1716 // declare vector of stack demand elements
1717 std::vector<GNEEdge::StackDemandElements> stackedContainers;
1718 // iterate over containers
1719 for (const auto& container : containerMap.second) {
1720 // get container's depart pos and length
1721 const double departPos = container->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1722 // make a stack position using departPos and length
1723 departPosContainers.push_back(std::make_pair(StackPosition(departPos, 1.8), container));
1724 // update depart element geometry
1725 container->updateDemandElementGeometry(containerMap.first, departPos);
1726 // reset container stack label
1727 container->updateDemandElementStackLabel(0);
1728 }
1729
1730 // sort departPosContainers
1731 std::sort(departPosContainers.begin(), departPosContainers.end());
1732 // iterate over departPosContainers
1733 for (const auto& departPosContainer : departPosContainers) {
1734 // obtain stack position and container
1735 const GNEEdge::StackPosition& containerStackPosition = departPosContainer.first;
1736 GNEDemandElement* container = departPosContainer.second;
1737 // if stackedContainers is empty, add a new StackDemandElements
1738 if (stackedContainers.empty()) {
1739 stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1740 } else if (areStackPositionOverlapped(containerStackPosition, stackedContainers.back().getStackPosition())) {
1741 // add new container to last inserted stackDemandElements
1742 stackedContainers[stackedContainers.size() - 1].addDemandElements(container);
1743 } else {
1744 // No overlapping, then add a new StackDemandElements
1745 stackedContainers.push_back(GNEEdge::StackDemandElements(containerStackPosition, container));
1746 }
1747 }
1748 // iterate over stackedContainers
1749 for (const auto& container : stackedContainers) {
1750 // only update containers with one or more stack
1751 if (container.getDemandElements().size() > 1) {
1752 // set stack labels
1753 container.getDemandElements().front()->updateDemandElementStackLabel((int)container.getDemandElements().size());
1754 }
1755 }
1756 }
1757}
1758
1759
1760bool
1762 // calculate angle between both junction positions
1763 double edgeAngle = RAD2DEG(getFromJunction()->getPositionInView().angleTo2D(getToJunction()->getPositionInView()));
1764 // adjust to 360 degrees
1765 while (edgeAngle < 0) {
1766 edgeAngle += 360;
1767 }
1768 // fmod round towards zero which is not want we want for negative numbers
1769 edgeAngle = fmod(edgeAngle, 360);
1770 // check angle
1771 return edgeAngle >= 0 && edgeAngle < 180;
1772}
1773
1774
1775bool
1777 // get incoming edges
1778 const auto incomingEdges = getFromJunction()->getGNEIncomingEdges();
1779 // iterate over connections
1780 for (const auto& incomingEdge : incomingEdges) {
1781 for (const auto& connection : incomingEdge->getGNEConnections()) {
1782 if (connection->getEdgeTo() == this) {
1783 return true;
1784 }
1785 }
1786 }
1787 return false;
1788}
1789
1790
1791bool
1793 return (myGNEConnections.size() > 0);
1794}
1795
1796
1797GNEEdge*
1799 for (const auto& outgoingEdge : getParentJunctions().back()->getGNEOutgoingEdges()) {
1800 if (outgoingEdge->getToJunction() == getFromJunction()) {
1801 return outgoingEdge;
1802 }
1803 }
1804 return nullptr;
1805}
1806
1807// ===========================================================================
1808// private
1809// ===========================================================================
1810
1811GNEEdge::StackPosition::StackPosition(const double departPos, const double length) :
1812 pair(departPos, departPos + length) {
1813}
1814
1815
1816double
1818 return first;
1819}
1820
1821
1822double
1824 return second;
1825}
1826
1827
1829 pair(stackedPosition, {
1830 demandElement
1831}) {
1832}
1833
1834
1835void
1837 second.push_back(demandElement);
1838}
1839
1840
1843 return first;
1844}
1845
1846
1847const std::vector<GNEDemandElement*>&
1849 return second;
1850}
1851
1852
1853void
1854GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
1855 switch (key) {
1856 case SUMO_ATTR_ID:
1857 myNet->getAttributeCarriers()->updateEdgeID(this, value);
1858 // enable save demand elements if there are stops
1859 for (const auto& stop : getChildDemandElements()) {
1860 if (stop->getTagProperty().isVehicleStop()) {
1862 }
1863 }
1864 // also for lanes
1865 for (const auto& lane : myLanes) {
1866 for (const auto& stop : lane->getChildDemandElements()) {
1867 if (stop->getTagProperty().isVehicleStop()) {
1869 }
1870 }
1871 }
1872 break;
1873 case SUMO_ATTR_FROM:
1874 myNet->changeEdgeEndpoints(this, value, getToJunction()->getID());
1875 // update this edge of list of outgoings edges of the old first parent junction
1877 // update first parent junction
1879 // update this edge of list of outgoings edges of the new first parent junction
1881 // update centering boundary and grid
1883 break;
1884 case SUMO_ATTR_TO:
1885 myNet->changeEdgeEndpoints(this, getFromJunction()->getID(), value);
1886 // update this edge of list of incomings edges of the old second parent junction
1888 // update second parent junction
1890 // update this edge of list of incomings edges of the new second parent junction
1892 // update centering boundary and grid
1894 break;
1895 case SUMO_ATTR_NUMLANES:
1896 throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
1897 case SUMO_ATTR_PRIORITY:
1898 myNBEdge->myPriority = parse<int>(value);
1899 break;
1900 case SUMO_ATTR_LENGTH:
1901 if (value.empty()) {
1903 } else {
1904 myNBEdge->setLoadedLength(parse<double>(value));
1905 }
1906 break;
1907 case SUMO_ATTR_TYPE:
1908 myNBEdge->myType = value;
1909 break;
1910 case SUMO_ATTR_SHAPE:
1911 // set new geometry
1912 setGeometry(parse<PositionVector>(value), true);
1913 // update centering boundary and grid
1915 break;
1918 break;
1919 case SUMO_ATTR_NAME:
1920 myNBEdge->setStreetName(value);
1921 break;
1922 case SUMO_ATTR_SPEED:
1923 myNBEdge->setSpeed(-1, parse<double>(value));
1924 break;
1925 case SUMO_ATTR_FRICTION:
1926 myNBEdge->setFriction(-1, parse<double>(value));
1927 break;
1928 case SUMO_ATTR_WIDTH:
1929 if (value.empty() || (value == "default")) {
1931 } else {
1932 myNBEdge->setLaneWidth(-1, parse<double>(value));
1933 }
1934 break;
1936 myNBEdge->setEndOffset(-1, parse<double>(value));
1937 break;
1938 case SUMO_ATTR_ALLOW:
1939 break; // no edge value
1940 case SUMO_ATTR_DISALLOW:
1941 break; // no edge value
1942 case SUMO_ATTR_DISTANCE:
1943 if (value.empty()) {
1944 myNBEdge->setDistance(0.0);
1945 } else {
1946 myNBEdge->setDistance(parse<double>(value));
1947 }
1948 break;
1950 myConnectionStatus = value;
1951 if (value == FEATURE_GUESSED) {
1952 WRITE_DEBUG("invalidating (removing) connections of edge '" + getID() + "' due it were guessed");
1955 } else if (value != FEATURE_GUESSED) {
1956 WRITE_DEBUG("declaring connections of edge '" + getID() + "' as loaded (It will not be removed)");
1958 }
1959 break;
1960 case GNE_ATTR_SHAPE_START: {
1961 // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1962 Position newShapeStart;
1963 if (value == "") {
1964 newShapeStart = getFromJunction()->getNBNode()->getPosition();
1965 } else {
1966 newShapeStart = parse<Position>(value);
1967 }
1968 // set shape start position
1969 setShapeStartPos(newShapeStart);
1970 // update centering boundary and grid
1972 break;
1973 }
1974 case GNE_ATTR_SHAPE_END: {
1975 // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destination position) and set it back to edge
1976 Position newShapeEnd;
1977 if (value == "") {
1978 newShapeEnd = getToJunction()->getNBNode()->getPosition();
1979 } else {
1980 newShapeEnd = parse<Position>(value);
1981 }
1982 // set shape end position
1983 setShapeEndPos(newShapeEnd);
1984 // update centering boundary and grid
1986 break;
1987 }
1988 case GNE_ATTR_BIDIR:
1989 myNBEdge->setBidi(parse<bool>(value));
1990 break;
1991 case GNE_ATTR_SELECTED:
1992 if (parse<bool>(value)) {
1994 } else {
1996 }
1997 break;
1999 if (value.empty()) {
2001 } else {
2002 myNBEdge->myEdgeStopOffset.setOffset(parse<double>(value));
2003 }
2004 break;
2007 break;
2009 myNBEdge->setParametersStr(value);
2010 break;
2011 default:
2012 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
2013 }
2014 // get template editor
2016 // check if update template (except for modification status)
2017 if (templateEditor->getEdgeTemplate() && (templateEditor->getEdgeTemplate()->getID() == getID()) &&
2020 }
2021 // invalidate demand path calculator
2023}
2024
2025
2026void
2028 // get start and end points
2029 const Position shapeStart = moveResult.shapeToUpdate.front();
2030 const Position shapeEnd = moveResult.shapeToUpdate.back();
2031 // get innen shape
2032 PositionVector innenShape = moveResult.shapeToUpdate;
2033 innenShape.pop_front();
2034 innenShape.pop_back();
2035 // set shape start
2036 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
2037 setShapeStartPos(shapeStart);
2038 }
2039 // set innen geometry
2040 setGeometry(innenShape, true);
2041 // set shape end
2042 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), ((int)moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
2043 setShapeEndPos(shapeEnd);
2044 }
2045}
2046
2047
2048void
2050 // make sure that newShape isn't empty
2051 if (moveResult.shapeToUpdate.size() > 0) {
2052 // get innen shape
2053 PositionVector innenShapeToUpdate = moveResult.shapeToUpdate;
2054 innenShapeToUpdate.pop_front();
2055 innenShapeToUpdate.pop_back();
2056 // commit new shape
2057 undoList->begin(this, "moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
2058 // update start position
2059 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
2061 }
2062 // check if update shape
2063 if (innenShapeToUpdate.size() > 0) {
2064 GNEChange_Attribute::changeAttribute(this, SUMO_ATTR_SHAPE, toString(innenShapeToUpdate), undoList);
2065 }
2066 // update end position
2067 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), ((int)moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
2069 }
2070 undoList->end();
2071 }
2072}
2073
2074
2075void
2076GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
2077 // begin undo list
2078 undoList->begin(this, "change number of " + toString(SUMO_TAG_LANE) + "s");
2079 // invalidate logic of source/destination edges
2080 getFromJunction()->setLogicValid(false, undoList);
2081 getToJunction()->setLogicValid(false, undoList);
2082 // disable update geometry (see #6336)
2083 myUpdateGeometry = false;
2084 // remove edge from grid
2086 // save old number of lanes
2087 const int oldNumLanes = (int)myLanes.size();
2088 // get opposite ID
2089 const auto oppositeID = myLanes.back()->getAttribute(GNE_ATTR_OPPOSITE);
2090 if (oppositeID != "") {
2091 // we'll have a different leftmost lane after adding/removing lanes
2093 }
2094 for (int i = oldNumLanes; i < numLanes; i++) {
2095 // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
2096 undoList->add(new GNEChange_Lane(this, myNBEdge->getLaneStruct(oldNumLanes - 1)), true);
2097 }
2098 for (int i = (oldNumLanes - 1); i > (numLanes - 1); i--) {
2099 // delete leftmost lane
2100 undoList->add(new GNEChange_Lane(this, myLanes[i], myNBEdge->getLaneStruct(i), false), true);
2101 }
2102 if (oppositeID != "") {
2103 GNEChange_Attribute::changeAttribute(myLanes.back(), GNE_ATTR_OPPOSITE, oppositeID, undoList);
2104 }
2105 // enable updateGeometry again
2106 myUpdateGeometry = true;
2107 // update geometry of entire edge
2109 // end undo list
2110 undoList->end();
2111 // update centering boundary (without updating RTREE)
2113 // insert edge in grid again
2115}
2116
2117
2118void
2119GNEEdge::updateFirstParentJunction(const std::string& value) {
2120 std::vector<GNEJunction*> parentJunctions = getParentJunctions();
2121 parentJunctions[0] = myNet->getAttributeCarriers()->retrieveJunction(value);
2122 // replace parent junctions
2123 replaceParentElements(this, parentJunctions);
2124}
2125
2126
2127void
2128GNEEdge::updateSecondParentJunction(const std::string& value) {
2129 std::vector<GNEJunction*> parentJunctions = getParentJunctions();
2130 parentJunctions[1] = myNet->getAttributeCarriers()->retrieveJunction(value);
2131 // replace parent junctions
2132 replaceParentElements(this, parentJunctions);
2133}
2134
2135
2136void
2137GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections) {
2138 const int index = lane ? lane->getIndex() : myNBEdge->getNumLanes();
2139 // the laneStruct must be created first to ensure we have some geometry
2140 // unless the connections are fully recomputed, existing indices must be shifted
2141 myNBEdge->addLane(index, true, recomputeConnections, !recomputeConnections);
2142 if (lane) {
2143 // restore a previously deleted lane
2144 myLanes.insert(myLanes.begin() + index, lane);
2145 } else {
2146 // create a new lane by copying leftmost lane
2147 lane = new GNELane(this, index);
2148 myLanes.push_back(lane);
2149 }
2150 lane->incRef("GNEEdge::addLane");
2151 // add in attributeCarriers
2153 // check if lane is selected
2154 if (lane->isAttributeCarrierSelected()) {
2155 lane->selectAttributeCarrier();
2156 }
2157 // we copy all attributes except shape since this is recomputed from edge shape
2158 myNBEdge->setSpeed(lane->getIndex(), laneAttrs.speed);
2159 myNBEdge->setFriction(lane->getIndex(), laneAttrs.friction);
2160 myNBEdge->setPermissions(laneAttrs.permissions, lane->getIndex());
2162 myNBEdge->setEndOffset(lane->getIndex(), laneAttrs.endOffset);
2163 myNBEdge->setLaneWidth(lane->getIndex(), laneAttrs.width);
2164 // update indices
2165 for (int i = 0; i < (int)myLanes.size(); ++i) {
2166 myLanes[i]->setIndex(i);
2167 }
2168 /* while technically correct, this looks ugly
2169 getFromJunction()->invalidateShape();
2170 getToJunction()->invalidateShape();
2171 */
2172 // Remake connections for this edge and all edges that target this lane
2174 // remake connections of all edges of junction source and destination
2175 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2176 fromEdge->remakeGNEConnections();
2177 }
2178 // remake connections of all edges of junction source and destination
2179 for (const auto& toEdge : getToJunction()->getChildEdges()) {
2180 toEdge->remakeGNEConnections();
2181 }
2182 // Update geometry with the new lane
2184 // update boundary and grid
2186}
2187
2188
2189void
2190GNEEdge::removeLane(GNELane* lane, bool recomputeConnections) {
2191 if (myLanes.size() == 0) {
2192 throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + getTagStr());
2193 }
2194 if (lane == nullptr) {
2195 lane = myLanes.back();
2196 }
2197 // check if lane is selected
2198 if (lane->isAttributeCarrierSelected()) {
2200 }
2201 // before removing, check that lane isn't being inspected
2204 // Delete lane of edge's container
2205 // unless the connections are fully recomputed, existing indices must be shifted
2206 myNBEdge->deleteLane(lane->getIndex(), recomputeConnections, !recomputeConnections);
2207 lane->decRef("GNEEdge::removeLane");
2208 myLanes.erase(myLanes.begin() + lane->getIndex());
2209 // remove from attributeCarriers
2211 // Delete lane if is unreferenced
2212 if (lane->unreferenced()) {
2213 // show extra information for tests
2214 WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in removeLane()");
2215 delete lane;
2216 }
2217 // update indices
2218 for (int i = 0; i < (int)myLanes.size(); ++i) {
2219 myLanes[i]->setIndex(i);
2220 }
2221 /* while technically correct, this looks ugly
2222 getFromJunction()->invalidateShape();
2223 getToJunction()->invalidateShape();
2224 */
2225 // Remake connections of this edge
2227 // remake connections of all edges of junction source and destination
2228 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
2229 fromEdge->remakeGNEConnections();
2230 }
2231 // remake connections of all edges of junction source and destination
2232 for (const auto& toEdge : getToJunction()->getChildEdges()) {
2233 toEdge->remakeGNEConnections();
2234 }
2235 // Update element
2237 // update boundary and grid
2239}
2240
2241
2242void
2243GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
2244 // If a new connection was successfully created
2246 nbCon.keepClear, nbCon.contPos, nbCon.visibility,
2247 nbCon.speed, nbCon.friction, nbCon.customLength, nbCon.customShape, nbCon.uncontrolled)) {
2248 // Create or retrieve existent GNEConnection
2249 GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
2250 // add it to GNEConnection container
2251 myGNEConnections.push_back(con);
2252 // Add reference
2253 myGNEConnections.back()->incRef("GNEEdge::addConnection");
2254 // select GNEConnection if needed
2255 if (selectAfterCreation) {
2257 }
2258 // update geometry
2259 con->updateGeometry();
2260 }
2261 // actually we only do this to force a redraw
2263}
2264
2265
2266void
2268 // check if is a explicit turnaround
2269 if (nbCon.toEdge == myNBEdge->getTurnDestination()) {
2271 }
2272 // remove NBEdge::connection from NBEdge
2274 // remove their associated GNEConnection
2275 GNEConnection* connection = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
2276 if (connection != nullptr) {
2277 // before removing, check that the connection isn't being inspected
2280 connection->decRef("GNEEdge::removeConnection");
2281 myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), connection));
2282 // check if connection is selected
2283 if (connection->isAttributeCarrierSelected()) {
2284 connection->unselectAttributeCarrier();
2285 }
2286 // remove it from network
2287 myNet->removeGLObjectFromGrid(connection);
2288 // check if remove it from Attribute Carriers
2289 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
2291 }
2292 if (connection->unreferenced()) {
2293 // show extra information for tests
2294 WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in removeConnection()");
2295 // actually we only do this to force a redraw
2297 }
2298 }
2299}
2300
2301
2303GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
2304 for (const auto& connection : myGNEConnections) {
2305 if ((connection->getFromLaneIndex() == fromLane) && (connection->getEdgeTo()->getNBEdge() == to) && (connection->getToLaneIndex() == toLane)) {
2306 return connection;
2307 }
2308 }
2309 if (createIfNoExist) {
2310 // create new connection. Will be added to the rTree on first geometry computation
2311 GNEConnection* connection = new GNEConnection(myLanes[fromLane], myNet->getAttributeCarriers()->retrieveEdge(to->getID())->getLanes()[toLane]);
2312 // show extra information for tests
2313 WRITE_DEBUG("Created " + connection->getTagStr() + " '" + connection->getID() + "' in retrieveGNEConnection()");
2314 // add it into network
2315 myNet->addGLObjectIntoGrid(connection);
2316 // add it in attributeCarriers
2318 return connection;
2319 } else {
2320 return nullptr;
2321 }
2322}
2323
2324
2325void
2326GNEEdge::setEdgeID(const std::string& newID) {
2327 setNetworkElementID(newID);
2328 for (const auto& lane : myLanes) {
2329 lane->setNetworkElementID(getNBEdge()->getLaneID(lane->getIndex()));
2330 }
2331}
2332
2333
2334bool
2336 for (const auto& lane : myLanes) {
2337 if (lane->isRestricted(vclass)) {
2338 return true;
2339 }
2340 }
2341 return false;
2342}
2343
2344
2345void
2347 // Remove all crossings that contain this edge in parameter "edges"
2348 for (const auto& crossing : junction->getGNECrossings()) {
2349 if (crossing->checkEdgeBelong(this)) {
2350 myNet->deleteCrossing(crossing, undoList);
2351 }
2352 }
2353}
2354
2355
2356void
2361 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2362 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2363}
2364
2365
2367GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
2368 const auto& neteditOptions = OptionsCont::getOptions();
2369 // distinguish 3 cases:
2370 // a) if the edge has exactly 3 or 4 points, use these as control points
2371 // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
2372 // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
2373 PositionVector init;
2374#ifdef DEBUG_SMOOTH_GEOM
2375 if (DEBUGCOND(this)) std::cout << getID()
2376 << " forElevation=" << forElevation
2377 << " fromGeometryLike=" << myNBEdge->getFromNode()->geometryLike()
2378 << " toGeometryLike=" << myNBEdge->getToNode()->geometryLike()
2379 << " smoothShape old=" << old << "\n";
2380#endif
2381 if (old.size() == 3 || old.size() == 4) {
2382 init = old;
2383 } else if (old.size() > 4 && !forElevation) {
2384 // for elevation, the initial segments are not useful
2385 init.push_back(old[0]);
2386 init.push_back(old[1]);
2387 init.push_back(old[-2]);
2388 init.push_back(old[-1]);
2389 } else if (myNBEdge->getFromNode()->geometryLike() && myNBEdge->getToNode()->geometryLike()) {
2390 PositionVector begShape;
2391 PositionVector endShape;
2392 const EdgeVector& incoming = myNBEdge->getFromNode()->getIncomingEdges();
2393 const EdgeVector& outgoing = myNBEdge->getToNode()->getOutgoingEdges();
2394 if (incoming.size() == 1) {
2395 begShape = incoming[0]->getGeometry();
2396 } else {
2397 assert(incoming.size() == 2);
2398 begShape = myNBEdge->isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
2399 }
2400 if (outgoing.size() == 1) {
2401 endShape = outgoing[0]->getGeometry();
2402 } else {
2403 assert(outgoing.size() == 2);
2404 endShape = myNBEdge->isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
2405 }
2406 const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
2407 if (forElevation) {
2408 // initialize control point elevation for smooth continuation
2409 init.push_back(old[0]);
2410 init.push_back(old.positionAtOffset2D(dist));
2411 init.push_back(old.positionAtOffset2D(old.length2D() - dist));
2412 init.push_back(old[-1]);
2413 double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
2414 double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
2415 // continue incline
2416 init[1].setz(2 * init[0].z() - begZ);
2417 init[2].setz(2 * init[-1].z() - endZ);
2418 } else {
2419 bool ok = true;
2420 const double straightThresh = DEG2RAD(neteditOptions.getFloat("opendrive-output.straight-threshold"));
2421 init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, nullptr, straightThresh);
2422 }
2423#ifdef DEBUG_SMOOTH_GEOM
2424 if (DEBUGCOND(this)) {
2425 std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
2426 }
2427#endif
2428 }
2429 if (init.size() == 0) {
2430 return PositionVector::EMPTY;
2431 } else {
2432 const int numPoints = MAX2(neteditOptions.getInt("junctions.internal-link-detail"),
2433 int(old.length2D() / neteditOptions.getFloat("opendrive.curve-resolution")));
2434 return init.bezier(numPoints);
2435 }
2436}
2437
2438
2439void
2441 PositionVector modifiedShape = smoothShape(myNBEdge->getGeometry(), false);
2442 if (modifiedShape.size() < 2) {
2443 WRITE_WARNINGF(TL("Could not compute smooth shape for edge '%'"), getID());
2444 } else {
2445 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2446 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2447 }
2448}
2449
2450
2451void
2453 PositionVector elevationBase;
2454 for (const Position& pos : myNBEdge->getGeometry()) {
2455 if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
2456 elevationBase.push_back(pos);
2457 }
2458 }
2459 PositionVector elevation = smoothShape(elevationBase, true);
2460 if (elevation.size() <= 2) {
2461 WRITE_WARNINGF(TL("Could not compute smooth elevation for edge '%'"), getID());
2462 } else {
2463 PositionVector modifiedShape = myNBEdge->getGeometry();
2464 if (modifiedShape.size() < 5) {
2465 modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"), false);
2466 }
2467 const double scale = elevation.length2D() / modifiedShape.length2D();
2468 //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
2469 double seen = 0;
2470 for (int i = 1; i < (int)modifiedShape.size(); ++i) {
2471 seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
2472 modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
2473 }
2474 //std::cout << " mod2=" << modifiedShape << "\n";
2475 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2476 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2477 }
2478}
2479
2480
2481void
2483 // remove start position and add it the new position
2485 geom.pop_front();
2486 geom.push_front(pos);
2487 // restore modified shape
2488 setGeometry(geom, false);
2489}
2490
2491
2492void
2494 // remove end position and add it the new position
2496 geom.pop_back();
2497 geom.push_back(pos);
2498 // restore modified shape
2499 setGeometry(geom, false);
2500}
2501
2502
2503const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2505 // declare vehicles over edge vector
2506 std::vector<GNEDemandElement*> vehiclesOverEdge;
2507 // declare solution map
2508 std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesOverEdgeMap;
2509 // declare a set of vehicles (to avoid duplicates)
2510 std::set<std::pair<double, GNEDemandElement*> > vehicles;
2511 // first obtain all vehicles of this edge
2512 for (const auto& edgeChild : getChildDemandElements()) {
2513 if (((edgeChild->getTagProperty().getTag() == SUMO_TAG_TRIP) || (edgeChild->getTagProperty().getTag() == SUMO_TAG_FLOW)) &&
2514 (edgeChild->getParentEdges().front() == this)) {
2515 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2516 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2517 } else if ((edgeChild->getTagProperty().getTag() == SUMO_TAG_ROUTE) && (edgeChild->getParentEdges().front() == this)) {
2518 for (const auto& routeChild : edgeChild->getChildDemandElements()) {
2519 if (routeChild->getTagProperty().vehicleRoute()) {
2520 vehicles.insert(std::make_pair(routeChild->getAttributeDouble(SUMO_ATTR_DEPART), routeChild));
2521 }
2522 }
2523 } else if ((edgeChild->getTagProperty().getTag() == GNE_TAG_ROUTE_EMBEDDED) && (edgeChild->getParentEdges().front() == this)) {
2524 vehicles.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild->getParentDemandElements().front()));
2525 }
2526 }
2527 // reserve
2528 vehiclesOverEdge.reserve(vehicles.size());
2529 // iterate over vehicles
2530 for (const auto& vehicle : vehicles) {
2531 // add it over vehiclesOverEdge;
2532 vehiclesOverEdge.push_back(vehicle.second);
2533 }
2534 // now split vehicles by lanes
2535 for (const auto& vehicle : vehiclesOverEdge) {
2536 const GNELane* vehicleLane = vehicle->getFirstPathLane();
2537 if (vehicleLane) {
2538 vehiclesOverEdgeMap[vehicleLane].push_back(vehicle);
2539 }
2540 }
2541 return vehiclesOverEdgeMap;
2542}
2543
2544
2545const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2547 // declare persons over edge vector
2548 std::vector<GNEDemandElement*> personsOverEdge;
2549 // declare solution map
2550 std::map<const GNELane*, std::vector<GNEDemandElement*> > personsOverEdgeMap;
2551 // declare a set of persons (to avoid duplicates)
2552 std::set<std::pair<double, GNEDemandElement*> > persons;
2553 // first obtain all persons of this edge
2554 for (const auto& edgeChild : getChildDemandElements()) {
2555 if (edgeChild->getTagProperty().isPlanPerson()) {
2556 persons.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2557 }
2558 }
2559 // reserve
2560 personsOverEdge.reserve(persons.size());
2561 // iterate over persons
2562 for (const auto& person : persons) {
2563 // add it over personsOverEdge;
2564 personsOverEdge.push_back(person.second);
2565 }
2566 // now split persons by lanes
2567 for (const auto& person : personsOverEdge) {
2568 const GNELane* personLane = person->getFirstPathLane();
2569 if (personLane) {
2570 personsOverEdgeMap[personLane].push_back(person);
2571 }
2572 }
2573 return personsOverEdgeMap;
2574}
2575
2576
2577
2578const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2580 // declare containers over edge vector
2581 std::vector<GNEDemandElement*> containersOverEdge;
2582 // declare solution map
2583 std::map<const GNELane*, std::vector<GNEDemandElement*> > containersOverEdgeMap;
2584 // declare a set of containers (to avoid duplicates)
2585 std::set<std::pair<double, GNEDemandElement*> > containers;
2586 // first obtain all containers of this edge
2587 for (const auto& edgeChild : getChildDemandElements()) {
2588 if (edgeChild->getTagProperty().isPlanContainer()) {
2589 containers.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPARTPOS), edgeChild->getParentDemandElements().front()));
2590 }
2591 }
2592 // reserve
2593 containersOverEdge.reserve(containers.size());
2594 // iterate over containers
2595 for (const auto& container : containers) {
2596 // add it over containersOverEdge;
2597 containersOverEdge.push_back(container.second);
2598 }
2599 // now split containers by lanes
2600 for (const auto& container : containersOverEdge) {
2601 const GNELane* containerLane = container->getFirstPathLane();
2602 if (containerLane) {
2603 containersOverEdgeMap[containerLane].push_back(container);
2604 }
2605 }
2606 return containersOverEdgeMap;
2607}
2608
2609
2610void
2612 // first check conditions
2614 // check if draw geometry points
2615 const bool bigGeometryPoints = drawBigGeometryPoints();
2616 // Obtain exaggeration of the draw
2617 const double exaggeration = getExaggeration(s);
2618 // get geometry point radius
2619 const double geometryPointRadius = getGeometryPointRadius();
2620 // obtain geometry point color
2621 RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2622 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2623 // override with special colors (unless the color scheme is based on selection)
2624 geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2625 }
2626 // draw geometry points except initial and final
2627 for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
2628 // obtain geometry point
2629 const auto geometryPointPos = myNBEdge->getGeometry()[i];
2630 // push geometry point drawing matrix
2632 // set color
2633 GLHelper::setColor(geometryPointColor);
2634 // move geometry point geometryPointPos
2635 glTranslated(geometryPointPos.x(), geometryPointPos.y(), bigGeometryPoints ? GLO_GEOMETRYPOINT : GLO_LANE + 1);
2636 // draw filled circle (resolution of drawn circle depending of the zoom, to improve smoothness)
2637 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius);
2638 // draw elevation or special symbols (Start, End and Block)
2640 // Translate to top
2641 glTranslated(0, 0, 0.2);
2642 // draw Z value
2643 GLHelper::drawText(toString(geometryPointPos.z()), Position(), 0, s.edgeValue.scaledSize(s.scale) / 2, s.edgeValue.color);
2644 }
2645 // pop geometry point drawing matrix
2647 }
2648 // draw start and end points
2649 if (bigGeometryPoints) {
2650 drawStartGeometryPoint(s, d, geometryPointRadius, layer, exaggeration);
2651 drawEndGeometryPoint(s, d, geometryPointRadius, layer, exaggeration);
2652 }
2653 // draw dotted contour geometry points
2656 }
2657}
2658
2659
2660void
2662 const double geometryPointRadius, const double layer, const double exaggeration) const {
2663 // check detail level
2665 // get first geometry point
2666 const auto& startGeometryPointPos = myNBEdge->getGeometry().front();
2667 // get flags
2668 const bool startPosEdited = (startGeometryPointPos != getParentJunctions().front()->getPositionInView());
2670 // check drawing conditions
2671 if (startPosEdited || forceDraw) {
2672 // calculate angle betwen first and second geometry point
2673 const double angle = RAD2DEG(startGeometryPointPos.angleTo2D(myNBEdge->getGeometry()[1])) * -1;
2674 // get selected geometry points
2675 const auto selectedGeometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(this);
2676 // override with special colors (unless the color scheme is based on selection)
2677 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2679 } else {
2680 GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2681 }
2682 // push drawing matrix
2684 // move to point position
2685 glTranslated(startGeometryPointPos.x(), startGeometryPointPos.y(), GLO_GEOMETRYPOINT);
2686 // resolution of drawn circle depending of detail
2687 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2688 // pop drawing matrix
2690 // draw a "s" over last point depending of detail level
2692 // push drawing matrix
2694 // move top
2695 glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2696 // draw S
2697 GLHelper::drawText("S", startGeometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2698 // pop drawing matrix
2700 // check if draw line between junctions
2701 if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.front() == 0)) {
2702 // set base color
2704 // push drawing matrix
2706 // draw line between geometry point and from junction
2707 const PositionVector lineA = {startGeometryPointPos, getFromJunction()->getNBNode()->getPosition()};
2708 GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2709 // draw line between begin point of last lane shape and the first edge shape point
2710 const PositionVector lineB = {startGeometryPointPos, myNBEdge->getLanes().back().shape.front()};
2711 GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2712 // pop drawing matrix
2714 }
2715 }
2716 // draw dotted contour geometry points
2718 geometryPointRadius, exaggeration);
2719 }
2720 }
2721}
2722
2723
2724void
2726 const double layer, const double geometryPointRadius, const double exaggeration) const {
2727 // check detail level
2729 // get first geometry point
2730 const auto& geometryPointPos = myNBEdge->getGeometry().back();
2731 // get flags
2732 const bool endPosEdited = (geometryPointPos != getParentJunctions().back()->getPositionInView());
2734 // check drawing conditions
2735 if (endPosEdited || forceDraw) {
2736 // calculate angle last and previous geometry point
2737 const double angle = RAD2DEG(geometryPointPos.angleTo2D(myNBEdge->getGeometry()[-2])) * -1;
2738 // get selected geometry points
2739 const auto selectedGeometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(this);
2740 // override with special colors (unless the color scheme is based on selection)
2741 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2743 } else {
2744 GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
2745 }
2746 // push drawing matrix
2748 // move to point position
2749 glTranslated(geometryPointPos.x(), geometryPointPos.y(), GLO_GEOMETRYPOINT);
2750 // resolution of drawn circle depending of detail
2751 GLHelper::drawFilledCircleDetailled(d, geometryPointRadius, angle + 90, angle + 270);
2752 // pop drawing matrix
2754 // draw a "s" over last point depending of detail level
2756 // push drawing matrix
2758 // move top
2759 glTranslated(0, 0, GLO_GEOMETRYPOINT + 0.1);
2760 // draw S
2761 GLHelper::drawText("E", geometryPointPos, 0, geometryPointRadius, RGBColor(0, 50, 255));
2762 // pop drawing matrix
2764 // check if draw line between junctions
2765 if ((selectedGeometryPoints.size() > 0) && (selectedGeometryPoints.back() == ((int)myNBEdge->getGeometry().size() - 1))) {
2766 // set base color
2768 // push drawing matrix
2770 // draw line between geometry point and from junction
2771 const PositionVector lineA = {geometryPointPos, getToJunction()->getNBNode()->getPosition()};
2772 GLHelper::drawBoxLine(lineA[1], RAD2DEG(lineA[0].angleTo2D(lineA[1])) - 90, lineA[0].distanceTo2D(lineA[1]), .1);
2773 // draw line between begin point of last lane shape and the first edge shape point
2774 const PositionVector lineB = {geometryPointPos, myNBEdge->getLanes().back().shape.back()};
2775 GLHelper::drawBoxLine(lineB[1], RAD2DEG(lineB[0].angleTo2D(lineB[1])) - 90, lineB[0].distanceTo2D(lineB[1]), .1);
2776 // pop drawing matrix
2778 }
2779 }
2780 // draw dotted contour geometry points
2782 geometryPointRadius, exaggeration);
2783 }
2784 }
2785}
2786
2787
2788void
2790 // draw the name and/or the street name
2791 const bool drawStreetName = s.streetName.show(this) && (myNBEdge->getStreetName() != "");
2792 const bool spreadSuperposed = s.spreadSuperposed && myNBEdge->getBidiEdge() != nullptr;
2793 // check conditions
2794 if (s.edgeName.show(this) || drawStreetName || s.edgeValue.show(this)) {
2795 // get first and last lanes
2796 const GNELane* firstLane = myLanes[0];
2797 const GNELane* lastLane = myLanes[myLanes.size() - 1];
2798 // calculate draw position
2799 Position drawPosition = firstLane->getLaneShape().positionAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2800 drawPosition.add(lastLane->getLaneShape().positionAtOffset(lastLane->getLaneShape().length() / (double) 2.));
2801 drawPosition.mul(.5);
2802 if (spreadSuperposed) {
2803 // move name to the right of the edge and towards its beginning
2804 const double dist = 0.6 * s.edgeName.scaledSize(s.scale);
2805 const double shiftA = firstLane->getLaneShape().rotationAtOffset(firstLane->getLaneShape().length() / (double) 2.) - DEG2RAD(135);
2806 const Position shift(dist * cos(shiftA), dist * sin(shiftA));
2807 drawPosition.add(shift);
2808 }
2809 // calculate drawing angle
2810 double drawAngle = firstLane->getLaneShape().rotationDegreeAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2811 drawAngle += 90;
2812 // avoid draw inverted text
2813 if (drawAngle > 90 && drawAngle < 270) {
2814 drawAngle -= 180;
2815 }
2816 // draw edge name
2817 if (s.edgeName.show(this)) {
2818 drawName(drawPosition, s.scale, s.edgeName, drawAngle);
2819 }
2820 // draw street name
2821 if (drawStreetName) {
2822 GLHelper::drawTextSettings(s.streetName, myNBEdge->getStreetName(), drawPosition, s.scale, drawAngle);
2823 }
2824 // draw edge values
2825 if (s.edgeValue.show(this)) {
2826 // get current scheme
2827 const int activeScheme = s.laneColorer.getActive();
2828 // calculate value depending of active scheme
2829 std::string value;
2830 if (activeScheme == 12) {
2831 // edge param, could be non-numerical
2832 value = getNBEdge()->getParameter(s.edgeParam, "");
2833 } else if (activeScheme == 13) {
2834 // lane param, could be non-numerical
2835 value = getNBEdge()->getLaneStruct(lastLane->getIndex()).getParameter(s.laneParam, "");
2836 } else {
2837 // use numerical value value of leftmost lane to hopefully avoid sidewalks, bikelanes etc
2838 const double doubleValue = lastLane->getColorValue(s, activeScheme);
2839 const RGBColor color = s.laneColorer.getScheme().getColor(doubleValue);
2840 value = color.alpha() == 0 ? "" : toString(doubleValue);
2841 }
2842 // check if value is empty
2843 if (value != "") {
2844 GLHelper::drawTextSettings(s.edgeValue, value, drawPosition, s.scale, drawAngle);
2845 }
2846 }
2847 }
2848}
2849
2850
2851void
2853 // draw geometry only if we'rent in drawForObjectUnderCursor mode
2855 // Push stopOffset matrix
2857 // translate to front (note: Special case)
2860 for (const auto& lane : getLanes()) {
2861 lane->drawLaneStopOffset(s);
2862 }
2863 }
2864 // Push stopOffset matrix
2866 }
2867}
2868
2869
2870void
2872 // draw child additional
2873 for (const auto& additional : getChildAdditionals()) {
2874 additional->drawGL(s);
2875 }
2876 // draw person stops
2878 for (const auto& stopEdge : getChildDemandElements()) {
2879 if ((stopEdge->getTagProperty().getTag() == GNE_TAG_STOPPERSON_EDGE) || (stopEdge->getTagProperty().getTag() == GNE_TAG_STOPCONTAINER_EDGE)) {
2880 stopEdge->drawGL(s);
2881 }
2882 }
2883 }
2884 // draw vehicles
2885 const std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesMap = getVehiclesOverEdgeMap();
2886 for (const auto& vehicleMap : vehiclesMap) {
2887 for (const auto& vehicle : vehicleMap.second) {
2888 vehicle->drawGL(s);
2889 }
2890 }
2891 // draw TAZ elements
2892 drawTAZElements(s);
2893}
2894
2895
2896void
2898 // if we're selecting using a boundary, first don't calculate contour bt check if edge boundary is within selection boundary
2900 // simply add object in ViewObjectsHandler with full boundary
2901 gViewObjectsHandler.selectObject(this, layer, false, true, nullptr);
2902 } else {
2903 // get geometry point radius
2904 const auto geometryPointRadius = getGeometryPointRadius();
2905 // check if edit extrems
2907 const bool firstExtrem = forceDrawExtrems || (myNBEdge->getGeometry().front() != getParentJunctions().front()->getPositionInView());
2908 const bool lastExtrem = forceDrawExtrems || (myNBEdge->getGeometry().back() != getParentJunctions().back()->getPositionInView());
2909 // check if we're in move mode
2911 // calculate contour
2912 myNetworkElementContour.calculateContourEdge(s, d, this, this, layer, true, true);
2913 // calculate edge geometry points
2914 myNetworkElementContour.calculateContourEdgeGeometryPoints(s, d, this, geometryPointRadius, moveMode, firstExtrem, lastExtrem);
2915 }
2916}
2917
2918
2919void
2921 // first check if draw TAZ Elements is enabled
2923 std::vector<GNEAdditional*> TAZSourceSinks;
2924 // get all TAZ source/sinks vinculated with this edge
2925 for (const auto& additional : getChildAdditionals()) {
2926 if ((additional->getTagProperty().getTag() == SUMO_TAG_TAZSOURCE) ||
2927 (additional->getTagProperty().getTag() == SUMO_TAG_TAZSINK)) {
2928 TAZSourceSinks.push_back(additional);
2929 }
2930 }
2931 if (TAZSourceSinks.size() > 0) {
2932 // check if TAZ Source/sink is selected
2933 bool selected = false;
2934 for (const auto& TAZSourceSink : TAZSourceSinks) {
2935 if (TAZSourceSink->isAttributeCarrierSelected()) {
2936 selected = true;
2937 }
2938 }
2939 // iterate over lanes
2940 for (const auto& lane : myLanes) {
2941 // Push layer matrix
2943 // translate to front (note: Special case)
2944 if (myNet->getViewNet()->getFrontAttributeCarrier() == this) {
2945 glTranslated(0, 0, GLO_FRONTELEMENT);
2946 } else if (lane->getLaneShape().length2D() <= (s.neteditSizeSettings.junctionBubbleRadius * 2)) {
2948 } else {
2950 }
2951 // move to front
2952 glTranslated(0, 0, 0.1);
2953 // set color
2954 if (selected) {
2956 } else {
2958 }
2959 // draw as box lines
2961 lane->getDrawingConstants()->getDrawingWidth());
2962 // Pop layer matrix
2964 }
2965 /*
2966 // check if curently we're inspecting a TAZ Source/Sink
2967 for (const auto& TAZSourceSink : TAZSourceSinks) {
2968 if (myNet->getViewNet()->isAttributeCarrierInspected(TAZSourceSink)) {
2969 drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::INSPECT, this, true, true);
2970 } else if (TAZSourceSink == frontAC) {
2971 drawDottedContourEdge(s, GUIDottedGeometry::DottedContourType::FRONT, this, true, true);
2972 }
2973 }
2974 */
2975 }
2976 }
2977}
2978
2979
2980void
2982 // avoid draw for railways
2983 if ((d <= GUIVisualizationSettings::Detail::LaneDetails) && !myLanes.front()->getDrawingConstants()->drawAsRailway() &&
2985 // push draw matrix
2987 // translate to front depending of big points
2988 if (drawBigGeometryPoints()) {
2989 glTranslated(0, 0, GLO_GEOMETRYPOINT - 1);
2990 } else {
2991 glTranslated(0, 0, layer);
2992 }
2993 // obtain color
2994 RGBColor geometryPointColor = s.junctionColorer.getSchemes()[0].getColor(2);
2995 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
2996 // override with special colors (unless the color scheme is based on selection)
2997 geometryPointColor = s.colorSettings.selectedEdgeColor.changedBrightness(-20);
2998 }
2999 // set color
3000 GLHelper::setColor(geometryPointColor);
3001 // iterate over NBEdge geometry
3002 for (int i = 1; i < (int)myNBEdge->getGeometry().size(); i++) {
3003 // calculate line between previous and current geometry point
3004 PositionVector line = {myNBEdge->getGeometry()[i - 1], myNBEdge->getGeometry()[i]};
3005 line.move2side(0.2);
3006 // draw box line
3007 GLHelper::drawBoxLine(line[1], RAD2DEG(line[0].angleTo2D(line[1])) - 90, line[0].distanceTo2D(line[1]), .1);
3008 }
3009 // pop draw matrix
3011 }
3012}
3013
3014
3015bool
3017 // get edit modes
3018 const auto& editModes = myNet->getViewNet()->getEditModes();
3019 // continue depending of conditions
3020 if (!editModes.isCurrentSupermodeNetwork()) {
3021 return false;
3022 } else if (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) {
3023 return true;
3024 } else if ((editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE) &&
3026 return true;
3027 } else {
3028 return false;
3029 }
3030}
3031
3032
3033bool
3035 if ((vehicleA.beginPosition() == vehicleB.beginPosition()) && (vehicleA.endPosition() == vehicleB.endPosition())) {
3036 return true;
3037 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
3038 return true;
3039 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.beginPosition())) {
3040 return true;
3041 } else if ((vehicleA.beginPosition() < vehicleB.endPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
3042 return true;
3043 } else {
3044 return false;
3045 }
3046}
3047
3048
3050GNEEdge::processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
3051 // calculate squared snapRadius
3052 const double squaredSnapRadius = (snapRadius * snapRadius);
3053 // declare shape to move
3054 PositionVector shapeToMove = originalShape;
3055 // obtain nearest index
3056 const int nearestIndex = originalShape.indexOfClosest(mousePosition);
3057 // obtain nearest position
3058 const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
3059 // generate indexes
3060 std::vector<int> indexes;
3061 // check conditions
3062 if (nearestIndex == -1) {
3063 return nullptr;
3064 } else if (nearestPosition == Position::INVALID) {
3065 // special case for extremes
3066 if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3067 for (int i = 1; i <= nearestIndex; i++) {
3068 indexes.push_back(i);
3069 }
3070 // move extrem without creating new geometry point
3071 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3072 } else {
3073 return nullptr;
3074 }
3075 } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3076 for (int i = 1; i <= nearestIndex; i++) {
3077 indexes.push_back(i);
3078 }
3079 // move geometry point without creating new geometry point
3080 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3081 } else {
3082 // create new geometry point and keep new index (if we clicked near of shape)
3083 const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
3084 for (int i = 1; i <= newIndex; i++) {
3085 indexes.push_back(i);
3086 }
3087 // move after setting new geometry point in shapeToMove
3088 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3089 }
3090}
3091
3092
3094GNEEdge::processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
3095 // calculate squared snapRadius
3096 const double squaredSnapRadius = (snapRadius * snapRadius);
3097 // declare shape to move
3098 PositionVector shapeToMove = originalShape;
3099 // obtain nearest index
3100 const int nearestIndex = originalShape.indexOfClosest(mousePosition);
3101 // obtain nearest position
3102 const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
3103 // generate indexes
3104 std::vector<int> indexes;
3105 // check conditions
3106 if (nearestIndex == -1) {
3107 return nullptr;
3108 } else if (nearestPosition == Position::INVALID) {
3109 // special case for extremes
3110 if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3111 for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
3112 indexes.push_back(i);
3113 }
3114 // move extrem without creating new geometry point
3115 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3116 } else {
3117 return nullptr;
3118 }
3119 } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
3120 for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
3121 indexes.push_back(i);
3122 }
3123 // move geometry point without creating new geometry point
3124 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3125 } else {
3126 // create new geometry point and keep new index (if we clicked near of shape)
3127 const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
3128 for (int i = newIndex; i < ((int)originalShape.size() - 1); i++) {
3129 indexes.push_back(i);
3130 }
3131 // move after setting new geometry point in shapeToMove
3132 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
3133 }
3134}
3135
3136
3139 std::vector<int> geometryPointsToMove;
3140 for (int i = 0; i < (int)myNBEdge->getGeometry().size(); i++) {
3141 geometryPointsToMove.push_back(i);
3142 }
3143 // move entire shape (including extremes)
3144 return new GNEMoveOperation(this, myNBEdge->getGeometry(), geometryPointsToMove, myNBEdge->getGeometry(), geometryPointsToMove);
3145}
3146
3147
3150 // get move multiple element values
3151 const auto& moveMultipleElementValues = myNet->getViewNet()->getMoveMultipleElementValues();
3152 // declare shape to move
3153 PositionVector shapeToMove = myNBEdge->getGeometry();
3154 // first check if kept offset is larger than geometry
3155 if (shapeToMove.length2D() < moveMultipleElementValues.getEdgeOffset()) {
3156 return nullptr;
3157 }
3158 // declare offset
3159 double offset = 0;
3160 // set offset depending of convex angle
3161 if (isConvexAngle()) {
3162 offset = moveMultipleElementValues.getEdgeOffset();
3163 } else {
3164 offset = shapeToMove.length2D() - moveMultipleElementValues.getEdgeOffset();
3165 }
3166 // obtain offset position
3167 const Position offsetPosition = myNBEdge->getGeometry().positionAtOffset2D(offset);
3168 // obtain nearest index to offset position
3169 const int nearestIndex = myNBEdge->getGeometry().indexOfClosest(offsetPosition);
3170 // check conditions
3171 if ((nearestIndex == -1) || (offsetPosition == Position::INVALID)) {
3172 return nullptr;
3173 } else if (offsetPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= (snapRadius * snapRadius)) {
3174 // move geometry point without creating new geometry point
3175 return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {nearestIndex});
3176 } else {
3177 // create new geometry point and keep new index (if we clicked near of shape)
3178 const int newIndex = shapeToMove.insertAtClosest(offsetPosition, true);
3179 // move after setting new geometry point in shapeToMove
3180 return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {newIndex});
3181 }
3182}
3183
3184
3185double
3189
3190
3191/****************************************************************************/
#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_SELECTED
element is selected
@ 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:654
static void popMatrix()
pop matrix
Definition GLHelper.cpp:130
static void drawBoundary(const GUIVisualizationSettings &s, const Boundary &b)
Draw a boundary (used for debugging)
Definition GLHelper.cpp:966
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition GLHelper.cpp:295
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:539
static void pushMatrix()
push matrix
Definition GLHelper.cpp:117
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:756
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:787
const std::string getID() const
get ID (all Attribute Carriers have one)
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
bool mySelected
boolean to check if this AC is selected (instead of GUIGlObjectStorage)
static const std::string True
true value in string format (used for comparing boolean values in getAttribute(......
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
void unselectAttributeCarrier(const bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
GNENet * myNet
pointer to net
void selectAttributeCarrier(const bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
static const std::string False
true value in string format(used for comparing boolean values in getAttribute(...))
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
void 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:1842
const std::vector< GNEDemandElement * > & getDemandElements() const
get demand elements
Definition GNEEdge.cpp:1848
void addDemandElements(GNEDemandElement *demandElement)
add demand elment to current StackDemandElements
Definition GNEEdge.cpp:1836
StackDemandElements(const StackPosition stackedPosition, GNEDemandElement *demandElement)
constructor
Definition GNEEdge.cpp:1828
Stack position (used to stack demand elements over edges)
Definition GNEEdge.h:388
double beginPosition() const
get begin position
Definition GNEEdge.cpp:1817
StackPosition(const double departPos, const double length)
constructor
Definition GNEEdge.cpp:1811
double endPosition() const
get end position
Definition GNEEdge.cpp:1823
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:2611
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:2789
bool isConvexAngle() const
check if edge makes a convex angle [0 - 180) degrees
Definition GNEEdge.cpp:1761
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:2076
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:2546
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getContainersOverEdgeMap() const
get containers a that start over this edge
Definition GNEEdge.cpp:2579
void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)
commit move shape
Definition GNEEdge.cpp:2049
bool hasPredecessors() const
check if this edge has predecessors (note: only for vehicles, this function ignore walking areas!...
Definition GNEEdge.cpp:1776
void setMoveShape(const GNEMoveResult &moveResult)
set move shape
Definition GNEEdge.cpp:2027
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:2440
void updateGeometry()
update pre-computed geometry information
Definition GNEEdge.cpp:152
double getGeometryPointRadius() const
get geometry point radius
Definition GNEEdge.cpp:3186
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:1241
void setResponsible(bool newVal)
set responsibility for deleting internal structures
Definition GNEEdge.cpp:1532
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:2504
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:1798
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:2452
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:1599
bool isValid(SumoXMLAttr key, const std::string &value)
Definition GNEEdge.cpp:1389
void remakeGNEConnections(bool junctionsReady=false)
remake connections
Definition GNEEdge.cpp:945
GNEMoveOperation * processMoveBothJunctionSelected()
process moving edge when both junctions are selected
Definition GNEEdge.cpp:3138
void calculateEdgeContour(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
calculate contours
Definition GNEEdge.cpp:2897
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:1538
bool hasCustomEndPoints() const
Definition GNEEdge.cpp:577
void updatePersonStackLabels()
Definition GNEEdge.cpp:1657
void setEdgeID(const std::string &newID)
set edge ID
Definition GNEEdge.cpp:2326
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition GNEEdge.cpp:2267
void drawChildrens(const GUIVisualizationSettings &s) const
draw children
Definition GNEEdge.cpp:2871
bool hasSuccessors() const
check if this edge has successors (note: only for vehicles, this function ignore walking areas!...
Definition GNEEdge.cpp:1792
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:2661
bool isAttributeComputed(SumoXMLAttr key) const
Definition GNEEdge.cpp:1509
bool drawBigGeometryPoints() const
check if draw big geometry points
Definition GNEEdge.cpp:3016
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:2190
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:2335
static const double SNAP_RADIUS_SQUARED
Definition GNEEdge.h:311
void updateSecondParentJunction(const std::string &value)
update last parent junction
Definition GNEEdge.cpp:2128
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:2367
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:2346
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:2137
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:2303
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:2725
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:3034
void updateFirstParentJunction(const std::string &value)
update front parent junction
Definition GNEEdge.cpp:2119
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition GNEEdge.cpp:2357
void updateContainerStackLabels()
Definition GNEEdge.cpp:1709
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:2482
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:1251
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:1494
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:2243
GNEMoveOperation * processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only from junction is selected
Definition GNEEdge.cpp:3050
GNEMoveOperation * processNoneJunctionSelected(const double snapRadius)
process moving edge when none junction are selected
Definition GNEEdge.cpp:3149
PositionVector getAttributePositionVector(SumoXMLAttr key) const
Definition GNEEdge.cpp:1230
void drawLaneStopOffset(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
draw edgeStopOffset
Definition GNEEdge.cpp:2852
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:1526
void drawTAZElements(const GUIVisualizationSettings &s) const
draw TAZElements
Definition GNEEdge.cpp:2920
void drawEdgeShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double layer) const
draw edge shape (only one line)
Definition GNEEdge.cpp:2981
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:1553
void updateVehicleSpreadGeometries()
Definition GNEEdge.cpp:1568
GNEMoveOperation * processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only to junction is selected
Definition GNEEdge.cpp:3094
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:2493
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:1571
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:1386
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1396
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:2179
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:2146
GNEViewNet * getViewNet() const
get view net
Definition GNENet.cpp:2155
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 GNEAttributeCarrier * getFrontAttributeCarrier() const
get front attributeCarrier
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
void drawTranslateFrontAttributeCarrier(const GNEAttributeCarrier *AC, double typeOrLayer, const double extraOffset=0)
draw front attributeCarrier
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:4355
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition NBEdge.cpp:4378
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:4341
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:4293
bool hasLaneSpecificFriction() const
whether lanes differ in friction
Definition NBEdge.cpp:2460
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:4030
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition NBEdge.cpp:2450
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:4164
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:3664
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition NBEdge.cpp:2436
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:4309
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:1447
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition NBEdge.cpp:1528
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition NBEdge.cpp:4085
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition NBEdge.cpp:2470
std::string getLaneID(int lane) const
get lane ID
Definition NBEdge.cpp:4016
@ 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:1185
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition NBEdge.cpp:2492
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:4007
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:4247
void setLoadedLength(double val)
set loaded length
Definition NBEdge.cpp:4393
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:4714
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:3829
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition NBNode.cpp:3783
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