Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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-2025 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
25#include <netbuild/NBOwnTLDef.h>
37#include <netedit/GNENet.h>
38#include <netedit/GNEUndoList.h>
39#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// method definitions
61// ===========================================================================
62
63GNEJunction::GNEJunction(GNENet* net, NBNode* nbn, bool loaded) :
64 GNENetworkElement(net, nbn->getID(), SUMO_TAG_JUNCTION),
65 myNBNode(nbn),
66 myDrawingToggle(new int),
67 myLogicStatus(loaded ? FEATURE_LOADED : FEATURE_GUESSED),
68 myHasValidLogic(loaded),
69 myTesselation(nbn->getID(), "", RGBColor::MAGENTA, nbn->getShape(), false, true, 0) {
70 // update centering boundary without updating grid
72}
73
74
76 // delete drawing toggle
77 delete myDrawingToggle;
78 // delete all GNECrossing
79 for (const auto& crossing : myGNECrossings) {
80 crossing->decRef();
81 if (crossing->unreferenced()) {
82 // check if remove it from Attribute Carriers
83 if (myNet->getAttributeCarriers()->getCrossings().count(crossing) > 0) {
85 }
86 delete crossing;
87 }
88 }
89 // delete all GNEWalkingArea
90 for (const auto& walkingArea : myGNEWalkingAreas) {
91 walkingArea->decRef();
92 if (walkingArea->unreferenced()) {
93 // check if remove it from Attribute Carriers
94 if (myNet->getAttributeCarriers()->getWalkingAreas().count(walkingArea) > 0) {
96 }
97 delete walkingArea;
98 }
99 }
100 if (myAmResponsible) {
101 delete myNBNode;
102 }
103}
104
105
106const PositionVector&
108 return myNBNode->getShape();
109}
110
111
112void
115 // trigger rebuilding tesselation
116 myExaggeration = 2;
117}
118
119
120void
121GNEJunction::updateGeometryAfterNetbuild(bool rebuildNBNodeCrossings) {
122 // rebuild crossings
123 rebuildGNECrossings(rebuildNBNodeCrossings);
124 // clear walking areas
126 // clear missing connections
128}
129
130
135
136
137bool
139 // get modes and viewParent (for code legibility)
140 const auto& modes = myNet->getViewNet()->getEditModes();
141 const auto& viewParent = myNet->getViewNet()->getViewParent();
142 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
143 // continue depending of current status
144 if (inspectedElements.isInspectingSingleElement()) {
145 // check if starts in this junction
146 if (inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_FROM_JUNCTION) &&
147 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_FROM_JUNCTION) == getID())) {
148 return true;
149 }
150 } else if (modes.isCurrentSupermodeNetwork()) {
151 if (modes.networkEditMode == NetworkEditMode::NETWORK_CREATE_EDGE) {
152 if (viewParent->getCreateEdgeFrame()->getJunctionSource()) {
153 return viewParent->getCreateEdgeFrame()->getJunctionSource() == this;
154 } else {
156 }
157 } else if ((modes.networkEditMode == NetworkEditMode::NETWORK_TLS) &&
158 viewParent->getTLSEditorFrame()->getTLSJunction()->isJoiningJunctions()) {
159 for (const auto& id : viewParent->getTLSEditorFrame()->getTLSJunction()->getSelectedJunctionIDs()) {
160 if (id == getMicrosimID()) {
161 return true;
162 }
163 }
164 }
165 } else if (modes.isCurrentSupermodeDemand()) {
166 // get current GNEPlanCreator
167 GNEPlanCreator* planCreator = nullptr;
168 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
169 planCreator = viewParent->getPersonFrame()->getPlanCreator();
170 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
171 planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
172 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
173 planCreator = viewParent->getContainerFrame()->getPlanCreator();
174 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
175 planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
176 }
177 // continue depending of planCreator
178 if (planCreator) {
179 if (planCreator->getPlanParameteres().fromJunction == getID()) {
180 return true;
181 }
182 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
183 const auto& selectedJunctions = viewParent->getVehicleFrame()->getPathCreator()->getSelectedJunctions();
184 // check if this is the first selected junction
185 if ((selectedJunctions.size() > 0) && (selectedJunctions.front() == this)) {
186 return true;
187 }
188 }
189 }
190 // nothing to draw
191 return false;
192}
193
194
195bool
197 // get modes and viewParent (for code legibility)
198 const auto& modes = myNet->getViewNet()->getEditModes();
199 const auto& viewParent = myNet->getViewNet()->getViewParent();
200 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
201 // continue depending of current status
202 if (inspectedElements.isInspectingSingleElement()) {
203 // check if ends in this junction
204 if (inspectedElements.getFirstAC()->getTagProperty()->vehicleJunctions() &&
205 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_TO_JUNCTION) == getID())) {
206 return true;
207 }
208 } else if (modes.isCurrentSupermodeNetwork()) {
209 if (modes.networkEditMode == NetworkEditMode::NETWORK_CREATE_EDGE) {
210 if (viewParent->getCreateEdgeFrame()->getJunctionSource() &&
211 (viewParent->getCreateEdgeFrame()->getJunctionSource() != this)) {
213 }
214 } else if (modes.networkEditMode == NetworkEditMode::NETWORK_MOVE) {
215 // check if we're moving a junction
216 const auto movedJunction = dynamic_cast<GNEJunction*>(myNet->getViewNet()->getMoveSingleElementValues().getMovedElement());
217 if (movedJunction && (movedJunction != this)) {
218 // continue depending of junction shape
219 if (myNBNode->getShape().area() < 4) {
220 // calculate distance between both centers
221 const double junctionBubbleRadius = myNet->getViewNet()->getVisualisationSettings().neteditSizeSettings.junctionBubbleRadius;
222 const double radiusTo = getExaggeration(myNet->getViewNet()->getVisualisationSettings()) * junctionBubbleRadius;
223 if (myNBNode->getPosition().distanceSquaredTo2D(movedJunction->getPositionInView()) < (radiusTo * radiusTo)) {
224 // add both it in the list of merging junction
227 return true;
228 }
229 } else if (myNBNode->getShape().around(movedJunction->getNBNode()->getPosition())) {
230 // add both it in the list of merging junction
233 return true;
234 }
235 }
236 }
237 } else if (modes.isCurrentSupermodeDemand()) {
238 // get current GNEPlanCreator
239 GNEPlanCreator* planCreator = nullptr;
240 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
241 planCreator = viewParent->getPersonFrame()->getPlanCreator();
242 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
243 planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
244 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
245 planCreator = viewParent->getContainerFrame()->getPlanCreator();
246 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
247 planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
248 }
249 // continue depending of planCreator
250 if (planCreator) {
251 if (planCreator->getPlanParameteres().toJunction == getID()) {
252 return true;
253 }
254 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
255 const auto& selectedJunctions = viewParent->getVehicleFrame()->getPathCreator()->getSelectedJunctions();
256 // check if this is the first selected junction
257 if ((selectedJunctions.size() > 1) && (selectedJunctions.back() == this)) {
258 return true;
259 }
260 }
261 }
262 // nothing to draw
263 return false;
264}
265
266
267bool
270 return true;
271 }
272 // check opened popup
273 if (myNet->getViewNet()->getPopup()) {
274 return myNet->getViewNet()->getPopup()->getGLObject() == this;
275 }
276 return false;
277}
278
279
280bool
282 // get modes and viewParent (for code legibility)
283 const auto& modes = myNet->getViewNet()->getEditModes();
284 const auto& viewParent = myNet->getViewNet()->getViewParent();
285 const auto& viewObjectsSelector = myNet->getViewNet()->getViewObjectsSelector();
286 if (viewObjectsSelector.getJunctionFront() != this) {
287 return false;
288 } else {
289 if (modes.isCurrentSupermodeNetwork()) {
290 if (modes.networkEditMode == NetworkEditMode::NETWORK_CROSSING) {
291 return (viewObjectsSelector.getJunctionFront() == this);
292 }
293 } else if (modes.isCurrentSupermodeDemand()) {
294 // get current plan selector
295 GNEPlanSelector* planSelector = nullptr;
296 if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
297 planSelector = viewParent->getPersonFrame()->getPlanSelector();
298 } else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
299 planSelector = viewParent->getPersonPlanFrame()->getPlanSelector();
300 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
301 planSelector = viewParent->getContainerFrame()->getPlanSelector();
302 } else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
303 planSelector = viewParent->getContainerPlanFrame()->getPlanSelector();
304 }
305 // continue depending of plan selector
306 if (planSelector && planSelector->markJunctions()) {
307 return (viewObjectsSelector.getAttributeCarrierFront() == viewObjectsSelector.getJunctionFront());
308 } else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
309 // get current vehicle template
310 const auto& vehicleTemplate = viewParent->getVehicleFrame()->getVehicleTagSelector()->getCurrentTemplateAC();
311 // check if vehicle can be placed over from-to TAZs
312 if (vehicleTemplate && vehicleTemplate->getTagProperty()->vehicleJunctions()) {
313 return (viewObjectsSelector.getAttributeCarrierFront() == viewObjectsSelector.getJunctionFront());
314 }
315 }
316 }
317 return false;
318 }
319}
320
321
322bool
324 // get edit modes
325 const auto& editModes = myNet->getViewNet()->getEditModes();
326 // check if we're in delete mode
327 if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE)) {
329 } else {
330 return false;
331 }
332}
333
334
335bool
337 return false;
338}
339
340
341bool
343 // get edit modes
344 const auto& editModes = myNet->getViewNet()->getEditModes();
345 // check if we're in select mode
346 if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_SELECT)) {
348 } else {
349 return false;
350 }
351}
352
353
354bool
356 // get edit modes
357 const auto& editModes = myNet->getViewNet()->getEditModes();
358 // check if we're in move mode
359 if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&
360 (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {
361 // check if we're editing this network element
363 if (editedNetworkElement) {
364 return editedNetworkElement == this;
365 } else {
366 // only move the first element
368 }
369 } else {
370 return false;
371 }
372}
373
374
377 // edit depending if shape is being edited
378 if (isShapeEdited()) {
379 // calculate move shape operation
380 return calculateMoveShapeOperation(this, myNBNode->getShape(), false);
381 } else {
382 // return move junction position
383 return new GNEMoveOperation(this, myNBNode->getPosition());
384 }
385}
386
387
388void
389GNEJunction::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
390 // edit depending if shape is being edited
391 if (isShapeEdited()) {
392 // get original shape
394 // check shape size
395 if (shape.size() > 2) {
396 // obtain index
397 int index = shape.indexOfClosest(clickedPosition);
398 // get snap radius
400 // check if we have to create a new index
401 if ((index != -1) && shape[index].distanceSquaredTo2D(clickedPosition) < (snap_radius * snap_radius)) {
402 // remove geometry point
403 shape.erase(shape.begin() + index);
404 // commit new shape
405 undoList->begin(this, "remove geometry point of " + getTagStr());
407 undoList->end();
408 }
409 }
410 }
411}
412
413
414void
415GNEJunction::rebuildGNECrossings(bool rebuildNBNodeCrossings) {
416 // rebuild GNECrossings only if create crossings and walkingAreas in net is enabled
418 if (rebuildNBNodeCrossings) {
419 // build new NBNode::Crossings and walking areas
423 }
424 // create a vector to keep retrieved and created crossings
425 std::vector<GNECrossing*> retrievedCrossings;
426 // iterate over NBNode::Crossings of GNEJunction
427 for (const auto& crossing : myNBNode->getCrossingsIncludingInvalid()) {
428 // retrieve existent GNECrossing, or create it
429 GNECrossing* retrievedGNECrossing = retrieveGNECrossing(crossing.get());
430 retrievedCrossings.push_back(retrievedGNECrossing);
431 // check if previously this GNECrossings exists, and if true, remove it from myGNECrossings and insert in tree again
432 std::vector<GNECrossing*>::iterator retrievedExists = std::find(myGNECrossings.begin(), myGNECrossings.end(), retrievedGNECrossing);
433 if (retrievedExists != myGNECrossings.end()) {
434 myGNECrossings.erase(retrievedExists);
435 // update geometry of retrieved crossing
436 retrievedGNECrossing->updateGeometry();
437 // update boundary
438 retrievedGNECrossing->updateCenteringBoundary(false);
439 } else {
440 // include reference to created GNECrossing
441 retrievedGNECrossing->incRef();
442 }
443 }
444 // delete non retrieved GNECrossings (we don't need to extract if from Tree two times)
445 for (const auto& crossing : myGNECrossings) {
446 crossing->decRef();
447 // check if crossing is selected
448 if (crossing->isAttributeCarrierSelected()) {
449 crossing->unselectAttributeCarrier();
450 }
451 // remove it from inspected ACS
452 if (myNet->getViewNet()) {
454 }
455 // remove it from net
456 myNet->removeGLObjectFromGrid(crossing);
457 // remove it from attributeCarriers
459 if (crossing->unreferenced()) {
460 delete crossing;
461 }
462 }
463 // copy retrieved (existent and created) GNECrossings to myGNECrossings
464 myGNECrossings = retrievedCrossings;
465 }
466}
467
468
469void
471 if (OptionsCont::getOptions().getBool("lefthand")) {
472 myNBNode->mirrorX();
473 for (NBEdge* e : myNBNode->getEdges()) {
474 e->mirrorX();
475
476 }
477 }
478}
479
480
481void
482GNEJunction::buildTLSOperations(GUISUMOAbstractView& parent, GUIGLObjectPopupMenu* ret, const int numSelectedJunctions) {
483 // create menu pane for edge operations
484 FXMenuPane* TLSOperations = new FXMenuPane(ret);
485 ret->insertMenuPaneChild(TLSOperations);
486 new FXMenuCascade(ret, TL("TLS operations"), GUIIconSubSys::getIcon(GUIIcon::MODETLS), TLSOperations);
487 // create menu commands for all TLS operations
488 FXMenuCommand* mcAddTLS = GUIDesigns::buildFXMenuCommand(TLSOperations, TL("Add TLS"), nullptr, &parent, MID_GNE_JUNCTION_ADDTLS);
489 FXMenuCommand* mcAddJoinedTLS = GUIDesigns::buildFXMenuCommand(TLSOperations, TL("Add joined TLS"), nullptr, &parent, MID_GNE_JUNCTION_ADDJOINTLS);
490 // check if disable create TLS
491 if (myNBNode->getControllingTLS().size() > 0) {
492 mcAddTLS->disable();
493 mcAddJoinedTLS->disable();
494 } else {
495 mcAddTLS->enable();
496 // check if add joined TLS
497 if (isAttributeCarrierSelected() && (numSelectedJunctions > 1)) {
498 mcAddJoinedTLS->enable();
499 } else {
500 mcAddJoinedTLS->disable();
501 }
502 }
503}
504
505
508 if (myShapeEdited) {
509 return getShapeEditedPopUpMenu(app, parent, myNBNode->getShape());
510 } else {
511 // create popup
512 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);
513 // build common options
515 // check if we're in supermode network
517 const int numSelectedJunctions = myNet->getAttributeCarriers()->getNumberOfSelectedJunctions();
518 const int numEndpoints = (int)myNBNode->getEndPoints().size();
519 // check if we're handling a selection
520 bool handlingSelection = isAttributeCarrierSelected() && (numSelectedJunctions > 1);
521 // check if menu commands has to be disabled
525 // build TLS operation
526 if (!invalidMode) {
527 buildTLSOperations(parent, ret, numSelectedJunctions);
528 }
529 // create menu commands
530 GUIDesigns::buildFXMenuCommand(ret, TL("Reset edge endpoints"), nullptr, &parent, MID_GNE_JUNCTION_RESET_EDGE_ENDPOINTS);
531 FXMenuCommand* mcCustomShape = GUIDesigns::buildFXMenuCommand(ret, TL("Set custom junction shape"), nullptr, &parent, MID_GNE_JUNCTION_EDIT_SHAPE);
532 FXMenuCommand* mcResetCustomShape = GUIDesigns::buildFXMenuCommand(ret, TL("Reset junction shape"), nullptr, &parent, MID_GNE_JUNCTION_RESET_SHAPE);
533 FXMenuCommand* mcReplaceByGeometryPoint = GUIDesigns::buildFXMenuCommand(ret, TL("Replace junction by geometry point"), nullptr, &parent, MID_GNE_JUNCTION_REPLACE);
534 FXMenuCommand* mcSplitJunction = GUIDesigns::buildFXMenuCommand(ret, TLF("Split junction (% end points)", numEndpoints), nullptr, &parent, MID_GNE_JUNCTION_SPLIT);
535 FXMenuCommand* mcSplitJunctionAndReconnect = GUIDesigns::buildFXMenuCommand(ret, TL("Split junction and reconnect"), nullptr, &parent, MID_GNE_JUNCTION_SPLIT_RECONNECT);
536 // check if is a roundabout
537 if (myNBNode->isRoundabout()) {
538 GUIDesigns::buildFXMenuCommand(ret, TL("Select roundabout"), nullptr, &parent, MID_GNE_JUNCTION_SELECT_ROUNDABOUT);
539 } else {
540 // get radius
541 const double radius = (myNBNode->getRadius() == NBNode::UNSPECIFIED_RADIUS) ? OptionsCont::getOptions().getFloat("default.junctions.radius") : myNBNode->getRadius();
542 const std::string menuEntryInfo = TLF("Convert to roundabout (using junction attribute radius %)", toString(radius));
543 FXMenuCommand* mcRoundabout = GUIDesigns::buildFXMenuCommand(ret, menuEntryInfo.c_str(), nullptr, &parent, MID_GNE_JUNCTION_CONVERT_ROUNDABOUT);
544 // check if disable depending of number of edges
545 if ((getChildEdges().size() < 2) ||
546 ((myGNEIncomingEdges.size() == 1) && (myGNEOutgoingEdges.size() == 1) && (myGNEIncomingEdges[0]->getFromJunction() == myGNEOutgoingEdges[0]->getToJunction()))) {
547 mcRoundabout->disable();
548 }
549 }
550 // check multijunctions
551 const std::string multi = ((numSelectedJunctions > 1) && isAttributeCarrierSelected()) ? TLF(" of % junctions", numSelectedJunctions) : "";
552 FXMenuCommand* mcClearConnections = GUIDesigns::buildFXMenuCommand(ret, TL("Clear connections") + multi, nullptr, &parent, MID_GNE_JUNCTION_CLEAR_CONNECTIONS);
553 FXMenuCommand* mcResetConnections = GUIDesigns::buildFXMenuCommand(ret, TL("Reset connections") + multi, nullptr, &parent, MID_GNE_JUNCTION_RESET_CONNECTIONS);
554 // check if current mode is correct
555 if (invalidMode) {
556 mcCustomShape->disable();
557 mcClearConnections->disable();
558 mcResetConnections->disable();
559 }
560 // check if we're handling a selection
561 if (handlingSelection) {
562 mcResetCustomShape->setText(TL("Reset junction shapes"));
563 }
564 // disable mcClearConnections if junction hasn't connections
565 if (getGNEConnections().empty()) {
566 mcClearConnections->disable();
567 }
568 // disable mcResetCustomShape if junction doesn't have a custom shape
569 if (myNBNode->getShape().size() == 0) {
570 mcResetCustomShape->disable();
571 }
572 // checkIsRemovable requires turnarounds to be computed. This is ugly
573 if ((myNBNode->getIncomingEdges().size() == 2) && (myNBNode->getOutgoingEdges().size() == 2)) {
575 }
576 std::string reason = TL("wrong edit mode");
577 if (invalidMode || !myNBNode->checkIsRemovableReporting(reason)) {
578 mcReplaceByGeometryPoint->setText(mcReplaceByGeometryPoint->getText() + " (" + reason.c_str() + ")");
579 mcReplaceByGeometryPoint->disable();
580 }
581 // check if disable split junctions
582 if (numEndpoints == 1) {
583 mcSplitJunction->disable();
584 mcSplitJunctionAndReconnect->disable();
585 }
586 }
587 return ret;
588 }
589}
590
591
592double
596
597
602
603
604void
606 // Remove object from grid
607 if (updateGrid) {
609 }
610 // calculate boundary using a radius bigger than geometry point
612 myNBNode->getPosition().x() + 1, myNBNode->getPosition().y() + 1);
614 // add shape
615 if (myNBNode->getShape().size() > 0) {
618 }
619 // add boundaries of all connections, walking areas and crossings
620 for (const auto& edge : myGNEIncomingEdges) {
621 for (const auto& connection : edge->getGNEConnections()) {
622 const auto boundary = connection->getCenteringBoundary();
623 if (boundary.isInitialised()) {
624 myJunctionBoundary.add(boundary);
625 }
626 }
627 }
628 for (const auto& crossing : myGNECrossings) {
629 const auto boundary = crossing->getCenteringBoundary();
630 if (boundary.isInitialised()) {
631 myJunctionBoundary.add(boundary);
632 }
633 }
634 for (const auto& walkingArea : myGNEWalkingAreas) {
635 const auto boundary = walkingArea->getCenteringBoundary();
636 if (boundary.isInitialised()) {
637 myJunctionBoundary.add(boundary);
638 }
639 }
640
641 // add object into grid
642 if (updateGrid) {
643 // if junction has at least one edge, then don't add in grid (because uses the edge's grid)
644 if (myGNEIncomingEdges.size() + myGNEOutgoingEdges.size() == 0) {
646 }
647 }
648 // trigger rebuilding tesselation
649 myExaggeration = 2;
650}
651
652
653void
655 // first check drawing toggle and boundary selection
657 // draw boundaries
658 if (inGrid()) {
660 }
661 // get junction exaggeration
662 const double junctionExaggeration = getExaggeration(s);
663 // only continue if exaggeration is greater than 0
664 if (junctionExaggeration > 0) {
665 // get detail level
666 const auto d = s.getDetailLevel(junctionExaggeration);
667 // get shape area
668 const double junctionShapeArea = myNBNode->getShape().area();
669 // check if draw junction as shape
670 const bool drawBubble = drawAsBubble(s, junctionShapeArea);
671 // draw geometry only if we'rent in drawForObjectUnderCursor mode
673 // push layer matrix
675 // translate to front
677 if (drawBubble) {
678 // draw junction as bubble
679 drawJunctionAsBubble(s, d, junctionExaggeration);
680 } else {
681 // draw junction as shape
682 drawJunctionAsShape(s, d, junctionExaggeration);
683 }
684 // draw junction center (only in move mode)
685 drawJunctionCenter(s, d);
686 // draw TLS
687 drawTLSIcon(s);
688 // draw elevation
689 drawElevation(s);
690 // pop layer Matrix
692 // draw lock icon
694 // draw junction name
696 // draw dotted contour depending if we're editing the custom shape
698 if (editedNetworkElement && (editedNetworkElement == this)) {
699 // draw dotted contour geometry points
701 junctionExaggeration, s.dottedContourSettings.segmentWidthSmall);
702 } else {
703 if (drawBubble) {
704 // draw dotted contour for bubble
706 } else {
707 // draw dotted contour for shape
708 if (junctionShapeArea >= 4) {
710 }
711 }
712 }
713 }
714 // calculate junction contour (always before children)
715 calculateJunctioncontour(s, d, junctionExaggeration, drawBubble);
716 // draw Junction childs
718 }
719 // update drawing toggle
721 }
722}
723
724
725void
727 // Check if edge can be deleted
730 }
731}
732
733
734void
738
739
740NBNode*
742 return myNBNode;
743}
744
745
746std::vector<GNEJunction*>
748 // use set to avoid duplicates junctions
749 std::set<GNEJunction*> junctions;
750 for (const auto& incomingEdge : myGNEIncomingEdges) {
751 junctions.insert(incomingEdge->getFromJunction());
752 }
753 for (const auto& outgoingEdge : myGNEOutgoingEdges) {
754 junctions.insert(outgoingEdge->getToJunction());
755 }
756 return std::vector<GNEJunction*>(junctions.begin(), junctions.end());
757}
758
759
760void
762 // Check if incoming edge was already inserted
763 std::vector<GNEEdge*>::iterator i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
764 if (i != myGNEIncomingEdges.end()) {
765 throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + getTagStr() + " with ID " + getID() + "'");
766 } else {
767 // Add edge into containers
768 myGNEIncomingEdges.push_back(edge);
769 }
770}
771
772
773
774void
776 // Check if outgoing edge was already inserted
777 const auto i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
778 if (i != myGNEOutgoingEdges.end()) {
779 throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' was already inserted into " + getTagStr() + " with ID " + getID() + "'");
780 } else {
781 // Add edge into containers
782 myGNEOutgoingEdges.push_back(edge);
783 }
784 // update centering boundary and grid
786}
787
788
789void
791 // Check if incoming edge was already inserted
792 auto i = std::find(myGNEIncomingEdges.begin(), myGNEIncomingEdges.end(), edge);
793 if (i == myGNEIncomingEdges.end()) {
794 throw InvalidArgument("Incoming " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + getTagStr() + " with ID " + getID() + "'");
795 } else {
796 // remove edge from containers
797 myGNEIncomingEdges.erase(i);
798 }
799 // update centering boundary and grid
801}
802
803
804void
806 // Check if outgoing edge was already inserted
807 std::vector<GNEEdge*>::iterator i = std::find(myGNEOutgoingEdges.begin(), myGNEOutgoingEdges.end(), edge);
808 if (i == myGNEOutgoingEdges.end()) {
809 throw InvalidArgument("Outgoing " + toString(SUMO_TAG_EDGE) + " with ID '" + edge->getID() + "' doesn't found into " + getTagStr() + " with ID " + getID() + "'");
810 } else {
811 // remove edge from containers
812 myGNEOutgoingEdges.erase(i);
813 }
814}
815
816
817const std::vector<GNEEdge*>&
821
822
823const std::vector<GNEEdge*>&
827
828
829const std::vector<GNECrossing*>&
833
834
835const std::vector<GNEWalkingArea*>&
839
840
841std::vector<GNEConnection*>
843 std::vector<GNEConnection*> connections;
844 for (const auto& incomingEdge : myGNEIncomingEdges) {
845 for (const auto& connection : incomingEdge->getGNEConnections()) {
846 connections.push_back(connection);
847 }
848 }
849 return connections;
850}
851
852
853void
857
858
859void
863
864
865void
867 myAmTLSSelected = selected;
868}
869
870
871void
873 if (!myNBNode->hasCustomShape()) {
874 if (myNBNode->myPoly.size() > 0) {
875 // clear poly
876 myNBNode->myPoly.clear();
877 // update centering boundary
879 }
881 }
882}
883
884
885void
886GNEJunction::setLogicValid(bool valid, GNEUndoList* undoList, const std::string& status) {
887 myHasValidLogic = valid;
888 if (!valid) {
889 assert(undoList != 0);
890 assert(undoList->hasCommandGroup());
893 for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
894 GNEEdge* srcEdge = myNet->getAttributeCarriers()->retrieveEdge((*it)->getID());
895 removeConnectionsFrom(srcEdge, undoList, false); // false, because the whole tls will be invalidated at the end
897 }
899 invalidateTLS(undoList);
900 } else {
901 // logic valed, then rebuild GNECrossings to adapt it to the new logic
902 // (but don't rebuild the crossings in NBNode because they are already finished)
903 rebuildGNECrossings(false);
904 }
905}
906
907
908void
909GNEJunction::removeConnectionsFrom(GNEEdge* edge, GNEUndoList* undoList, bool updateTLS, int lane) {
910 NBEdge* srcNBE = edge->getNBEdge();
911 NBEdge* turnEdge = srcNBE->getTurnDestination();
912 // Make a copy of connections
913 std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
914 // delete in reverse so that undoing will add connections in the original order
915 for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
916 if (lane >= 0 && (*con_it).fromLane != lane) {
917 continue;
918 }
919 bool hasTurn = con_it->toEdge == turnEdge;
920 undoList->add(new GNEChange_Connection(edge, *con_it, false, false), true);
921 // needs to come after GNEChange_Connection
922 // XXX bug: this code path will not be used on a redo!
923 if (hasTurn) {
925 }
926 }
927 if (updateTLS) {
928 std::vector<NBConnection> removeConnections;
929 for (NBEdge::Connection con : connections) {
930 removeConnections.push_back(NBConnection(srcNBE, con.fromLane, con.toEdge, con.toLane));
931 }
932 removeTLSConnections(removeConnections, undoList);
933 }
934}
935
936
937void
938GNEJunction::removeConnectionsTo(GNEEdge* edge, GNEUndoList* undoList, bool updateTLS, int lane) {
939 NBEdge* destNBE = edge->getNBEdge();
940 std::vector<NBConnection> removeConnections;
941 for (NBEdge* srcNBE : myNBNode->getIncomingEdges()) {
942 GNEEdge* srcEdge = myNet->getAttributeCarriers()->retrieveEdge(srcNBE->getID());
943 std::vector<NBEdge::Connection> connections = srcNBE->getConnections();
944 for (std::vector<NBEdge::Connection>::reverse_iterator con_it = connections.rbegin(); con_it != connections.rend(); con_it++) {
945 if ((*con_it).toEdge == destNBE) {
946 if (lane >= 0 && (*con_it).toLane != lane) {
947 continue;
948 }
949 bool hasTurn = srcNBE->getTurnDestination() == destNBE;
950 undoList->add(new GNEChange_Connection(srcEdge, *con_it, false, false), true);
951 // needs to come after GNEChange_Connection
952 // XXX bug: this code path will not be used on a redo!
953 if (hasTurn) {
954 myNet->addExplicitTurnaround(srcNBE->getID());
955 }
956 removeConnections.push_back(NBConnection(srcNBE, (*con_it).fromLane, destNBE, (*con_it).toLane));
957 }
958 }
959 }
960 if (updateTLS) {
961 removeTLSConnections(removeConnections, undoList);
962 }
963}
964
965
966void
967GNEJunction::removeTLSConnections(std::vector<NBConnection>& connections, GNEUndoList* undoList) {
968 if (connections.size() > 0) {
969 const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
970 for (const auto& TLS : coypOfTls) {
971 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
972 // guessed TLS (NBOwnTLDef) do not need to be updated
973 if (tlDef != nullptr) {
974 std::string newID = tlDef->getID();
975 // create replacement before deleting the original because deletion will mess up saving original nodes
976 NBLoadedSUMOTLDef* replacementDef = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
977 for (NBConnection& con : connections) {
978 replacementDef->removeConnection(con);
979 }
980 undoList->add(new GNEChange_TLS(this, tlDef, false), true);
981 undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
982 // the removed traffic light may have controlled more than one junction. These too have become invalid now
983 const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
984 for (const auto& node : copyOfNodes) {
985 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
986 undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
987 undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
988 }
989 }
990 }
991 }
992}
993
994
995void
997 // remap connections of the edge
998 assert(which->getChildLanes().size() == by->getChildLanes().size());
999 std::vector<NBEdge::Connection> connections = which->getNBEdge()->getConnections();
1000 for (NBEdge::Connection& c : connections) {
1001 undoList->add(new GNEChange_Connection(which, c, false, false), true);
1002 undoList->add(new GNEChange_Connection(by, c, false, true), true);
1003 }
1004 // also remap tls connections
1005 const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
1006 for (const auto& TLS : coypOfTls) {
1007 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
1008 // guessed TLS (NBOwnTLDef) do not need to be updated
1009 if (tlDef != nullptr) {
1010 std::string newID = tlDef->getID();
1011 // create replacement before deleting the original because deletion will mess up saving original nodes
1012 NBLoadedSUMOTLDef* replacementDef = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
1013 for (int i = 0; i < (int)which->getChildLanes().size(); ++i) {
1014 replacementDef->replaceRemoved(which->getNBEdge(), i, by->getNBEdge(), i, true);
1015 }
1016 undoList->add(new GNEChange_TLS(this, tlDef, false), true);
1017 undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
1018 // the removed traffic light may have controlled more than one junction. These too have become invalid now
1019 const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
1020 for (const auto& node : copyOfNodes) {
1021 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1022 undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
1023 undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
1024 }
1025 }
1026 }
1027}
1028
1029
1030void
1032 EdgeVector incoming = myNBNode->getIncomingEdges();
1033 for (EdgeVector::iterator it = incoming.begin(); it != incoming.end(); it++) {
1034 NBEdge* srcNBE = *it;
1035 GNEEdge* srcEdge = myNet->getAttributeCarriers()->retrieveEdge(srcNBE->getID());
1037 }
1038}
1039
1040
1041void
1042GNEJunction::invalidateTLS(GNEUndoList* undoList, const NBConnection& deletedConnection, const NBConnection& addedConnection) {
1043 assert(undoList->hasCommandGroup());
1044 // NBLoadedSUMOTLDef becomes invalid, replace with NBOwnTLDef which will be dynamically recomputed
1045 const std::set<NBTrafficLightDefinition*> coypOfTls = myNBNode->getControllingTLS(); // make a copy!
1046 for (const auto& TLS : coypOfTls) {
1047 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
1048 if (tlDef != nullptr) {
1049 // the removed traffic light may have controlled more than one junction. These too have become invalid now
1050 const std::vector<NBNode*> copyOfNodes = tlDef->getNodes(); // make a copy!
1051 if (myGNECrossings.size() == 0 && getNBNode()->getCrossings().size() != 0) {
1052 // crossings were not computed yet. We need them as netedit elements to manage tlIndex resetting
1055 for (const auto& node : copyOfNodes) {
1056 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1057 if (sharing != this) {
1058 sharing->rebuildGNECrossings();
1059 }
1060 }
1061 }
1062 NBTrafficLightDefinition* replacementDef = nullptr;
1063 std::string newID = tlDef->getID(); // + "_reguessed"; // changes due to reguessing will be visible in diff
1064 if (deletedConnection != NBConnection::InvalidConnection) {
1065 // create replacement before deleting the original because deletion will mess up saving original nodes
1066 NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
1067 repl->removeConnection(deletedConnection);
1068 replacementDef = repl;
1069 } else if (addedConnection != NBConnection::InvalidConnection) {
1070 if (addedConnection.getTLIndex() == NBConnection::InvalidTlIndex) {
1071 // custom tl indices of crossings might become invalid upon recomputation so we must save them
1072 // however, they could remain valid so we register a change but keep them at their old value
1073 for (const auto& crossing : myGNECrossings) {
1074 const std::string oldValue = crossing->getAttribute(SUMO_ATTR_TLLINKINDEX);
1076 GNEChange_Attribute::changeAttribute(crossing, SUMO_ATTR_TLLINKINDEX, oldValue, undoList, true);
1077 const std::string oldValue2 = crossing->getAttribute(SUMO_ATTR_TLLINKINDEX2);
1079 GNEChange_Attribute::changeAttribute(crossing, SUMO_ATTR_TLLINKINDEX2, oldValue2, undoList, true);
1080 }
1081 }
1082 NBLoadedSUMOTLDef* repl = new NBLoadedSUMOTLDef(*tlDef, *tlDef->getLogic());
1083 repl->addConnection(addedConnection.getFrom(), addedConnection.getTo(),
1084 addedConnection.getFromLane(), addedConnection.getToLane(), addedConnection.getTLIndex(), addedConnection.getTLIndex2());
1085 replacementDef = repl;
1086 } else {
1087 // recompute crossing indices along with everything else
1088 for (const auto& crossing : myGNECrossings) {
1091 }
1092 replacementDef = new NBOwnTLDef(newID, tlDef->getOffset(), tlDef->getType());
1093 replacementDef->setProgramID(tlDef->getProgramID());
1094 }
1095 undoList->add(new GNEChange_TLS(this, tlDef, false), true);
1096 undoList->add(new GNEChange_TLS(this, replacementDef, true, false, newID), true);
1097 // reset nodes of joint tls
1098 for (const auto& node : copyOfNodes) {
1099 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1100 if (sharing != this) {
1101 if (deletedConnection == NBConnection::InvalidConnection && addedConnection == NBConnection::InvalidConnection) {
1102 // recompute crossing indices for shared
1103 // (they won't do this on subsequent call to invalidateTLS if they received an NBOwnTLDef)
1104 for (const auto& crossing : sharing->getGNECrossings()) {
1107 }
1108 }
1109 undoList->add(new GNEChange_TLS(sharing, tlDef, false), true);
1110 undoList->add(new GNEChange_TLS(sharing, replacementDef, true, false, newID), true);
1111 }
1112 }
1113 }
1114 }
1115}
1116
1117void
1119 // obtain a copy of GNECrossing of junctions
1120 const auto copyOfGNECrossings = myGNECrossings;
1121 // iterate over copy of GNECrossings
1122 for (const auto& crossing : copyOfGNECrossings) {
1123 // obtain the set of edges vinculated with the crossing (due it works as ID)
1124 EdgeSet edgeSet(crossing->getCrossingEdges().begin(), crossing->getCrossingEdges().end());
1125 // If this edge is part of the set of edges of crossing
1126 if (edgeSet.count(edge->getNBEdge()) == 1) {
1127 // delete crossing if this is their last edge
1128 if ((crossing->getCrossingEdges().size() == 1) && (crossing->getCrossingEdges().front() == edge->getNBEdge())) {
1129 myNet->deleteCrossing(crossing, undoList);
1130 } else {
1131 // remove this edge of the edge's attribute of crossing (note: This can invalidate the crossing)
1132 std::vector<std::string> edges = GNEAttributeCarrier::parse<std::vector<std::string>>(crossing->getAttribute(SUMO_ATTR_EDGES));
1133 edges.erase(std::find(edges.begin(), edges.end(), edge->getID()));
1134 crossing->setAttribute(SUMO_ATTR_EDGES, joinToString(edges, " "), undoList);
1135 }
1136 }
1137 }
1138}
1139
1140
1141bool
1145
1146
1148GNEJunction::retrieveGNECrossing(NBNode::Crossing* NBNodeCrossing, bool createIfNoExist) {
1149 // iterate over all crossing
1150 for (const auto& crossing : myGNECrossings) {
1151 // if found, return it
1152 if (crossing->getCrossingEdges() == NBNodeCrossing->edges) {
1153 return crossing;
1154 }
1155 }
1156 if (createIfNoExist) {
1157 // create new GNECrossing
1158 GNECrossing* createdGNECrossing = new GNECrossing(this, NBNodeCrossing->edges);
1159 // update geometry after creating
1160 createdGNECrossing->updateGeometry();
1161 // add it in Network
1162 myNet->addGLObjectIntoGrid(createdGNECrossing);
1163 // add it in attributeCarriers
1164 myNet->getAttributeCarriers()->insertCrossing(createdGNECrossing);
1165 return createdGNECrossing;
1166 } else {
1167 return nullptr;
1168 }
1169}
1170
1171
1173GNEJunction::retrieveGNEWalkingArea(const std::string& NBNodeWalkingAreaID, bool createIfNoExist) {
1174 // iterate over all walkingArea
1175 for (const auto& walkingArea : myGNEWalkingAreas) {
1176 // if found, return it
1177 if (walkingArea->getID() == NBNodeWalkingAreaID) {
1178 return walkingArea;
1179 }
1180 }
1181 if (createIfNoExist) {
1182 // create new GNEWalkingArea
1183 GNEWalkingArea* createdGNEWalkingArea = new GNEWalkingArea(this, NBNodeWalkingAreaID);
1184 // update geometry after creating
1185 createdGNEWalkingArea->updateGeometry();
1186 // add it in Network
1187 myNet->addGLObjectIntoGrid(createdGNEWalkingArea);
1188 // add it in attributeCarriers
1189 myNet->getAttributeCarriers()->insertWalkingArea(createdGNEWalkingArea);
1190 return createdGNEWalkingArea;
1191 } else {
1192 return nullptr;
1193 }
1194}
1195
1196
1197void
1199 // only it's needed to mark the connections of incoming edges
1200 for (const auto& i : myGNEIncomingEdges) {
1201 for (const auto& j : i->getGNEConnections()) {
1202 j->markConnectionGeometryDeprecated();
1203 }
1204 if (includingNeighbours) {
1205 i->getFromJunction()->markConnectionsDeprecated(false);
1206 }
1207 }
1208}
1209
1210
1211void
1212GNEJunction::setJunctionType(const std::string& value, GNEUndoList* undoList) {
1213 undoList->begin(this, "change " + getTagStr() + " type");
1215 if (getNBNode()->isTLControlled() &&
1216 // if switching changing from or to traffic_light_right_on_red we need to remove the old plan
1219 ) {
1220 // make a copy because we will modify the original
1221 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1222 for (const auto& TLS : copyOfTls) {
1223 undoList->add(new GNEChange_TLS(this, TLS, false), true);
1224 }
1225 }
1226 if (!getNBNode()->isTLControlled()) {
1227 // create new traffic light
1228 undoList->add(new GNEChange_TLS(this, nullptr, true), true);
1229 }
1230 } else if (getNBNode()->isTLControlled()) {
1231 // delete old traffic light
1232 // make a copy because we will modify the original
1233 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1234 for (const auto& TLS : copyOfTls) {
1235 undoList->add(new GNEChange_TLS(this, TLS, false, false), true);
1236 const std::vector<NBNode*> copyOfNodes = TLS->getNodes(); // make a copy!
1237 for (const auto& node : copyOfNodes) {
1238 GNEJunction* sharing = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1239 sharing->invalidateTLS(undoList);
1240 }
1241 }
1242 }
1243 // must be the final step, otherwise we do not know which traffic lights to remove via GNEChange_TLS
1244 GNEChange_Attribute::changeAttribute(this, SUMO_ATTR_TYPE, value, undoList, true);
1245 for (const auto& crossing : myGNECrossings) {
1246 GNEChange_Attribute::changeAttribute(crossing, SUMO_ATTR_TLLINKINDEX, "-1", undoList, true);
1247 GNEChange_Attribute::changeAttribute(crossing, SUMO_ATTR_TLLINKINDEX2, "-1", undoList, true);
1248 }
1249 undoList->end();
1250}
1251
1252
1253void
1255 // delete non retrieved GNEWalkingAreas (we don't need to extract if from Tree two times)
1256 for (const auto& walkingArea : myGNEWalkingAreas) {
1257 walkingArea->decRef();
1258 // check if walkingArea is selected
1259 if (walkingArea->isAttributeCarrierSelected()) {
1260 walkingArea->unselectAttributeCarrier();
1261 }
1262 // remove it from inspected ACS
1264 // remove it from net
1265 myNet->removeGLObjectFromGrid(walkingArea);
1266 // remove it from attributeCarriers
1268 if (walkingArea->unreferenced()) {
1269 delete walkingArea;
1270 }
1271 }
1272 myGNEWalkingAreas.clear();
1273}
1274
1275
1276void
1278 // first clear GNEWalkingAreas
1280 // iterate over NBNode::WalkingAreas of GNEJunction
1281 for (const auto& walkingArea : myNBNode->getWalkingAreas()) {
1282 // retrieve existent GNEWalkingArea, or create it
1283 GNEWalkingArea* retrievedGNEWalkingArea = retrieveGNEWalkingArea(walkingArea.id, true);
1284 // include reference to created GNEWalkingArea
1285 retrievedGNEWalkingArea->incRef();
1286 // update geometry of retrieved walkingArea
1287 retrievedGNEWalkingArea->updateGeometry();
1288 // update boundary
1289 retrievedGNEWalkingArea->updateCenteringBoundary(false);
1290 // add in walkingAreas
1291 myGNEWalkingAreas.push_back(retrievedGNEWalkingArea);
1292 }
1293}
1294
1295
1296
1297void
1299 if (std::find(myInternalLanes.begin(), myInternalLanes.end(), internalLane) != myInternalLanes.end()) {
1300 throw ProcessError(internalLane->getTagStr() + " with ID='" + internalLane->getID() + "' already exist");
1301 } else {
1302 myInternalLanes.push_back(internalLane);
1303 }
1304}
1305
1306
1307void
1309 const auto finder = std::find(myInternalLanes.begin(), myInternalLanes.end(), internalLane);
1310 if (finder == myInternalLanes.end()) {
1311 throw ProcessError(internalLane->getTagStr() + " with ID='" + internalLane->getID() + "' wasn't previously inserted");
1312 } else {
1313 myInternalLanes.erase(finder);
1314 }
1315}
1316
1317
1318std::string
1320 switch (key) {
1321 case SUMO_ATTR_ID:
1322 return getMicrosimID();
1323 case SUMO_ATTR_POSITION:
1324 return toString(myNBNode->getPosition());
1325 case SUMO_ATTR_TYPE:
1326 return toString(myNBNode->getType());
1328 return myLogicStatus;
1329 case SUMO_ATTR_SHAPE:
1330 return toString(myNBNode->getShape());
1331 case SUMO_ATTR_RADIUS:
1332 if (myNBNode->getRadius() < 0) {
1333 return "default";
1334 } else {
1335 return toString(myNBNode->getRadius());
1336 }
1337 case SUMO_ATTR_TLTYPE:
1339 // @todo this causes problems if the node were to have multiple programs of different type (plausible)
1340 return toString((*myNBNode->getControllingTLS().begin())->getType());
1341 } else {
1342 return "No TLS";
1343 }
1344 case SUMO_ATTR_TLLAYOUT:
1346 return toString((*myNBNode->getControllingTLS().begin())->getLayout());
1347 } else {
1348 return "No TLS";
1349 }
1350 case SUMO_ATTR_TLID:
1352 return toString((*myNBNode->getControllingTLS().begin())->getID());
1353 } else {
1354 return "No TLS";
1355 }
1357 return myNBNode->isRoundabout() ? True : False;
1359 // keep clear is only used as a convenience feature in plain xml
1360 // input. When saving to .net.xml the status is saved only for the connections
1361 // to show the correct state we must check all connections
1362 for (const auto& i : myGNEIncomingEdges) {
1363 for (const auto& j : i->getGNEConnections()) {
1364 if (j->getNBEdgeConnection().keepClear) {
1365 return True;
1366 }
1367 }
1368 }
1369 return False;
1372 case SUMO_ATTR_FRINGE:
1374 case SUMO_ATTR_NAME:
1375 return myNBNode->getName();
1376 default:
1377 return getCommonAttribute(myNBNode, key);
1378 }
1379}
1380
1381
1384 switch (key) {
1385 case SUMO_ATTR_SHAPE:
1386 return myNBNode->getShape();
1387 default:
1388 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1389 }
1390}
1391
1392
1393void
1394GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
1395 if (value == getAttribute(key)) {
1396 return; //avoid needless changes, later logic relies on the fact that attributes have changed
1397 }
1398 switch (key) {
1399 case SUMO_ATTR_ID:
1401 case SUMO_ATTR_SHAPE:
1402 case SUMO_ATTR_RADIUS:
1404 case SUMO_ATTR_FRINGE:
1405 case SUMO_ATTR_NAME:
1406 GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1407 break;
1408 case SUMO_ATTR_POSITION: {
1409 const GNEJunction* junctionToMerge = nullptr;
1410 bool alreadyAsked = false;
1411 // parse position
1412 Position newPosition = GNEAttributeCarrier::parse<Position>(value);
1413 // check if caculate new position based in edges
1414 if (newPosition == Position::INVALID) {
1415 Boundary b;
1416 // set new position of adjacent edges
1417 for (const auto& edge : myGNEIncomingEdges) {
1418 b.add(edge->getNBEdge()->getGeometry().back());
1419 }
1420 for (const auto& edge : myGNEOutgoingEdges) {
1421 b.add(edge->getNBEdge()->getGeometry().front());
1422 }
1423 newPosition = b.getCenter();
1424 }
1425 // retrieve all junctions placed in this position
1426 myNet->getViewNet()->updateObjectsInPosition(newPosition);
1427 for (const auto& junction : myNet->getViewNet()->getViewObjectsSelector().getJunctions()) {
1428 // check distance position
1429 if ((junctionToMerge == nullptr) && (junction != this) && (junction->getPositionInView().distanceTo2D(newPosition) < POSITION_EPS) &&
1430 myNet->getViewNet()->askMergeJunctions(this, junction, alreadyAsked)) {
1431 junctionToMerge = junction;
1432 }
1433 }
1434 // also check the merging junctions located during drawGL
1435 for (const auto& junction : myNet->getViewNet()->getViewObjectsSelector().getMergingJunctions()) {
1436 // check distance position
1437 if ((junctionToMerge == nullptr) && (junction != this) && myNet->getViewNet()->askMergeJunctions(this, junction, alreadyAsked)) {
1438 junctionToMerge = junction;
1439 }
1440 }
1441 // if we merge the junction, this junction will be removed, therefore we don't have to change the position
1442 if (junctionToMerge) {
1443 myNet->mergeJunctions(this, junctionToMerge, undoList);
1444 } else {
1445 // change Keep Clear attribute in all connections
1446 undoList->begin(this, TL("change junction position"));
1447 // obtain NBNode position
1448 const Position orig = myNBNode->getPosition();
1449 // change junction position
1450 GNEChange_Attribute::changeAttribute(this, key, toString(newPosition), undoList, true);
1451 // calculate delta using new position
1453 const Position delta = myNBNode->getPosition() - (moveOnlyCenter ? myNBNode->getPosition() : orig);
1454 // set new position of adjacent edges
1455 for (const auto& edge : myGNEIncomingEdges) {
1456 const Position newEnd = edge->getNBEdge()->getGeometry().back() + delta;
1458 }
1459 for (const auto& edge : myGNEOutgoingEdges) {
1460 const Position newStart = edge->getNBEdge()->getGeometry().front() + delta;
1461 GNEChange_Attribute::changeAttribute(edge, GNE_ATTR_SHAPE_START, toString(newStart), undoList, true);
1462 }
1463 undoList->end();
1464 }
1465 break;
1466 }
1468 // change Keep Clear attribute in all connections
1469 undoList->begin(this, TL("change keepClear for whole junction"));
1470 for (const auto& incomingEdge : myGNEIncomingEdges) {
1471 for (const auto& junction : incomingEdge->getGNEConnections()) {
1472 GNEChange_Attribute::changeAttribute(junction, key, value, undoList, true);
1473 }
1474 }
1475 undoList->end();
1476 break;
1477 case SUMO_ATTR_TYPE: {
1478 // set junction type
1479 setJunctionType(value, undoList);
1480 break;
1481 }
1482 case SUMO_ATTR_TLTYPE: {
1483 undoList->begin(this, "change " + getTagStr() + " tl-type");
1484 // make a copy because we will modify the original
1485 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1486 for (const auto& TLS : copyOfTls) {
1487 NBLoadedSUMOTLDef* oldLoaded = dynamic_cast<NBLoadedSUMOTLDef*>(TLS);
1488 if (oldLoaded != nullptr) {
1489 NBTrafficLightDefinition* newDef = nullptr;
1490 if (value == toString(TrafficLightType::NEMA) || oldLoaded->getType() == TrafficLightType::NEMA) {
1491 // rebuild the program because the old and new ones are incompatible
1492 newDef = new NBOwnTLDef(oldLoaded->getID(), oldLoaded->getOffset(), TrafficLightType::NEMA);
1493 newDef->setProgramID(oldLoaded->getProgramID());
1494 } else {
1495 NBLoadedSUMOTLDef* newLDef = new NBLoadedSUMOTLDef(*oldLoaded, *oldLoaded->getLogic());
1496 newLDef->guessMinMaxDuration(); // minDur and maxDur are never written for a static tls
1497 newDef = newLDef;
1498 }
1499 std::vector<NBNode*> nodes = TLS->getNodes();
1500 for (const auto& node : nodes) {
1501 GNEJunction* junction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1502 undoList->add(new GNEChange_TLS(junction, TLS, false), true);
1503 undoList->add(new GNEChange_TLS(junction, newDef, true), true);
1504 }
1505 }
1506 }
1507 GNEChange_Attribute::changeAttribute(this, key, value, undoList, true);
1508 undoList->end();
1509 break;
1510 }
1511 case SUMO_ATTR_TLLAYOUT: {
1512 undoList->begin(this, "change " + getTagStr() + " tlLayout");
1513 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1514 for (const auto& oldTLS : copyOfTls) {
1515 std::vector<NBNode*> copyOfNodes = oldTLS->getNodes();
1516 NBOwnTLDef* newTLS = new NBOwnTLDef(oldTLS->getID(), oldTLS->getOffset(), oldTLS->getType());
1518 newTLS->setProgramID(oldTLS->getProgramID());
1519 for (const auto& node : copyOfNodes) {
1520 GNEJunction* oldJunction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1521 undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
1522 }
1523 for (const auto& node : copyOfNodes) {
1524 GNEJunction* oldJunction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1525 undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
1526 }
1527 }
1528 undoList->end();
1529 break;
1530 }
1531 case SUMO_ATTR_TLID: {
1532 undoList->begin(this, "change " + toString(SUMO_TAG_TRAFFIC_LIGHT) + " id");
1533 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1534 assert(copyOfTls.size() > 0);
1535 NBTrafficLightDefinition* currentTLS = *copyOfTls.begin();
1536 NBTrafficLightDefinition* currentTLSCopy = nullptr;
1537 const bool currentIsSingle = currentTLS->getNodes().size() == 1;
1538 const bool currentIsLoaded = dynamic_cast<NBLoadedSUMOTLDef*>(currentTLS) != nullptr;
1539 if (currentIsLoaded) {
1540 currentTLSCopy = new NBLoadedSUMOTLDef(*currentTLS,
1541 *dynamic_cast<NBLoadedSUMOTLDef*>(currentTLS)->getLogic());
1542 }
1543 // remove from previous tls
1544 for (const auto& TLS : copyOfTls) {
1545 undoList->add(new GNEChange_TLS(this, TLS, false), true);
1546 }
1548 // programs to which the current node shall be added
1549 const std::map<std::string, NBTrafficLightDefinition*> programs = tlCont.getPrograms(value);
1550 if (programs.size() > 0) {
1551 for (const auto& TLSProgram : programs) {
1552 NBTrafficLightDefinition* oldTLS = TLSProgram.second;
1553 if (dynamic_cast<NBOwnTLDef*>(oldTLS) != nullptr) {
1554 undoList->add(new GNEChange_TLS(this, oldTLS, true), true);
1555 } else {
1556 // delete and re-create the definition because the loaded phases are now invalid
1557 if (dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS) != nullptr &&
1558 dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS)->usingSignalGroups()) {
1559 // keep the old program and add all-red state for the added links
1560 NBLoadedSUMOTLDef* newTLSJoined = new NBLoadedSUMOTLDef(*oldTLS, *dynamic_cast<NBLoadedSUMOTLDef*>(oldTLS)->getLogic());
1561 newTLSJoined->joinLogic(currentTLSCopy);
1562 undoList->add(new GNEChange_TLS(this, newTLSJoined, true, true), true);
1563 } else {
1564 undoList->add(new GNEChange_TLS(this, nullptr, true, false, value), true);
1565 }
1567 // switch from old to new definition
1568 std::vector<NBNode*> copyOfNodes = oldTLS->getNodes();
1569 for (const auto& node : copyOfNodes) {
1570 GNEJunction* oldJunction = myNet->getAttributeCarriers()->retrieveJunction(node->getID());
1571 undoList->add(new GNEChange_TLS(oldJunction, oldTLS, false), true);
1572 undoList->add(new GNEChange_TLS(oldJunction, newTLS, true), true);
1573 }
1574 }
1575 }
1576 } else {
1577 if (currentIsSingle && currentIsLoaded) {
1578 // rename the traffic light but keep everything else
1579 NBTrafficLightLogic* renamedLogic = dynamic_cast<NBLoadedSUMOTLDef*>(currentTLSCopy)->getLogic();
1580 renamedLogic->setID(value);
1581 NBLoadedSUMOTLDef* renamedTLS = new NBLoadedSUMOTLDef(*currentTLSCopy, *renamedLogic);
1582 renamedTLS->setID(value);
1583 undoList->add(new GNEChange_TLS(this, renamedTLS, true, true), true);
1584 } else {
1585 // create new traffic light
1586 undoList->add(new GNEChange_TLS(this, nullptr, true, false, value), true);
1587 }
1588 }
1589 delete currentTLSCopy;
1590 undoList->end();
1591 break;
1592 }
1593 default:
1594 setCommonAttribute(key, value, undoList);
1595 break;
1596 }
1597}
1598
1599
1600bool
1601GNEJunction::isValid(SumoXMLAttr key, const std::string& value) {
1602 switch (key) {
1603 case SUMO_ATTR_ID:
1604 return SUMOXMLDefinitions::isValidNetID(value) && (myNet->getAttributeCarriers()->retrieveJunction(value, false) == nullptr);
1605 case SUMO_ATTR_TYPE:
1607 case SUMO_ATTR_POSITION:
1608 if (value.empty()) {
1609 return (myGNEIncomingEdges.size() + myGNEOutgoingEdges.size()) > 0;
1610 } else {
1611 return canParse<Position>(value);
1612 }
1613 case SUMO_ATTR_SHAPE:
1614 // empty shapes are allowed
1615 return canParse<PositionVector>(value);
1616 case SUMO_ATTR_RADIUS:
1617 if (value.empty() || (value == "default")) {
1618 return true;
1619 } else {
1620 return canParse<double>(value) && ((parse<double>(value) >= 0) || (parse<double>(value) == -1));
1621 }
1622 case SUMO_ATTR_TLTYPE:
1624 case SUMO_ATTR_TLLAYOUT:
1626 case SUMO_ATTR_TLID:
1627 return myNBNode->isTLControlled() && (value != "");
1629 return canParse<bool>(value);
1632 case SUMO_ATTR_FRINGE:
1634 case SUMO_ATTR_NAME:
1635 return true;
1636 default:
1637 return isCommonValid(key, value);
1638 }
1639}
1640
1641
1642bool
1644 switch (key) {
1645 case SUMO_ATTR_TLTYPE:
1646 case SUMO_ATTR_TLLAYOUT:
1647 case SUMO_ATTR_TLID:
1648 return myNBNode->isTLControlled();
1649 case SUMO_ATTR_KEEP_CLEAR: {
1650 // check if at least there is an incoming connection
1651 for (const auto& incomingEdge : myGNEIncomingEdges) {
1652 if (incomingEdge->getGNEConnections().size() > 0) {
1653 return true;
1654 }
1655 }
1656 return false;
1657 }
1659 return false;
1660 default:
1661 return true;
1662 }
1663}
1664
1665
1666bool
1668 switch (key) {
1669 case SUMO_ATTR_SHAPE:
1670 return !myNBNode->hasCustomShape();
1671 default:
1672 return false;
1673 }
1674}
1675
1676
1677const Parameterised::Map&
1681
1682
1683void
1685 myAmResponsible = newVal;
1686}
1687
1688// ===========================================================================
1689// private
1690// ===========================================================================
1691
1692bool
1693GNEJunction::drawAsBubble(const GUIVisualizationSettings& s, const double junctionShapeArea) const {
1694 const auto& editModes = myNet->getViewNet()->getEditModes();
1695 const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
1696 // check conditions
1697 if (junctionShapeArea < 4) {
1698 // force draw if this junction is a candidate
1701 return true;
1702 }
1703 // force draw if we're in person/container plan mode
1704 if (editModes.isCurrentSupermodeDemand() &&
1705 ((editModes.demandEditMode == DemandEditMode::DEMAND_PERSON) ||
1706 (editModes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) ||
1707 (editModes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) ||
1708 (editModes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN))) {
1709 return true;
1710 }
1711 // force draw if we're inspecting a vehicle that start or ends in a junction
1712 if (inspectedElements.isInspectingSingleElement()) {
1713 // check if starts or ends in this junction
1714 if ((inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_FROM_JUNCTION) &&
1715 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_FROM_JUNCTION) == getID())) ||
1716 (inspectedElements.getFirstAC()->hasAttribute(SUMO_ATTR_TO_JUNCTION) &&
1717 (inspectedElements.getFirstAC()->getAttribute(SUMO_ATTR_TO_JUNCTION) == getID()))) {
1718 return true;
1719 }
1720 }
1721 }
1722 if (!s.drawJunctionShape) {
1723 // don't draw bubble if it was disabled in GUIVisualizationSettings
1724 return false;
1725 }
1727 // force draw bubbles if we enabled option in checkbox of viewNet
1728 return true;
1729 }
1730 if (junctionShapeArea >= 4) {
1731 // don't draw if shape area is greater than 4
1732 return false;
1733 }
1734 if (!editModes.isCurrentSupermodeNetwork()) {
1735 // only draw bubbles in network mode
1736 return false;
1737 }
1738 return true;
1739}
1740
1741
1742void
1744 const double exaggeration) const {
1745 // calculate bubble radius
1746 const double bubbleRadius = s.neteditSizeSettings.junctionBubbleRadius * exaggeration;
1747 // set bubble color
1748 const RGBColor bubbleColor = setColor(s, true);
1749 // push matrix
1751 // set color
1752 GLHelper::setColor(bubbleColor);
1753 // move matrix junction center
1754 glTranslated(myNBNode->getPosition().x(), myNBNode->getPosition().y(), 1.5);
1755 // draw filled circle
1756 GLHelper::drawFilledCircleDetailled(d, bubbleRadius);
1757 // pop matrix
1759}
1760
1761
1762void
1764 // first check drawing conditions
1765 if (s.drawJunctionShape && (myNBNode->getShape().size() > 0)) {
1766 // set shape color
1767 const RGBColor junctionShapeColor = setColor(s, false);
1768 // set color
1769 GLHelper::setColor(junctionShapeColor);
1770 // adjust shape to exaggeration (check)
1771 if ((exaggeration > 1 || myExaggeration > 1) && exaggeration != myExaggeration) {
1772 myExaggeration = exaggeration;
1775 myTesselation.getShapeRef().scaleRelative(exaggeration);
1777 }
1778 // check if draw tesselation or or polygon
1780 // draw shape with high detail
1782 } else {
1783 // draw shape
1785 }
1786 // draw shape points only in Network supermode
1789 // set color
1790 const RGBColor darkerColor = junctionShapeColor.changedBrightness(-32);
1791 // calculate geometry
1792 GUIGeometry junctionGeometry;
1793 // obtain junction Shape
1794 PositionVector junctionOpenShape = myNBNode->getShape();
1795 // adjust shape to exaggeration
1796 if (exaggeration > 1) {
1797 junctionOpenShape.scaleRelative(exaggeration);
1798 }
1799 // update geometry
1800 junctionGeometry.updateGeometry(junctionOpenShape);
1801 // set color
1802 GLHelper::setColor(darkerColor);
1803 // draw shape
1805 // draw geometry points
1806 GUIGeometry::drawGeometryPoints(d, junctionOpenShape, darkerColor,
1809 }
1810 }
1811}
1812
1813
1814void
1817 // push matrix
1819 // set color
1820 GLHelper::setColor(setColor(s, true).changedBrightness(-20));
1821 // move matrix junction center
1822 glTranslated(myNBNode->getPosition().x(), myNBNode->getPosition().y(), 1.7);
1823 // draw filled circle
1825 // pop matrix
1827 }
1828}
1829
1830
1831void
1833 // draw TLS icon if isn't being drawn for selecting
1837 const Position pos = myNBNode->getPosition();
1838 glTranslated(pos.x(), pos.y(), 2.2);
1839 glColor3d(1, 1, 1);
1840 const double halfWidth = 32 / s.scale;
1841 const double halfHeight = 64 / s.scale;
1842 GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GUITexture::TLS), -halfWidth, -halfHeight, halfWidth, halfHeight);
1844 }
1845}
1846
1847
1848void
1850 // check if draw elevation
1853 // Translate to center of junction
1854 glTranslated(myNBNode->getPosition().x(), myNBNode->getPosition().y(), 0.1);
1855 // draw Z value
1858 }
1859}
1860
1861
1862void
1869
1870
1871void
1873 // check if draw junction elements
1875 // draw crossings
1876 for (const auto& crossing : myGNECrossings) {
1877 crossing->drawGL(s);
1878 }
1879 // draw walking areas
1880 for (const auto& walkingArea : myGNEWalkingAreas) {
1881 walkingArea->drawGL(s);
1882 }
1883 // draw internalLanes
1884 for (const auto& internalLanes : myInternalLanes) {
1885 internalLanes->drawGL(s);
1886 }
1887 // draw connections
1888 for (const auto& incomingEdge : myGNEIncomingEdges) {
1889 for (const auto& connection : incomingEdge->getGNEConnections()) {
1890 connection->drawGL(s);
1891 }
1892 }
1893 // draw child demand elements
1894 for (const auto& demandElement : getChildDemandElements()) {
1895 demandElement->drawGL(s);
1896 }
1897 // draw child demand elements
1898 for (const auto& demandElement : getChildDemandElements()) {
1899 demandElement->drawGL(s);
1900 }
1901 // draw path additional elements
1905 }
1906}
1907
1908
1909void
1911 const double exaggeration, const bool drawBubble) const {
1912 // if we're selecting using a boundary, first don't calculate contour bt check if edge boundary is within selection boundary
1914 // simply add object in ViewObjectsHandler with full boundary
1915 gViewObjectsHandler.selectObject(this, getType(), false, true, nullptr);
1916 } else {
1917 // always calculate for shape
1918 myNetworkElementContour.calculateContourClosedShape(s, d, this, myNBNode->getShape(), getType(), exaggeration, this);
1919 // check if calculate contour for bubble
1920 if (drawBubble) {
1922 }
1923 // check geometry points if we're editing shape
1924 if (myShapeEdited) {
1926 exaggeration, true);
1927 }
1928 }
1929}
1930
1931
1932void
1933GNEJunction::setAttribute(SumoXMLAttr key, const std::string& value) {
1934 switch (key) {
1935 case SUMO_ATTR_KEEP_CLEAR: {
1936 throw InvalidArgument(toString(key) + " cannot be edited");
1937 }
1938 case SUMO_ATTR_ID: {
1940 break;
1941 }
1942 case SUMO_ATTR_TYPE: {
1947 }
1949 break;
1950 }
1951 case SUMO_ATTR_POSITION: {
1952 // set new position in NBNode updating edge boundaries
1953 moveJunctionGeometry(parse<Position>(value), true);
1954 // mark this connections and all of the junction's Neighbours as deprecated
1956 // update centering boundary and grid
1957 if (myGNEIncomingEdges.size() + myGNEOutgoingEdges.size() > 0) {
1959 } else {
1961 }
1962 break;
1963 }
1965 if (myLogicStatus == FEATURE_GUESSED && value != FEATURE_GUESSED) {
1966 // clear guessed connections. previous connections will be restored
1968 // Clear GNEConnections of incoming edges
1969 for (const auto& i : myGNEIncomingEdges) {
1970 i->clearGNEConnections();
1971 }
1972 }
1973 myLogicStatus = value;
1974 break;
1975 case SUMO_ATTR_SHAPE: {
1976 // set new shape (without updating grid)
1977 myNBNode->setCustomShape(parse<PositionVector>(value));
1978 // mark this connections and all of the junction's neighbors as deprecated
1980 // update centering boundary and grid
1982 break;
1983 }
1984 case SUMO_ATTR_RADIUS: {
1985 if (value.empty() || (value == "default")) {
1986 myNBNode->setRadius(-1);
1987 } else {
1988 myNBNode->setRadius(parse<double>(value));
1989 }
1990 break;
1991 }
1992 case SUMO_ATTR_TLTYPE: {
1993 // we need to make a copy of controlling TLS (because original will be updated)
1994 const std::set<NBTrafficLightDefinition*> copyOfTls = myNBNode->getControllingTLS();
1995 for (const auto& TLS : copyOfTls) {
1996 TLS->setType(SUMOXMLDefinitions::TrafficLightTypes.get(value));
1997 }
1998 break;
1999 }
2000 case SUMO_ATTR_TLLAYOUT:
2001 // should not be triggered (handled via GNEChange_TLS)
2002 break;
2005 break;
2006 case SUMO_ATTR_FRINGE:
2008 break;
2009 case SUMO_ATTR_NAME:
2010 myNBNode->setName(value);
2011 break;
2012 default:
2013 setCommonAttribute(myNBNode, key, value);
2014 break;
2015 }
2016 // invalidate demand path calculator
2018}
2019
2020
2021void
2023 // clear contour
2025 // set new position in NBNode without updating grid
2026 if (isShapeEdited()) {
2027 // set new shape
2029 } else if (moveResult.shapeToUpdate.size() > 0) {
2030 // obtain NBNode position
2031 const Position orig = myNBNode->getPosition();
2032 // move geometry
2033 moveJunctionGeometry(moveResult.shapeToUpdate.front(), false);
2034 // check if move only center
2036 // set new position of adjacent edges depending if we're moving a selection
2037 for (const auto& NBEdge : getNBNode()->getEdges()) {
2038 myNet->getAttributeCarriers()->retrieveEdge(NBEdge->getID())->updateJunctionPosition(this, onlyMoveCenter ? myNBNode->getPosition() : orig);
2039 }
2040 }
2042}
2043
2044
2045void
2047 // make sure that newShape isn't empty
2048 if (moveResult.shapeToUpdate.size() > 0) {
2049 // check if we're editing a shape
2050 if (isShapeEdited()) {
2051 // commit new shape
2052 undoList->begin(this, "moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
2053 setAttribute(SUMO_ATTR_SHAPE, toString(moveResult.shapeToUpdate), undoList);
2054 undoList->end();
2055 } else if (myNBNode->hasCustomShape()) {
2056 // commit new shape
2057 undoList->begin(this, "moving custom " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
2058 setAttribute(SUMO_ATTR_POSITION, toString(moveResult.shapeToUpdate.front()), undoList);
2059 // calculate offset and apply to custom shape
2060 const auto customShapeOffset = moveResult.shapeToUpdate.front() - myNBNode->getCenter();
2061 const auto customShapeMoved = myNBNode->getShape().added(customShapeOffset);
2062 setAttribute(SUMO_ATTR_SHAPE, toString(customShapeMoved), undoList);
2063 undoList->end();
2064 } else {
2065 setAttribute(SUMO_ATTR_POSITION, toString(moveResult.shapeToUpdate.front()), undoList);
2066 }
2067 }
2068}
2069
2070
2071double
2072GNEJunction::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
2073 switch (activeScheme) {
2074 case 0:
2076 return 3;
2077 } else {
2078 return 0;
2079 }
2080 case 1:
2082 case 2:
2083 switch (myNBNode->getType()) {
2085 return 0;
2087 return 1;
2089 return 2;
2091 return 3;
2093 return 4;
2095 return 5;
2097 return 6;
2099 return 7;
2102 return 8;
2104 return 8; // may happen before first network computation
2106 assert(false);
2107 return 8;
2109 return 9;
2111 return 10;
2113 return 11;
2115 return 12;
2117 return 13;
2118 default:
2119 assert(false);
2120 return 0;
2121 }
2122 case 3:
2123 return myNBNode->getPosition().z();
2124 default:
2125 assert(false);
2126 return 0;
2127 }
2128}
2129
2130void
2132 for (auto edge : myGNEIncomingEdges) {
2133 if (edge->getGNEConnections().size() > 0) {
2135 return;
2136 }
2137 }
2138 // no connections. Use normal color for border edges and cul-de-sac
2139 if (myGNEIncomingEdges.size() == 0 || myGNEOutgoingEdges.size() == 0) {
2141 return;
2142 } else if (myGNEIncomingEdges.size() == 1 && myGNEOutgoingEdges.size() == 1) {
2143 NBEdge* in = myGNEIncomingEdges[0]->getNBEdge();
2144 NBEdge* out = myGNEOutgoingEdges[0]->getNBEdge();
2145 if (in->isTurningDirectionAt(out)) {
2147 return;
2148 }
2149 }
2151}
2152
2153
2154void
2155GNEJunction::moveJunctionGeometry(const Position& pos, const bool updateEdgeBoundaries) {
2156 // reinit NBNode
2157 myNBNode->reinit(pos, myNBNode->getType());
2158 // declare three sets with all affected GNEJunctions, GNEEdges and GNEConnections
2159 std::set<GNEJunction*> affectedJunctions;
2160 std::set<GNEEdge*> affectedEdges;
2161 // Iterate over GNEEdges
2162 for (const auto& edge : getChildEdges()) {
2163 // Add source and destination junctions
2164 affectedJunctions.insert(edge->getFromJunction());
2165 affectedJunctions.insert(edge->getToJunction());
2166 // Obtain neighbors of Junction source
2167 for (const auto& junctionSourceEdge : edge->getFromJunction()->getChildEdges()) {
2168 affectedEdges.insert(junctionSourceEdge);
2169 }
2170 // Obtain neighbors of Junction destination
2171 for (const auto& junctionDestinationEdge : edge->getToJunction()->getChildEdges()) {
2172 affectedEdges.insert(junctionDestinationEdge);
2173 }
2174 }
2175 // reset walking areas of affected edges
2176 for (const auto& affectedJunction : affectedJunctions) {
2177 affectedJunction->clearWalkingAreas();
2178 }
2179 // Iterate over affected Edges
2180 for (const auto& affectedEdge : affectedEdges) {
2181 // update edge boundaries
2182 if (updateEdgeBoundaries) {
2183 affectedEdge->updateCenteringBoundary(true);
2184 }
2185 // Update edge geometry
2186 affectedEdge->updateGeometry();
2187 }
2188}
2189
2190
2193 // get active scheme
2194 const int scheme = s.junctionColorer.getActive();
2195 // first check if we're editing shape
2196 if (myShapeEdited) {
2198 }
2199 // set default color
2201 // set special bubble color
2202 if (bubble && (scheme == 0) && !myColorForMissingConnections) {
2203 color = s.junctionColorer.getScheme().getColor(1);
2204 }
2205 // override with special colors (unless the color scheme is based on selection)
2206 if (drawUsingSelectColor() && scheme != 1) {
2207 color = s.colorSettings.selectionColor;
2208 }
2209 // overwrite color if we're in data mode
2211 color = s.junctionColorer.getScheme().getColor(6);
2212 }
2213 // special color for source candidate junction
2214 if (mySourceCandidate) {
2216 }
2217 // special color for target candidate junction
2218 if (myTargetCandidate) {
2220 }
2221 // special color for special candidate junction
2222 if (mySpecialCandidate) {
2224 }
2225 // special color for possible candidate junction
2226 if (myPossibleCandidate) {
2228 }
2229 // special color for conflicted candidate junction
2232 }
2233 // return color
2234 return color;
2235}
2236
2237
2238void
2241 tlCont.insert(tlDef, forceInsert); // may return false for tlDef which controls multiple junctions
2242 tlDef->addNode(myNBNode);
2243}
2244
2245
2246void
2249 if (tlDef->getNodes().size() == 1) {
2250 tlCont.extract(tlDef);
2251 }
2253}
2254
2255
2256/****************************************************************************/
@ 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_CROSSING
Mode for editing crossing.
@ 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
#define TL(string)
Definition MsgHandler.h:305
#define TLF(string,...)
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
@ SUMO_ATTR_EDGES
the edges of a route
@ 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
Position getCenter() const
Returns the center of the boundary.
Definition Boundary.cpp:109
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:75
Boundary & grow(double by)
extends the boundary by the given amount
Definition Boundary.cpp:340
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:204
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:649
static void popMatrix()
pop matrix
Definition GLHelper.cpp:131
static void drawBoundary(const GUIVisualizationSettings &s, const Boundary &b)
Draw a boundary (used for debugging)
Definition GLHelper.cpp:952
static void drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius)
Draws a filled circle around (0,0) depending of level of detail.
Definition GLHelper.cpp:534
static void pushMatrix()
push matrix
Definition GLHelper.cpp:118
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition GLHelper.cpp:742
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:773
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 (more quickly as checking GUIGlObjectStorage)
std::string getCommonAttribute(const Parameterised *parameterised, SumoXMLAttr key) const
static const std::string True
true value in string format (used for comparing boolean values in getAttribute(......
void setCommonAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
const std::string & getTagStr() const
get tag assigned to this object in string format
static const std::string FEATURE_GUESSED
feature has been reguessed (may still be unchanged be we can't tell (yet)
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
void drawInLayer(const double typeOrLayer, const double extraOffset=0) const
draw element in the given layer, or in front if corresponding flag is enabled
GNENet * myNet
pointer to net
bool inGrid() const
check if this AC was inserted in grid
bool isCommonValid(SumoXMLAttr key, const std::string &value) const
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(...))
const GNETagProperties * myTagProperty
reference to tagProperty associated with this attribute carrier
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 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 calculateContourCircleShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const Position &pos, double radius, const double layer, const double scale, const GUIGlObject *boundaryParent) const
calculate contour (circle elements)
void calculateContourClosedShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const PositionVector &shape, const double layer, const double scale, const GUIGlObject *boundaryParent, const bool addToSelectedObjects=true) const
calculate contours
bool drawDottedContours(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, const double lineWidth, const bool addOffset) const
draw dotted contours (basics, select, delete, inspect...)
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
GNEJunction * getCurrentJunction() const
get current junction
GNECrossingFrame::EdgesSelector * getEdgesSelector() const
get edge selector modul
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:829
const GNEHierarchicalContainerChildren< GNEEdge * > & getChildEdges() const
get child edges
const GNEHierarchicalContainerChildren< GNELane * > & getChildLanes() const
get child lanes
const GNEHierarchicalContainerChildren< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
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:54
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
bool checkDrawDeleteContourSmall() const
check if draw delete contour small (pink/white)
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)
bool isLogicValid()
whether this junction has a valid logic
void drawTLSIcon(const GUIVisualizationSettings &s) const
draw TLS icon
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.
void drawJunctionCenter(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d) const
draw junction center (only in move mode)
void drawElevation(const GUIVisualizationSettings &s) const
draw elevation
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
~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
bool getMoveOnlyJunctionCenter() const
check if option "move only junction center" is enabled
NetworkMoveOptions * getNetworkMoveOptions() const
get network mode options
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:697
NBNetBuilder * getNetBuilder() const
get net builder
Definition GNENet.cpp:1619
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1443
GNEPathManager * getDataPathManager()
get data path manager
Definition GNENet.cpp:183
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1453
NBTrafficLightLogicCont & getTLLogicCont()
returns the tllcont of the underlying netbuilder
Definition GNENet.cpp:2201
void mergeJunctions(GNEJunction *moved, const GNEJunction *target, GNEUndoList *undoList)
merge the given junctions edges between the given junctions will be deleted
Definition GNENet.cpp:1171
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:177
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition GNENet.cpp:147
GNEPathManager * getNetworkPathManager()
get network path manager
Definition GNENet.cpp:171
void requireRecompute()
inform the net about the need for recomputation
Definition GNENet.cpp:1601
void addExplicitTurnaround(std::string id)
add edge id to the list of explicit turnarounds
Definition GNENet.cpp:2213
void deleteJunction(GNEJunction *junction, GNEUndoList *undoList)
removes junction and all incident edges
Definition GNENet.cpp:414
GNEViewNet * getViewNet() const
get view net
Definition GNENet.cpp:2195
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.
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
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 std::vector< const GNEJunction * > & getMergingJunctions() const
get merging junctions
const GUIGlObject * getGUIGlObjectFront() const
get front GUIGLObject or a pointer to nullptr
GNEJunction * getJunctionFront() const
get front junction or a pointer to nullptr
const std::vector< GNEJunction * > & getJunctions() const
get vector with junctions
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
void updateObjectsInPosition(const Position &pos)
update objects and boundaries in position
GNEViewNetHelper::InspectedElements & getInspectedElements()
get inspected elements
const GNEViewNetHelper::MoveSingleElementModul & getMoveSingleElementValues() const
get move single element values
bool askMergeJunctions(const GNEJunction *movedJunction, const GNEJunction *targetJunction, bool &alreadyAsked)
ask merge junctions
bool showJunctionAsBubbles() const
return true if junction must be showed as bubbles
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
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
GNECrossingFrame * getCrossingFrame() const
get frame for NETWORK_CROSSING
GNEMoveFrame * getMoveFrame() const
get frame for move elements
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.
GUIGlObject * getGLObject() const
The object that belongs to this popup-menu.
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.
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
void buildPopUpMenuCommonOptions(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, GUISUMOAbstractView *parent, const SumoXMLTag tag, const bool selected, bool addSeparator=true)
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)
GUIGLObjectPopupMenu * getPopup() const
ge the current popup-menu
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 Triangle & getSelectionTriangle() const
get selection triangle
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)
bool selectingUsingRectangle() const
return true if we're selecting using a triangle
Stores the information about how to visualize structures.
GUIVisualizationTextSettings junctionName
GUIVisualizationSizeSettings junctionSize
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:1531
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition NBEdge.cpp:3755
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition NBEdge.cpp:4098
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:4197
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:340
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition NBNode.cpp:345
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:3023
SumoXMLNodeType getType() const
Returns the type of this node.
Definition NBNode.h:285
bool isTrafficLight() const
Definition NBNode.h:826
void setRightOfWay(RightOfWay rightOfWay)
set method for computing right-of-way
Definition NBNode.h:573
void setCustomShape(const PositionVector &shape)
set the junction shape
Definition NBNode.cpp:2763
void invalidateIncomingConnections(bool reallowSetting=false)
invalidate incoming connections
Definition NBNode.cpp:2102
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:384
std::vector< std::pair< Position, std::string > > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
Definition NBNode.cpp:4353
const std::vector< std::unique_ptr< Crossing > > & getCrossingsIncludingInvalid() const
Definition NBNode.h:746
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:588
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
Definition NBNode.cpp:3072
const std::string & getName() const
Returns intersection name.
Definition NBNode.h:310
void setRadius(double radius)
set the turning radius
Definition NBNode.h:563
void setName(const std::string &name)
set intersection name
Definition NBNode.h:583
const Position & getPosition() const
Definition NBNode.h:260
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition NBNode.cpp:413
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:2757
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:4057
bool checkIsRemovableReporting(std::string &reason) const
check if node is removable and return reason if not
Definition NBNode.cpp:2644
const std::vector< WalkingArea > & getWalkingAreas() const
return this junctions pedestrian walking areas
Definition NBNode.h:751
PositionVector myPoly
the (outer) shape of the junction
Definition NBNode.h:959
void setFringeType(FringeType fringeType)
set method for computing right-of-way
Definition NBNode.h:578
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.
std::map< std::string, std::string > Map
parameters map
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
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:278
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:319
double x() const
Returns the x-position.
Definition Position.h:52
double z() const
Returns the z-position.
Definition Position.h:62
double y() const
Returns the y-position.
Definition Position.h:57
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
get string
bool hasString(const std::string &str) const
check if the given string exist
T get(const std::string &str) const
get key
std::vector< GLPrimitive > myTesselation
id of the display list for the cached tesselation
Definition GUIPolygon.h:72
void drawTesselation(const PositionVector &shape) const
perform the tesselation / drawing
bool isBoundaryFullWithin(const Boundary &boundary) const
check if the given position is FULL within this triangle
Definition Triangle.cpp:59
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
static const double edgeGeometryPointRadius
moving edge geometry point radius
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
bool show(const GUIGlObject *o) const
whether to show the text
double scaledSize(double scale, double constFactor=0.1) const
get scale size
A structure which describes a connection between edges or lanes.
Definition NBEdge.h:201