Eclipse SUMO - Simulation of Urban MObility
GNEEdge.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2001-2022 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>
37
38#include "GNEConnection.h"
39#include "GNECrossing.h"
40#include "GNEEdge.h"
41#include "GNEEdgeType.h"
42#include "GNELaneType.h"
43#include "GNEEdgeTemplate.h"
44#include "GNELaneTemplate.h"
45
46
47//#define DEBUG_SMOOTH_GEOM
48//#define DEBUGCOND(obj) (true)
49#define VEHICLE_GAP 1
50#define ENDPOINT_TOLERANCE 2
51
52// ===========================================================================
53// static
54// ===========================================================================
57
58// ===========================================================================
59// members methods
60// ===========================================================================
61
62GNEEdge::GNEEdge(GNENet* net, NBEdge* nbe, bool wasSplit, bool loaded):
63 GNENetworkElement(net, nbe->getID(), GLO_EDGE, SUMO_TAG_EDGE, GUIIconSubSys::getIcon(GUIIcon::EDGE), {
66},
67{}, {}, {}, {}, {}),
68myNBEdge(nbe),
69myLanes(0),
70myAmResponsible(false),
71myWasSplit(wasSplit),
72myConnectionStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED),
73myUpdateGeometry(true) {
74 // Create lanes
75 int numLanes = myNBEdge->getNumLanes();
76 myLanes.reserve(numLanes);
77 for (int i = 0; i < numLanes; i++) {
78 myLanes.push_back(new GNELane(this, i));
79 myLanes.back()->incRef("GNEEdge::GNEEdge");
80 }
81 // update Lane geometries
82 for (const auto& lane : myLanes) {
83 lane->updateGeometry();
84 }
85 // update centering boundary without updating grid
86 updateCenteringBoundary(false);
87}
88
89
91 // Delete references to this edge in lanes
92 for (const auto& lane : myLanes) {
93 lane->decRef("GNEEdge::~GNEEdge");
94 if (lane->unreferenced()) {
95 // check if remove it from Attribute Carriers
96 if (myNet->getAttributeCarriers()->getLanes().count(lane) > 0) {
98 }
99 // show extra information for tests
100 WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in GNEEdge destructor");
101 delete lane;
102 }
103 }
104 // delete references to this edge in connections
105 for (const auto& connection : myGNEConnections) {
106 connection->decRef("GNEEdge::~GNEEdge");
107 if (connection->unreferenced()) {
108 // check if remove it from Attribute Carriers
109 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
111 }
112 // show extra information for tests
113 WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in GNEEdge destructor");
114 delete connection;
115 }
116 }
117 if (myAmResponsible) {
118 delete myNBEdge;
119 }
120}
121
122
123bool
125 if (getFromJunction()->getNBNode()->getPosition() != getToJunction()->getNBNode()->getPosition()) {
126 return true;
127 } else {
128 return false;
129 }
130}
131
132
133std::string
135 return "Parent junctions are in the same position: " +
136 toString(getFromJunction()->getNBNode()->getPosition().x()) + ", " +
137 toString(getFromJunction()->getNBNode()->getPosition().y());
138}
139
140
141void
143 // first check if myUpdateGeometry flag is enabled
144 if (myUpdateGeometry) {
145 // Update geometry of lanes
146 for (const auto& lane : myLanes) {
147 lane->updateGeometry();
148 }
149 // Update geometry of connections
150 for (const auto& connection : myGNEConnections) {
151 connection->updateGeometry();
152 }
153 // Update geometry of additionals children vinculated to this edge
154 for (const auto& childAdditional : getChildAdditionals()) {
155 childAdditional->updateGeometry();
156 }
157 // Update geometry of additionals demand elements vinculated to this edge
158 for (const auto& childDemandElement : getChildDemandElements()) {
159 childDemandElement->updateGeometry();
160 }
161 // Update geometry of additionals generic datas vinculated to this edge
162 for (const auto& childGenericData : getChildGenericDatas()) {
163 childGenericData->updateGeometry();
164 }
165 // compute geometry of path elements elements vinculated with this edge (depending of showDemandElements)
167 for (const auto& childAdditional : getChildAdditionals()) {
168 childAdditional->computePathElement();
169 }
170 for (const auto& childDemandElement : getChildDemandElements()) {
171 childDemandElement->computePathElement();
172 }
173 for (const auto& childGenericData : getChildGenericDatas()) {
174 childGenericData->computePathElement();
175 }
176 }
177 }
178 // update vehicle geometry
180 // update vehicle stack labels
182}
183
184
187 return myLanes.front()->getPositionInView();
188}
189
190
193 // get snapRadius
195 // check if edge is selected
197 // check if both junctions are selected
205 return processNoneJunctionSelected(snapRadius);
206 } else {
207 // calculate move shape operation (because there are only an edge selected)
209 }
210 } else {
211 // calculate move shape operation
213 }
214}
215
216
217void
218GNEEdge::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
219 // declare shape to move
221 // obtain flags for start and end positions
222 const bool customStartPosition = (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE);
223 const bool customEndPosition = (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE);
224 // get variable for last index
225 const int lastIndex = (int)myNBEdge->getGeometry().size() - 1;
226 // flag to enable/disable remove geometry point
227 bool removeGeometryPoint = true;
228 // obtain index
229 const int index = myNBEdge->getGeometry().indexOfClosest(clickedPosition, true);
230 // check index
231 if (index == -1) {
232 removeGeometryPoint = false;
233 }
234 // check distance
235 if (shape[index].distanceSquaredTo2D(clickedPosition) > SNAP_RADIUS_SQUARED) {
236 removeGeometryPoint = false;
237 }
238 // check custom start position
239 if (!customStartPosition && (index == 0)) {
240 removeGeometryPoint = false;
241 }
242 // check custom end position
243 if (!customEndPosition && (index == lastIndex)) {
244 removeGeometryPoint = false;
245 }
246 // check if we can remove geometry point
248 // check if we're removing first geometry proint
249 if (index == 0) {
250 // commit new geometry start
251 undoList->begin(GUIIcon::EDGE, "remove first geometry point of " + getTagStr());
253 undoList->end();
254 } else if (index == lastIndex) {
255 // commit new geometry end
256 undoList->begin(GUIIcon::EDGE, "remove last geometry point of " + getTagStr());
258 undoList->end();
259 } else {
260 // remove geometry point
261 shape.erase(shape.begin() + index);
262 // get innen shape
263 shape.pop_front();
264 shape.pop_back();
265 // remove double points
267 // commit new shape
268 undoList->begin(GUIIcon::EDGE, "remove geometry point of " + getTagStr());
269 undoList->changeAttribute(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(shape)));
270 undoList->end();
271 }
272 }
273}
274
275
276bool
278 if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
279 return true;
280 } else if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
281 return true;
282 } else {
283 return false;
284 }
285}
286
287
288bool
290 if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
291 return (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED);
292 } else {
293 return false;
294 }
295}
296
297
298bool
300 if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) {
301 return (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED);
302 } else {
303 return false;
304 }
305}
306
307
308bool
310 // first check inner geometry
311 const PositionVector innenShape = myNBEdge->getInnerGeometry();
312 // iterate over geometry point
313 for (const auto& geometryPoint : innenShape) {
314 if (geometryPoint.distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED) {
315 return true;
316 }
317 }
318 // check start and end shapes
320 return true;
321 } else {
322 return false;
323 }
324}
325
326
327void
329 Position delta = junction->getNBNode()->getPosition() - origPos;
331 // geometry endpoint need not equal junction position hence we modify it with delta
332 if (junction == getFromJunction()) {
333 geom[0].add(delta);
334 } else {
335 geom[-1].add(delta);
336 }
337 setGeometry(geom, false);
338}
339
340
341double
343 return s.addSize.getExaggeration(s, this);
344}
345
346
347void
348GNEEdge::updateCenteringBoundary(const bool updateGrid) {
349 // Remove object from net
350 if (updateGrid) {
352 }
353 // use as boundary the first lane boundary
354 myBoundary = myLanes.front()->getCenteringBoundary();
355 // add lane boundaries
356 for (const auto& lane : myLanes) {
357 lane->updateCenteringBoundary(false);
358 myBoundary.add(lane->getCenteringBoundary());
359 // add parkingArea boundaries
360 for (const auto& additional : lane->getChildAdditionals()) {
361 if (additional->getTagProperty().getTag() == SUMO_TAG_PARKING_AREA) {
362 myBoundary.add(additional->getCenteringBoundary());
363 }
364 }
365 }
366 // ensure that geometry points are selectable even if the lane geometry is strange
367 for (const Position& pos : myNBEdge->getGeometry()) {
368 myBoundary.add(pos);
369 }
370 // add junction positions
373 // grow boundary
374 myBoundary.grow(10);
375 // add object into net
376 if (updateGrid) {
378 }
379}
380
381
382const std::string
384 return myNBEdge->getStreetName();
385}
386
387
390 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
391 buildPopupHeader(ret, app);
394 // build selection and show parameters menu
397 // build position copy entry
398 buildPositionCopyEntry(ret, app);
399 return ret;
400}
401
402
403std::vector<GNEEdge*>
406}
407
408
409void
411 // check if boundary has to be drawn
412 if (s.drawBoundaries) {
414 }
415 // draw lanes
416 for (const auto& lane : myLanes) {
417 lane->drawGL(s);
418 }
419 // draw child additional
420 for (const auto& additional : getChildAdditionals()) {
421 additional->drawGL(s);
422 }
423 // draw person stops
425 for (const auto& stopEdge : getChildDemandElements()) {
426 if ((stopEdge->getTagProperty().getTag() == GNE_TAG_STOPPERSON_EDGE) || (stopEdge->getTagProperty().getTag() == GNE_TAG_STOPCONTAINER_EDGE)) {
427 stopEdge->drawGL(s);
428 }
429 }
430 }
431 // draw vehicles
432 const std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesMap = getVehiclesOverEdgeMap();
433 for (const auto& vehicleMap : vehiclesMap) {
434 for (const auto& vehicle : vehicleMap.second) {
435 vehicle->drawGL(s);
436 }
437 }
438 // draw edge stopOffset
440 // draw TAZ elements
442 // draw name if isn't being drawn for selecting
443 drawEdgeName(s);
444 // draw dotted contours
445 if (myLanes.size() > 1) {
448 }
449 if ((myNet->getViewNet()->getFrontAttributeCarrier() == this)) {
451 }
452 if (myNet->getViewNet()->drawDeleteContour(this, this)) {
454 }
455 if (myNet->getViewNet()->drawSelectContour(this, this)) {
457 }
460 }
461 }
462}
463
464
465void
467 // Check if edge can be deleted
469 myNet->deleteEdge(this, myNet->getViewNet()->getUndoList(), false);
470 }
471}
472
473
474void
477}
478
479
480NBEdge*
482 return myNBEdge;
483}
484
485
488 const PositionVector& geom = myNBEdge->getGeometry();
489 int index = geom.indexOfClosest(clickPos, true);
490 if (geom[index].distanceSquaredTo2D(clickPos) < SNAP_RADIUS_SQUARED) {
491 // split at existing geometry point
492 return myNet->getViewNet()->snapToActiveGrid(geom[index]);
493 } else {
494 // split straight between the next two points
496 }
497}
498
499
500void
502 if ((myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
503 (myNBEdge->getGeometry().front().distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED)) {
504 undoList->begin(GUIIcon::EDGE, "remove endpoint");
505 setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
506 undoList->end();
507 } else if ((myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
508 (myNBEdge->getGeometry().back().distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED)) {
509 undoList->begin(GUIIcon::EDGE, "remove endpoint");
510 setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
511 undoList->end();
512 } else {
513 // we need to create new Start/End position over Edge shape, not over clicked position
515 if (offset != GeomHelper::INVALID_OFFSET) {
517 // calculate position over edge shape relative to clicked position
518 Position newPos = geom.positionAtOffset2D(offset);
519 // snap new position to grid
520 newPos = myNet->getViewNet()->snapToActiveGrid(newPos);
521 undoList->begin(GUIIcon::EDGE, "set endpoint");
522 int index = geom.indexOfClosest(pos, true);
523 // check if snap to existing geometry
524 if (geom[index].distanceSquaredTo2D(pos) < SNAP_RADIUS_SQUARED) {
525 pos = geom[index];
526 }
528 Position sourcePos = getFromJunction()->getNBNode()->getPosition();
529 if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
530 setAttribute(GNE_ATTR_SHAPE_END, toString(newPos), undoList);
532 } else {
533 setAttribute(GNE_ATTR_SHAPE_START, toString(newPos), undoList);
535 }
536 /*
537 // possibly existing inner point is no longer needed
538 if (myNBEdge->getInnerGeometry().size() > 0 && getEdgeVertexIndex(pos, false) != -1) {
539 deleteEdgeGeometryPoint(pos, false);
540 }
541 */
542 undoList->end();
543 }
544 }
545}
546
547
548void
551 Position sourcePos = getFromJunction()->getNBNode()->getPosition();
552 if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
553 setAttribute(GNE_ATTR_SHAPE_END, toString(destPos), undoList);
555 } else {
556 setAttribute(GNE_ATTR_SHAPE_START, toString(sourcePos), undoList);
558 }
559}
560
561
562void
564 // reset shape start
565 setAttribute(GNE_ATTR_SHAPE_END, "", undoList);
567 // reset shape end
568 setAttribute(GNE_ATTR_SHAPE_START, "", undoList);
570}
571
572void
574 // set new geometry
575 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
576 if (lefthand) {
577 geom.mirrorX();
578 myNBEdge->mirrorX();
579 }
580 myNBEdge->setGeometry(geom, inner);
581 if (lefthand) {
582 myNBEdge->mirrorX();
583 }
584 // update geometry
586 // invalidate junction source shape
588 // iterate over first parent junction edges and update geometry
589 for (const auto& edge : getFromJunction()->getGNEIncomingEdges()) {
590 edge->updateGeometry();
591 }
592 for (const auto& edge : getFromJunction()->getGNEOutgoingEdges()) {
593 edge->updateGeometry();
594 }
595 // invalidate junction destiny shape
597 // iterate over second parent junction edges and update geometry
598 for (const auto& edge : getToJunction()->getGNEIncomingEdges()) {
599 edge->updateGeometry();
600 }
601 for (const auto& edge : getToJunction()->getGNEOutgoingEdges()) {
602 edge->updateGeometry();
603 }
604}
605
606
607const Position
609 PositionVector laneShape = myLanes.front()->getLaneShape();
610 laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
611 return laneShape.front();
612}
613
614
615const Position
617 PositionVector laneShape = myLanes.back()->getLaneShape();
618 laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
619 return laneShape.front();
620}
621
622
623const Position
625 PositionVector laneShape = myLanes.front()->getLaneShape();
626 laneShape.move2side(myLanes.front()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.front()->getIndex()) / 2);
627 return laneShape.back();
628}
629
630
631const Position
633 PositionVector laneShape = myLanes.back()->getLaneShape();
634 laneShape.move2side(-1 * myLanes.back()->getParentEdge()->getNBEdge()->getLaneWidth(myLanes.back()->getIndex()) / 2);
635 return laneShape.back();
636}
637
638void
639GNEEdge::remakeGNEConnections(bool junctionsReady) {
640 // create new and removed unused GNEConnections
641 const std::vector<NBEdge::Connection>& connections = myNBEdge->getConnections();
642 // create a vector to keep retrieved and created connections
643 std::vector<GNEConnection*> retrievedConnections;
644 // iterate over NBEdge::Connections of GNEEdge
645 for (const auto& connection : connections) {
646 // retrieve existent GNEConnection, or create it
647 GNEConnection* retrievedGNEConnection = retrieveGNEConnection(connection.fromLane, connection.toEdge, connection.toLane);
648 if (junctionsReady) {
649 retrievedGNEConnection->updateLinkState();
650 }
651 retrievedConnections.push_back(retrievedGNEConnection);
652 // check if previously this GNEConnections exists, and if true, remove it from myGNEConnections
653 std::vector<GNEConnection*>::iterator retrievedExists = std::find(myGNEConnections.begin(), myGNEConnections.end(), retrievedGNEConnection);
654 if (retrievedExists != myGNEConnections.end()) {
655 myGNEConnections.erase(retrievedExists);
656 } else {
657 // include reference to created GNEConnection
658 retrievedGNEConnection->incRef("GNEEdge::remakeGNEConnections");
659 }
660 // mark it as deprecated
661 retrievedGNEConnection->markConnectionGeometryDeprecated();
662 }
663 // delete non retrieved GNEConnections
664 for (const auto& connection : myGNEConnections) {
665 // decrease reference
666 connection->decRef();
667 // remove it from network
668 myNet->removeGLObjectFromGrid(connection);
669 // and from AttributeCarriers
670 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
672 }
673 // delete GNEConnection if is unreferenced
674 if (connection->unreferenced()) {
675
676 // show extra information for tests
677 WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in rebuildGNEConnections()");
678 delete connection;
679 }
680 }
681 // copy retrieved (existent and created) GNECrossings to myGNEConnections
682 myGNEConnections = retrievedConnections;
683}
684
685
686void
688 // Drop all existents connections that aren't referenced anymore
689 for (const auto& connection : myGNEConnections) {
690 // check if connection is selected
691 if (connection->isAttributeCarrierSelected()) {
692 connection->unselectAttributeCarrier();
693 }
694 // Dec reference of connection
695 connection->decRef("GNEEdge::clearGNEConnections");
696 // remove it from network
697 myNet->removeGLObjectFromGrid(connection);
698 // and from AttributeCarriers
699 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
701 }
702 // Delete GNEConnectionToErase if is unreferenced
703 if (connection->unreferenced()) {
704 // show extra information for tests
705 WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in clearGNEConnections()");
706 delete connection;
707 }
708 }
709 myGNEConnections.clear();
710}
711
712
713int
715 std::vector<GNEAdditional*> routeProbes;
716 for (auto i : getChildAdditionals()) {
717 if (i->getTagProperty().getTag() == routeProbe->getTagProperty().getTag()) {
718 routeProbes.push_back(i);
719 }
720 }
721 // return index of routeProbe in routeProbes vector
722 auto it = std::find(routeProbes.begin(), routeProbes.end(), routeProbe);
723 if (it == routeProbes.end()) {
724 return -1;
725 } else {
726 return (int)(it - routeProbes.begin());
727 }
728}
729
730
731std::vector<GNECrossing*>
733 std::vector<GNECrossing*> crossings;
734 for (auto i : getFromJunction()->getGNECrossings()) {
735 if (i->checkEdgeBelong(this)) {
736 crossings.push_back(i);
737 }
738 }
739 for (auto i : getToJunction()->getGNECrossings()) {
740 if (i->checkEdgeBelong(this)) {
741 crossings.push_back(i);
742 }
743 }
744 return crossings;
745}
746
747
748void
749GNEEdge::copyTemplate(const GNEEdgeTemplate* edgeTemplate, GNEUndoList* undoList) {
750 // copy edge-specific attributes
752 setAttribute(SUMO_ATTR_TYPE, edgeTemplate->getAttribute(SUMO_ATTR_TYPE), undoList);
757 // copy raw values for lane-specific attributes
759 setAttribute(SUMO_ATTR_SPEED, edgeTemplate->getAttribute(SUMO_ATTR_SPEED), undoList);
760 }
763 }
765 setAttribute(SUMO_ATTR_WIDTH, edgeTemplate->getAttribute(SUMO_ATTR_WIDTH), undoList);
766 }
769 }
770 // copy lane attributes as well
771 for (int i = 0; i < (int)myLanes.size(); i++) {
772 myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_ALLOW), undoList);
773 myLanes[i]->setAttribute(SUMO_ATTR_SPEED, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_SPEED), undoList);
774 myLanes[i]->setAttribute(SUMO_ATTR_FRICTION, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_FRICTION), undoList);
775 myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_WIDTH), undoList);
776 myLanes[i]->setAttribute(SUMO_ATTR_ENDOFFSET, edgeTemplate->getLaneTemplates().at(i)->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
777 myLanes[i]->setAttribute(GNE_ATTR_STOPOFFSET, edgeTemplate->getLaneTemplates().at(i)->getAttribute(GNE_ATTR_STOPOFFSET), undoList);
778 myLanes[i]->setAttribute(GNE_ATTR_STOPOEXCEPTION, edgeTemplate->getLaneTemplates().at(i)->getAttribute(GNE_ATTR_STOPOEXCEPTION), undoList);
779 }
780}
781
782
783void
784GNEEdge::copyEdgeType(const GNEEdgeType* edgeType, GNEUndoList* undoList) {
785 // set type (only for info)
787 // set num lanes
789 // set speed
791 // set friction
793 // set allow (no disallow)
795 // set spreadType
797 // set width
799 // set priority
801 // set parameters
803 // copy lane attributes as well
804 for (int i = 0; i < (int)myLanes.size(); i++) {
805 // now copy custom lane values
806 if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_SPEED).size() > 0) {
807 myLanes[i]->setAttribute(SUMO_ATTR_SPEED, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_SPEED), undoList);
808 }
809 if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_FRICTION).size() > 0) {
810 myLanes[i]->setAttribute(SUMO_ATTR_FRICTION, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_FRICTION), undoList);
811 }
812 if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_ALLOW).size() > 0) {
813 myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_ALLOW), undoList);
814 }
815 if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_DISALLOW).size() > 0) {
816 myLanes[i]->setAttribute(SUMO_ATTR_DISALLOW, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_DISALLOW), undoList);
817 }
818 if (edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_WIDTH).size() > 0) {
819 myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, edgeType->getLaneTypes().at(i)->getAttribute(SUMO_ATTR_WIDTH), undoList);
820 }
821 if (edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS).size() > 0) {
822 myLanes[i]->setAttribute(GNE_ATTR_PARAMETERS, edgeType->getLaneTypes().at(i)->getAttribute(GNE_ATTR_PARAMETERS), undoList);
823 }
824 }
825}
826
827
828std::set<GUIGlID>
830 std::set<GUIGlID> result;
831 for (auto i : myLanes) {
832 result.insert(i->getGlID());
833 }
834 return result;
835}
836
837
838const std::vector<GNELane*>&
840 return myLanes;
841}
842
843
844const std::vector<GNEConnection*>&
846 return myGNEConnections;
847}
848
849
850bool
852 return myWasSplit;
853}
854
855
856std::string
858 switch (key) {
859 case SUMO_ATTR_ID:
860 return getMicrosimID();
861 case SUMO_ATTR_FROM:
862 return getFromJunction()->getID();
863 case SUMO_ATTR_TO:
864 return getToJunction()->getID();
866 return toString(myNBEdge->getNumLanes());
868 return toString(myNBEdge->getPriority());
869 case SUMO_ATTR_LENGTH:
871 case SUMO_ATTR_TYPE:
872 return myNBEdge->getTypeID();
873 case SUMO_ATTR_SHAPE:
877 case SUMO_ATTR_NAME:
878 return myNBEdge->getStreetName();
879 case SUMO_ATTR_ALLOW:
880 return (getVehicleClassNames(myNBEdge->getPermissions()) + (myNBEdge->hasLaneSpecificPermissions() ? " (combined!)" : ""));
881 case SUMO_ATTR_DISALLOW: {
883 }
884 case SUMO_ATTR_SPEED:
886 return "lane specific";
887 } else {
888 return toString(myNBEdge->getSpeed());
889 }
892 return "lane specific";
893 } else {
894 return toString(myNBEdge->getFriction());
895 }
896 case SUMO_ATTR_WIDTH:
898 return "lane specific";
900 return "default";
901 } else {
902 return toString(myNBEdge->getLaneWidth());
903 }
906 return "lane specific";
907 } else {
908 return toString(myNBEdge->getEndOffset());
909 }
911 return toString(myNBEdge->getDistance());
913 return myConnectionStatus;
915 if (myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
916 return "";
917 } else {
918 return toString(myNBEdge->getGeometry().front());
919 }
921 if (myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) <= ENDPOINT_TOLERANCE) {
922 return "";
923 } else {
924 return toString(myNBEdge->getGeometry().back());
925 }
926 case GNE_ATTR_BIDIR:
927 return toString(myNBEdge->getBidiEdge() != nullptr);
933 } else {
934 return "";
935 }
939 return myNBEdge->getParametersStr();
940 default:
941 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
942 }
943}
944
945
946std::string
948 std::string result = getAttribute(key);
949 if ((key == SUMO_ATTR_ALLOW || key == SUMO_ATTR_DISALLOW) && result.find("all") != std::string::npos) {
950 result += " " + getVehicleClassNames(SVCAll, true);
951 }
952 return result;
953}
954
955
956void
957GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
958 // get template editor
960 // check if we have to update template
961 const bool updateTemplate = templateEditor->getEdgeTemplate() ? (templateEditor->getEdgeTemplate()->getID() == getID()) : false;
962 switch (key) {
963 case SUMO_ATTR_WIDTH:
965 case SUMO_ATTR_SPEED:
967 case SUMO_ATTR_ALLOW:
968 case SUMO_ATTR_DISALLOW: {
969 undoList->begin(GUIIcon::EDGE, "change " + getTagStr() + " attribute");
970 const std::string origValue = myLanes.at(0)->getAttribute(key); // will have intermediate value of "lane specific"
971 // lane specific attributes need to be changed via lanes to allow undo
972 for (auto it : myLanes) {
973 it->setAttribute(key, value, undoList);
974 }
975 // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
976 undoList->changeAttribute(new GNEChange_Attribute(this, key, value, origValue));
977 undoList->end();
978 break;
979 }
980 case SUMO_ATTR_FROM: {
981 if (value != getAttribute(key)) {
982 undoList->begin(GUIIcon::EDGE, "change " + getTagStr() + " attribute");
983 // Remove edge from crossings of junction source
985 // continue changing from junction
986 GNEJunction* originalFirstParentJunction = getFromJunction();
987 getFromJunction()->setLogicValid(false, undoList);
988 undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
989 getFromJunction()->setLogicValid(false, undoList);
990 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
991 setAttribute(GNE_ATTR_SHAPE_START, toString(getFromJunction()->getNBNode()->getPosition()), undoList);
993 undoList->end();
994 // update geometries of all implicated junctions
995 originalFirstParentJunction->updateGeometry();
998 }
999 break;
1000 }
1001 case SUMO_ATTR_TO: {
1002 if (value != getAttribute(key)) {
1003 undoList->begin(GUIIcon::EDGE, "change " + getTagStr() + " attribute");
1004 // Remove edge from crossings of junction destiny
1006 // continue changing destiny junction
1007 GNEJunction* originalSecondParentJunction = getToJunction();
1008 getToJunction()->setLogicValid(false, undoList);
1009 undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1010 getToJunction()->setLogicValid(false, undoList);
1011 myNet->getAttributeCarriers()->retrieveJunction(value)->setLogicValid(false, undoList);
1012 setAttribute(GNE_ATTR_SHAPE_END, toString(getToJunction()->getNBNode()->getPosition()), undoList);
1014 undoList->end();
1015 // update geometries of all implicated junctions
1016 originalSecondParentJunction->updateGeometry();
1019 }
1020 break;
1021 }
1022 case SUMO_ATTR_ID:
1023 case SUMO_ATTR_PRIORITY:
1024 case SUMO_ATTR_LENGTH:
1025 case SUMO_ATTR_TYPE:
1027 case SUMO_ATTR_DISTANCE:
1029 case GNE_ATTR_SELECTED:
1033 undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1034 break;
1036 case GNE_ATTR_SHAPE_END: {
1037 auto change = new GNEChange_Attribute(this, key, value);
1038 // due to ENDPOINT_TOLERANCE, change might be ignored unless forced
1039 change->forceChange();
1040 undoList->changeAttribute(change);
1041 break;
1042 }
1043 case SUMO_ATTR_NAME:
1044 // user cares about street names. Make sure they appear in the output
1046 OptionsCont::getOptions().set("output.street-names", "true");
1047 undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1048 break;
1049 case SUMO_ATTR_NUMLANES:
1050 if (value != getAttribute(key)) {
1051 // set num lanes
1052 setNumLanes(parse<int>(value), undoList);
1053 }
1054 break;
1055 case GNE_ATTR_BIDIR:
1056 undoList->begin(GUIIcon::EDGE, "change " + getTagStr() + " attribute");
1057 undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1058 if (myNBEdge->getTurnDestination(true) != nullptr) {
1060 undoList->changeAttribute(new GNEChange_Attribute(bidi, key, value));
1061 if (myNBEdge->getGeometry() != bidi->getNBEdge()->getGeometry().reverse() && myNBEdge->getGeometry().size() == 2 && bidi->getNBEdge()->getGeometry().size() == 2) {
1062 // NBEdge::avoidOverlap was already active so we need to reset the
1063 // geometry to it's default
1064 resetBothEndpoint(undoList);
1065 bidi->resetBothEndpoint(undoList);
1066 }
1067 }
1068 undoList->end();
1069 break;
1070 case SUMO_ATTR_SHAPE:
1071 // @note: assumes value of inner geometry!
1072 // actually the geometry is already updated (incrementally
1073 // during mouse movement). We set the restore point to the end
1074 // of the last change-set
1075 undoList->changeAttribute(new GNEChange_Attribute(this, key, value));
1076 break;
1077 default:
1078 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1079 }
1080 // update template
1081 if (updateTemplate) {
1082 templateEditor->setEdgeTemplate(this);
1083 }
1084}
1085
1086
1087bool
1088GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
1089 switch (key) {
1090 case SUMO_ATTR_ID:
1091 return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveEdge(value, false) == nullptr);
1092 case SUMO_ATTR_FROM: {
1093 // check that is a valid ID and is different of ID of junction destiny
1094 if (value == getFromJunction()->getID()) {
1095 return true;
1096 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getToJunction()->getID())) {
1097 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1098 } else {
1099 return false;
1100 }
1101 }
1102 case SUMO_ATTR_TO: {
1103 // check that is a valid ID and is different of ID of junction Source
1104 if (value == getToJunction()->getID()) {
1105 return true;
1106 } else if (SUMOXMLDefinitions::isValidNetID(value) && (value != getFromJunction()->getID())) {
1107 return (myNet->getAttributeCarriers()->retrieveJunction(value, false) != nullptr);
1108 } else {
1109 return false;
1110 }
1111 }
1112 case SUMO_ATTR_SPEED:
1113 return canParse<double>(value) && (parse<double>(value) > 0);
1114 case SUMO_ATTR_FRICTION:
1115 return canParse<double>(value) && (parse<double>(value) > 0);
1116 case SUMO_ATTR_NUMLANES:
1117 return canParse<int>(value) && (parse<double>(value) > 0);
1118 case SUMO_ATTR_PRIORITY:
1119 return canParse<int>(value);
1120 case SUMO_ATTR_LENGTH:
1121 if (value.empty()) {
1122 return true;
1123 } else {
1124 return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH));
1125 }
1126 case SUMO_ATTR_ALLOW:
1127 case SUMO_ATTR_DISALLOW:
1128 return canParseVehicleClasses(value);
1129 case SUMO_ATTR_TYPE:
1130 return true;
1131 case SUMO_ATTR_SHAPE:
1132 // empty shapes are allowed
1133 return canParse<PositionVector>(value);
1136 case SUMO_ATTR_NAME:
1137 return true;
1138 case SUMO_ATTR_WIDTH:
1139 if (value.empty() || (value == "default")) {
1140 return true;
1141 } else {
1142 return canParse<double>(value) && ((parse<double>(value) >= -1) || (parse<double>(value) == NBEdge::UNSPECIFIED_WIDTH));
1143 }
1145 return canParse<double>(value) && parse<double>(value) >= 0 && parse<double>(value) < myNBEdge->getLoadedLength();
1146 case SUMO_ATTR_DISTANCE:
1147 if (value.empty()) {
1148 return true;
1149 } else {
1150 return canParse<double>(value);
1151 }
1152 case GNE_ATTR_SHAPE_START: {
1153 if (value.empty()) {
1154 return true;
1155 } else if (canParse<Position>(value)) {
1156 Position shapeStart = parse<Position>(value);
1157 return (shapeStart != myNBEdge->getGeometry()[-1]);
1158 } else {
1159 return false;
1160 }
1161 }
1162 case GNE_ATTR_SHAPE_END: {
1163 if (value.empty()) {
1164 return true;
1165 } else if (canParse<Position>(value)) {
1166 Position shapeEnd = parse<Position>(value);
1167 return (shapeEnd != myNBEdge->getGeometry()[0]);
1168 } else {
1169 return false;
1170 }
1171 }
1172 case GNE_ATTR_BIDIR:
1173 return canParse<bool>(value) && (!parse<bool>(value) || myNBEdge->isBidiEdge(true));
1175 return canParse<int>(value) && (parse<double>(value) >= 0);
1177 return canParseVehicleClasses(value);
1178 case GNE_ATTR_SELECTED:
1179 return canParse<bool>(value);
1182 default:
1183 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1184 }
1185}
1186
1187
1188bool
1190 switch (key) {
1191 case GNE_ATTR_BIDIR:
1192 return myNBEdge->isBidiEdge(true);
1193 default:
1194 return true;
1195 }
1196}
1197
1198
1199bool
1201 switch (key) {
1202 case SUMO_ATTR_LENGTH:
1203 return (myNBEdge->hasLoadedLength() == false);
1204 case SUMO_ATTR_WIDTH:
1206 return false;
1207 } else {
1209 }
1210 default:
1211 return false;
1212 }
1213}
1214
1215
1216const Parameterised::Map&
1218 return myNBEdge->getParametersMap();
1219}
1220
1221
1222void
1224 myAmResponsible = newVal;
1225}
1226
1227
1228GNELane*
1230 // iterate over all NBEdge lanes
1231 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1232 // if given VClass is in permissions, return lane
1233 if (myNBEdge->getLanes().at(i).permissions & vClass) {
1234 // return GNELane
1235 return myLanes.at(i);
1236 }
1237 }
1238 // return first lane
1239 return myLanes.front();
1240}
1241
1242
1243GNELane*
1245 // iterate over all NBEdge lanes
1246 for (int i = 0; i < (int)myNBEdge->getLanes().size(); i++) {
1247 // if given VClass isn't in permissions, return lane
1248 if (~(myNBEdge->getLanes().at(i).permissions) & vClass) {
1249 // return GNELane
1250 return myLanes.at(i);
1251 }
1252 }
1253 // return first lane
1254 return myLanes.front();
1255}
1256
1257
1258void
1260 // get lane vehicles map
1261 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1262 // iterate over every lane
1263 for (const auto& laneVehicle : laneVehiclesMap) {
1264 // obtain total length
1265 double totalLength = 0;
1266 for (const auto& vehicle : laneVehicle.second) {
1267 totalLength += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1268 }
1269 // calculate multiplier for vehicle positions
1270 double multiplier = 1;
1271 const double laneShapeLength = laneVehicle.first->getLaneShape().length();
1272 if (laneShapeLength == 0) {
1273 multiplier = 0;
1274 } else if (totalLength > laneShapeLength) {
1275 multiplier = (laneShapeLength / totalLength);
1276 }
1277 // declare current length
1278 double length = 0;
1279 // iterate over vehicles to calculate position and rotations
1280 for (const auto& vehicle : laneVehicle.second) {
1281 vehicle->updateDemandElementSpreadGeometry(laneVehicle.first, length * multiplier);
1282 // update length
1283 length += vehicle->getAttributeDouble(SUMO_ATTR_LENGTH) + VEHICLE_GAP;
1284 }
1285 }
1286}
1287
1288
1289void
1291 // get lane vehicles map
1292 const std::map<const GNELane*, std::vector<GNEDemandElement*> > laneVehiclesMap = getVehiclesOverEdgeMap();
1293 // iterate over laneVehiclesMap and obtain a vector with
1294 for (const auto& vehicleMap : laneVehiclesMap) {
1295 // declare map for sort vehicles using their departpos+length position (StackPosition)
1296 std::vector<std::pair<GNEEdge::StackPosition, GNEDemandElement*> > departPosVehicles;
1297 // declare vector of stack demand elements
1298 std::vector<GNEEdge::StackDemandElements> stackedVehicles;
1299 // iterate over vehicles
1300 for (const auto& vehicle : vehicleMap.second) {
1301 // get vehicle's depart pos and length
1302 const double departPos = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1303 const double length = vehicle->getAttributeDouble(SUMO_ATTR_LENGTH);
1304 double posOverLane = vehicle->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
1305 // check if we have to adapt posOverLane
1306 if (posOverLane < 0) {
1307 posOverLane += vehicleMap.first->getLaneShape().length();
1308 }
1309 // make a stack position using departPos and length
1310 departPosVehicles.push_back(std::make_pair(StackPosition(departPos, length), vehicle));
1311 // update depart element geometry
1312 vehicle->updateDemandElementGeometry(vehicleMap.first, posOverLane);
1313 // reset vehicle stack label
1314 vehicle->updateDemandElementStackLabel(0);
1315 }
1316
1317 // sort departPosVehicles
1318 std::sort(departPosVehicles.begin(), departPosVehicles.end());
1319 // iterate over departPosVehicles
1320 for (const auto& departPosVehicle : departPosVehicles) {
1321 // obtain stack position and vehicle
1322 const GNEEdge::StackPosition& vehicleStackPosition = departPosVehicle.first;
1323 GNEDemandElement* vehicle = departPosVehicle.second;
1324 // if stackedVehicles is empty, add a new StackDemandElements
1325 if (stackedVehicles.empty()) {
1326 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1327 } else if (areStackPositionOverlapped(vehicleStackPosition, stackedVehicles.back().getStackPosition())) {
1328 // add new vehicle to last inserted stackDemandElements
1329 stackedVehicles[stackedVehicles.size() - 1].addDemandElements(vehicle);
1330 } else {
1331 // No overlapping, then add a new StackDemandElements
1332 stackedVehicles.push_back(GNEEdge::StackDemandElements(vehicleStackPosition, vehicle));
1333 }
1334 }
1335 // iterate over stackedVehicles
1336 for (const auto& vehicle : stackedVehicles) {
1337 // only update vehicles with one or more stack
1338 if (vehicle.getDemandElements().size() > 1) {
1339 // set stack labels
1340 vehicle.getDemandElements().front()->updateDemandElementStackLabel((int)vehicle.getDemandElements().size());
1341 }
1342 }
1343 }
1344}
1345
1346
1347void
1349 // declare conditions
1350 const bool lastLane = (lane == myLanes.back());
1351 const bool validScale = (s.scale > 8.0);
1353 // first check conditions
1354 if (lastLane && (validScale || elevationMode) && !myNet->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {
1355 // Obtain exaggeration of the draw
1356 const double exaggeration = getExaggeration(s);
1357 // get circle width
1358 bool drawBigGeometryPoints = false;
1360 drawBigGeometryPoints = true;
1361 }
1364 drawBigGeometryPoints = true;
1365 }
1366 double circleWidth = drawBigGeometryPoints ? SNAP_RADIUS * MIN2((double)1, s.laneWidthExaggeration) : 0.5;
1367 double circleWidthSquared = circleWidth * circleWidth;
1368 // obtain color
1369 RGBColor color = s.junctionColorer.getSchemes()[0].getColor(2);
1370 if (drawUsingSelectColor() && s.laneColorer.getActive() != 1) {
1371 // override with special colors (unless the color scheme is based on selection)
1373 }
1374 GLHelper::setColor(color);
1375 // recognize full transparency and simply don't draw
1376 if (color.alpha() > 0) {
1377 // add edge layer matrix
1379 // translate to front
1380 glTranslated(0, 0, 1);
1381 // draw geometry points expect initial and final
1382 for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
1383 Position pos = myNBEdge->getGeometry()[i];
1384 if (!s.drawForRectangleSelection || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(pos) <= (circleWidthSquared + 2))) {
1386 glTranslated(pos.x(), pos.y(), 0.1);
1387 // resolution of drawn circle depending of the zoom (To improve smoothness)
1390 // draw elevation or special symbols (Start, End and Block)
1393 // Translate to geometry point
1394 glTranslated(pos.x(), pos.y(), 0.2);
1395 // draw Z value
1398 }
1399 }
1400 }
1401 // draw line geometry, start and end points if shapeStart or shape end is edited, and depending of drawForRectangleSelection
1402 if (drawBigGeometryPoints) {
1403 if ((myNBEdge->getGeometry().front().distanceSquaredTo2D(getFromJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
1404 (!s.drawForRectangleSelection || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(myNBEdge->getGeometry().front()) <= (circleWidthSquared + 2)))) {
1405 // calculate angle
1406 const double angle = RAD2DEG(myNBEdge->getGeometry().front().angleTo2D(myNBEdge->getGeometry()[1])) * -1;
1408 glTranslated(myNBEdge->getGeometry().front().x(), myNBEdge->getGeometry().front().y(), 0.1);
1409 // resolution of drawn circle depending of the zoom (To improve smoothness)
1410 GLHelper::drawFilledCircle(circleWidth, s.getCircleResolution(), angle + 90, angle + 270);
1412 // draw a "s" over last point depending of drawForRectangleSelection
1415 glTranslated(myNBEdge->getGeometry().front().x(), myNBEdge->getGeometry().front().y(), 0.2);
1416 GLHelper::drawText("S", Position(), 0, circleWidth, RGBColor(0, 50, 255));
1418 // draw line between Junction and point
1420 glTranslated(0, 0, 0.1);
1421 glLineWidth(4);
1422 GLHelper::drawLine(myNBEdge->getGeometry().front(), getFromJunction()->getNBNode()->getPosition());
1423 // draw line between begin point of last lane shape and the first edge shape point
1424 GLHelper::drawLine(myNBEdge->getGeometry().front(), myNBEdge->getLanes().back().shape.front());
1426 }
1427 }
1428 if ((myNBEdge->getGeometry().back().distanceSquaredTo2D(getToJunction()->getNBNode()->getPosition()) > ENDPOINT_TOLERANCE) &&
1429 (!s.drawForRectangleSelection || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(myNBEdge->getGeometry().back()) <= (circleWidthSquared + 2)))) {
1430 // calculate angle
1431 const double angle = RAD2DEG(myNBEdge->getGeometry()[-1].angleTo2D(myNBEdge->getGeometry()[-2])) * -1;
1433 glTranslated(myNBEdge->getGeometry().back().x(), myNBEdge->getGeometry().back().y(), 0.1);
1434 // resolution of drawn circle depending of the zoom (To improve smoothness)
1435 GLHelper::drawFilledCircle(circleWidth, s.getCircleResolution(), angle - 90, angle + 90);
1437 // draw a "e" over last point depending of drawForRectangleSelection
1440 glTranslated(myNBEdge->getGeometry().back().x(), myNBEdge->getGeometry().back().y(), 0.2);
1441 GLHelper::drawText("E", Position(), 0, circleWidth, RGBColor(0, 50, 255));
1443 // draw line between Junction and point
1445 glTranslated(0, 0, 0.1);
1446 glLineWidth(4);
1447 GLHelper::drawLine(myNBEdge->getGeometry().back(), getToJunction()->getNBNode()->getPosition());
1448 // draw line between last point of first lane shape and the last edge shape point
1449 GLHelper::drawLine(myNBEdge->getGeometry().back(), myNBEdge->getLanes().back().shape.back());
1451 }
1452 }
1453 }
1454 // pop edge layer matrix
1456 // draw lock icon
1458 }
1459 }
1460}
1461
1462
1463void
1465 const bool drawFrontExtreme, const bool drawBackExtreme, const double exaggeration) {
1466 if (edge->getLanes().size() == 1) {
1467 GNELane::LaneDrawingConstants laneDrawingConstants(s, edge->getLanes().front());
1468 GUIDottedGeometry::drawDottedContourShape(s, type, edge->getLanes().front()->getLaneShape(),
1469 laneDrawingConstants.halfWidth * exaggeration, 1, drawFrontExtreme, drawBackExtreme);
1470 } else {
1471 // set left hand flag
1472 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
1473 // obtain lanes
1474 const GNELane* topLane = lefthand ? edge->getLanes().back() : edge->getLanes().front();
1475 const GNELane* botLane = lefthand ? edge->getLanes().front() : edge->getLanes().back();
1476 // obtain a copy of both geometries
1477 GUIDottedGeometry dottedGeometryTop(s, topLane->getLaneGeometry().getShape(), false);
1478 GUIDottedGeometry dottedGeometryBot(s, botLane->getLaneGeometry().getShape(), false);
1479 // obtain both LaneDrawingConstants
1480 GNELane::LaneDrawingConstants laneDrawingConstantsFront(s, topLane);
1481 GNELane::LaneDrawingConstants laneDrawingConstantsBack(s, botLane);
1482 // move shapes to side
1483 dottedGeometryTop.moveShapeToSide(laneDrawingConstantsFront.halfWidth * exaggeration);
1484 dottedGeometryBot.moveShapeToSide(laneDrawingConstantsBack.halfWidth * -1 * exaggeration);
1485 // invert offset of top dotted geometry
1486 dottedGeometryTop.invertOffset();
1487 // declare DottedGeometryColor
1488 GUIDottedGeometry::DottedGeometryColor dottedGeometryColor(s);
1489 // calculate extremes
1490 GUIDottedGeometry extremes(s, dottedGeometryTop, drawFrontExtreme, dottedGeometryBot, drawBackExtreme);
1491 // Push draw matrix
1493 // draw inspect or front dotted contour
1495 // translate to front
1496 glTranslated(0, 0, GLO_DOTTEDCONTOUR_FRONT);
1497 } else {
1498 // translate to front
1499 glTranslated(0, 0, GLO_DOTTEDCONTOUR_INSPECTED);
1500 }
1501 // draw top dotted geometry
1502 dottedGeometryTop.drawDottedGeometry(s, type, dottedGeometryColor);
1503 // reset color
1504 dottedGeometryColor.reset();
1505 // draw top dotted geometry
1506 dottedGeometryBot.drawDottedGeometry(s, type, dottedGeometryColor);
1507 // change color
1508 dottedGeometryColor.changeColor();
1509 // draw extrem dotted geometry
1510 extremes.drawDottedGeometry(s, type, dottedGeometryColor);
1511 // pop matrix
1513 }
1514}
1515
1516
1517bool
1519 // calculate angle between both junction positions
1520 double edgeAngle = RAD2DEG(getFromJunction()->getPositionInView().angleTo2D(getToJunction()->getPositionInView()));
1521 // adjust to 360 degrees
1522 while (edgeAngle < 0) {
1523 edgeAngle += 360;
1524 }
1525 // fmod round towards zero which is not want we want for negative numbers
1526 edgeAngle = fmod(edgeAngle, 360);
1527 // check angle
1528 return edgeAngle >= 0 && edgeAngle < 180;
1529}
1530
1531
1532bool
1534 // get incoming edges
1535 const auto incomingEdges = getFromJunction()->getGNEIncomingEdges();
1536 // iterate over connections
1537 for (const auto& incomingEdge : incomingEdges) {
1538 for (const auto& connection : incomingEdge->getGNEConnections()) {
1539 if (connection->getEdgeTo() == this) {
1540 return true;
1541 }
1542 }
1543 }
1544 return false;
1545}
1546
1547
1548bool
1550 return (myGNEConnections.size() > 0);
1551}
1552
1553
1554GNEEdge*
1556 for (const auto& outgoingEdge : getParentJunctions().back()->getGNEOutgoingEdges()) {
1557 if (outgoingEdge->getToJunction() == getFromJunction()) {
1558 return outgoingEdge;
1559 }
1560 }
1561 return nullptr;
1562}
1563
1564// ===========================================================================
1565// private
1566// ===========================================================================
1567
1568GNEEdge::StackPosition::StackPosition(const double departPos, const double length) :
1569 pair(departPos, departPos + length) {
1570}
1571
1572
1573double
1575 return first;
1576}
1577
1578
1579double
1581 return second;
1582}
1583
1584
1586 pair(stackedPosition, {
1587 demandElement
1588}) {
1589}
1590
1591
1592void
1594 second.push_back(demandElement);
1595}
1596
1597
1600 return first;
1601}
1602
1603
1604const std::vector<GNEDemandElement*>&
1606 return second;
1607}
1608
1609
1610void
1611GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
1612 switch (key) {
1613 case SUMO_ATTR_ID:
1614 myNet->getAttributeCarriers()->updateEdgeID(this, value);
1615 // enable save demand elements if there are stops
1616 for (const auto& stop : getChildDemandElements()) {
1617 if (stop->getTagProperty().isStop() || stop->getTagProperty().isStopPerson()) {
1619 }
1620 }
1621 // also for lanes
1622 for (const auto& lane : myLanes) {
1623 for (const auto& stop : lane->getChildDemandElements()) {
1624 if (stop->getTagProperty().isStop() || stop->getTagProperty().isStopPerson()) {
1626 }
1627 }
1628 }
1629 break;
1630 case SUMO_ATTR_FROM:
1631 myNet->changeEdgeEndpoints(this, value, getToJunction()->getID());
1632 // update this edge of list of outgoings edges of the old first parent junction
1634 // update first parent junction
1636 // update this edge of list of outgoings edges of the new first parent junction
1638 // update centering boundary and grid
1640 break;
1641 case SUMO_ATTR_TO:
1642 myNet->changeEdgeEndpoints(this, getFromJunction()->getID(), value);
1643 // update this edge of list of incomings edges of the old second parent junction
1645 // update second parent junction
1647 // update this edge of list of incomings edges of the new second parent junction
1649 // update centering boundary and grid
1651 break;
1652 case SUMO_ATTR_NUMLANES:
1653 throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
1654 case SUMO_ATTR_PRIORITY:
1655 myNBEdge->myPriority = parse<int>(value);
1656 break;
1657 case SUMO_ATTR_LENGTH:
1658 if (value.empty()) {
1660 } else {
1661 myNBEdge->setLoadedLength(parse<double>(value));
1662 }
1663 break;
1664 case SUMO_ATTR_TYPE:
1665 myNBEdge->myType = value;
1666 break;
1667 case SUMO_ATTR_SHAPE:
1668 // set new geometry
1669 setGeometry(parse<PositionVector>(value), true);
1670 // update centering boundary and grid
1672 break;
1675 break;
1676 case SUMO_ATTR_NAME:
1677 myNBEdge->setStreetName(value);
1678 break;
1679 case SUMO_ATTR_SPEED:
1680 myNBEdge->setSpeed(-1, parse<double>(value));
1681 break;
1682 case SUMO_ATTR_FRICTION:
1683 myNBEdge->setFriction(-1, parse<double>(value));
1684 break;
1685 case SUMO_ATTR_WIDTH:
1686 if (value.empty() || (value == "default")) {
1688 } else {
1689 myNBEdge->setLaneWidth(-1, parse<double>(value));
1690 }
1691 break;
1693 myNBEdge->setEndOffset(-1, parse<double>(value));
1694 break;
1695 case SUMO_ATTR_ALLOW:
1696 break; // no edge value
1697 case SUMO_ATTR_DISALLOW:
1698 break; // no edge value
1699 case SUMO_ATTR_DISTANCE:
1700 if (value.empty()) {
1701 myNBEdge->setDistance(0.0);
1702 } else {
1703 myNBEdge->setDistance(parse<double>(value));
1704 }
1705 break;
1707 myConnectionStatus = value;
1708 if (value == FEATURE_GUESSED) {
1709 WRITE_DEBUG("invalidating (removing) connections of edge '" + getID() + "' due it were guessed");
1712 } else if (value != FEATURE_GUESSED) {
1713 WRITE_DEBUG("declaring connections of edge '" + getID() + "' as loaded (It will not be removed)");
1715 }
1716 break;
1717 case GNE_ATTR_SHAPE_START: {
1718 // get geometry of NBEdge, remove FIRST element with the new value (or with the Junction Source position) and set it back to edge
1719 Position newShapeStart;
1720 if (value == "") {
1721 newShapeStart = getFromJunction()->getNBNode()->getPosition();
1722 } else {
1723 newShapeStart = parse<Position>(value);
1724 }
1725 // set shape start position
1726 setShapeStartPos(newShapeStart);
1727 // update centering boundary and grid
1729 break;
1730 }
1731 case GNE_ATTR_SHAPE_END: {
1732 // get geometry of NBEdge, remove LAST element with the new value (or with the Junction Destiny position) and set it back to edge
1733 Position newShapeEnd;
1734 if (value == "") {
1735 newShapeEnd = getToJunction()->getNBNode()->getPosition();
1736 } else {
1737 newShapeEnd = parse<Position>(value);
1738 }
1739 // set shape end position
1740 setShapeEndPos(newShapeEnd);
1741 // update centering boundary and grid
1743 break;
1744 }
1745 case GNE_ATTR_BIDIR:
1746 myNBEdge->setBidi(parse<bool>(value));
1747 break;
1748 case GNE_ATTR_SELECTED:
1749 if (parse<bool>(value)) {
1751 } else {
1753 }
1754 break;
1756 myNBEdge->myEdgeStopOffset.setOffset(parse<double>(value));
1757 break;
1759 if (value.empty()) {
1761 } else {
1763 }
1764 break;
1766 myNBEdge->setParametersStr(value);
1767 break;
1768 default:
1769 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1770 }
1771 // get template editor
1773 // check update template
1774 if (templateEditor->getEdgeTemplate() && (templateEditor->getEdgeTemplate()->getID() == getID())) {
1776 }
1777 // invalidate path calculator
1779}
1780
1781
1782void
1784 // get start and end points
1785 const Position shapeStart = moveResult.shapeToUpdate.front();
1786 const Position shapeEnd = moveResult.shapeToUpdate.back();
1787 // get innen shape
1788 PositionVector innenShape = moveResult.shapeToUpdate;
1789 innenShape.pop_front();
1790 innenShape.pop_back();
1791 // set shape start
1792 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
1793 setShapeStartPos(shapeStart);
1794 }
1795 // set innen geometry
1796 setGeometry(innenShape, true);
1797 // set shape end
1798 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), ((int)moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
1799 setShapeEndPos(shapeEnd);
1800 }
1801}
1802
1803
1804void
1806 // make sure that newShape isn't empty
1807 if (moveResult.shapeToUpdate.size() > 0) {
1808 // get start and end points
1809 const Position shapeStart = moveResult.shapeToUpdate.front();
1810 const Position shapeEnd = moveResult.shapeToUpdate.back();
1811 // get innen shape
1812 PositionVector innenShape = moveResult.shapeToUpdate;
1813 innenShape.pop_front();
1814 innenShape.pop_back();
1815 // commit new shape
1816 undoList->begin(GUIIcon::EDGE, "moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
1817 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), 0) != moveResult.geometryPointsToMove.end()) {
1818 undoList->changeAttribute(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_START, toString(shapeStart)));
1819 }
1820 // update shape
1821 undoList->changeAttribute(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(innenShape)));
1822 // check if we have to update shape end
1823 if (std::find(moveResult.geometryPointsToMove.begin(), moveResult.geometryPointsToMove.end(), (int)(moveResult.shapeToUpdate.size() - 1)) != moveResult.geometryPointsToMove.end()) {
1824 undoList->changeAttribute(new GNEChange_Attribute(this, GNE_ATTR_SHAPE_END, toString(shapeEnd)));
1825 }
1826 undoList->end();
1827 }
1828}
1829
1830
1831void
1832GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
1833 // begin undo list
1834 undoList->begin(GUIIcon::EDGE, "change number of " + toString(SUMO_TAG_LANE) + "s");
1835 // invalidate logic of source/destiny edges
1836 getFromJunction()->setLogicValid(false, undoList);
1837 getToJunction()->setLogicValid(false, undoList);
1838 // disable update geometry (see #6336)
1839 myUpdateGeometry = false;
1840 // remove edge from grid
1842 // save old number of lanes
1843 const int oldNumLanes = (int)myLanes.size();
1844 // get opposite ID
1845 const auto oppositeID = myLanes.back()->getAttribute(GNE_ATTR_OPPOSITE);
1846 if (oppositeID != "") {
1847 // we'll have a different leftmost lane after adding/removing lanes
1849 }
1850 for (int i = oldNumLanes; i < numLanes; i++) {
1851 // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
1852 undoList->add(new GNEChange_Lane(this, myNBEdge->getLaneStruct(oldNumLanes - 1)), true);
1853 }
1854 for (int i = (oldNumLanes - 1); i > (numLanes - 1); i--) {
1855 // delete leftmost lane
1856 undoList->add(new GNEChange_Lane(this, myLanes[i], myNBEdge->getLaneStruct(i), false), true);
1857 }
1858 if (oppositeID != "") {
1859 undoList->changeAttribute(new GNEChange_Attribute(myLanes.back(), GNE_ATTR_OPPOSITE, oppositeID));
1860 }
1861 // enable updateGeometry again
1862 myUpdateGeometry = true;
1863 // update geometry of entire edge
1865 // end undo list
1866 undoList->end();
1867 // update centering boundary (without updating RTREE)
1869 // insert edge in grid again
1871}
1872
1873
1874void
1875GNEEdge::updateFirstParentJunction(const std::string& value) {
1876 std::vector<GNEJunction*> parentJunctions = getParentJunctions();
1877 parentJunctions[0] = myNet->getAttributeCarriers()->retrieveJunction(value);
1878 // replace parent junctions
1879 replaceParentElements(this, parentJunctions);
1880}
1881
1882
1883void
1884GNEEdge::updateSecondParentJunction(const std::string& value) {
1885 std::vector<GNEJunction*> parentJunctions = getParentJunctions();
1886 parentJunctions[1] = myNet->getAttributeCarriers()->retrieveJunction(value);
1887 // replace parent junctions
1888 replaceParentElements(this, parentJunctions);
1889}
1890
1891
1892void
1893GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections) {
1894 const int index = lane ? lane->getIndex() : myNBEdge->getNumLanes();
1895 // the laneStruct must be created first to ensure we have some geometry
1896 // unless the connections are fully recomputed, existing indices must be shifted
1897 myNBEdge->addLane(index, true, recomputeConnections, !recomputeConnections);
1898 if (lane) {
1899 // restore a previously deleted lane
1900 myLanes.insert(myLanes.begin() + index, lane);
1901 } else {
1902 // create a new lane by copying leftmost lane
1903 lane = new GNELane(this, index);
1904 myLanes.push_back(lane);
1905 }
1906 lane->incRef("GNEEdge::addLane");
1907 // add in attributeCarriers
1909 // check if lane is selected
1910 if (lane->isAttributeCarrierSelected()) {
1911 lane->selectAttributeCarrier();
1912 }
1913 // we copy all attributes except shape since this is recomputed from edge shape
1914 myNBEdge->setSpeed(lane->getIndex(), laneAttrs.speed);
1915 myNBEdge->setFriction(lane->getIndex(), laneAttrs.friction);
1916 myNBEdge->setPermissions(laneAttrs.permissions, lane->getIndex());
1918 myNBEdge->setEndOffset(lane->getIndex(), laneAttrs.endOffset);
1919 myNBEdge->setLaneWidth(lane->getIndex(), laneAttrs.width);
1920 // update indices
1921 for (int i = 0; i < (int)myLanes.size(); ++i) {
1922 myLanes[i]->setIndex(i);
1923 }
1924 /* while technically correct, this looks ugly
1925 getFromJunction()->invalidateShape();
1926 getToJunction()->invalidateShape();
1927 */
1928 // Remake connections for this edge and all edges that target this lane
1930 // remake connections of all edges of junction source and destiny
1931 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
1932 fromEdge->remakeGNEConnections();
1933 }
1934 // remake connections of all edges of junction source and destiny
1935 for (const auto& toEdge : getToJunction()->getChildEdges()) {
1936 toEdge->remakeGNEConnections();
1937 }
1938 // Update geometry with the new lane
1940 // update boundary and grid
1942}
1943
1944
1945void
1946GNEEdge::removeLane(GNELane* lane, bool recomputeConnections) {
1947 if (myLanes.size() == 0) {
1948 throw ProcessError("Should not remove the last " + toString(SUMO_TAG_LANE) + " from an " + getTagStr());
1949 }
1950 if (lane == nullptr) {
1951 lane = myLanes.back();
1952 }
1953 // check if lane is selected
1954 if (lane->isAttributeCarrierSelected()) {
1956 }
1957 // before removing, check that lane isn't being inspected
1960 // Delete lane of edge's container
1961 // unless the connections are fully recomputed, existing indices must be shifted
1962 myNBEdge->deleteLane(lane->getIndex(), recomputeConnections, !recomputeConnections);
1963 lane->decRef("GNEEdge::removeLane");
1964 myLanes.erase(myLanes.begin() + lane->getIndex());
1965 // remove from attributeCarriers
1967 // Delete lane if is unreferenced
1968 if (lane->unreferenced()) {
1969 // show extra information for tests
1970 WRITE_DEBUG("Deleting unreferenced " + lane->getTagStr() + " '" + lane->getID() + "' in removeLane()");
1971 delete lane;
1972 }
1973 // update indices
1974 for (int i = 0; i < (int)myLanes.size(); ++i) {
1975 myLanes[i]->setIndex(i);
1976 }
1977 /* while technically correct, this looks ugly
1978 getFromJunction()->invalidateShape();
1979 getToJunction()->invalidateShape();
1980 */
1981 // Remake connections of this edge
1983 // remake connections of all edges of junction source and destiny
1984 for (const auto& fromEdge : getFromJunction()->getChildEdges()) {
1985 fromEdge->remakeGNEConnections();
1986 }
1987 // remake connections of all edges of junction source and destiny
1988 for (const auto& toEdge : getToJunction()->getChildEdges()) {
1989 toEdge->remakeGNEConnections();
1990 }
1991 // Update element
1993 // update boundary and grid
1995}
1996
1997
1998void
1999GNEEdge::addConnection(NBEdge::Connection nbCon, bool selectAfterCreation) {
2000 // If a new connection was successfully created
2002 nbCon.keepClear, nbCon.contPos, nbCon.visibility,
2003 nbCon.speed, nbCon.friction, nbCon.customLength, nbCon.customShape, nbCon.uncontrolled)) {
2004 // Create or retrieve existent GNEConnection
2005 GNEConnection* con = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane);
2006 // add it to GNEConnection container
2007 myGNEConnections.push_back(con);
2008 // Add reference
2009 myGNEConnections.back()->incRef("GNEEdge::addConnection");
2010 // select GNEConnection if needed
2011 if (selectAfterCreation) {
2013 }
2014 // update geometry
2015 con->updateGeometry();
2016 }
2017 // actually we only do this to force a redraw
2019}
2020
2021
2022void
2024 // check if is a explicit turnaround
2025 if (nbCon.toEdge == myNBEdge->getTurnDestination()) {
2027 }
2028 // remove NBEdge::connection from NBEdge
2030 // remove their associated GNEConnection
2031 GNEConnection* connection = retrieveGNEConnection(nbCon.fromLane, nbCon.toEdge, nbCon.toLane, false);
2032 if (connection != nullptr) {
2033 connection->decRef("GNEEdge::removeConnection");
2034 myGNEConnections.erase(std::find(myGNEConnections.begin(), myGNEConnections.end(), connection));
2035 // check if connection is selected
2036 if (connection->isAttributeCarrierSelected()) {
2037 connection->unselectAttributeCarrier();
2038 }
2039 // remove it from network
2040 myNet->removeGLObjectFromGrid(connection);
2041 // check if remove it from Attribute Carriers
2042 if (myNet->getAttributeCarriers()->getConnections().count(connection) > 0) {
2044 }
2045 if (connection->unreferenced()) {
2046 // show extra information for tests
2047 WRITE_DEBUG("Deleting unreferenced " + connection->getTagStr() + " '" + connection->getID() + "' in removeConnection()");
2048 // actually we only do this to force a redraw
2050 }
2051 }
2052}
2053
2054
2056GNEEdge::retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist) {
2057 for (const auto& connection : myGNEConnections) {
2058 if ((connection->getFromLaneIndex() == fromLane) && (connection->getEdgeTo()->getNBEdge() == to) && (connection->getToLaneIndex() == toLane)) {
2059 return connection;
2060 }
2061 }
2062 if (createIfNoExist) {
2063 // create new connection. Will be added to the rTree on first geometry computation
2064 GNEConnection* connection = new GNEConnection(myLanes[fromLane], myNet->getAttributeCarriers()->retrieveEdge(to->getID())->getLanes()[toLane]);
2065 // show extra information for tests
2066 WRITE_DEBUG("Created " + connection->getTagStr() + " '" + connection->getID() + "' in retrieveGNEConnection()");
2067 // add it into network
2068 myNet->addGLObjectIntoGrid(connection);
2069 // add it in attributeCarriers
2071 return connection;
2072 } else {
2073 return nullptr;
2074 }
2075}
2076
2077
2078void
2079GNEEdge::setMicrosimID(const std::string& newID) {
2081 for (const auto& lane : myLanes) {
2082 lane->setMicrosimID(getNBEdge()->getLaneID(lane->getIndex()));
2083 }
2084}
2085
2086
2087bool
2089 for (const auto& lane : myLanes) {
2090 if (lane->isRestricted(vclass)) {
2091 return true;
2092 }
2093 }
2094 return false;
2095}
2096
2097
2098void
2100 // Remove all crossings that contain this edge in parameter "edges"
2101 for (const auto& crossing : junction->getGNECrossings()) {
2102 if (crossing->checkEdgeBelong(this)) {
2103 myNet->deleteCrossing(crossing, undoList);
2104 }
2105 }
2106}
2107
2108
2109void
2114 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2115 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2116}
2117
2118
2120GNEEdge::smoothShape(const PositionVector& old, bool forElevation) {
2122 // distinguish 3 cases:
2123 // a) if the edge has exactly 3 or 4 points, use these as control points
2124 // b) if the edge has more than 4 points, use the first 2 and the last 2 as control points
2125 // c) if the edge is straight and both nodes are geometry-like nodes, use geometry of the continuation edges as control points
2126 PositionVector init;
2127#ifdef DEBUG_SMOOTH_GEOM
2128 if (DEBUGCOND(this)) std::cout << getID()
2129 << " forElevation=" << forElevation
2130 << " fromGeometryLike=" << myNBEdge->getFromNode()->geometryLike()
2131 << " toGeometryLike=" << myNBEdge->getToNode()->geometryLike()
2132 << " smoothShape old=" << old << "\n";
2133#endif
2134 if (old.size() == 3 || old.size() == 4) {
2135 init = old;
2136 } else if (old.size() > 4 && !forElevation) {
2137 // for elevation, the initial segments are not useful
2138 init.push_back(old[0]);
2139 init.push_back(old[1]);
2140 init.push_back(old[-2]);
2141 init.push_back(old[-1]);
2142 } else if (myNBEdge->getFromNode()->geometryLike() && myNBEdge->getToNode()->geometryLike()) {
2143 PositionVector begShape;
2144 PositionVector endShape;
2145 const EdgeVector& incoming = myNBEdge->getFromNode()->getIncomingEdges();
2146 const EdgeVector& outgoing = myNBEdge->getToNode()->getOutgoingEdges();
2147 if (incoming.size() == 1) {
2148 begShape = incoming[0]->getGeometry();
2149 } else {
2150 assert(incoming.size() == 2);
2151 begShape = myNBEdge->isTurningDirectionAt(incoming[0]) ? incoming[1]->getGeometry() : incoming[0]->getGeometry();
2152 }
2153 if (outgoing.size() == 1) {
2154 endShape = outgoing[0]->getGeometry();
2155 } else {
2156 assert(outgoing.size() == 2);
2157 endShape = myNBEdge->isTurningDirectionAt(outgoing[0]) ? outgoing[1]->getGeometry() : outgoing[0]->getGeometry();
2158 }
2159 const double dist = MIN2(old.length2D(), MAX2(old.length2D() / 8, fabs(old[0].z() - old[-1].z()) * OptionsCont::getOptions().getFloat("geometry.max-grade") / 3));
2160 if (forElevation) {
2161 // initialize control point elevation for smooth continuation
2162 init.push_back(old[0]);
2163 init.push_back(old.positionAtOffset2D(dist));
2164 init.push_back(old.positionAtOffset2D(old.length2D() - dist));
2165 init.push_back(old[-1]);
2166 double begZ = begShape.positionAtOffset2D(MAX2(0.0, begShape.length2D() - dist)).z();
2167 double endZ = endShape.positionAtOffset2D(MIN2(begShape.length2D(), dist)).z();
2168 // continue incline
2169 init[1].setz(2 * init[0].z() - begZ);
2170 init[2].setz(2 * init[-1].z() - endZ);
2171 } else {
2172 bool ok = true;
2173 const double straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold"));
2174 init = NBNode::bezierControlPoints(begShape, endShape, false, dist, dist, ok, nullptr, straightThresh);
2175 }
2176#ifdef DEBUG_SMOOTH_GEOM
2177 if (DEBUGCOND(this)) {
2178 std::cout << " begShape=" << begShape << " endShape=" << endShape << " forElevation=" << forElevation << " dist=" << dist << " ok=" << ok << " init=" << init << "\n";
2179 }
2180#endif
2181 }
2182 if (init.size() == 0) {
2183 return PositionVector::EMPTY;
2184 } else {
2185 const int numPoints = MAX2(oc.getInt("junctions.internal-link-detail"),
2186 int(old.length2D() / oc.getFloat("opendrive.curve-resolution")));
2187 return init.bezier(numPoints);
2188 }
2189}
2190
2191
2192void
2194 PositionVector modifiedShape = smoothShape(myNBEdge->getGeometry(), false);
2195 if (modifiedShape.size() < 2) {
2196 WRITE_WARNING("Could not compute smooth shape for edge '" + getID() + "'");
2197 } else {
2198 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2199 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2200 }
2201}
2202
2203
2204void
2206 PositionVector elevationBase;
2207 for (const Position& pos : myNBEdge->getGeometry()) {
2208 if (elevationBase.size() == 0 || elevationBase[-1].z() != pos.z()) {
2209 elevationBase.push_back(pos);
2210 }
2211 }
2212 PositionVector elevation = smoothShape(elevationBase, true);
2213 if (elevation.size() <= 2) {
2214 WRITE_WARNING("Could not compute smooth elevation for edge '" + getID() + "'");
2215 } else {
2216 PositionVector modifiedShape = myNBEdge->getGeometry();
2217 if (modifiedShape.size() < 5) {
2218 modifiedShape = modifiedShape.resample(OptionsCont::getOptions().getFloat("opendrive.curve-resolution"), false);
2219 }
2220 const double scale = elevation.length2D() / modifiedShape.length2D();
2221 //std::cout << " elevation=" << elevation << "\n mod1=" << modifiedShape << " scale=" << scale << "\n";
2222 double seen = 0;
2223 for (int i = 1; i < (int)modifiedShape.size(); ++i) {
2224 seen += modifiedShape[i - 1].distanceTo2D(modifiedShape[i]);
2225 modifiedShape[i].setz(elevation.positionAtOffset2D(seen * scale).z());
2226 }
2227 //std::cout << " mod2=" << modifiedShape << "\n";
2228 PositionVector innerShape(modifiedShape.begin() + 1, modifiedShape.end() - 1);
2229 setAttribute(SUMO_ATTR_SHAPE, toString(innerShape), undoList);
2230 }
2231}
2232
2233
2234void
2236 // remove start position and add it the new position
2238 geom.pop_front();
2239 geom.push_front(pos);
2240 // restore modified shape
2241 setGeometry(geom, false);
2242}
2243
2244
2245void
2247 // remove end position and add it the new position
2249 geom.pop_back();
2250 geom.push_back(pos);
2251 // restore modified shape
2252 setGeometry(geom, false);
2253}
2254
2255
2256const std::map<const GNELane*, std::vector<GNEDemandElement*> >
2258 // declare vehicles over edge vector
2259 std::vector<GNEDemandElement*> vehiclesOverEdge;
2260 // declare solution map
2261 std::map<const GNELane*, std::vector<GNEDemandElement*> > vehiclesOverEdgeMap;
2262 // declare a set of vehicles (to avoid duplicates)
2263 std::set<std::pair<double, GNEDemandElement*> > vehicles;
2264 // first obtain all vehicles of this edge
2265 for (const auto& edgeChild : getChildDemandElements()) {
2266 if (((edgeChild->getTagProperty().getTag() == SUMO_TAG_TRIP) || (edgeChild->getTagProperty().getTag() == SUMO_TAG_FLOW)) &&
2267 (edgeChild->getParentEdges().front() == this)) {
2268 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2269 vehicles.insert(std::make_pair(edgeChild->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild));
2270 } else if ((edgeChild->getTagProperty().getTag() == SUMO_TAG_ROUTE) && (edgeChild->getParentEdges().front() == this)) {
2271 for (const auto& routeChild : edgeChild->getChildDemandElements()) {
2272 if ((routeChild->getTagProperty().getTag() == SUMO_TAG_VEHICLE) || (routeChild->getTagProperty().getTag() == GNE_TAG_FLOW_ROUTE)) {
2273 vehicles.insert(std::make_pair(routeChild->getAttributeDouble(SUMO_ATTR_DEPART), routeChild));
2274 }
2275 }
2276 } else if ((edgeChild->getTagProperty().getTag() == GNE_TAG_ROUTE_EMBEDDED) && (edgeChild->getParentEdges().front() == this)) {
2277 vehicles.insert(std::make_pair(edgeChild->getParentDemandElements().front()->getAttributeDouble(SUMO_ATTR_DEPART), edgeChild->getParentDemandElements().front()));
2278 }
2279 }
2280 // reserve
2281 vehiclesOverEdge.reserve(vehicles.size());
2282 // iterate over vehicles
2283 for (const auto& vehicle : vehicles) {
2284 // add it over vehiclesOverEdge;
2285 vehiclesOverEdge.push_back(vehicle.second);
2286 }
2287 // now split vehicles by lanes
2288 for (const auto& vehicle : vehiclesOverEdge) {
2289 const GNELane* vehicleLane = vehicle->getFirstPathLane();
2290 if (vehicleLane) {
2291 vehiclesOverEdgeMap[vehicleLane].push_back(vehicle);
2292 }
2293 }
2294 return vehiclesOverEdgeMap;
2295}
2296
2297
2298void
2300 // check if we can draw it
2302 // draw the name and/or the street name
2303 const bool drawStreetName = s.streetName.show(this) && (myNBEdge->getStreetName() != "");
2304 const bool spreadSuperposed = s.spreadSuperposed && myNBEdge->getBidiEdge() != nullptr;
2305 // check conditions
2306 if (s.edgeName.show(this) || drawStreetName || s.edgeValue.show(this)) {
2307 // get first and last lanes
2308 const GNELane* firstLane = myLanes[0];
2309 const GNELane* lastLane = myLanes[myLanes.size() - 1];
2310 // calculate draw position
2311 Position drawPosition = firstLane->getLaneShape().positionAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2312 drawPosition.add(lastLane->getLaneShape().positionAtOffset(lastLane->getLaneShape().length() / (double) 2.));
2313 drawPosition.mul(.5);
2314 if (spreadSuperposed) {
2315 // move name to the right of the edge and towards its beginning
2316 const double dist = 0.6 * s.edgeName.scaledSize(s.scale);
2317 const double shiftA = firstLane->getLaneShape().rotationAtOffset(firstLane->getLaneShape().length() / (double) 2.) - DEG2RAD(135);
2318 const Position shift(dist * cos(shiftA), dist * sin(shiftA));
2319 drawPosition.add(shift);
2320 }
2321 // calculate drawing angle
2322 double drawAngle = firstLane->getLaneShape().rotationDegreeAtOffset(firstLane->getLaneShape().length() / (double) 2.);
2323 drawAngle += 90;
2324 // avoid draw inverted text
2325 if (drawAngle > 90 && drawAngle < 270) {
2326 drawAngle -= 180;
2327 }
2328 // draw edge name
2329 if (s.edgeName.show(this)) {
2330 drawName(drawPosition, s.scale, s.edgeName, drawAngle);
2331 }
2332 // draw street name
2333 if (drawStreetName) {
2334 GLHelper::drawTextSettings(s.streetName, myNBEdge->getStreetName(), drawPosition, s.scale, drawAngle);
2335 }
2336 // draw edge values
2337 if (s.edgeValue.show(this)) {
2338 // get current scheme
2339 const int activeScheme = s.laneColorer.getActive();
2340 // calculate value depending of active scheme
2341 std::string value;
2342 if (activeScheme == 12) {
2343 // edge param, could be non-numerical
2344 value = getNBEdge()->getParameter(s.edgeParam, "");
2345 } else if (activeScheme == 13) {
2346 // lane param, could be non-numerical
2347 value = getNBEdge()->getLaneStruct(lastLane->getIndex()).getParameter(s.laneParam, "");
2348 } else {
2349 // use numerical value value of leftmost lane to hopefully avoid sidewalks, bikelanes etc
2350 const double doubleValue = lastLane->getColorValue(s, activeScheme);
2351 const RGBColor color = s.laneColorer.getScheme().getColor(doubleValue);
2352 value = color.alpha() == 0 ? "" : toString(doubleValue);
2353 }
2354 // check if value is empty
2355 if (value != "") {
2356 GLHelper::drawTextSettings(s.edgeValue, value, drawPosition, s.scale, drawAngle);
2357 }
2358 }
2359 }
2360 }
2361}
2362
2363
2364void
2366 // Push stopOffset matrix
2368 // translate to front (note: Special case)
2369 if (myNet->getViewNet()->getFrontAttributeCarrier() == this) {
2370 glTranslated(0, 0, GLO_DOTTEDCONTOUR_FRONT);
2371 } else {
2373 }
2375 for (const auto& lane : getLanes()) {
2376 lane->drawLaneStopOffset(s, myNBEdge->myEdgeStopOffset.getOffset());
2377 }
2378 }
2379 // Push stopOffset matrix
2381}
2382
2383
2384void
2386 // first check if draw TAZ Elements is enabled
2388 std::vector<GNEAdditional*> TAZSourceSinks;
2389 // get all TAZ source/sinks vinculated with this edge
2390 for (const auto& additional : getChildAdditionals()) {
2391 if ((additional->getTagProperty().getTag() == SUMO_TAG_TAZSOURCE) ||
2392 (additional->getTagProperty().getTag() == SUMO_TAG_TAZSINK)) {
2393 TAZSourceSinks.push_back(additional);
2394 }
2395 }
2396 if (TAZSourceSinks.size() > 0) {
2397 // check if current front element is a Source/sink
2398 const auto frontAC = myNet->getViewNet()->getFrontAttributeCarrier();
2399 // push all GLIDs
2400 for (const auto& TAZSourceSink : TAZSourceSinks) {
2401 if (TAZSourceSink == frontAC) {
2402 GLHelper::pushName(TAZSourceSink->getGUIGlObject()->getGlID());
2403 }
2404 }
2405 for (const auto& TAZSourceSink : TAZSourceSinks) {
2406 if (TAZSourceSink != frontAC) {
2407 GLHelper::pushName(TAZSourceSink->getGlID());
2408 }
2409 }
2410 // check if TAZ Source/sink is selected
2411 bool selected = false;
2412 for (const auto& TAZSourceSink : TAZSourceSinks) {
2413 if (TAZSourceSink->isAttributeCarrierSelected()) {
2414 selected = true;
2415 }
2416 }
2417 // iterate over lanes
2418 for (const auto& lane : myLanes) {
2419 // get lane drawing constants
2420 GNELane::LaneDrawingConstants laneDrawingConstants(s, lane);
2421 // Push layer matrix
2423 // translate to front (note: Special case)
2424 if (myNet->getViewNet()->getFrontAttributeCarrier() == this) {
2425 glTranslated(0, 0, GLO_DOTTEDCONTOUR_FRONT);
2426 } else if (lane->getLaneShape().length2D() <= (s.neteditSizeSettings.junctionBubbleRadius * 2)) {
2428 } else {
2430 }
2431 // move to front
2432 glTranslated(0, 0, 0.1);
2433 // set color
2434 if (selected) {
2436 } else {
2438 }
2439 // draw as box lines
2441 lane->getLaneGeometry(), laneDrawingConstants.halfWidth);
2442 // Pop layer matrix
2444 }
2445 // pop all GLIDs
2446 for (const auto& TAZSourceSink : TAZSourceSinks) {
2447 if (TAZSourceSink == frontAC) {
2449 }
2450 }
2451 for (const auto& TAZSourceSink : TAZSourceSinks) {
2452 if (TAZSourceSink != frontAC) {
2454 }
2455 }
2456 // check if curently we're inspecting a TAZ Source/Sink
2457 for (const auto& TAZSourceSink : TAZSourceSinks) {
2458 if (myNet->getViewNet()->isAttributeCarrierInspected(TAZSourceSink)) {
2460 } else if (TAZSourceSink == frontAC) {
2462 }
2463 }
2464 }
2465 }
2466}
2467
2468
2469bool
2471 if ((vehicleA.beginPosition() == vehicleB.beginPosition()) && (vehicleA.endPosition() == vehicleB.endPosition())) {
2472 return true;
2473 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2474 return true;
2475 } else if ((vehicleA.beginPosition() < vehicleB.beginPosition()) && (vehicleA.endPosition() > vehicleB.beginPosition())) {
2476 return true;
2477 } else if ((vehicleA.beginPosition() < vehicleB.endPosition()) && (vehicleA.endPosition() > vehicleB.endPosition())) {
2478 return true;
2479 } else {
2480 return false;
2481 }
2482}
2483
2484
2486GNEEdge::processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
2487 // calculate squared snapRadius
2488 const double squaredSnapRadius = (snapRadius * snapRadius);
2489 // declare shape to move
2490 PositionVector shapeToMove = originalShape;
2491 // obtain nearest index
2492 const int nearestIndex = originalShape.indexOfClosest(mousePosition);
2493 // obtain nearest position
2494 const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
2495 // generate indexes
2496 std::vector<int> indexes;
2497 // check conditions
2498 if (nearestIndex == -1) {
2499 return nullptr;
2500 } else if (nearestPosition == Position::INVALID) {
2501 // special case for extremes
2502 if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2503 for (int i = 1; i <= nearestIndex; i++) {
2504 indexes.push_back(i);
2505 }
2506 // move extrem without creating new geometry point
2507 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2508 } else {
2509 return nullptr;
2510 }
2511 } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2512 for (int i = 1; i <= nearestIndex; i++) {
2513 indexes.push_back(i);
2514 }
2515 // move geometry point without creating new geometry point
2516 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2517 } else {
2518 // create new geometry point and keep new index (if we clicked near of shape)
2519 const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
2520 for (int i = 1; i <= newIndex; i++) {
2521 indexes.push_back(i);
2522 }
2523 // move after setting new geometry point in shapeToMove
2524 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2525 }
2526}
2527
2528
2530GNEEdge::processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius) {
2531 // calculate squared snapRadius
2532 const double squaredSnapRadius = (snapRadius * snapRadius);
2533 // declare shape to move
2534 PositionVector shapeToMove = originalShape;
2535 // obtain nearest index
2536 const int nearestIndex = originalShape.indexOfClosest(mousePosition);
2537 // obtain nearest position
2538 const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
2539 // generate indexes
2540 std::vector<int> indexes;
2541 // check conditions
2542 if (nearestIndex == -1) {
2543 return nullptr;
2544 } else if (nearestPosition == Position::INVALID) {
2545 // special case for extremes
2546 if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2547 for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
2548 indexes.push_back(i);
2549 }
2550 // move extrem without creating new geometry point
2551 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2552 } else {
2553 return nullptr;
2554 }
2555 } else if (nearestPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
2556 for (int i = nearestIndex; i < ((int)originalShape.size() - 1); i++) {
2557 indexes.push_back(i);
2558 }
2559 // move geometry point without creating new geometry point
2560 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2561 } else {
2562 // create new geometry point and keep new index (if we clicked near of shape)
2563 const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
2564 for (int i = newIndex; i < ((int)originalShape.size() - 1); i++) {
2565 indexes.push_back(i);
2566 }
2567 // move after setting new geometry point in shapeToMove
2568 return new GNEMoveOperation(this, originalShape, indexes, shapeToMove, indexes);
2569 }
2570}
2571
2572
2575 // declare a vector for saving geometry points to move (all except extremes)
2576 std::vector<int> geometryPointsToMove;
2577 for (int i = 1; i < (int)myNBEdge->getGeometry().size() - 1; i++) {
2578 geometryPointsToMove.push_back(i);
2579 }
2580 // move entire shape (except extremes)
2581 return new GNEMoveOperation(this, myNBEdge->getGeometry(), geometryPointsToMove, myNBEdge->getGeometry(), geometryPointsToMove);
2582}
2583
2584
2587 // get move multiple element values
2588 const auto& moveMultipleElementValues = myNet->getViewNet()->getMoveMultipleElementValues();
2589 // declare shape to move
2590 PositionVector shapeToMove = myNBEdge->getGeometry();
2591 // first check if kept offset is larger than geometry
2592 if (shapeToMove.length2D() < moveMultipleElementValues.getEdgeOffset()) {
2593 return nullptr;
2594 }
2595 // declare offset
2596 double offset = 0;
2597 // set offset depending of convex angle
2598 if (isConvexAngle()) {
2599 offset = moveMultipleElementValues.getEdgeOffset();
2600 } else {
2601 offset = shapeToMove.length2D() - moveMultipleElementValues.getEdgeOffset();
2602 }
2603 // obtain offset position
2604 const Position offsetPosition = myNBEdge->getGeometry().positionAtOffset2D(offset);
2605 // obtain nearest index to offset position
2606 const int nearestIndex = myNBEdge->getGeometry().indexOfClosest(offsetPosition);
2607 // check conditions
2608 if ((nearestIndex == -1) || (offsetPosition == Position::INVALID)) {
2609 return nullptr;
2610 } else if (offsetPosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= (snapRadius * snapRadius)) {
2611 // move geometry point without creating new geometry point
2612 return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {nearestIndex});
2613 } else {
2614 // create new geometry point and keep new index (if we clicked near of shape)
2615 const int newIndex = shapeToMove.insertAtClosest(offsetPosition, true);
2616 // move after setting new geometry point in shapeToMove
2617 return new GNEMoveOperation(this, myNBEdge->getGeometry(), {nearestIndex}, shapeToMove, {newIndex});
2618 }
2619}
2620
2621/****************************************************************************/
#define ENDPOINT_TOLERANCE
Definition: GNEEdge.cpp:50
#define VEHICLE_GAP
Definition: GNEEdge.cpp:49
@ NETWORK_DELETE
mode for deleting network elements
@ NETWORK_MOVE
mode for moving network elements
@ GLO_DOTTEDCONTOUR_INSPECTED
dotted contour inspected element (used in NETEDIT)
@ GLO_DOTTEDCONTOUR_FRONT
dotted contour front element (used in NETEDIT)
@ GLO_MAX
empty max
@ GLO_JUNCTION
a junction
@ GLO_LANE
a lane
@ GLO_EDGE
an edge
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(PEDID)
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:276
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
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_VEHICLE
description of a vehicle
@ GNE_TAG_FLOW_ROUTE
a flow definition using a route instead of a from-to edges route (used in NETEDIT)
@ SUMO_TAG_FLOW
a flow definitio nusing a from-to edges instead of a route (used by router)
@ SUMO_TAG_PARKING_AREA
A parking area.
@ 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_TAZSOURCE
a source within a district (connection road)
@ GNE_TAG_ROUTE_EMBEDDED
embedded route (used in NETEDIT)
@ 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_SPEED
@ GNE_ATTR_STOPOFFSET
stop offset (virtual, used by edge and lanes)
@ GNE_ATTR_OPPOSITE
neighboring lane, simplified lane attr instead of child element
@ 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.
@ 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:71
T MAX2(T a, T b)
Definition: StdDefs.h:77
const double SUMO_const_halfLaneWidth
Definition: StdDefs.h:49
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:78
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:300
static void drawBoundary(const Boundary &b)
Draw a boundary (used for debugging)
Definition: GLHelper.cpp:894
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition: GLHelper.cpp:421
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:583
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:498
static void pushName(unsigned int name)
push Name
Definition: GLHelper.cpp:139
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:130
static void popName()
pop Name
Definition: GLHelper.cpp:148
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:685
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:716
GNENetworkSelector * getEdgesSelector() const
get edges selector
const std::string getID() const
get ID (all Attribute Carriers have one)
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
friend class GNEChange_Attribute
declare friend class
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
void markConnectionGeometryDeprecated()
check that connection's Geometry has to be updated
void updateGeometry()
update pre-computed geometry information
void updateLinkState()
recompute cached myLinkState
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
An Element which don't belong to GNENet but has influence in the simulation.
void updateDemandElementStackLabel(const int stack)
update stack label
Stack demand elements.
Definition: GNEEdge.h:366
const StackPosition & getStackPosition() const
get stack position
Definition: GNEEdge.cpp:1599
const std::vector< GNEDemandElement * > & getDemandElements() const
get demand elements
Definition: GNEEdge.cpp:1605
void addDemandElements(GNEDemandElement *demandElement)
add demand elment to current StackDemandElements
Definition: GNEEdge.cpp:1593
StackDemandElements(const StackPosition stackedPosition, GNEDemandElement *demandElement)
constructor
Definition: GNEEdge.cpp:1585
Stack position (used to stack demand elements over edges)
Definition: GNEEdge.h:352
double beginPosition() const
get begin position
Definition: GNEEdge.cpp:1574
StackPosition(const double departPos, const double length)
constructor
Definition: GNEEdge.cpp:1568
double endPosition() const
get end position
Definition: GNEEdge.cpp:1580
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:53
const Position getFrontDownShapePosition() const
get front down shape position
Definition: GNEEdge.cpp:616
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
Definition: GNEEdge.cpp:348
void drawEdgeName(const GUIVisualizationSettings &s) const
draw edge name
Definition: GNEEdge.cpp:2299
bool isConvexAngle() const
check if edge makes a convex angle [0 - 180) degrees
Definition: GNEEdge.cpp:1518
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:1832
std::string getNetworkElementProblem() const
return a string with the current network element problem
Definition: GNEEdge.cpp:134
void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)
commit move shape
Definition: GNEEdge.cpp:1805
bool hasPredecessors() const
check if this edge has predecessors (note: only for vehicles, this function ignore walking areas!...
Definition: GNEEdge.cpp:1533
void setMoveShape(const GNEMoveResult &moveResult)
set move shape
Definition: GNEEdge.cpp:1783
friend class GNEChange_Lane
Friend class.
Definition: GNEEdge.h:56
~GNEEdge()
Destructor.
Definition: GNEEdge.cpp:90
void smooth(GNEUndoList *undoList)
make geometry smooth
Definition: GNEEdge.cpp:2193
void updateGeometry()
update pre-computed geometry information
Definition: GNEEdge.cpp:142
GNEMoveOperation * getMoveOperation()
get move operation
Definition: GNEEdge.cpp:192
std::string getAttributeForSelection(SumoXMLAttr key) const
method for getting the attribute in the context of object selection
Definition: GNEEdge.cpp:947
void setResponsible(bool newVal)
set responsibility for deleting internal structures
Definition: GNEEdge.cpp:1223
static void drawDottedContourEdge(const GUIVisualizationSettings &s, const GUIDottedGeometry::DottedContourType type, const GNEEdge *edge, const bool drawFrontExtreme, const bool drawBackExtreme, const double exaggeration=1)
draw dotted contour for the given dottedGeometries
Definition: GNEEdge.cpp:1464
void copyEdgeType(const GNEEdgeType *edgeType, GNEUndoList *undoList)
copy edge attributes from edgeType
Definition: GNEEdge.cpp:784
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition: GNEEdge.cpp:481
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEEdge.cpp:389
const std::map< const GNELane *, std::vector< GNEDemandElement * > > getVehiclesOverEdgeMap() const
get vehicles a that start over this edge
Definition: GNEEdge.cpp:2257
std::set< GUIGlID > getLaneGlIDs() const
returns GLIDs of all lanes
Definition: GNEEdge.cpp:829
GNEEdge * getReverseEdge() const
get reverse edge (if exist)
Definition: GNEEdge.cpp:1555
const Position getFrontUpShapePosition() const
get front up shape position
Definition: GNEEdge.cpp:608
void setGeometry(PositionVector geom, bool inner)
update edge geometry and inform the lanes
Definition: GNEEdge.cpp:573
void smoothElevation(GNEUndoList *undoList)
smooth elevation with regard to adjoining edges
Definition: GNEEdge.cpp:2205
void drawLaneStopOffset(const GUIVisualizationSettings &s) const
draw edgeStopOffset
Definition: GNEEdge.cpp:2365
bool clickedOverGeometryPoint(const Position &pos) const
return true if user clicked over a Geometry Point
Definition: GNEEdge.cpp:309
bool clickedOverShapeEnd(const Position &pos) const
return true if user clicked over ShapeEnd
Definition: GNEEdge.cpp:299
void updateVehicleStackLabels()
Definition: GNEEdge.cpp:1290
bool isValid(SumoXMLAttr key, const std::string &value)
Definition: GNEEdge.cpp:1088
void remakeGNEConnections(bool junctionsReady=false)
remake connections
Definition: GNEEdge.cpp:639
GNEMoveOperation * processMoveBothJunctionSelected()
process moving edge when both junctions are selected
Definition: GNEEdge.cpp:2574
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList)
remove geometry point in the clicked position
Definition: GNEEdge.cpp:218
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:839
LaneVector myLanes
vector with the lanes of this edge
Definition: GNEEdge.h:333
static const double SNAP_RADIUS
Definition: GNEEdge.h:271
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:1229
bool hasCustomEndPoints() const
Definition: GNEEdge.cpp:277
void removeConnection(NBEdge::Connection nbCon)
removes a connection
Definition: GNEEdge.cpp:2023
bool hasSuccessors() const
check if this edge has successors (note: only for vehicles, this function ignore walking areas!...
Definition: GNEEdge.cpp:1549
bool isAttributeComputed(SumoXMLAttr key) const
Definition: GNEEdge.cpp:1200
bool myWasSplit
whether this edge was created from a split
Definition: GNEEdge.h:345
void removeLane(GNELane *lane, bool recomputeConnections)
@briefdecrease the number of lanes by one. argument is only used to increase robustness (assertions)
Definition: GNEEdge.cpp:1946
double getExaggeration(const GUIVisualizationSettings &s) const
return exaggeration associated with this GLObject
Definition: GNEEdge.cpp:342
bool hasRestrictedLane(SUMOVehicleClass vclass) const
check if edge has a restricted lane
Definition: GNEEdge.cpp:2088
static const double SNAP_RADIUS_SQUARED
Definition: GNEEdge.h:274
void updateSecondParentJunction(const std::string &value)
update last parent junction
Definition: GNEEdge.cpp:1884
std::vector< GNEEdge * > getOppositeEdges() const
get opposite edges
Definition: GNEEdge.cpp:404
PositionVector smoothShape(const PositionVector &shape, bool forElevation)
return smoothed shape
Definition: GNEEdge.cpp:2120
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:851
NBEdge * myNBEdge
the underlying NBEdge
Definition: GNEEdge.h:330
void copyTemplate(const GNEEdgeTemplate *edgeTemplate, GNEUndoList *undoList)
copy edge attributes from edgetemplate
Definition: GNEEdge.cpp:749
void removeEdgeFromCrossings(GNEJunction *junction, GNEUndoList *undoList)
remove crossing of junction
Definition: GNEEdge.cpp:2099
Position getPositionInView() const
Returns position of hierarchical element in view.
Definition: GNEEdge.cpp:186
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:1893
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:2056
ConnectionVector myGNEConnections
vector with the connections of this edge
Definition: GNEEdge.h:336
void editEndpoint(Position pos, GNEUndoList *undoList)
makes pos the new geometry endpoint at the appropriate end, or remove current existent endpoint
Definition: GNEEdge.cpp:501
void resetBothEndpoint(GNEUndoList *undoList)
restores both endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:563
Position getSplitPos(const Position &clickPos)
Definition: GNEEdge.cpp:487
const std::vector< GNEConnection * > & getGNEConnections() const
returns a reference to the GNEConnection vector
Definition: GNEEdge.cpp:845
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEEdge.cpp:857
int getRouteProbeRelativePosition(GNERouteProbe *routeProbe) const
obtain relative positions of RouteProbes
Definition: GNEEdge.cpp:714
std::string myConnectionStatus
modification status of the connections
Definition: GNEEdge.h:348
void deleteGLObject()
delete element
Definition: GNEEdge.cpp:466
const std::string getOptionalName() const
Returns the street name.
Definition: GNEEdge.cpp:383
void clearGNEConnections()
clear current connections
Definition: GNEEdge.cpp:687
bool myUpdateGeometry
flag to enable/disable update geometry of lanes (used mainly by setNumLanes)
Definition: GNEEdge.h:383
const Position getBackDownShapePosition() const
get back down shape position
Definition: GNEEdge.cpp:632
bool areStackPositionOverlapped(const GNEEdge::StackPosition &vehicleA, const GNEEdge::StackPosition &vehicleB) const
check if given stacked positions are overlapped
Definition: GNEEdge.cpp:2470
void updateFirstParentJunction(const std::string &value)
update front parent junction
Definition: GNEEdge.cpp:1875
void straightenElevation(GNEUndoList *undoList)
interpolate z values linear between junctions
Definition: GNEEdge.cpp:2110
bool clickedOverShapeStart(const Position &pos) const
return true if user clicked over ShapeStart
Definition: GNEEdge.cpp:289
bool isNetworkElementValid() const
check if current network element is valid to be written into XML
Definition: GNEEdge.cpp:124
void setShapeStartPos(const Position &pos)
change Shape StartPos
Definition: GNEEdge.cpp:2235
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:957
void setMicrosimID(const std::string &newID)
override to also set lane ids
Definition: GNEEdge.cpp:2079
const Position getBackUpShapePosition() const
get back up shape position
Definition: GNEEdge.cpp:624
void resetEndpoint(const Position &pos, GNEUndoList *undoList)
restores the endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:549
bool isAttributeEnabled(SumoXMLAttr key) const
Definition: GNEEdge.cpp:1189
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEEdge.cpp:410
void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation=false)
adds a connection
Definition: GNEEdge.cpp:1999
GNEMoveOperation * processMoveFromJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only from junction is selected
Definition: GNEEdge.cpp:2486
void drawEdgeGeometryPoints(const GUIVisualizationSettings &s, const GNELane *lane) const
draw edge geometry points (note: This function is called by GNELane::drawGL(...)
Definition: GNEEdge.cpp:1348
GNEMoveOperation * processNoneJunctionSelected(const double snapRadius)
process moving edge when none junction are selected
Definition: GNEEdge.cpp:2586
const Parameterised::Map & getACParametersMap() const
get parameters map
Definition: GNEEdge.cpp:1217
void drawTAZElements(const GUIVisualizationSettings &s) const
draw TAZElements
Definition: GNEEdge.cpp:2385
std::vector< GNECrossing * > getGNECrossings()
get GNECrossings vinculated with this Edge
Definition: GNEEdge.cpp:732
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:1244
void updateVehicleSpreadGeometries()
Definition: GNEEdge.cpp:1259
GNEMoveOperation * processMoveToJunctionSelected(const PositionVector originalShape, const Position mousePosition, const double snapRadius)
process moving edge when only to junction is selected
Definition: GNEEdge.cpp:2530
void updateGLObject()
update GLObject (geometry, ID, etc.)
Definition: GNEEdge.cpp:475
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition: GNEEdge.cpp:328
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition: GNEEdge.h:342
GNEEdge(GNENet *net, NBEdge *nbe, bool wasSplit=false, bool loaded=false)
Constructor.
Definition: GNEEdge.cpp:62
void setShapeEndPos(const Position &pos)
change Shape EndPos
Definition: GNEEdge.cpp:2246
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 addIncomingGNEEdge(GNEEdge *edge)
add incoming GNEEdge
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
FOX-declaration.
Definition: GNELane.h:52
const double halfWidth
Draw as a normal lane, and reduce width to make sure that a selected edge can still be seen.
Definition: GNELane.h:68
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:142
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:876
const GUIGeometry & getLaneGeometry() const
Definition: GNELane.cpp:136
double getColorValue(const GUIVisualizationSettings &s, int activeScheme) const
return value for lane coloring according to the given scheme
Definition: GNELane.cpp:1375
GNEMoveOperation * calculateMoveShapeOperation(const PositionVector originalShape, const Position mousePosition, const double snapRadius, const bool onlyContour)
calculate move shape operation
move operation
move result
std::vector< int > geometryPointsToMove
shape points to move (of shapeToMove)
PositionVector shapeToUpdate
shape to update (edited in moveElement)
std::vector< GNEEdge * > retrieveEdges(GNEJunction *from, GNEJunction *to) const
get all edges by from and to GNEJunction
const std::set< GNELane * > & getLanes() const
get lanes
const std::set< GNEConnection * > & getConnections() const
get connections
void insertLane(GNELane *lane)
insert lane
void deleteConnection(GNEConnection *connection)
delete connection
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
void insertConnection(GNEConnection *connection)
insert connection
void updateEdgeID(GNEEdge *edge, const std::string &newID)
update edge ID in container
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
void deleteLane(GNELane *lane)
delete lane
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:420
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition: GNENet.cpp:611
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1245
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1257
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition: GNENet.cpp:2011
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:132
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition: GNENet.cpp:1978
void requireSaveDemandElements(bool value)
inform that demand elements has to be saved
Definition: GNENet.cpp:2083
GNEPathManager * getPathManager()
get path manager
Definition: GNENet.cpp:138
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1987
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Boundary myBoundary
object boundary
bool isNetworkElementSelected(const GNENetworkElement *networkElement) const
check if the given networkElement is being selected
void invalidatePathCalculator()
invalidate pathCalculator
PathCalculator * getPathCalculator()
obtain instance of PathCalculator
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.
Definition: GNERouteProbe.h:32
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
void begin(GUIIcon icon, const std::string &description)
Begin undo command sub-group with current supermode. This begins a new group of commands that are tre...
void add(GNEChange *command, bool doit=false, bool merge=true)
Add new command, executing it if desired. The new command will be merged with the previous command if...
void changeAttribute(GNEChange_Attribute *change)
special method for change attributes, avoid empty changes, always execute
const GNEViewNetHelper::DataViewOptions & getDataViewOptions() const
get data view options
Definition: GNEViewNet.cpp:656
const GNEAttributeCarrier * getFrontAttributeCarrier() const
get front attributeCarrier
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:632
bool drawSelectContour(const GUIGlObject *GLObject, const GNEAttributeCarrier *AC) const
check if draw select contour
bool drawDeleteContour(const GUIGlObject *GLObject, const GNEAttributeCarrier *AC) const
check if draw delete contour
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
Definition: GNEViewNet.cpp:644
void drawTranslateFrontAttributeCarrier(const GNEAttributeCarrier *AC, double typeOrLayer, const double extraOffset=0)
draw front attributeCarrier
GNEViewParent * getViewParent() const
get the net object
GNEUndoList * getUndoList() const
get the undoList object
void removeFromAttributeCarrierInspected(const GNEAttributeCarrier *AC)
remove given AC of list of inspected Attribute Carriers
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:474
bool isAttributeCarrierInspected(const GNEAttributeCarrier *AC) const
check if attribute carrier is being inspected
const GNEViewNetHelper::MoveMultipleElementValues & getMoveMultipleElementValues() const
get move multiple element values
Definition: GNEViewNet.cpp:468
GNEDeleteFrame * getDeleteFrame() const
get frame for delete elements
GNEAdditionalFrame * getAdditionalFrame() const
get frame for NETWORK_ADDITIONAL
GNEInspectorFrame * getInspectorFrame() const
get frame for inspect elements
class for pack all variables related with GUIDottedGeometry color
void reset()
rest Dotted Geometry Color
void drawDottedGeometry(const GUIVisualizationSettings &s, GUIDottedGeometry::DottedContourType type, DottedGeometryColor &dottedGeometryColor, const double customWidth=1) const
draw inspected dottedShape
void moveShapeToSide(const double value)
move shape to side
void invertOffset()
invert offset of all segments
static void drawDottedContourShape(const GUIVisualizationSettings &s, const DottedContourType type, const PositionVector &shape, const double width, const double exaggeration, const bool drawFirstExtrem, const bool drawLastExtrem)
draw dotted contour for the given shape (used by additionals)
The popup menu of a globject.
static void drawGeometry(const GUIVisualizationSettings &s, const Position &mousePos, const GUIGeometry &geometry, const double width, double offset=0)
draw geometry
const PositionVector & getShape() const
The shape of the additional element.
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
Definition: GUIGlObject.h:141
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
Definition: GUIGlObject.h:154
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, const GUIMainWindow &app) const
Builds an entry which allows to copy the cursor position if geo projection is used,...
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0, bool forceShow=false) const
draw name of item
const 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.
Stores the information about how to visualize structures.
bool drawBoundaries
enable or disable draw boundaries
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
GUIVisualizationDetailSettings detailSettings
detail settings
GUIVisualizationSizeSettings addSize
bool drawForPositionSelection
whether drawing is performed for the purpose of selecting objects with a single click
GUIVisualizationTextSettings edgeValue
double laneWidthExaggeration
The lane exaggeration (upscale thickness)
GUIVisualizationColorSettings colorSettings
color settings
double scale
information about a lane's width (temporary, used for a single view)
bool drawDetail(const double detail, const double exaggeration) const
check if details can be drawn for the given GUIVisualizationDetailSettings and current scale and exxa...
GUIVisualizationTextSettings streetName
GUIColorer laneColorer
The lane colorer.
GUIVisualizationTextSettings edgeName
int getCircleResolution() const
function to calculate circle resolution for all circles drawn in drawGL(...) functions
bool spreadSuperposed
Whether to improve visualisation of superposed (rail) edges.
GUIColorer junctionColorer
The junction colorer.
std::string edgeParam
key for coloring by edge parameter
GUIVisualizationNeteditSizeSettings neteditSizeSettings
netedit size settings
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
Definition: GeomHelper.h:50
The representation of a single edge during network building.
Definition: NBEdge.h:92
void setStreetName(const std::string &name)
sets the street name of this edge
Definition: NBEdge.h:680
void mirrorX()
mirror coordinates along the x-axis
Definition: NBEdge.cpp:595
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
Definition: NBEdge.cpp:4114
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:4137
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:1043
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:4100
StopOffset myEdgeStopOffset
A vClass specific stop offset - assumed of length 0 (unspecified) or 1. For the latter case the int i...
Definition: NBEdge.h:1793
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition: NBEdge.h:608
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4052
bool hasLaneSpecificFriction() const
whether lanes differ in friction
Definition: NBEdge.cpp:2387
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:648
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:552
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1426
void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices)
add lane
Definition: NBEdge.cpp:3790
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:2377
std::string myType
The type of the edge.
Definition: NBEdge.h:1730
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:787
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition: NBEdge.cpp:974
bool hasLoadedLength() const
Returns whether a length was set explicitly.
Definition: NBEdge.h:618
void setDistance(double distance)
set kilometrage at start of edge (negative value implies couting down along the edge)
Definition: NBEdge.h:1416
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:736
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:625
const std::string & getID() const
Definition: NBEdge.h:1526
double getDistance() const
get distance
Definition: NBEdge.h:685
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:375
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3923
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:968
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:3430
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:2363
bool isBidiEdge(bool checkPotential=false) const
whether this edge is part of a bidirectional edge pair
Definition: NBEdge.cpp:773
void setBidi(bool isBidi)
mark this edge as a bidi edge
Definition: NBEdge.h:1421
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:526
void setFriction(int lane, double friction)
set lane specific friction (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4068
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:1402
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1483
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
Definition: NBEdge.cpp:3845
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:2397
@ USER
The connection was given by the user.
double getFriction() const
Returns the friction on this edge.
Definition: NBEdge.h:632
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double friction=UNSPECIFIED_FRICTION, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:1145
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:2419
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1183
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:675
const NBEdge * getBidiEdge() const
Definition: NBEdge.h:1512
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:545
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3767
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:533
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:357
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:1440
double getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:695
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:4006
void setLoadedLength(double val)
set loaded length
Definition: NBEdge.cpp:4152
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:615
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:4469
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition: NBEdge.cpp:650
int myPriority
The priority of the edge.
Definition: NBEdge.h:1749
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:258
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:263
const Position & getPosition() const
Definition: NBNode.h:250
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:3468
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:544
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
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.
Definition: OptionsCont.cpp:59
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
Definition: Parameterised.h:45
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:257
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:298
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:252
double x() const
Returns the x-position.
Definition: Position.h:55
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:125
void mul(double val)
Multiplies both positions with the given value.
Definition: Position.h:105
double z() const
Returns the z-position.
Definition: Position.h:65
double y() const
Returns the y-position.
Definition: Position.h:60
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 ammount
PositionVector interpolateZ(double zStart, double zEnd) const
returned vector that varies z smoothly over its length
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 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
void reset()
reset stopOffset
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
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:4451
bool showDemandElements() const
check if show demand elements checkbox is enabled
NetworkEditMode networkEditMode
the current Network edit mode
bool isCurrentSupermodeDemand() const
@check if current supermode is Demand
bool isCurrentSupermodeNetwork() const
@check if current supermode is Network
static void drawLockIcon(const GNEAttributeCarrier *AC, GUIGlObjectType type, const Position viewPosition, 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 geometryPointsText
details for Geometry Points Texts
static const double junctionBubbleRadius
junction bubble radius
static const double edgeGeometryPointRadius
moving edge geometry point 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:227
int toLane
The lane the connections yields in.
Definition: NBEdge.h:233
double speed
custom speed for connection
Definition: NBEdge.h:257
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:230
KeepClear keepClear
whether the junction must be kept clear when using this connection
Definition: NBEdge.h:248
double customLength
custom length for connection
Definition: NBEdge.h:263
bool uncontrolled
check if Connection is uncontrolled
Definition: NBEdge.h:314
PositionVector customShape
custom shape for connection
Definition: NBEdge.h:266
bool mayDefinitelyPass
Information about being definitely free to drive (on-ramps)
Definition: NBEdge.h:245
double contPos
custom position for internal junction on this connection
Definition: NBEdge.h:251
double visibility
custom foe visiblity for connection
Definition: NBEdge.h:254
double friction
Definition: NBEdge.h:260
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