Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GNEJunction.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
18// A class for visualizing and editing junctions in netedit (adapted from
19// GUIJunctionWrapper)
20/****************************************************************************/
21#include <config.h>
22
26#include <netbuild/NBOwnTLDef.h>
36#include <netedit/GNENet.h>
37#include <netedit/GNEUndoList.h>
38#include <netedit/GNEViewNet.h>
52
53#include "GNEConnection.h"
54#include "GNEJunction.h"
55#include "GNECrossing.h"
56#include "GNEWalkingArea.h"
57#include "GNEInternalLane.h"
58
59
60// ===========================================================================
61// method definitions
62// ===========================================================================
63
64GNEJunction::GNEJunction(GNENet* net, NBNode* nbn, bool loaded) :
66 GUIIconSubSys::getIcon(GUIIcon::JUNCTION), {}, {}, {}, {}, {}, {}),
67 myNBNode(nbn),
68 myDrawingToggle(new int),
69 myLogicStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED),
70 myHasValidLogic(loaded),
71myTesselation(nbn->getID(), "", RGBColor::MAGENTA, nbn->getShape(), false, true, 0) {
72 // update centering boundary without updating grid
73 updateCenteringBoundary(false);
74}
75
76
78 // delete drawing toggle
79 delete myDrawingToggle;
80 // delete all GNECrossing
81 for (const auto& crossing : myGNECrossings) {
82 crossing->decRef();
83 if (crossing->unreferenced()) {
84 // check if remove it from Attribute Carriers
85 if (myNet->getAttributeCarriers()->getCrossings().count(crossing) > 0) {
87 }
88 // show extra information for tests
89 WRITE_DEBUG("Deleting unreferenced " + crossing->getTagStr() + " '" + crossing->getID() + "' in GNEJunction destructor");
90 delete crossing;
91 }
92 }
93 // delete all GNEWalkingArea
94 for (const auto& walkingArea : myGNEWalkingAreas) {
95 walkingArea->decRef();
96 if (walkingArea->unreferenced()) {
97 // check if remove it from Attribute Carriers
98 if (myNet->getAttributeCarriers()->getWalkingAreas().count(walkingArea) > 0) {
100 }
101 // show extra information for tests
102 WRITE_DEBUG("Deleting unreferenced " + walkingArea->getTagStr() + " '" + walkingArea->getID() + "' in GNEJunction destructor");
103 delete walkingArea;
104 }
105 }
106 if (myAmResponsible) {
107 // show extra information for tests
108 WRITE_DEBUG("Deleting NBNode of '" + getID() + "' in GNEJunction destructor");
109 delete myNBNode;
110 }
111}
112
113
114const PositionVector&
116 return myNBNode->getShape();
117}
118
119
120void
123 // trigger rebuilding tesselation
124 myExaggeration = 2;
125}
126
127
128void
129GNEJunction::updateGeometryAfterNetbuild(bool rebuildNBNodeCrossings) {
130 // rebuild crossings
131 rebuildGNECrossings(rebuildNBNodeCrossings);
132 // clear walking areas
134 // clear missing connections
136}
137
138
143
144
145bool
147 // get modes and viewParent (for code legibility)
148 const auto& modes = myNet->getViewNet()->getEditModes();
149 const auto& viewParent = myNet->getViewNet()->getViewParent();
150 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
151 // continue depending of current status
152 if (inspectedElements.isInspectingSingleElement()) {
153 // check if starts in this junction
154 if (inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_FROM_JUNCTION) &&
155 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_FROM_JUNCTION) == getID())) {
156 return true;
157 }
158 } else if (modes.isCurrentSupermodeNetwork()) {
159 if (modes.networkEditMode == NetworkEditMode::NETWORK_CREATE_EDGE) {
160 if (viewParent->getCreateEdgeFrame()->getJunctionSource()) {
161 return viewParent->getCreateEdgeFrame()->getJunctionSource() == this;
162 } else {
164 }
165 }
166 } else if (modes.isCurrentSupermodeDemand()) {
167 // get current GNEPlanCreator
168 GNEPlanCreator* planCreator = nullptr;
169 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
170 planCreator = viewParent->getPersonFrame()->getPlanCreator();
171 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
172 planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
173 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
174 planCreator = viewParent->getContainerFrame()->getPlanCreator();
175 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
176 planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
177 }
178 // continue depending of planCreator
179 if (planCreator) {
180 if (planCreator->getPlanParameteres().fromJunction == getID()) {
181 return true;
182 }
183 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
184 const auto& selectedJunctions = viewParent->getVehicleFrame()->getPathCreator()->getSelectedJunctions();
185 // check if this is the first selected junction
186 if ((selectedJunctions.size() > 0) && (selectedJunctions.front() == this)) {
187 return true;
188 }
189 }
190 }
191 // nothing to draw
192 return false;
193}
194
195
196bool
198 // get modes and viewParent (for code legibility)
199 const auto& modes = myNet->getViewNet()->getEditModes();
200 const auto& viewParent = myNet->getViewNet()->getViewParent();
201 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
202 // continue depending of current status
203 if (inspectedElements.isInspectingSingleElement()) {
204 // check if ends in this junction
205 if (inspectedElements.getFirstAC()->getTagProperty().vehicleJunctions() &&
206 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_TO_JUNCTION) == getID())) {
207 return true;
208 }
209 } else if (modes.isCurrentSupermodeNetwork()) {
210 if (modes.networkEditMode == NetworkEditMode::NETWORK_CREATE_EDGE) {
211 if (viewParent->getCreateEdgeFrame()->getJunctionSource() &&
212 (viewParent->getCreateEdgeFrame()->getJunctionSource() != this)) {
214 }
215 } else if (modes.networkEditMode == NetworkEditMode::NETWORK_MOVE) {
216 // check if we're moving a junction
217 const auto movedJunction = dynamic_cast<GNEJunction*>(myNet->getViewNet()->getMoveSingleElementValues().getMovedElement());
218 if (movedJunction && (movedJunction != this)) {
219 // continue depending of junction shape
220 if (myNBNode->getShape().area() < 4) {
221 // calculate distance between both centers
222 const double junctionBubbleRadius = myNet->getViewNet()->getVisualisationSettings().neteditSizeSettings.junctionBubbleRadius;
223 const double radiusTo = getExaggeration(myNet->getViewNet()->getVisualisationSettings()) * junctionBubbleRadius;
224 if (myNBNode->getPosition().distanceSquaredTo2D(movedJunction->getPositionInView()) < (radiusTo * radiusTo)) {
225 // add it in the list of merging junction (first the moved junction)
228 return true;
229 }
230 } else if (myNBNode->getShape().around(movedJunction->getNBNode()->getPosition())) {
231 // add it in the list of merging junction (first the moved junction)
234 return true;
235 }
236 }
237 }
238 } else if (modes.isCurrentSupermodeDemand()) {
239 // get current GNEPlanCreator
240 GNEPlanCreator* planCreator = nullptr;
241 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
242 planCreator = viewParent->getPersonFrame()->getPlanCreator();
243 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
244 planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
245 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
246 planCreator = viewParent->getContainerFrame()->getPlanCreator();
247 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
248 planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
249 }
250 // continue depending of planCreator
251 if (planCreator) {
252 if (planCreator->getPlanParameteres().toJunction == getID()) {
253 return true;
254 }
255 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
256 const auto& selectedJunctions = viewParent->getVehicleFrame()->getPathCreator()->getSelectedJunctions();
257 // check if this is the first selected junction
258 if ((selectedJunctions.size() > 1) && (selectedJunctions.back() == this)) {
259 return true;
260 }
261 }
262 }
263 // nothing to draw
264 return false;
265}
266
267
268bool
270 return false;
271}
272
273
274bool
276 // get modes and viewParent (for code legibility)
277 const auto& modes = myNet->getViewNet()->getEditModes();
278 const auto& viewParent = myNet->getViewNet()->getViewParent();
279 const auto& viewObjectsSelector = myNet->getViewNet()->getViewObjectsSelector();
280 if (viewObjectsSelector.getJunctionFront() != this) {
281 return false;
282 } else {
283 if (modes.isCurrentSupermodeDemand()) {
284 // get current plan selector
285 GNEPlanSelector* planSelector = nullptr;
286 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
287 planSelector = viewParent->getPersonFrame()->getPlanSelector();
288 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
289 planSelector = viewParent->getPersonPlanFrame()->getPlanSelector();
290 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
291 planSelector = viewParent->getContainerFrame()->getPlanSelector();
292 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
293 planSelector = viewParent->getContainerPlanFrame()->getPlanSelector();
294 }
295 // continue depending of plan selector
296 if (planSelector && planSelector->markJunctions()) {
297 return (viewObjectsSelector.getAttributeCarrierFront() == viewObjectsSelector.getJunctionFront());
298 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
299 // get current vehicle template
300 const auto& vehicleTemplate = viewParent->getVehicleFrame()->getVehicleTagSelector()->getCurrentTemplateAC();
301 // check if vehicle can be placed over from-to TAZs
302 if (vehicleTemplate && vehicleTemplate->getTagProperty().vehicleJunctions()) {
303 return (viewObjectsSelector.getAttributeCarrierFront() == viewObjectsSelector.getJunctionFront());
304 }
305 }
306 }
307 return false;
308 }
309}
310
311
312bool
314 // get edit modes
315 const auto& editModes = myNet->getViewNet()->getEditModes();
316 // check if we're in delete mode
317 if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE)) {
319 } else {
320 return false;
321 }
322}
323
324
325bool
327 // get edit modes
328 const auto& editModes = myNet->getViewNet()->getEditModes();
329 // check if we're in select mode
330 if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_SELECT)) {
332 } else {
333 return false;
334 }
335}
336
337
338bool
340 // get edit modes
341 const auto& editModes = myNet->getViewNet()->getEditModes();
342 // check if we're in move mode
343 if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&
344 (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {
345 // check if we're editing this network element
347 if (editedNetworkElement) {
348 return editedNetworkElement == this;
349 } else {
350 // only move the first element
352 }
353 } else {
354 return false;
355 }
356}
357
358
361 // edit depending if shape is being edited
362 if (isShapeEdited()) {
363 // calculate move shape operation
364 return calculateMoveShapeOperation(this, myNBNode->getShape(), false);
365 } else {
366 // return move junction position
367 return new GNEMoveOperation(this, myNBNode->getPosition());
368 }
369}
370
371
372void
373GNEJunction::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
374 // edit depending if shape is being edited
375 if (isShapeEdited()) {
376 // get original shape
378 // check shape size
379 if (shape.size() > 2) {
380 // obtain index
381 int index = shape.indexOfClosest(clickedPosition);
382 // get snap radius
384 // check if we have to create a new index
385 if ((index != -1) && shape[index].distanceSquaredTo2D(clickedPosition) < (snap_radius * snap_radius)) {
386 // remove geometry point
387 shape.erase(shape.begin() + index);
388 // commit new shape
389 undoList->begin(this, "remove geometry point of " + getTagStr());
391 undoList->end();
392 }
393 }
394 }
395}
396
397
398void
399GNEJunction::rebuildGNECrossings(bool rebuildNBNodeCrossings) {
400 // rebuild GNECrossings only if create crossings and walkingAreas in net is enabled
402 if (rebuildNBNodeCrossings) {
403 // build new NBNode::Crossings and walking areas
407 }
408 // create a vector to keep retrieved and created crossings
409 std::vector<GNECrossing*> retrievedCrossings;
410 // iterate over NBNode::Crossings of GNEJunction
411 for (const auto& crossing : myNBNode->getCrossingsIncludingInvalid()) {
412 // retrieve existent GNECrossing, or create it
413 GNECrossing* retrievedGNECrossing = retrieveGNECrossing(crossing.get());
414 retrievedCrossings.push_back(retrievedGNECrossing);
415 // check if previously this GNECrossings exists, and if true, remove it from myGNECrossings and insert in tree again
416 std::vector<GNECrossing*>::iterator retrievedExists = std::find(myGNECrossings.begin(), myGNECrossings.end(), retrievedGNECrossing);
417 if (retrievedExists != myGNECrossings.end()) {
418 myGNECrossings.erase(retrievedExists);
419 // update geometry of retrieved crossing
420 retrievedGNECrossing->updateGeometry();
421 // update boundary
422 retrievedGNECrossing->updateCenteringBoundary(false);
423 } else {
424 // include reference to created GNECrossing
425 retrievedGNECrossing->incRef();
426 }
427 }
428 // delete non retrieved GNECrossings (we don't need to extract if from Tree two times)
429 for (const auto& crossing : myGNECrossings) {
430 crossing->decRef();
431 // check if crossing is selected
432 if (crossing->isAttributeCarrierSelected()) {
433 crossing->unselectAttributeCarrier();
434 }
435 // remove it from inspected ACS
437 // remove it from net
438 myNet->removeGLObjectFromGrid(crossing);
439 // remove it from attributeCarriers
441 if (crossing->unreferenced()) {
442 // show extra information for tests
443 WRITE_DEBUG("Deleting unreferenced " + crossing->getTagStr() + " in rebuildGNECrossings()");
444 delete crossing;
445 }
446 }
447 // copy retrieved (existent and created) GNECrossings to myGNECrossings
448 myGNECrossings = retrievedCrossings;
449 }
450}
451
452
453void
455 if (OptionsCont::getOptions().getBool("lefthand")) {
456 myNBNode->mirrorX();
457 for (NBEdge* e : myNBNode->getEdges()) {
458 e->mirrorX();
459
460 }
461 }
462}
463
464
465void
466GNEJunction::buildTLSOperations(GUISUMOAbstractView& parent, GUIGLObjectPopupMenu* ret, const int numSelectedJunctions) {
467 // create menu pane for edge operations
468 FXMenuPane* TLSOperations = new FXMenuPane(ret);
469 ret->insertMenuPaneChild(TLSOperations);
470 new FXMenuCascade(ret, TL("TLS operations"), GUIIconSubSys::getIcon(GUIIcon::MODETLS), TLSOperations);
471 // create menu commands for all TLS operations
472 FXMenuCommand* mcAddTLS = GUIDesigns::buildFXMenuCommand(TLSOperations, TL("Add TLS"), nullptr, &parent, MID_GNE_JUNCTION_ADDTLS);
473 FXMenuCommand* mcAddJoinedTLS = GUIDesigns::buildFXMenuCommand(TLSOperations, TL("Add joined TLS"), nullptr, &parent, MID_GNE_JUNCTION_ADDJOINTLS);
474 // check if disable create TLS
475 if (myNBNode->getControllingTLS().size() > 0) {
476 mcAddTLS->disable();
477 mcAddJoinedTLS->disable();
478 } else {
479 mcAddTLS->enable();
480 // check if add joined TLS
481 if (isAttributeCarrierSelected() && (numSelectedJunctions > 1)) {
482 mcAddJoinedTLS->enable();
483 } else {
484 mcAddJoinedTLS->disable();
485 }
486 }
487}
488
489
492 if (myShapeEdited) {
493 return getShapeEditedPopUpMenu(app, parent, myNBNode->getShape());
494 } else {
495 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
496 // build common commands
497 buildPopupHeader(ret, app);
500 // build selection and show parameters menu
503 buildPositionCopyEntry(ret, app);
504 // add separator
505 new FXMenuSeparator(ret);
506 // check if we're in supermode network
508 const int numSelectedJunctions = myNet->getAttributeCarriers()->getNumberOfSelectedJunctions();
509 const int numEndpoints = (int)myNBNode->getEndPoints().size();
510 // check if we're handling a selection
511 bool handlingSelection = isAttributeCarrierSelected() && (numSelectedJunctions > 1);
512 // check if menu commands has to be disabled
516 // build TLS operation
517 if (!invalidMode) {
518 buildTLSOperations(parent, ret, numSelectedJunctions);
519 }
520 // create menu commands
521 GUIDesigns::buildFXMenuCommand(ret, TL("Reset edge endpoints"), nullptr, &parent, MID_GNE_JUNCTION_RESET_EDGE_ENDPOINTS);
522 FXMenuCommand* mcCustomShape = GUIDesigns::buildFXMenuCommand(ret, TL("Set custom junction shape"), nullptr, &parent, MID_GNE_JUNCTION_EDIT_SHAPE);
523 FXMenuCommand* mcResetCustomShape = GUIDesigns::buildFXMenuCommand(ret, TL("Reset junction shape"), nullptr, &parent, MID_GNE_JUNCTION_RESET_SHAPE);
524 FXMenuCommand* mcReplaceByGeometryPoint = GUIDesigns::buildFXMenuCommand(ret, TL("Replace junction by geometry point"), nullptr, &parent, MID_GNE_JUNCTION_REPLACE);
525 FXMenuCommand* mcSplitJunction = GUIDesigns::buildFXMenuCommand(ret, TLF("Split junction (% end points)", numEndpoints), nullptr, &parent, MID_GNE_JUNCTION_SPLIT);
526 FXMenuCommand* mcSplitJunctionAndReconnect = GUIDesigns::buildFXMenuCommand(ret, TL("Split junction and reconnect"), nullptr, &parent, MID_GNE_JUNCTION_SPLIT_RECONNECT);
527 // check if is a roundabout
528 if (myNBNode->isRoundabout()) {
529 GUIDesigns::buildFXMenuCommand(ret, TL("Select roundabout"), nullptr, &parent, MID_GNE_JUNCTION_SELECT_ROUNDABOUT);
530 } else {
531 // get radius
532 const double radius = (myNBNode->getRadius() == NBNode::UNSPECIFIED_RADIUS) ? OptionsCont::getOptions().getFloat("default.junctions.radius") : myNBNode->getRadius();
533 const std::string menuEntryInfo = TLF("Convert to roundabout (using junction attribute radius %)", toString(radius));
534 FXMenuCommand* mcRoundabout = GUIDesigns::buildFXMenuCommand(ret, menuEntryInfo.c_str(), nullptr, &parent, MID_GNE_JUNCTION_CONVERT_ROUNDABOUT);
535 // check if disable depending of number of edges
536 if ((getChildEdges().size() < 2) ||
537 ((myGNEIncomingEdges.size() == 1) && (myGNEOutgoingEdges.size() == 1) && (myGNEIncomingEdges[0]->getFromJunction() == myGNEOutgoingEdges[0]->getToJunction()))) {
538 mcRoundabout->disable();
539 }
540 }
541 // check multijunctions
542 const std::string multi = ((numSelectedJunctions > 1) && isAttributeCarrierSelected()) ? TLF(" of % junctions", numSelectedJunctions) : "";
543 FXMenuCommand* mcClearConnections = GUIDesigns::buildFXMenuCommand(ret, TL("Clear connections") + multi, nullptr, &parent, MID_GNE_JUNCTION_CLEAR_CONNECTIONS);
544 FXMenuCommand* mcResetConnections = GUIDesigns::buildFXMenuCommand(ret, TL("Reset connections") + multi, nullptr, &parent, MID_GNE_JUNCTION_RESET_CONNECTIONS);
545 // check if current mode is correct
546 if (invalidMode) {
547 mcCustomShape->disable();
548 mcClearConnections->disable();
549 mcResetConnections->disable();
550 }
551 // check if we're handling a selection
552 if (handlingSelection) {
553 mcResetCustomShape->setText(TL("Reset junction shapes"));
554 }
555 // disable mcClearConnections if junction hasn't connections
556 if (getGNEConnections().empty()) {
557 mcClearConnections->disable();
558 }
559 // disable mcResetCustomShape if junction doesn't have a custom shape
560 if (myNBNode->getShape().size() == 0) {
561 mcResetCustomShape->disable();
562 }
563 // checkIsRemovable requires turnarounds to be computed. This is ugly
564 if ((myNBNode->getIncomingEdges().size() == 2) && (myNBNode->getOutgoingEdges().size() == 2)) {
566 }
567 std::string reason = TL("wrong edit mode");
568 if (invalidMode || !myNBNode->checkIsRemovableReporting(reason)) {
569 mcReplaceByGeometryPoint->setText(mcReplaceByGeometryPoint->getText() + " (" + reason.c_str() + ")");
570 mcReplaceByGeometryPoint->disable();
571 }
572 // check if disable split junctions
573 if (numEndpoints == 1) {
574 mcSplitJunction->disable();
575 mcSplitJunctionAndReconnect->disable();
576 }
577 }
578 return ret;
579 }
580}
581
582
583double
587
588
593
594
595void
597 // Remove object from grid
598 if (updateGrid) {
600 }
601 // calculate boundary using a radius bigger than geometry point
603 myNBNode->getPosition().x() + 1, myNBNode->getPosition().y() + 1);
605 // add shape
606 if (myNBNode->getShape().size() > 0) {
609 }
610 // add boundaries of all connections, walking areas and crossings
611 for (const auto& edge : myGNEIncomingEdges) {
612 for (const auto& connection : edge->getGNEConnections()) {
613 const auto boundary = connection->getCenteringBoundary();
614 if (boundary.isInitialised()) {
615 myJunctionBoundary.add(boundary);
616 }
617 }
618 }
619 for (const auto& crossing : myGNECrossings) {
620 const auto boundary = crossing->getCenteringBoundary();
621 if (boundary.isInitialised()) {
622 myJunctionBoundary.add(boundary);
623 }
624 }
625 for (const auto& walkingArea : myGNEWalkingAreas) {
626 const auto boundary = walkingArea->getCenteringBoundary();
627 if (boundary.isInitialised()) {
628 myJunctionBoundary.add(boundary);
629 }
630 }
631
632 // add object into grid
633 if (updateGrid) {
634 // if junction has at least one edge, then don't add in grid (because uses the edge's grid)
635 if (myGNEIncomingEdges.size() + myGNEOutgoingEdges.size() == 0) {
637 }
638 }
639 // trigger rebuilding tesselation
640 myExaggeration = 2;
641}
642
643
644void
646 // first check drawing toggle and boundary selection
648 // draw boundaries
649 if (inGrid()) {
651 }
652 // get junction exaggeration
653 const double junctionExaggeration = getExaggeration(s);
654 // only continue if exaggeration is greater than 0
655 if (junctionExaggeration > 0) {
656 // get detail level
657 const auto d = s.getDetailLevel(junctionExaggeration);
658 // get shape area
659 const double junctionShapeArea = myNBNode->getShape().area();
660 // check if draw junction as shape
661 const bool drawBubble = drawAsBubble(s, junctionShapeArea);
662 // draw geometry only if we'rent in drawForObjectUnderCursor mode
664 // push layer matrix
666 // translate to front
668 // draw junction as shape
669 drawJunctionAsShape(s, d, junctionExaggeration);
670 // draw junction as bubble
671 if (drawBubble) {
672 drawJunctionAsBubble(s, d, junctionExaggeration);
673 }
674 // draw TLS
675 drawTLSIcon(s, d);
676 // draw elevation
677 drawElevation(s, d);
678 // pop layer Matrix
680 // draw lock icon
682 // draw junction name
684 // draw dotted contour depending if we're editing the custom shape
686 if (editedNetworkElement && (editedNetworkElement == this)) {
687 // draw dotted contour geometry points
689 junctionExaggeration, s.dottedContourSettings.segmentWidthSmall);
690 } else {
691 // draw dotted contour for shape
692 if (junctionShapeArea >= 4) {
694 }
695 // draw dotted contour for bubble
696 if (drawBubble) {
698 }
699 }
700 }
701 // calculate junction contour (always before children)
702 calculateJunctioncontour(s, d, junctionExaggeration, drawBubble);
703 // draw Junction childs
705 }
706 // update drawing toggle
708 }
709}
710
711
712void
714 // Check if edge can be deleted
717 }
718}
719
720
721void
725
726
727NBNode*
729 return myNBNode;
730}
731
732
733std::vector<GNEJunction*>
735 // use set to avoid duplicates junctions
736 std::set<GNEJunction*> junctions;
737 for (const auto& incomingEdge : myGNEIncomingEdges) {
738 junctions.insert(incomingEdge->getFromJunction());
739 }
740 for (const auto& outgoingEdge : myGNEOutgoingEdges) {
741 junctions.insert(outgoingEdge->getToJunction());
742 }
743 return std::vector<GNEJunction*>(junctions.begin(), junctions.end());
744}
745
746
747void
749 // Check if incoming edge was already inserted
750 std::vector<GNEEdge*>::iterator i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
751 if (i != myGNEIncomingEdges.end()) {
752 throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + getTagStr() + " with ID " + getID() + "'");
753 } else {
754 // Add edge into containers
755 myGNEIncomingEdges.push_back(edge);
756 }
757}
758
759
760
761void
763 // Check if outgoing edge was already inserted
764 std::vector<GNEEdge*>::iterator i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
765 if (i != myGNEOutgoingEdges.end()) {
766 throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + getTagStr() + " with ID " + getID() + "'");
767 } else {
768 // Add edge into containers
769 myGNEOutgoingEdges.push_back(edge);
770 }
771}
772
773
774void
776 // Check if incoming edge was already inserted
777 std::vector<GNEEdge*>::iterator i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
778 if (i == myGNEIncomingEdges.end()) {
779 throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + getTagStr() + " with ID " + getID() + "'");
780 } else {
781 // remove edge from containers
782 myGNEIncomingEdges.erase(i);
783 }
784}
785
786
787void
789 // Check if outgoing edge was already inserted
790 std::vector<GNEEdge*>::iterator i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
791 if (i == myGNEOutgoingEdges.end()) {
792 throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + getTagStr() + " with ID " + getID() + "'");
793 } else {
794 // remove edge from containers
795 myGNEOutgoingEdges.erase(i);
796 }
797}
798
799
800const std::vector<GNEEdge*>&
804
805
806const std::vector<GNEEdge*>&
810
811
812const std::vector<GNECrossing*>&
816
817
818const std::vector<GNEWalkingArea*>&
822
823
824std::vector<GNEConnection*>
826 std::vector<GNEConnection*> connections;
827 for (const auto& incomingEdge : myGNEIncomingEdges) {
828 for (const auto& connection : incomingEdge->getGNEConnections()) {
829 connections.push_back(connection);
830 }
831 }
832 return connections;
833}
834
835
836void
840
841
842void
846
847
848void
850 myAmTLSSelected = selected;
851}
852
853
854void
856 if (!myNBNode->hasCustomShape()) {
857 if (myNBNode->myPoly.size() > 0) {
858 // write GL Debug
859 WRITE_GLDEBUG("<-- Invalidating shape of junction '" + getID() + "' -->");
860 // clear poly
861 myNBNode->myPoly.clear();
862 // update centering boundary
864 }
866 }
867}
868
869
870void
871GNEJunction::setLogicValid(bool valid, GNEUndoList* undoList, const std::string& status) {
872 myHasValidLogic = valid;
873 if (!valid) {
874 assert(undoList != 0);
875 assert(undoList->hasCommandGroup());
878 for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
879 GNEEdge* srcEdge = myNet->getAttributeCarriers()->retrieveEdge((*it)->getID());
880 removeConnectionsFrom(srcEdge, undoList, false); // false, because the whole tls will be invalidated at the end
882 }
884 invalidateTLS(undoList);
885 } else {
886 // logic valed, then rebuild GNECrossings to adapt it to the new logic
887 // (but don't rebuild the crossings in NBNode because they are already finished)
888 rebuildGNECrossings(false);
889 }
890}
891
892
893void
894GNEJunction::removeConnectionsFrom(GNEEdge* edge, GNEUndoList* undoList, bool updateTLS, int lane) {
895 NBEdge* srcNBE = edge->getNBEdge();
896 NBEdge* turnEdge = srcNBE->getTurnDestination();
897 // Make a copy of connections
898 std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
899 // delete in reverse so that undoing will add connections in the original order
900 for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
901 if (lane >= 0 && (*con_it).fromLane != lane) {
902 continue;
903 }
904 bool hasTurn = con_it->toEdge == turnEdge;
905 undoList->add(new GNEChange_Connection(edge, *con_it, false, false), true);
906 // needs to come after GNEChange_Connection
907 // XXX bug: this code path will not be used on a redo!
908 if (hasTurn) {
910 }
911 }
912 if (updateTLS) {
913 std::vector<NBConnection> removeConnections;
914 for (NBEdge::Connection con : connections) {
915 removeConnections.push_back(NBConnection(srcNBE, con.fromLane, con.toEdge, con.toLane));
916 }
917 removeTLSConnections(removeConnections, undoList);
918 }
919}
920
921
922void
923GNEJunction::removeConnectionsTo(GNEEdge* edge, GNEUndoList* undoList, bool updateTLS, int lane) {
924 NBEdge* destNBE = edge->getNBEdge();
925 std::vector<NBConnection> removeConnections;
926 for (NBEdge* srcNBE : myNBNode->getIncomingEdges()) {
927 GNEEdge* srcEdge = myNet->getAttributeCarriers()->retrieveEdge(srcNBE->getID());
928 std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
929 for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
930 if ((*con_it).toEdge == destNBE) {
931 if (lane >= 0 && (*con_it).toLane != lane) {
932 continue;
933 }
934 bool hasTurn = srcNBE->getTurnDestination() == destNBE;
935 undoList->add(new GNEChange_Connection(srcEdge, *con_it, false, false), true);
936 // needs to come after GNEChange_Connection
937 // XXX bug: this code path will not be used on a redo!
938 if (hasTurn) {
939 myNet->addExplicitTurnaround(srcNBE->getID());
940 }
941 removeConnections.push_back(NBConnection(srcNBE, (*con_it).fromLane, destNBE, (*con_it).toLane));
942 }
943 }
944 }
945 if (updateTLS) {
946 removeTLSConnections(removeConnections, undoList);
947 }
948}
949
950
951void
952GNEJunction::removeTLSConnections(std::vector<NBConnection>& connections, GNEUndoList* undoList) {
953 if (connections.size() > 0) {
954 const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
955 for (const auto& TLS : coypOfTls) {
956 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
957 // guessed TLS (NBOwnTLDef) do not need to be updated
958 if (tlDef != nullptr) {
959 std::string newID = tlDef->getID();
960 // create replacement before deleting the original because deletion will mess up saving original nodes
961 NBLoadedSUMOTLDef* replacementDef = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
962 for (NBConnection& con : connections) {
963 replacementDef->removeConnection(con);
964 }
965 undoList->add(new GNEChange_TLS(this, tlDef, false), true);
966 undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
967 // the removed traffic light may have controlled more than one junction. These too have become invalid now
968 const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
969 for (const auto& node : copyOfNodes) {
970 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
971 undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
972 undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
973 }
974 }
975 }
976 }
977}
978
979
980void
982 // remap connections of the edge
983 assert(which->getLanes().size() == by->getLanes().size());
984 std::vector<NBEdge::Connection> connections = which->getNBEdge()->getConnections();
985 for (NBEdge::Connection& c : connections) {
986 undoList->add(new GNEChange_Connection(which, c, false, false), true);
987 undoList->add(new GNEChange_Connection(by, c, false, true), true);
988 }
989 // also remap tls connections
990 const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
991 for (const auto& TLS : coypOfTls) {
992 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
993 // guessed TLS (NBOwnTLDef) do not need to be updated
994 if (tlDef != nullptr) {
995 std::string newID = tlDef->getID();
996 // create replacement before deleting the original because deletion will mess up saving original nodes
997 NBLoadedSUMOTLDef* replacementDef = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
998 for (int i = 0; i < (int)which->getLanes().size(); ++i) {
999 replacementDef->replaceRemoved(which->getNBEdge(), i, by->getNBEdge(), i, true);
1000 }
1001 undoList->add(new GNEChange_TLS(this, tlDef, false), true);
1002 undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
1003 // the removed traffic light may have controlled more than one junction. These too have become invalid now
1004 const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
1005 for (const auto& node : copyOfNodes) {
1006 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1007 undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
1008 undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
1009 }
1010 }
1011 }
1012}
1013
1014
1015void
1017 EdgeVector incoming = myNBNode->getIncomingEdges();
1018 for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
1019 NBEdge* srcNBE = *it;
1020 GNEEdge* srcEdge = myNet->getAttributeCarriers()->retrieveEdge(srcNBE->getID());
1022 }
1023}
1024
1025
1026void
1027GNEJunction::invalidateTLS(GNEUndoList* undoList, const NBConnection& deletedConnection, const NBConnection& addedConnection) {
1028 assert(undoList->hasCommandGroup());
1029 // NBLoadedSUMOTLDef becomes invalid, replace with NBOwnTLDef which will be dynamically recomputed
1030 const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
1031 for (const auto& TLS : coypOfTls) {
1032 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
1033 if (tlDef != nullptr) {
1034 // the removed traffic light may have controlled more than one junction. These too have become invalid now
1035 const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
1036 if (myGNECrossings.size() == 0 && getNBNode()->getCrossings().size() != 0) {
1037 // crossings were not computed yet. We need them as netedit elements to manage tlIndex resetting
1040 for (const auto& node : copyOfNodes) {
1041 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1042 if (sharing != this) {
1043 sharing->rebuildGNECrossings();
1044 }
1045 }
1046 }
1047 NBTrafficLightDefinition* replacementDef = nullptr;
1048 std::string newID = tlDef->getID(); // + "_reguessed"; // changes due to reguessing will be visible in diff
1049 if (deletedConnection != NBConnection::InvalidConnection) {
1050 // create replacement before deleting the original because deletion will mess up saving original nodes
1051 NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
1052 repl->removeConnection(deletedConnection);
1053 replacementDef = repl;
1054 } else if (addedConnection != NBConnection::InvalidConnection) {
1055 if (addedConnection.getTLIndex() == NBConnection::InvalidTlIndex) {
1056 // custom tl indices of crossings might become invalid upon recomputation so we must save them
1057 // however, they could remain valid so we register a change but keep them at their old value
1058 for (const auto& crossing : myGNECrossings) {
1059 const std::string oldValue = crossing->getAttribute(SUMO_ATTR_TLLINKINDEX);
1061 GNEChange_Attribute::changeAttribute(crossing, SUMO_ATTR_TLLINKINDEX, oldValue, undoList, true);
1062 const std::string oldValue2 = crossing->getAttribute(SUMO_ATTR_TLLINKINDEX2);
1064 GNEChange_Attribute::changeAttribute(crossing, SUMO_ATTR_TLLINKINDEX2, oldValue2, undoList, true);
1065 }
1066 }
1067 NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
1068 repl->addConnection(addedConnection.getFrom(), addedConnection.getTo(),
1069 addedConnection.getFromLane(), addedConnection.getToLane(), addedConnection.getTLIndex(), addedConnection.getTLIndex2());
1070 replacementDef = repl;
1071 } else {
1072 // recompute crossing indices along with everything else
1073 for (const auto& crossing : myGNECrossings) {
1076 }
1077 replacementDef = new NBOwnTLDef(newID, tlDef->getOffset(), tlDef->getType());
1078 replacementDef->setProgramID(tlDef->getProgramID());
1079 }
1080 undoList->add(new GNEChange_TLS(this, tlDef, false), true);
1081 undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
1082 // reset nodes of joint tls
1083 for (const auto& node : copyOfNodes) {
1084 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1085 if (sharing != this) {
1086 if (deletedConnection == NBConnection::InvalidConnection && addedConnection == NBConnection::InvalidConnection) {
1087 // recompute crossing indices for shared
1088 // (they won't do this on subsequent call to invalidateTLS if they received an NBOwnTLDef)
1089 for (const auto& crossing : sharing->getGNECrossings()) {
1092 }
1093 }
1094 undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
1095 undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
1096 }
1097 }
1098 }
1099 }
1100}
1101
1102void
1104 // obtain a copy of GNECrossing of junctions
1105 const auto copyOfGNECrossings = myGNECrossings;
1106 // iterate over copy of GNECrossings
1107 for (const auto& crossing : copyOfGNECrossings) {
1108 // obtain the set of edges vinculated with the crossing (due it works as ID)
1109 EdgeSet edgeSet(crossing->getCrossingEdges().begin(), crossing->getCrossingEdges().end());
1110 // If this edge is part of the set of edges of crossing
1111 if (edgeSet.count(edge->getNBEdge()) == 1) {
1112 // delete crossing if this is their last edge
1113 if ((crossing->getCrossingEdges().size() == 1) && (crossing->getCrossingEdges().front() == edge->getNBEdge())) {
1114 myNet->deleteCrossing(crossing, undoList);
1115 } else {
1116 // remove this edge of the edge's attribute of crossing (note: This can invalidate the crossing)
1117 std::vector<std::string> edges = GNEAttributeCarrier::parse<std::vector<std::string>>(crossing->getAttribute(SUMO_ATTR_EDGES));
1118 edges.erase(std::find(edges.begin(), edges.end(), edge->getID()));
1119 crossing->setAttribute(SUMO_ATTR_EDGES, joinToString(edges, " "), undoList);
1120 }
1121 }
1122 }
1123}
1124
1125
1126bool
1130
1131
1133GNEJunction::retrieveGNECrossing(NBNode::Crossing* NBNodeCrossing, bool createIfNoExist) {
1134 // iterate over all crossing
1135 for (const auto& crossing : myGNECrossings) {
1136 // if found, return it
1137 if (crossing->getCrossingEdges() == NBNodeCrossing->edges) {
1138 return crossing;
1139 }
1140 }
1141 if (createIfNoExist) {
1142 // create new GNECrossing
1143 GNECrossing* createdGNECrossing = new GNECrossing(this, NBNodeCrossing->edges);
1144 // show extra information for tests
1145 WRITE_DEBUG("Created " + createdGNECrossing->getTagStr() + " '" + createdGNECrossing->getID() + "' in retrieveGNECrossing()");
1146 // update geometry after creating
1147 createdGNECrossing->updateGeometry();
1148 // add it in Network
1149 myNet->addGLObjectIntoGrid(createdGNECrossing);
1150 // add it in attributeCarriers
1151 myNet->getAttributeCarriers()->insertCrossing(createdGNECrossing);
1152 return createdGNECrossing;
1153 } else {
1154 return nullptr;
1155 }
1156}
1157
1158
1160GNEJunction::retrieveGNEWalkingArea(const std::string& NBNodeWalkingAreaID, bool createIfNoExist) {
1161 // iterate over all walkingArea
1162 for (const auto& walkingArea : myGNEWalkingAreas) {
1163 // if found, return it
1164 if (walkingArea->getID() == NBNodeWalkingAreaID) {
1165 return walkingArea;
1166 }
1167 }
1168 if (createIfNoExist) {
1169 // create new GNEWalkingArea
1170 GNEWalkingArea* createdGNEWalkingArea = new GNEWalkingArea(this, NBNodeWalkingAreaID);
1171 // show extra information for tests
1172 WRITE_DEBUG("Created " + createdGNEWalkingArea->getTagStr() + " '" + createdGNEWalkingArea->getID() + "' in retrieveGNEWalkingArea()");
1173 // update geometry after creating
1174 createdGNEWalkingArea->updateGeometry();
1175 // add it in Network
1176 myNet->addGLObjectIntoGrid(createdGNEWalkingArea);
1177 // add it in attributeCarriers
1178 myNet->getAttributeCarriers()->insertWalkingArea(createdGNEWalkingArea);
1179 return createdGNEWalkingArea;
1180 } else {
1181 return nullptr;
1182 }
1183}
1184
1185
1186void
1188 // only it's needed to mark the connections of incoming edges
1189 for (const auto& i : myGNEIncomingEdges) {
1190 for (const auto& j : i->getGNEConnections()) {
1191 j->markConnectionGeometryDeprecated();
1192 }
1193 if (includingNeighbours) {
1194 i->getFromJunction()->markConnectionsDeprecated(false);
1195 }
1196 }
1197}
1198
1199
1200void
1201GNEJunction::setJunctionType(const std::string& value, GNEUndoList* undoList) {
1202 undoList->begin(this, "change " + getTagStr() + " type");
1204 if (getNBNode()->isTLControlled() &&
1205 // if switching changing from or to traffic_light_right_on_red we need to remove the old plan
1208 ) {
1209 // make a copy because we will modify the original
1210 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1211 for (const auto& TLS : copyOfTls) {
1212 undoList->add(new GNEChange_TLS(this, TLS, false), true);
1213 }
1214 }
1215 if (!getNBNode()->isTLControlled()) {
1216 // create new traffic light
1217 undoList->add(new GNEChange_TLS(this, nullptr, true), true);
1218 }
1219 } else if (getNBNode()->isTLControlled()) {
1220 // delete old traffic light
1221 // make a copy because we will modify the original
1222 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1223 for (const auto& TLS : copyOfTls) {
1224 undoList->add(new GNEChange_TLS(this, TLS, false, false), true);
1225 const std::vector<NBNode*> copyOfNodes = TLS->getNodes(); // make a copy!
1226 for (const auto& node : copyOfNodes) {
1227 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1228 sharing->invalidateTLS(undoList);
1229 }
1230 }
1231 }
1232 // must be the final step, otherwise we do not know which traffic lights to remove via GNEChange_TLS
1233 GNEChange_Attribute::changeAttribute(this, SUMO_ATTR_TYPE, value, undoList, true);
1234 for (const auto& crossing : myGNECrossings) {
1235 GNEChange_Attribute::changeAttribute(crossing, SUMO_ATTR_TLLINKINDEX, "-1", undoList, true);
1236 GNEChange_Attribute::changeAttribute(crossing, SUMO_ATTR_TLLINKINDEX2, "-1", undoList, true);
1237 }
1238 undoList->end();
1239}
1240
1241
1242void
1244 // delete non retrieved GNEWalkingAreas (we don't need to extract if from Tree two times)
1245 for (const auto& walkingArea : myGNEWalkingAreas) {
1246 walkingArea->decRef();
1247 // check if walkingArea is selected
1248 if (walkingArea->isAttributeCarrierSelected()) {
1249 walkingArea->unselectAttributeCarrier();
1250 }
1251 // remove it from inspected ACS
1253 // remove it from net
1254 myNet->removeGLObjectFromGrid(walkingArea);
1255 // remove it from attributeCarriers
1257 if (walkingArea->unreferenced()) {
1258 // show extra information for tests
1259 WRITE_DEBUG("Deleting unreferenced " + walkingArea->getTagStr() + " in rebuildGNEWalkingAreas()");
1260 delete walkingArea;
1261 }
1262 }
1263 myGNEWalkingAreas.clear();
1264}
1265
1266
1267void
1269 // first clear GNEWalkingAreas
1271 // iterate over NBNode::WalkingAreas of GNEJunction
1272 for (const auto& walkingArea : myNBNode->getWalkingAreas()) {
1273 // retrieve existent GNEWalkingArea, or create it
1274 GNEWalkingArea* retrievedGNEWalkingArea = retrieveGNEWalkingArea(walkingArea.id, true);
1275 // include reference to created GNEWalkingArea
1276 retrievedGNEWalkingArea->incRef();
1277 // update geometry of retrieved walkingArea
1278 retrievedGNEWalkingArea->updateGeometry();
1279 // update boundary
1280 retrievedGNEWalkingArea->updateCenteringBoundary(false);
1281 // add in walkingAreas
1282 myGNEWalkingAreas.push_back(retrievedGNEWalkingArea);
1283 }
1284}
1285
1286
1287
1288void
1290 if (std::find(myInternalLanes.begin(), myInternalLanes.end(), internalLane) != myInternalLanes.end()) {
1291 throw ProcessError(internalLane->getTagStr() + " with ID='" + internalLane->getID() + "' already exist");
1292 } else {
1293 myInternalLanes.push_back(internalLane);
1294 }
1295}
1296
1297
1298void
1300 const auto finder = std::find(myInternalLanes.begin(), myInternalLanes.end(), internalLane);
1301 if (finder == myInternalLanes.end()) {
1302 throw ProcessError(internalLane->getTagStr() + " with ID='" + internalLane->getID() + "' wasn't previously inserted");
1303 } else {
1304 myInternalLanes.erase(finder);
1305 }
1306}
1307
1308
1309std::string
1311 switch (key) {
1312 case SUMO_ATTR_ID:
1313 return getMicrosimID();
1314 case SUMO_ATTR_POSITION:
1315 return toString(myNBNode->getPosition());
1316 case SUMO_ATTR_TYPE:
1317 return toString(myNBNode->getType());
1319 return myLogicStatus;
1320 case SUMO_ATTR_SHAPE:
1321 return toString(myNBNode->getShape());
1322 case SUMO_ATTR_RADIUS:
1323 if (myNBNode->getRadius() < 0) {
1324 return "default";
1325 } else {
1326 return toString(myNBNode->getRadius());
1327 }
1328 case SUMO_ATTR_TLTYPE:
1330 // @todo this causes problems if the node were to have multiple programs of different type (plausible)
1331 return toString((*myNBNode->getControllingTLS().begin())->getType());
1332 } else {
1333 return "No TLS";
1334 }
1335 case SUMO_ATTR_TLLAYOUT:
1337 return toString((*myNBNode->getControllingTLS().begin())->getLayout());
1338 } else {
1339 return "No TLS";
1340 }
1341 case SUMO_ATTR_TLID:
1343 return toString((*myNBNode->getControllingTLS().begin())->getID());
1344 } else {
1345 return "No TLS";
1346 }
1348 return myNBNode->isRoundabout() ? True : False;
1350 // keep clear is only used as a convenience feature in plain xml
1351 // input. When saving to .net.xml the status is saved only for the connections
1352 // to show the correct state we must check all connections
1353 for (const auto& i : myGNEIncomingEdges) {
1354 for (const auto& j : i->getGNEConnections()) {
1355 if (j->getNBEdgeConnection().keepClear) {
1356 return True;
1357 }
1358 }
1359 }
1360 return False;
1363 case SUMO_ATTR_FRINGE:
1365 case SUMO_ATTR_NAME:
1366 return myNBNode->getName();
1367 case GNE_ATTR_SELECTED:
1370 return myNBNode->getParametersStr();
1371 default:
1372 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1373 }
1374}
1375
1376
1379 switch (key) {
1380 case SUMO_ATTR_SHAPE:
1381 return myNBNode->getShape();
1382 default:
1383 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1384 }
1385}
1386
1387
1388void
1389GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1390 if (value == getAttribute(key)) {
1391 return; //avoid needless changes, later logic relies on the fact that attributes have changed
1392 }
1393 switch (key) {
1394 case SUMO_ATTR_ID:
1396 case SUMO_ATTR_SHAPE:
1397 case SUMO_ATTR_RADIUS:
1399 case SUMO_ATTR_FRINGE:
1400 case SUMO_ATTR_NAME:
1401 case GNE_ATTR_SELECTED:
1403 GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1404 break;
1405 case SUMO_ATTR_POSITION: {
1406 // change Keep Clear attribute in all connections
1407 undoList->begin(this, TL("change junction position"));
1408 // obtain NBNode position
1409 const Position orig = myNBNode->getPosition();
1410 // change junction position
1411 GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1412 // calculate delta using new position
1413 const Position delta = myNBNode->getPosition() - orig;
1414 // set new position of adjacent edges
1415 for (const auto& edge : myGNEIncomingEdges) {
1416 const Position newEnd = edge->getNBEdge()->getGeometry().back() + delta;
1418 }
1419 for (const auto& edge : myGNEOutgoingEdges) {
1420 const Position newStart = edge->getNBEdge()->getGeometry().front() + delta;
1421 GNEChange_Attribute::changeAttribute(edge, GNE_ATTR_SHAPE_START, toString(newStart), undoList, true);
1422 }
1423 undoList->end();
1424 break;
1425 }
1427 // change Keep Clear attribute in all connections
1428 undoList->begin(this, TL("change keepClear for whole junction"));
1429 for (const auto& incomingEdge : myGNEIncomingEdges) {
1430 for (const auto& junction : incomingEdge->getGNEConnections()) {
1431 GNEChange_Attribute::changeAttribute(junction, key, value, undoList, true);
1432 }
1433 }
1434 undoList->end();
1435 break;
1436 case SUMO_ATTR_TYPE: {
1437 // set junction type
1438 setJunctionType(value, undoList);
1439 break;
1440 }
1441 case SUMO_ATTR_TLTYPE: {
1442 undoList->begin(this, "change " + getTagStr() + " tl-type");
1443 // make a copy because we will modify the original
1444 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1445 for (const auto& TLS : copyOfTls) {
1446 NBLoadedSUMOTLDef* oldLoaded = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
1447 if (oldLoaded != nullptr) {
1448 NBTrafficLightDefinition* newDef = nullptr;
1449 if (value == toString(TrafficLightType::NEMA) || oldLoaded->getType() == TrafficLightType::NEMA) {
1450 // rebuild the program because the old and new ones are incompatible
1451 newDef = new NBOwnTLDef(oldLoaded->getID(), oldLoaded->getOffset(), TrafficLightType::NEMA);
1452 newDef->setProgramID(oldLoaded->getProgramID());
1453 } else {
1454 NBLoadedSUMOTLDef* newLDef = new NBLoadedSUMOTLDef(*oldLoaded, *oldLoaded->getLogic());
1455 newLDef->guessMinMaxDuration(); // minDur and maxDur are never written for a static tls
1456 newDef = newLDef;
1457 }
1458 std::vector<NBNode*> nodes = TLS->getNodes();
1459 for (const auto& node : nodes) {
1460 GNEJunction* junction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1461 undoList->add(new GNEChange_TLS(junction, TLS, false), true);
1462 undoList->add(new GNEChange_TLS(junction, newDef, true), true);
1463 }
1464 }
1465 }
1466 GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1467 undoList->end();
1468 break;
1469 }
1470 case SUMO_ATTR_TLLAYOUT: {
1471 undoList->begin(this, "change " + getTagStr() + " tlLayout");
1472 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1473 for (const auto& oldTLS : copyOfTls) {
1474 std::vector<NBNode*> copyOfNodes = oldTLS->getNodes();
1475 NBOwnTLDef* newTLS = new NBOwnTLDef(oldTLS->getID(), oldTLS->getOffset(), oldTLS->getType());
1477 newTLS->setProgramID(oldTLS->getProgramID());
1478 for (const auto& node : copyOfNodes) {
1479 GNEJunction* oldJunction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1480 undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
1481 }
1482 for (const auto& node : copyOfNodes) {
1483 GNEJunction* oldJunction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1484 undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
1485 }
1486 }
1487 undoList->end();
1488 break;
1489 }
1490 case SUMO_ATTR_TLID: {
1491 undoList->begin(this, "change " + toString(SUMO_TAG_TRAFFIC_LIGHT) + " id");
1492 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1493 assert(copyOfTls.size() > 0);
1494 NBTrafficLightDefinition* currentTLS = *copyOfTls.begin();
1495 NBTrafficLightDefinition* currentTLSCopy = nullptr;
1496 const bool currentIsSingle = currentTLS->getNodes().size() == 1;
1497 const bool currentIsLoaded = dynamic_cast<NBLoadedSUMOTLDef*>(currentTLS) != nullptr;
1498 if (currentIsLoaded) {
1499 currentTLSCopy = new NBLoadedSUMOTLDef(*currentTLS,
1500 *dynamic_cast<NBLoadedSUMOTLDef*>(currentTLS)->getLogic());
1501 }
1502 // remove from previous tls
1503 for (const auto& TLS : copyOfTls) {
1504 undoList->add(new GNEChange_TLS(this, TLS, false), true);
1505 }
1507 // programs to which the current node shall be added
1508 const std::map<std::string, NBTrafficLightDefinition*> programs = tlCont.getPrograms(value);
1509 if (programs.size() > 0) {
1510 for (const auto& TLSProgram : programs) {
1511 NBTrafficLightDefinition* oldTLS = TLSProgram.second;
1512 if (dynamic_cast<NBOwnTLDef*>(oldTLS) != nullptr) {
1513 undoList->add(new GNEChange_TLS(this, oldTLS, true), true);
1514 } else {
1515 // delete and re-create the definition because the loaded phases are now invalid
1516 if (dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS) != nullptr &&
1517 dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS)->usingSignalGroups()) {
1518 // keep the old program and add all-red state for the added links
1519 NBLoadedSUMOTLDef* newTLSJoined = new NBLoadedSUMOTLDef(*oldTLS, *dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS)->getLogic());
1520 newTLSJoined->joinLogic(currentTLSCopy);
1521 undoList->add(new GNEChange_TLS(this, newTLSJoined, true, true), true);
1522 } else {
1523 undoList->add(new GNEChange_TLS(this, nullptr, true, false, value), true);
1524 }
1526 // switch from old to new definition
1527 std::vector<NBNode*> copyOfNodes = oldTLS->getNodes();
1528 for (const auto& node : copyOfNodes) {
1529 GNEJunction* oldJunction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1530 undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
1531 undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
1532 }
1533 }
1534 }
1535 } else {
1536 if (currentIsSingle && currentIsLoaded) {
1537 // rename the traffic light but keep everything else
1538 NBTrafficLightLogic* renamedLogic = dynamic_cast<NBLoadedSUMOTLDef*>(currentTLSCopy)->getLogic();
1539 renamedLogic->setID(value);
1540 NBLoadedSUMOTLDef* renamedTLS = new NBLoadedSUMOTLDef(*currentTLSCopy, *renamedLogic);
1541 renamedTLS->setID(value);
1542 undoList->add(new GNEChange_TLS(this, renamedTLS, true, true), true);
1543 } else {
1544 // create new traffic light
1545 undoList->add(new GNEChange_TLS(this, nullptr, true, false, value), true);
1546 }
1547 }
1548 delete currentTLSCopy;
1549 undoList->end();
1550 break;
1551 }
1552 default:
1553 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1554 }
1555}
1556
1557
1558bool
1559GNEJunction::isValid(SumoXMLAttr key, const std::string& value) {
1560 switch (key) {
1561 case SUMO_ATTR_ID:
1562 return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveJunction(value, false) == nullptr);
1563 case SUMO_ATTR_TYPE:
1565 case SUMO_ATTR_POSITION:
1566 return canParse<Position>(value);
1567 case SUMO_ATTR_SHAPE:
1568 // empty shapes are allowed
1569 return canParse<PositionVector>(value);
1570 case SUMO_ATTR_RADIUS:
1571 if (value.empty() || (value == "default")) {
1572 return true;
1573 } else {
1574 return canParse<double>(value) && ((parse<double>(value) >= 0) || (parse<double>(value) == -1));
1575 }
1576 case SUMO_ATTR_TLTYPE:
1578 case SUMO_ATTR_TLLAYOUT:
1580 case SUMO_ATTR_TLID:
1581 return myNBNode->isTLControlled() && (value != "");
1583 return canParse<bool>(value);
1586 case SUMO_ATTR_FRINGE:
1588 case SUMO_ATTR_NAME:
1589 return true;
1590 case GNE_ATTR_SELECTED:
1591 return canParse<bool>(value);
1594 default:
1595 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1596 }
1597}
1598
1599
1600bool
1602 switch (key) {
1603 case SUMO_ATTR_TLTYPE:
1604 case SUMO_ATTR_TLLAYOUT:
1605 case SUMO_ATTR_TLID:
1606 return myNBNode->isTLControlled();
1607 case SUMO_ATTR_KEEP_CLEAR: {
1608 // check if at least there is an incoming connection
1609 for (const auto& incomingEdge : myGNEIncomingEdges) {
1610 if (incomingEdge->getGNEConnections().size() > 0) {
1611 return true;
1612 }
1613 }
1614 return false;
1615 }
1617 return false;
1618 default:
1619 return true;
1620 }
1621}
1622
1623
1624bool
1626 switch (key) {
1627 case SUMO_ATTR_SHAPE:
1628 return !myNBNode->hasCustomShape();
1629 default:
1630 return false;
1631 }
1632}
1633
1634
1635const Parameterised::Map&
1639
1640
1641void
1643 myAmResponsible = newVal;
1644}
1645
1646// ===========================================================================
1647// private
1648// ===========================================================================
1649
1650bool
1651GNEJunction::drawAsBubble(const GUIVisualizationSettings& s, const double junctionShapeArea) const {
1652 const auto& editModes = myNet->getViewNet()->getEditModes();
1653 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
1654 // check conditions
1655 if (junctionShapeArea < 4) {
1656 // force draw if this junction is a candidate
1659 return true;
1660 }
1661 // force draw if we're in person/container plan mode
1662 if (editModes.isCurrentSupermodeDemand() &&
1663 ((editModes.demandEditMode == DemandEditMode::DEMAND_PERSON) ||
1664 (editModes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) ||
1665 (editModes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) ||
1666 (editModes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN))) {
1667 return true;
1668 }
1669 // force draw if we're inspecting a vehicle that start or ends in a junction
1670 if (inspectedElements.isInspectingSingleElement()) {
1671 // check if starts or ends in this junction
1672 if ((inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_FROM_JUNCTION) &&
1673 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_FROM_JUNCTION) == getID())) ||
1674 (inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_TO_JUNCTION) &&
1675 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_TO_JUNCTION) == getID()))) {
1676 return true;
1677 }
1678 }
1679 }
1680 if (!s.drawJunctionShape) {
1681 // don't draw bubble if it was disabled in GUIVisualizationSettings
1682 return false;
1683 }
1685 // force draw bubbles if we enabled option in checkbox of viewNet
1686 return true;
1687 }
1688 if (junctionShapeArea >= 4) {
1689 // don't draw if shape area is greater than 4
1690 return false;
1691 }
1692 if (!editModes.isCurrentSupermodeNetwork()) {
1693 // only draw bubbles in network mode
1694 return false;
1695 }
1696 return true;
1697}
1698
1699
1700void
1702 const double exaggeration) const {
1703 // calculate bubble radius
1704 const double bubbleRadius = s.neteditSizeSettings.junctionBubbleRadius * exaggeration;
1705 // set bubble color
1706 const RGBColor bubbleColor = setColor(s, true);
1707 // push matrix
1709 // set color
1710 GLHelper::setColor(bubbleColor);
1711 // move matrix junction center
1712 glTranslated(myNBNode->getPosition().x(), myNBNode->getPosition().y(), 1.5);
1713 // draw filled circle
1714 GLHelper::drawFilledCircleDetailled(d, bubbleRadius);
1715 // pop matrix
1717}
1718
1719
1720void
1722 // first check drawing conditions
1723 if (s.drawJunctionShape && (myNBNode->getShape().size() > 0)) {
1724 // set shape color
1725 const RGBColor junctionShapeColor = setColor(s, false);
1726 // set color
1727 GLHelper::setColor(junctionShapeColor);
1728 // adjust shape to exaggeration (check)
1729 if ((exaggeration > 1 || myExaggeration > 1) && exaggeration != myExaggeration) {
1730 myExaggeration = exaggeration;
1733 myTesselation.getShapeRef().scaleRelative(exaggeration);
1735 }
1736 // check if draw tesselation or or polygon
1738 // draw shape with high detail
1740 } else {
1741 // draw shape
1743 }
1744 // draw shape points only in Network supermode
1747 // set color
1748 const RGBColor darkerColor = junctionShapeColor.changedBrightness(-32);
1749 // calculate geometry
1750 GUIGeometry junctionGeometry;
1751 // obtain junction Shape
1752 PositionVector junctionOpenShape = myNBNode->getShape();
1753 // adjust shape to exaggeration
1754 if (exaggeration > 1) {
1755 junctionOpenShape.scaleRelative(exaggeration);
1756 }
1757 // update geometry
1758 junctionGeometry.updateGeometry(junctionOpenShape);
1759 // set color
1760 GLHelper::setColor(darkerColor);
1761 // draw shape
1763 // draw geometry points
1764 GUIGeometry::drawGeometryPoints(d, junctionOpenShape, darkerColor,
1767 }
1768 }
1769}
1770
1771
1772void
1774 // draw TLS icon if isn't being drawn for selecting
1779 const Position pos = myNBNode->getPosition();
1780 glTranslated(pos.x(), pos.y(), 2.2);
1781 glColor3d(1, 1, 1);
1782 const double halfWidth = 32 / s.scale;
1783 const double halfHeight = 64 / s.scale;
1784 GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GUITexture::TLS), -halfWidth, -halfHeight, halfWidth, halfHeight);
1786 }
1787}
1788
1789
1790void
1792 // check if draw elevation
1795 // Translate to center of junction
1796 glTranslated(myNBNode->getPosition().x(), myNBNode->getPosition().y(), 0.1);
1797 // draw Z value
1800 }
1801}
1802
1803
1804void
1811
1812
1813void
1815 // check if draw junction elements
1817 // draw crossings
1818 for (const auto& crossing : myGNECrossings) {
1819 crossing->drawGL(s);
1820 }
1821 // draw walking areas
1822 for (const auto& walkingArea : myGNEWalkingAreas) {
1823 walkingArea->drawGL(s);
1824 }
1825 // draw internalLanes
1826 for (const auto& internalLanes : myInternalLanes) {
1827 internalLanes->drawGL(s);
1828 }
1829 // draw connections
1830 for (const auto& incomingEdge : myGNEIncomingEdges) {
1831 for (const auto& connection : incomingEdge->getGNEConnections()) {
1832 connection->drawGL(s);
1833 }
1834 }
1835 // draw child demand elements
1836 for (const auto& demandElement : getChildDemandElements()) {
1837 demandElement->drawGL(s);
1838 }
1839 // draw child demand elements
1840 for (const auto& demandElement : getChildDemandElements()) {
1841 demandElement->drawGL(s);
1842 }
1843 // draw path additional elements
1847 }
1848}
1849
1850
1851void
1853 const double exaggeration, const bool drawBubble) const {
1854 // if we're selecting using a boundary, first don't calculate contour bt check if edge boundary is within selection boundary
1856 // simply add object in ViewObjectsHandler with full boundary
1857 gViewObjectsHandler.selectObject(this, getType(), false, true, nullptr);
1858 } else {
1859 // always calculate for shape
1861 // check if calculate contour for bubble
1862 if (drawBubble) {
1864 }
1865 // check geometry points if we're editing shape
1866 if (myShapeEdited) {
1868 exaggeration, true);
1869 }
1870 }
1871}
1872
1873
1874void
1875GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value) {
1876 switch (key) {
1877 case SUMO_ATTR_KEEP_CLEAR: {
1878 throw InvalidArgument(toString(key) + " cannot be edited");
1879 }
1880 case SUMO_ATTR_ID: {
1882 break;
1883 }
1884 case SUMO_ATTR_TYPE: {
1889 }
1891 break;
1892 }
1893 case SUMO_ATTR_POSITION: {
1894 // set new position in NBNode updating edge boundaries
1895 moveJunctionGeometry(parse<Position>(value), true);
1896 // mark this connections and all of the junction's Neighbours as deprecated
1898 // update centering boundary and grid
1900 break;
1901 }
1903 if (myLogicStatus == FEATURE_GUESSED && value != FEATURE_GUESSED) {
1904 // clear guessed connections. previous connections will be restored
1906 // Clear GNEConnections of incoming edges
1907 for (const auto& i : myGNEIncomingEdges) {
1908 i->clearGNEConnections();
1909 }
1910 }
1911 myLogicStatus = value;
1912 break;
1913 case SUMO_ATTR_SHAPE: {
1914 // set new shape (without updating grid)
1915 myNBNode->setCustomShape(parse<PositionVector>(value));
1916 // mark this connections and all of the junction's neighbors as deprecated
1918 // update centering boundary and grid
1920 break;
1921 }
1922 case SUMO_ATTR_RADIUS: {
1923 if (value.empty() || (value == "default")) {
1924 myNBNode->setRadius(-1);
1925 } else {
1926 myNBNode->setRadius(parse<double>(value));
1927 }
1928 break;
1929 }
1930 case SUMO_ATTR_TLTYPE: {
1931 // we need to make a copy of controlling TLS (because original will be updated)
1932 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1933 for (const auto& TLS : copyOfTls) {
1934 TLS->setType(SUMOXMLDefinitions::TrafficLightTypes.get(value));
1935 }
1936 break;
1937 }
1938 case SUMO_ATTR_TLLAYOUT:
1939 // should not be triggered (handled via GNEChange_TLS)
1940 break;
1943 break;
1944 case SUMO_ATTR_FRINGE:
1946 break;
1947 case SUMO_ATTR_NAME:
1948 myNBNode->setName(value);
1949 break;
1950 case GNE_ATTR_SELECTED:
1951 if (parse<bool>(value)) {
1953 } else {
1955 }
1956 break;
1958 myNBNode->setParametersStr(value);
1959 break;
1960 default:
1961 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1962 }
1963 // invalidate demand path calculator
1965}
1966
1967
1968void
1970 // clear contour
1972 // set new position in NBNode without updating grid
1973 if (isShapeEdited()) {
1974 // set new shape
1976 } else if (moveResult.shapeToUpdate.size() > 0) {
1977 // obtain NBNode position
1978 const Position orig = myNBNode->getPosition();
1979 // move geometry
1980 moveJunctionGeometry(moveResult.shapeToUpdate.front(), false);
1981 // set new position of adjacent edges depending if we're moving a selection
1982 for (const auto& NBEdge : getNBNode()->getEdges()) {
1983 myNet->getAttributeCarriers()->retrieveEdge(NBEdge->getID())->updateJunctionPosition(this, orig);
1984 }
1985 }
1987}
1988
1989
1990void
1992 // make sure that newShape isn't empty
1993 if (moveResult.shapeToUpdate.size() > 0) {
1994 // check if we're editing a shape
1995 if (isShapeEdited()) {
1996 // commit new shape
1997 undoList->begin(this, "moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
1998 setAttribute(SUMO_ATTR_SHAPE, toString(moveResult.shapeToUpdate), undoList);
1999 undoList->end();
2000 } else if (myNBNode->hasCustomShape()) {
2001 // commit new shape
2002 undoList->begin(this, "moving custom " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
2003 setAttribute(SUMO_ATTR_POSITION, toString(moveResult.shapeToUpdate.front()), undoList);
2004 // calculate offset and apply to custom shape
2005 const auto customShapeOffset = moveResult.shapeToUpdate.front() - myNBNode->getCenter();
2006 const auto customShapeMoved = myNBNode->getShape().added(customShapeOffset);
2007 setAttribute(SUMO_ATTR_SHAPE, toString(customShapeMoved), undoList);
2008 undoList->end();
2009 } else {
2010 setAttribute(SUMO_ATTR_POSITION, toString(moveResult.shapeToUpdate.front()), undoList);
2011 }
2012 // check merge junctions
2014 }
2015}
2016
2017
2018double
2019GNEJunction::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
2020 switch (activeScheme) {
2021 case 0:
2023 return 3;
2024 } else {
2025 return 0;
2026 }
2027 case 1:
2029 case 2:
2030 switch (myNBNode->getType()) {
2032 return 0;
2034 return 1;
2036 return 2;
2038 return 3;
2040 return 4;
2042 return 5;
2044 return 6;
2046 return 7;
2049 return 8;
2051 return 8; // may happen before first network computation
2053 assert(false);
2054 return 8;
2056 return 9;
2058 return 10;
2060 return 11;
2062 return 12;
2064 return 13;
2065 default:
2066 assert(false);
2067 return 0;
2068 }
2069 case 3:
2070 return myNBNode->getPosition().z();
2071 default:
2072 assert(false);
2073 return 0;
2074 }
2075}
2076
2077void
2079 for (auto edge : myGNEIncomingEdges) {
2080 if (edge->getGNEConnections().size() > 0) {
2082 return;
2083 }
2084 }
2085 // no connections. Use normal color for border edges and cul-de-sac
2086 if (myGNEIncomingEdges.size() == 0 || myGNEOutgoingEdges.size() == 0) {
2088 return;
2089 } else if (myGNEIncomingEdges.size() == 1 && myGNEOutgoingEdges.size() == 1) {
2090 NBEdge* in = myGNEIncomingEdges[0]->getNBEdge();
2091 NBEdge* out = myGNEOutgoingEdges[0]->getNBEdge();
2092 if (in->isTurningDirectionAt(out)) {
2094 return;
2095 }
2096 }
2098}
2099
2100
2101void
2102GNEJunction::moveJunctionGeometry(const Position& pos, const bool updateEdgeBoundaries) {
2103 // reinit NBNode
2104 myNBNode->reinit(pos, myNBNode->getType());
2105 // declare three sets with all affected GNEJunctions, GNEEdges and GNEConnections
2106 std::set<GNEJunction*> affectedJunctions;
2107 std::set<GNEEdge*> affectedEdges;
2108 // Iterate over GNEEdges
2109 for (const auto& edge : getChildEdges()) {
2110 // Add source and destination junctions
2111 affectedJunctions.insert(edge->getFromJunction());
2112 affectedJunctions.insert(edge->getToJunction());
2113 // Obtain neighbors of Junction source
2114 for (const auto& junctionSourceEdge : edge->getFromJunction()->getChildEdges()) {
2115 affectedEdges.insert(junctionSourceEdge);
2116 }
2117 // Obtain neighbors of Junction destination
2118 for (const auto& junctionDestinationEdge : edge->getToJunction()->getChildEdges()) {
2119 affectedEdges.insert(junctionDestinationEdge);
2120 }
2121 }
2122 // reset walking areas of affected edges
2123 for (const auto& affectedJunction : affectedJunctions) {
2124 affectedJunction->clearWalkingAreas();
2125 }
2126 // Iterate over affected Edges
2127 for (const auto& affectedEdge : affectedEdges) {
2128 // update edge boundaries
2129 if (updateEdgeBoundaries) {
2130 affectedEdge->updateCenteringBoundary(true);
2131 }
2132 // Update edge geometry
2133 affectedEdge->updateGeometry();
2134 }
2135}
2136
2137
2140 // get active scheme
2141 const int scheme = s.junctionColorer.getActive();
2142 // first check if we're editing shape
2143 if (myShapeEdited) {
2145 }
2146 // set default color
2148 // set special bubble color
2149 if (bubble && (scheme == 0) && !myColorForMissingConnections) {
2150 color = s.junctionColorer.getScheme().getColor(1);
2151 }
2152 // override with special colors (unless the color scheme is based on selection)
2153 if (drawUsingSelectColor() && scheme != 1) {
2154 color = s.colorSettings.selectionColor;
2155 }
2156 // overwrite color if we're in data mode
2158 color = s.junctionColorer.getScheme().getColor(6);
2159 }
2160 // special color for source candidate junction
2161 if (mySourceCandidate) {
2163 }
2164 // special color for target candidate junction
2165 if (myTargetCandidate) {
2167 }
2168 // special color for special candidate junction
2169 if (mySpecialCandidate) {
2171 }
2172 // special color for possible candidate junction
2173 if (myPossibleCandidate) {
2175 }
2176 // special color for conflicted candidate junction
2179 }
2180 // return color
2181 return color;
2182}
2183
2184
2185void
2188 tlCont.insert(tlDef, forceInsert); // may return false for tlDef which controls multiple junctions
2189 tlDef->addNode(myNBNode);
2190}
2191
2192
2193void
2196 if (tlDef->getNodes().size() == 1) {
2197 tlCont.extract(tlDef);
2198 }
2200}
2201
2202
2203/****************************************************************************/
@ NETWORK_DELETE
mode for deleting network elements
@ NETWORK_MOVE
mode for moving network elements
@ NETWORK_CREATE_EDGE
mode for creating new edges
@ NETWORK_TLS
mode for editing tls
@ NETWORK_SELECT
mode for selecting network elements
@ NETWORK_CONNECT
mode for connecting lanes
@ DEMAND_PERSONPLAN
Mode for editing person plan.
@ DEMAND_CONTAINER
Mode for editing container.
@ DEMAND_PERSON
Mode for editing person.
@ DEMAND_VEHICLE
Mode for editing vehicles.
@ DEMAND_CONTAINERPLAN
Mode for editing container plan.
@ MID_GNE_JUNCTION_ADDTLS
Add TLS into junction.
@ MID_GNE_JUNCTION_RESET_EDGE_ENDPOINTS
reset edge endpoints
@ MID_GNE_JUNCTION_CLEAR_CONNECTIONS
clear junction's connections
@ MID_GNE_JUNCTION_SELECT_ROUNDABOUT
select all roundabout nodes and edges of the current roundabout
@ MID_GNE_JUNCTION_RESET_SHAPE
reset junction shape
@ MID_GNE_JUNCTION_RESET_CONNECTIONS
reset junction's connections
@ MID_GNE_JUNCTION_SPLIT
turn junction into multiple junctions
@ MID_GNE_JUNCTION_REPLACE
turn junction into geometry node
@ MID_GNE_JUNCTION_CONVERT_ROUNDABOUT
convert junction to roundabout
@ MID_GNE_JUNCTION_SPLIT_RECONNECT
turn junction into multiple junctions and reconnect them heuristically
@ MID_GNE_JUNCTION_EDIT_SHAPE
edit junction shape
@ MID_GNE_JUNCTION_ADDJOINTLS
Add join TLS into junctions.
@ GLO_MAX
empty max
@ GLO_JUNCTION
a junction
GUIViewObjectsHandler gViewObjectsHandler
GUIIcon
An enumeration of icons used by the gui applications.
Definition GUIIcons.h:33
#define WRITE_DEBUG(msg)
Definition MsgHandler.h:306
#define TL(string)
Definition MsgHandler.h:315
#define TLF(string,...)
Definition MsgHandler.h:317
#define WRITE_GLDEBUG(msg)
Definition MsgHandler.h:307
std::set< NBEdge * > EdgeSet
container for unique edges
Definition NBCont.h:50
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition NBCont.h:42
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ SUMO_TAG_TRAFFIC_LIGHT
a traffic light
@ SUMO_TAG_EDGE
begin/end of the description of an edge
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_TLLINKINDEX2
link: the index of the opposite direction link of a pedestrian crossing
@ SUMO_ATTR_FROM_JUNCTION
@ SUMO_ATTR_RADIUS
The turning radius at an intersection in m.
@ SUMO_ATTR_TO_JUNCTION
@ SUMO_ATTR_TLLAYOUT
node: the layout of the traffic light program
@ GNE_ATTR_SELECTED
element is selected
@ SUMO_ATTR_EDGES
the edges of a route
@ GNE_ATTR_PARAMETERS
parameters "key1=value1|key2=value2|...|keyN=valueN"
@ SUMO_ATTR_FRINGE
Fringe type of node.
@ 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_TLTYPE
node: the type of traffic light
@ SUMO_ATTR_NAME
@ GNE_ATTR_IS_ROUNDABOUT
@ GNE_ATTR_SHAPE_END
last coordinate of edge shape
@ SUMO_ATTR_TLID
link,node: the traffic light id responsible for this link
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_RIGHT_OF_WAY
How to compute right of way.
@ GNE_ATTR_SHAPE_START
first coordinate of edge shape
@ SUMO_ATTR_TLLINKINDEX
link: the index of the link within the traffic light
@ SUMO_ATTR_KEEP_CLEAR
Whether vehicles must keep the junction clear.
@ SUMO_ATTR_POSITION
const unsigned char TLS[]
Definition TLS.cpp:22
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition ToString.h:283
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:78
bool isInitialised() const
check if Boundary is Initialised
Definition Boundary.cpp:259
Boundary & grow(double by)
extends the boundary by the given amount
Definition Boundary.cpp:343
bool contains2D(const Boundary &b) const
return true if this boundary contains the given boundary (only X-Y)
Definition Boundary.cpp:232
std::string fromJunction
from junction
static void drawFilledPoly(const PositionVector &v, bool close)
Draws a filled polygon described by the list of points.
Definition GLHelper.cpp:203
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:654
static void popMatrix()
pop matrix
Definition GLHelper.cpp:130
static void drawBoundary(const GUIVisualizationSettings &s, const Boundary &b)
Draw a boundary (used for debugging)
Definition GLHelper.cpp:966
static void drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius)
Draws a filled circle around (0,0) depending of level of detail.
Definition GLHelper.cpp:539
static void pushMatrix()
push matrix
Definition GLHelper.cpp:117
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition GLHelper.cpp:756
static void drawTextSettings(const GUIVisualizationTextSettings &settings, const std::string &text, const Position &pos, const double scale, const double angle=0, const double layer=2048, const int align=0)
Definition GLHelper.cpp:787
const std::string getID() const
get ID (all Attribute Carriers have one)
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
bool mySelected
boolean to check if this AC is selected (instead of GUIGlObjectStorage)
static const std::string True
true value in string format (used for comparing boolean values in getAttribute(......
const std::string & getTagStr() const
get tag assigned to this object in string format
static const std::string FEATURE_GUESSED
feature has been reguessed (may still be unchanged be we can't tell (yet)
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
bool inGrid() const
check if this AC was inserted in grid
void selectAttributeCarrier(const bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
static const std::string FEATURE_MODIFIED
feature has been manually modified (implies approval)
static const std::string False
true value in string format(used for comparing boolean values in getAttribute(...))
bool myPossibleCandidate
flag to mark this element as possible candidate
bool mySpecialCandidate
flag to mark this element as special candidate
bool myTargetCandidate
flag to mark this element as target candidate
bool myConflictedCandidate
flag to mark this element as conflicted candidate
bool mySourceCandidate
flag to mark this element as source candidate
static void changeAttribute(GNEAttributeCarrier *AC, SumoXMLAttr key, const std::string &value, GNEUndoList *undoList, const bool force=false)
change attribute
void calculateContourCircleShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const Position &pos, double radius, const double layer, const double scale) const
calculate contour (circle elements)
void clearContour() const
void clear contour
void drawDottedContourGeometryPoints(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, const PositionVector &shape, const double radius, const double scale, const double lineWidth) const
draw dotted contour for geometry points
void calculateContourClosedShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const PositionVector &shape, const double layer, const double scale) const
calculate contours
void drawDottedContours(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, const double lineWidth, const bool addOffset) const
draw dotted contours (basics, select, delete, inspect...)
void calculateContourAllGeometryPoints(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const PositionVector &shape, const double layer, const double radius, const double scale, const bool calculatePosOverShape) const
calculate contour for all geometry points
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
Definition GNECrossing.h:44
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
void updateGeometry()
update pre-computed geometry information
struct for saving subordinated elements (Junction->Edge->Lane->(Additional | DemandElement)
ProtectElements * getProtectElements() const
get protect elements modul
A road/street connecting two junctions (netedit-version)
Definition GNEEdge.h:53
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition GNEEdge.cpp:781
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition GNEEdge.cpp:1118
const std::vector< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
const std::vector< GNEEdge * > & getChildEdges() const
get child edges
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
void removeTLSConnections(std::vector< NBConnection > &connections, GNEUndoList *undoList)
remove the given connections from all traffic light definitions of this junction
bool checkDrawRelatedContour() const
check if draw related contour (cyan)
void updateGLObject()
update GLObject (geometry, ID, etc.)
void markAsCreateEdgeSource()
marks as first junction in createEdge-mode
void addTrafficLight(NBTrafficLightDefinition *tlDef, bool forceInsert)
adds a traffic light
const std::vector< GNEEdge * > & getGNEIncomingEdges() const
Returns incoming GNEEdges.
void rebuildGNEWalkingAreas()
rebuilds WalkingAreas objects for this junction
void updateGeometryAfterNetbuild(bool rebuildNBNodeCrossings=false)
update pre-computed geometry information without modifying netbuild structures
bool myAmResponsible
whether we are responsible for deleting myNBNode
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList)
remove geometry point in the clicked position
const std::vector< GNECrossing * > & getGNECrossings() const
Returns GNECrossings.
friend class GNEChange_TLS
Declare friend class.
Definition GNEJunction.h:53
TesselatedPolygon myTesselation
An object that stores the shape and its tesselation.
const std::vector< GNEWalkingArea * > & getGNEWalkingAreas() const
Returns GNEWalkingAreas.
std::string getAttribute(SumoXMLAttr key) const
void setResponsible(bool newVal)
set responsibility for deleting internal structures
void deleteGLObject()
delete element
bool myColorForMissingConnections
whether this junction probably should have some connections but doesn't
std::vector< const GNEInternalLane * > myInternalLanes
internal lanes related placed in this junction
GNEJunction(GNENet *net, NBNode *nbn, bool loaded=false)
Constructor.
void unMarkAsCreateEdgeSource()
removes mark as first junction in createEdge-mode
void moveJunctionGeometry(const Position &pos, const bool updateEdgeBoundaries)
reposition the node at pos without updating GRID and informs the edges
double getExaggeration(const GUIVisualizationSettings &s) const
return exaggeration associated with this GLObject
void invalidateShape()
GNEContour myCircleContour
variable used for draw circle contours
void updateGeometry()
update pre-computed geometry information (including crossings)
void drawTLSIcon(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d) const
draw TLS icon
bool isLogicValid()
whether this junction has a valid logic
std::vector< GNEEdge * > myGNEOutgoingEdges
vector with the (child) outgoings GNEEdges vinculated with this junction
double getColorValue(const GUIVisualizationSettings &s, int activeScheme) const
determines color value
void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)
commit move shape
void selectTLS(bool selected)
notify the junction of being selected in tls-mode. (used to control drawing)
void replaceIncomingConnections(GNEEdge *which, GNEEdge *by, GNEUndoList *undoList)
replace one edge by another in all tls connections
void removeOutgoingGNEEdge(GNEEdge *edge)
remove outgoing GNEEdge
void markAsModified(GNEUndoList *undoList)
prevent re-guessing connections at this junction
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
std::vector< GNECrossing * > myGNECrossings
the built crossing objects
bool checkDrawMoveContour() const
check if draw move contour (red)
void invalidateTLS(GNEUndoList *undoList, const NBConnection &deletedConnection=NBConnection::InvalidConnection, const NBConnection &addedConnection=NBConnection::InvalidConnection)
PositionVector getAttributePositionVector(SumoXMLAttr key) const
void clearWalkingAreas()
clear walking areas
void removeIncomingGNEEdge(GNEEdge *edge)
remove incoming GNEEdge
std::vector< GNEConnection * > getGNEConnections() const
Returns all GNEConnections vinculated with this junction.
bool checkDrawSelectContour() const
check if draw select contour (blue)
GNEWalkingArea * retrieveGNEWalkingArea(const std::string &NBNodeWalkingAreaID, bool createIfNoExist=true)
get GNEWalkingArea if exist, and if not create it if create is enabled
GNEMoveOperation * getMoveOperation()
get move operation
bool checkDrawFromContour() const
check if draw from contour (green)
bool checkDrawOverContour() const
check if draw over contour (orange)
GNECrossing * retrieveGNECrossing(NBNode::Crossing *NBNodeCrossing, bool createIfNoExist=true)
get GNECrossing if exist, and if not create it if create is enabled
std::vector< GNEEdge * > myGNEIncomingEdges
vector with the (child) incomings GNEEdges vinculated with this junction
Boundary myJunctionBoundary
edge boundary
void calculateJunctioncontour(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double exaggeration, const bool drawBubble) const
calculate contour
void addInternalLane(const GNEInternalLane *internalLane)
add internal lane
const PositionVector & getJunctionShape() const
void setMoveShape(const GNEMoveResult &moveResult)
set move shape
void drawJunctionName(const GUIVisualizationSettings &s) const
draw junction name
void markConnectionsDeprecated(bool includingNeighbours)
mark connections as deprecated
bool checkDrawToContour() const
check if draw from contour (magenta)
const Parameterised::Map & getACParametersMap() const
get parameters map
void mirrorXLeftHand()
temporarily mirror coordinates in lefthand network to compute correct crossing geometries
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Position getPositionInView() const
Returns position of hierarchical element in view.
void drawJunctionAsBubble(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double exaggeration) const
draw junction as bubble
bool isAttributeComputed(SumoXMLAttr key) const
void removeInternalLane(const GNEInternalLane *internalLane)
remove internal lane
bool myAmTLSSelected
whether this junction is selected in tls-mode
void removeConnectionsFrom(GNEEdge *edge, GNEUndoList *undoList, bool updateTLS, int lane=-1)
remove all connections from the given edge
bool isValid(SumoXMLAttr key, const std::string &value)
void addIncomingGNEEdge(GNEEdge *edge)
add incoming GNEEdge
RGBColor setColor(const GUIVisualizationSettings &s, bool bubble) const
sets junction color depending on circumstances
bool myHasValidLogic
whether this junctions logic is valid
std::string myLogicStatus
modification status of the junction logic (all connections across this junction)
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
void removeEdgeFromCrossings(GNEEdge *edge, GNEUndoList *undoList)
removes the given edge from all pedestrian crossings
void drawJunctionChildren(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d) const
draw junction childs
bool drawAsBubble(const GUIVisualizationSettings &s, const double junctionShapeArea) const
check if draw junction as bubble
NBNode * getNBNode() const
Return net build node.
NBNode * myNBNode
A reference to the represented junction.
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
int * myDrawingToggle
drawing toggle (used to avoid double draws)
void checkMissingConnections()
compute whether this junction probably should have some connections but doesn't
std::vector< GNEJunction * > getJunctionNeighbours() const
return GNEJunction neighbours
void setJunctionType(const std::string &value, GNEUndoList *undoList)
set junction Type (using undo/redo)
bool checkDrawDeleteContour() const
check if draw delete contour (pink/white)
void drawJunctionAsShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double exaggeration) const
draw junction as bubble
double myExaggeration
exaggeration used in tesselation
void drawElevation(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d) const
draw elevation
~GNEJunction()
Destructor.
void setLogicValid(bool valid, GNEUndoList *undoList, const std::string &status=FEATURE_GUESSED)
std::vector< GNEWalkingArea * > myGNEWalkingAreas
the built walkingArea objects
void removeConnectionsTo(GNEEdge *edge, GNEUndoList *undoList, bool updateTLS, int lane=-1)
remove all connections to the given edge
bool myAmCreateEdgeSource
whether this junction is the first junction for a newly creatededge
void buildTLSOperations(GUISUMOAbstractView &parent, GUIGLObjectPopupMenu *ret, const int numSelectedJunctions)
build TLS operations contextual menu
void addOutgoingGNEEdge(GNEEdge *edge)
add outgoing GNEEdge
void rebuildGNECrossings(bool rebuildNBNodeCrossings=true)
rebuilds crossing objects for this junction
bool isAttributeEnabled(SumoXMLAttr key) const
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
removes a traffic light
GNEMoveOperation * calculateMoveShapeOperation(const GUIGlObject *obj, const PositionVector originalShape, const bool maintainShapeClosed)
calculate move shape operation
move operation
move result
PositionVector shapeToUpdate
shape to update (edited in moveElement)
void insertWalkingArea(GNEWalkingArea *walkingArea)
insert walkingArea in container
const std::unordered_map< const GUIGlObject *, GNECrossing * > & getCrossings() const
get crossings
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
void updateJunctionID(GNEJunction *junction, const std::string &newID)
update junction ID in container
void insertCrossing(GNECrossing *crossing)
insert crossing in container
void deleteWalkingArea(GNEWalkingArea *walkingArea)
delete walkingArea from container
int getNumberOfSelectedJunctions() const
get number of selected junctions
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
const std::unordered_map< const GUIGlObject *, GNEWalkingArea * > & getWalkingAreas() const
get walkingAreas
void deleteCrossing(GNECrossing *crossing)
delete crossing from container
A NBNetBuilder extended by visualisation and editing capabilities.
Definition GNENet.h:42
void deleteCrossing(GNECrossing *crossing, GNEUndoList *undoList)
remove crossing
Definition GNENet.cpp:658
NBNetBuilder * getNetBuilder() const
get net builder
Definition GNENet.cpp:1559
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1386
GNEPathManager * getDataPathManager()
get data path manager
Definition GNENet.cpp:151
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1396
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition GNENet.cpp:2161
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:145
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition GNENet.cpp:127
GNEPathManager * getNetworkPathManager()
get network path manager
Definition GNENet.cpp:139
void requireRecompute()
inform the net about the need for recomputation
Definition GNENet.cpp:1541
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition GNENet.cpp:2173
void deleteJunction(GNEJunction *junction, GNEUndoList *undoList)
removes junction and all incident edges
Definition GNENet.cpp:386
GNEViewNet * getViewNet() const
get view net
Definition GNENet.cpp:2155
bool checkDrawingBoundarySelection() const
GNEContour myNetworkElementContour
network element contour
bool myShapeEdited
flag to check if element shape is being edited
GUIGLObjectPopupMenu * getShapeEditedPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent, const PositionVector &shape)
get shape edited popup menu
bool isShapeEdited() const
check if shape is being edited
void invalidatePathCalculator()
invalidate pathCalculator
PathCalculator * getPathCalculator()
obtain instance of PathCalculator
void drawJunctionPathElements(const GUIVisualizationSettings &s, const GNEJunction *junction) const
draw junction path elements
const CommonXMLStructure::PlanParameters & getPlanParameteres() const
get plan parameters
bool markJunctions() const
check if mark junctions with dotted contours
void incRef(const std::string &debugMsg="")
Increase reference.
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
bool hasCommandGroup() const
Check if undoList has command group.
void begin(GUIIcon icon, const std::string &description)
Begin undo command sub-group with current supermode. This begins a new group of commands that are tre...
void add(GNEChange *command, bool doit=false, bool merge=true)
Add new command, executing it if desired. The new command will be merged with the previous command if...
void uninspectAC(GNEAttributeCarrier *AC)
uninspect AC
const GUIGlObject * getGUIGlObjectFront() const
get front GUIGLObject or a pointer to nullptr
GNEJunction * getJunctionFront() const
get front junction or a pointer to nullptr
bool isCurrentlyMovingElements() const
check if an element is being moved
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
const GNEViewNetHelper::EditNetworkElementShapes & getEditNetworkElementShapes() const
get Edit Shape module
GNEViewNetHelper::InspectedElements & getInspectedElements()
get inspected elements
const GNEViewNetHelper::MoveSingleElementModul & getMoveSingleElementValues() const
get move single element values
bool showJunctionAsBubbles() const
return true if junction must be showed as bubbles
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
void drawTranslateFrontAttributeCarrier(const GNEAttributeCarrier *AC, double typeOrLayer, const double extraOffset=0)
draw front attributeCarrier
int getDrawingToggle() const
get draw toggle (used to avoid drawing junctions twice)
GNEViewParent * getViewParent() const
get the net object
bool checkOverLockedElement(const GUIGlObject *GLObject, const bool isSelected) const
check if given element is locked (used for drawing select and delete contour)
GNEUndoList * getUndoList() const
get the undoList object
const GNEViewNetHelper::ViewObjectsSelector & getViewObjectsSelector() const
get objects under cursor
bool checkMergeJunctions()
try to merge moved junction with another junction in that spot return true if merging did take place
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
GNEDeleteFrame * getDeleteFrame() const
get frame for delete elements
This object is responsible for drawing a shape and for supplying a a popup menu. Messages are routete...
void updateCenteringBoundary(const bool updateGrid)
update centering boundary (implies change in RTREE)
void updateGeometry()
update pre-computed geometry information
static FXMenuCommand * buildFXMenuCommand(FXComposite *p, const std::string &text, FXIcon *icon, FXObject *tgt, FXSelector sel, const bool disable=false)
build menu command
The popup menu of a globject.
void insertMenuPaneChild(FXMenuPane *child)
Insert a sub-menu pane in this GUIGLObjectPopupMenu.
static void drawGeometryPoints(const GUIVisualizationSettings::Detail d, const PositionVector &shape, const RGBColor &color, const double radius, const double exaggeration, const bool editingElevation)
draw geometry points
static void drawGeometry(const GUIVisualizationSettings::Detail d, const GUIGeometry &geometry, const double width, double offset=0)
draw geometry
void updateGeometry(const PositionVector &shape)
update entire geometry
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
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.
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
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
T getColor(const double value) const
const GUIVisualizationSettings & getVisualisationSettings() const
get visualization settings (read only)
static GUIGlID getTexture(GUITexture which)
returns a texture previously defined in the enum GUITexture
static void drawTexturedBox(int which, double size)
Draws a named texture as a box with the given size.
const Boundary & getSelectionBoundary() const
get selection boundary
bool selectObject(const GUIGlObject *GLObject, const double layer, const bool checkDuplicated, const bool fullBoundary, const GNESegment *segment)
bool addMergingJunctions(const GNEJunction *junction)
add to merging junctions (used for marking junctions to merge)
Stores the information about how to visualize structures.
GUIVisualizationTextSettings junctionName
GUIVisualizationSizeSettings junctionSize
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
bool drawJunctionShape
whether the shape of the junction should be drawn
Detail getDetailLevel(const double exaggeration) const
return the detail level
GUIVisualizationCandidateColorSettings candidateColorSettings
candidate color settings
GUIVisualizationTextSettings junctionID
bool drawMovingGeometryPoint(const double exaggeration, const double radius) const
check if moving geometry point can be draw
GUIVisualizationColorSettings colorSettings
color settings
GUIVisualizationDottedContourSettings dottedContourSettings
dotted contour settings
double scale
information about a lane's width (temporary, used for a single view)
bool drawForViewObjectsHandler
whether drawing is performed for the purpose of selecting objects in view using ViewObjectsHandler
GUIColorer junctionColorer
The junction colorer.
GUIVisualizationNeteditSizeSettings neteditSizeSettings
netedit size settings
double angle
The current view rotation angle.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
int getFromLane() const
returns the from-lane
int getTLIndex2() const
int getTLIndex() const
returns the index within the controlling tls or InvalidTLIndex if this link is unontrolled
static const int InvalidTlIndex
int getToLane() const
returns the to-lane
NBEdge * getTo() const
returns the to-edge (end of the connection)
static const NBConnection InvalidConnection
void removeRoundabout(const NBNode *node)
remove roundabout that contains the given node
The representation of a single edge during network building.
Definition NBEdge.h:92
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition NBEdge.h:1041
const std::string & getID() const
Definition NBEdge.h:1528
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition NBEdge.cpp:3664
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:4007
A loaded (complete) traffic light logic.
void setID(const std::string &newID)
resets the id
NBTrafficLightLogic * getLogic()
Returns the internal logic.
void removeConnection(const NBConnection &conn, bool reconstruct=true)
removes the given connection from the traffic light if recontruct=true, reconstructs the logic and in...
void joinLogic(NBTrafficLightDefinition *def)
join nodes and states from the given logic (append red state)
void addConnection(NBEdge *from, NBEdge *to, int fromLane, int toLane, int linkIndex, int linkIndex2, bool reconstruct=true)
Adds a connection and immediately informs the edges.
void guessMinMaxDuration()
heuristically add minDur and maxDur when switching from tlType fixed to actuated
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane, bool incoming)
Replaces a removed edge/lane.
bool haveNetworkCrossings()
notify about style of loaded network (Without Crossings)
void setHaveNetworkCrossings(bool value)
enable crossing in networks
NBEdgeCont & getEdgeCont()
A definition of a pedestrian crossing.
Definition NBNode.h:135
EdgeVector edges
The edges being crossed.
Definition NBNode.h:142
Represents a single node (junction) during network building.
Definition NBNode.h:66
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
Definition NBNode.h:300
Position getCenter() const
Returns a position that is guaranteed to lie within the node shape.
Definition NBNode.cpp:3966
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
Definition NBNode.h:336
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition NBNode.cpp:338
static const double UNSPECIFIED_RADIUS
unspecified lane width
Definition NBNode.h:220
FringeType getFringeType() const
Returns fringe type.
Definition NBNode.h:305
void buildCrossingsAndWalkingAreas()
build crossings, and walkingareas. Also removes invalid loaded crossings if wished
Definition NBNode.cpp:2880
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:285
bool isTrafficLight() const
Definition NBNode.h:822
void setRightOfWay(RightOfWay rightOfWay)
set method for computing right-of-way
Definition NBNode.h:569
void setCustomShape(const PositionVector &shape)
set the junction shape
Definition NBNode.cpp:2622
void invalidateIncomingConnections(bool reallowSetting=false)
invalidate incoming connections
Definition NBNode.cpp:1990
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition NBNode.h:268
void mirrorX()
mirror coordinates along the x-axis
Definition NBNode.cpp:377
std::vector< std::pair< Position, std::string > > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
Definition NBNode.cpp:4122
const std::vector< std::unique_ptr< Crossing > > & getCrossingsIncludingInvalid() const
Definition NBNode.h:742
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition NBNode.h:273
bool hasCustomShape() const
return whether the shape was set by the user
Definition NBNode.h:584
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:2929
const std::string & getName() const
Returns intersection name.
Definition NBNode.h:310
void setRadius(double radius)
set the turning radius
Definition NBNode.h:559
void setName(const std::string &name)
set intersection name
Definition NBNode.h:579
const Position & getPosition() const
Definition NBNode.h:260
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition NBNode.cpp:406
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
Definition NBNode.h:278
const PositionVector & getShape() const
retrieve the junction shape
Definition NBNode.cpp:2616
double getRadius() const
Returns the turning radius of this node.
Definition NBNode.h:290
bool isRoundabout() const
return whether this node is part of a roundabout
Definition NBNode.cpp:3829
bool checkIsRemovableReporting(std::string &reason) const
check if node is removable and return reason if not
Definition NBNode.cpp:2503
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition NBNode.h:747
PositionVector myPoly
the (outer) shape of the junction
Definition NBNode.h:937
void setFringeType(FringeType fringeType)
set method for computing right-of-way
Definition NBNode.h:574
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition NBNode.h:331
A traffic light logics which must be computed (only nodes/edges are given)
Definition NBOwnTLDef.h:44
void setLayout(TrafficLightLayout layout)
sets the layout for the generated signal plan
Definition NBOwnTLDef.h:143
The base class for traffic light logic definitions.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
const std::string & getProgramID() const
Returns the ProgramID.
TrafficLightType getType() const
get the algorithm type (static etc..)
virtual void setProgramID(const std::string &programID)
Sets the programID.
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
SUMOTime getOffset()
Returns the offset.
A container for traffic light definitions and built programs.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
void extract(NBTrafficLightDefinition *definition)
Extracts a traffic light definition from myDefinitions but keeps it in myExtracted for eventual * del...
A SUMO-compliant built logic for a traffic light.
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any)
virtual void setID(const std::string &newID)
resets the id
Definition Named.h:82
const std::string & getID() const
Returns the id.
Definition Named.h:74
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
static OptionsCont & getOptions()
Retrieves the options.
static bool areParametersValid(const std::string &value, bool report=false, const std::string kvsep="=", const std::string sep="|")
check if given string can be parsed to a parameters map "key1=value1|key2=value2|....
std::map< std::string, std::string > Map
parameters map
void setParametersStr(const std::string &paramsString, const std::string kvsep="=", const std::string sep="|")
set the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN"
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
std::string getParametersStr(const std::string kvsep="=", const std::string sep="|") const
Returns the inner key/value map in string format "key1=value1|key2=value2|...|keyN=valueN".
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition Position.h:281
double x() const
Returns the x-position.
Definition Position.h:55
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.
PositionVector added(const Position &offset) const
void closePolygon()
ensures that the last position equals the first
int indexOfClosest(const Position &p, bool twoD=false) const
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
void scaleRelative(double factor)
enlarges/shrinks the polygon by a factor based at the centroid
double area() const
Returns the area (0 for non-closed)
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point.
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition RGBColor.cpp:200
const PositionVector & getShape() const
Returns the shape of the polygon.
virtual void setShape(const PositionVector &shape)
Sets the shape of the polygon.
PositionVector & getShapeRef()
Return the exterior shape of the polygon.
static StringBijection< SumoXMLNodeType > NodeTypes
node types
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
static StringBijection< TrafficLightLayout > TrafficLightLayouts
traffic light layouts
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
static StringBijection< RightOfWay > RightOfWayValues
righ of way algorithms
static StringBijection< FringeType > FringeTypeValues
fringe types
const std::string & getString(const T key) const
bool hasString(const std::string &str) const
T get(const std::string &str) const
std::vector< GLPrimitive > myTesselation
id of the display list for the cached tesselation
Definition GUIPolygon.h:74
void drawTesselation(const PositionVector &shape) const
perform the tesselation / drawing
NetworkEditMode networkEditMode
the current Network edit mode
bool isCurrentSupermodeData() const
@check if current supermode is Data
bool isCurrentSupermodeNetwork() const
@check if current supermode is Network
GNENetworkElement * getEditedNetworkElement() const
pointer to edited network element
static void drawLockIcon(const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, GUIGlObjectType type, const Position position, const double exaggeration, const double size=0.5, const double offsetx=0, const double offsety=0)
draw lock icon
GNEMoveElement * getMovedElement() const
get moved element
bool editingElevation() const
check if we're editing elevation
static const RGBColor special
color for selected special candidate element (Usually selected using shift+click)
static const RGBColor conflict
color for selected conflict candidate element (Usually selected using ctrl+click)
static const RGBColor target
color for selected candidate target
static const RGBColor possible
color for possible candidate element
static const RGBColor source
color for selected candidate source
RGBColor selectionColor
basic selection color
static const RGBColor editShapeColor
color for edited shapes (Junctions, crossings and connections)
static const double segmentWidthSmall
width of small dotted contour segments
static const double segmentWidth
width of dotted contour segments
static const double junctionGeometryPointRadius
moving junction geometry point radius
static const double junctionBubbleRadius
junction bubble radius
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
bool show(const GUIGlObject *o) const
whether to show the text
double scaledSize(double scale, double constFactor=0.1) const
get scale size
A structure which describes a connection between edges or lanes.
Definition NBEdge.h:201