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