Path: blob/main/src/netedit/elements/additional/GNERerouter.cpp
193674 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file GNERerouter.cpp14/// @author Pablo Alvarez Lopez15/// @date Nov 201516///17//18/****************************************************************************/1920#include <netedit/changes/GNEChange_Attribute.h>21#include <netedit/dialogs/elements/GNERerouterDialog.h>22#include <netedit/elements/moving/GNEMoveElementView.h>23#include <netedit/GNENet.h>24#include <netedit/GNEUndoList.h>2526#include "GNERerouter.h"27#include "GNERerouterSymbol.h"2829// ===========================================================================30// member method definitions31// ===========================================================================3233GNERerouter::GNERerouter(GNENet* net) :34GNEAdditional(net, SUMO_TAG_REROUTER),35GNEAdditionalSquared(this) {36}373839GNERerouter::GNERerouter(const std::string& id, GNENet* net, FileBucket* fileBucket, const Position& pos, const std::string& name,40double probability, bool off, bool optional, SUMOTime timeThreshold, const std::vector<std::string>& vTypes,41const Parameterised::Map& parameters) :42GNEAdditional(id, net, SUMO_TAG_REROUTER, fileBucket, name),43GNEAdditionalSquared(this, pos),44Parameterised(parameters),45myProbability(probability),46myOff(off),47myOptional(optional),48myTimeThreshold(timeThreshold),49myVTypes(vTypes) {50// update centering boundary without updating grid51updateCenteringBoundary(false);52}535455GNERerouter::~GNERerouter() {56}575859GNEMoveElement*60GNERerouter::getMoveElement() const {61return myMoveElementView;62}636465Parameterised*66GNERerouter::getParameters() {67return this;68}697071const Parameterised*72GNERerouter::getParameters() const {73return this;74}757677void78GNERerouter::writeAdditional(OutputDevice& device) const {79// avoid write rerouters without edges80if (getAttribute(SUMO_ATTR_EDGES).size() > 0) {81device.openTag(SUMO_TAG_REROUTER);82// write common additional attributes83writeAdditionalAttributes(device);84// write move atributes85myMoveElementView->writeMoveAttributes(device);86// write specific attributes87device.writeAttr(SUMO_ATTR_EDGES, getAttribute(SUMO_ATTR_EDGES));88if (myProbability != 1.0) {89device.writeAttr(SUMO_ATTR_PROB, myProbability);90}91if (time2string(myTimeThreshold) != "0.00") {92device.writeAttr(SUMO_ATTR_HALTING_TIME_THRESHOLD, time2string(myTimeThreshold));93}94if (!myVTypes.empty()) {95device.writeAttr(SUMO_ATTR_VTYPES, myVTypes);96}97if (myOff) {98device.writeAttr(SUMO_ATTR_OFF, myOff);99}100if (myOptional) {101device.writeAttr(SUMO_ATTR_OPTIONAL, myOptional);102}103// write all rerouter interval104for (const auto& rerouterInterval : getChildAdditionals()) {105if (!rerouterInterval->getTagProperty()->isSymbol()) {106rerouterInterval->writeAdditional(device);107}108}109// write parameters (Always after children to avoid problems with additionals.xsd)110writeParams(device);111device.closeTag();112} else {113WRITE_WARNING("Rerouter '" + getID() + TL("' needs at least one edge"));114}115}116117118bool119GNERerouter::isAdditionalValid() const {120return true;121}122123124std::string GNERerouter::getAdditionalProblem() const {125return "";126}127128129void130GNERerouter::fixAdditionalProblem() {131// nothing to fix132}133134135bool136GNERerouter::checkDrawMoveContour() const {137// get edit modes138const auto& editModes = myNet->getViewNet()->getEditModes();139// check if we're in move mode140if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&141!myNet->getViewNet()->getEditNetworkElementShapes().getEditedNetworkElement() &&142(editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {143// only move the first element144return myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() == this;145} else {146return false;147}148}149150151void152GNERerouter::updateGeometry() {153updatedSquaredGeometry();154}155156157Position158GNERerouter::getPositionInView() const {159return myPosOverView;160}161162163void164GNERerouter::updateCenteringBoundary(const bool updateGrid) {165updatedSquaredCenteringBoundary(updateGrid);166}167168169void170GNERerouter::splitEdgeGeometry(const double /*splitPosition*/, const GNENetworkElement* /*originalElement*/, const GNENetworkElement* /*newElement*/, GNEUndoList* /*undoList*/) {171// geometry of this element cannot be splitted172}173174175void176GNERerouter::openAdditionalDialog(FXWindow* restoringFocusWindow) {177// Open rerouter dialog178UNUSED_PARAMETER(restoringFocusWindow);179GNERerouterDialog(this);180}181182183std::string184GNERerouter::getParentName() const {185return myNet->getMicrosimID();186}187188189void190GNERerouter::drawGL(const GUIVisualizationSettings& s) const {191const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();192// first check if additional has to be drawn193if (myNet->getViewNet()->getDataViewOptions().showAdditionals()) {194// draw parent and child lines195drawParentChildLines(s, s.additionalSettings.connectionColor, true);196// draw Rerouter197drawSquaredAdditional(s, s.additionalSettings.rerouterSize, GUITexture::REROUTER, GUITexture::REROUTER_SELECTED);198// iterate over additionals and check if drawn199for (const auto& interval : getChildAdditionals()) {200// if rerouter or their intevals are selected, then draw201if (myNet->getViewNet()->getNetworkViewOptions().showSubAdditionals() ||202isAttributeCarrierSelected() || inspectedElements.isACInspected(this) ||203interval->isAttributeCarrierSelected() || inspectedElements.isACInspected(interval) ||204interval->isMarkedForDrawingFront()) {205interval->drawGL(s);206} else {207// if rerouterElements are inspected or selected, then draw208for (const auto& rerouterElement : interval->getChildAdditionals()) {209if (rerouterElement->isAttributeCarrierSelected() || inspectedElements.isACInspected(rerouterElement) ||210rerouterElement->isMarkedForDrawingFront()) {211interval->drawGL(s);212}213}214}215}216}217}218219220std::string221GNERerouter::getAttribute(SumoXMLAttr key) const {222switch (key) {223case SUMO_ATTR_ID:224return getMicrosimID();225case SUMO_ATTR_EDGES: {226std::vector<std::string> edges;227for (const auto& rerouterSymbol : getChildAdditionals()) {228if (rerouterSymbol->getTagProperty()->isSymbol()) {229edges.push_back(rerouterSymbol->getAttribute(SUMO_ATTR_EDGE));230}231}232return toString(edges);233}234case SUMO_ATTR_NAME:235return myAdditionalName;236case SUMO_ATTR_PROB:237return toString(myProbability);238case SUMO_ATTR_HALTING_TIME_THRESHOLD:239return time2string(myTimeThreshold);240case SUMO_ATTR_VTYPES:241return toString(myVTypes);242case SUMO_ATTR_OFF:243return toString(myOff);244case SUMO_ATTR_OPTIONAL:245return toString(myOptional);246default:247return myMoveElementView->getMovingAttribute(key);248}249}250251252double253GNERerouter::getAttributeDouble(SumoXMLAttr key) const {254switch (key) {255case SUMO_ATTR_PROB:256return myProbability;257default:258return myMoveElementView->getMovingAttributeDouble(key);259}260}261262263Position264GNERerouter::getAttributePosition(SumoXMLAttr key) const {265return myMoveElementView->getMovingAttributePosition(key);266}267268269PositionVector270GNERerouter::getAttributePositionVector(SumoXMLAttr key) const {271return myMoveElementView->getMovingAttributePositionVector(key);272}273274275void276GNERerouter::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {277if (value == getAttribute(key)) {278return; //avoid needless changes, later logic relies on the fact that attributes have changed279}280switch (key) {281// special case for lanes due rerouter Symbols282case SUMO_ATTR_EDGES:283// rebuild rerouter Symbols284rebuildRerouterSymbols(value, undoList);285break;286case SUMO_ATTR_ID:287case SUMO_ATTR_NAME:288case SUMO_ATTR_PROB:289case SUMO_ATTR_HALTING_TIME_THRESHOLD:290case SUMO_ATTR_VTYPES:291case SUMO_ATTR_OFF:292case SUMO_ATTR_OPTIONAL:293GNEChange_Attribute::changeAttribute(this, key, value, undoList);294break;295default:296myMoveElementView->setMovingAttribute(key, value, undoList);297break;298}299}300301302bool303GNERerouter::isValid(SumoXMLAttr key, const std::string& value) {304switch (key) {305case SUMO_ATTR_ID:306return isValidAdditionalID(value);307case SUMO_ATTR_EDGES:308return canParse<std::vector<GNEEdge*> >(myNet, value, false);309case SUMO_ATTR_NAME:310return SUMOXMLDefinitions::isValidAttribute(value);311case SUMO_ATTR_PROB:312return canParse<double>(value) && (parse<double>(value) >= 0) && (parse<double>(value) <= 1);313case SUMO_ATTR_HALTING_TIME_THRESHOLD:314return canParse<SUMOTime>(value);315case SUMO_ATTR_VTYPES:316if (value.empty()) {317return true;318} else {319return SUMOXMLDefinitions::isValidListOfTypeID(value);320}321case SUMO_ATTR_OFF:322return canParse<bool>(value);323case SUMO_ATTR_OPTIONAL:324return canParse<bool>(value);325default:326return myMoveElementView->isMovingAttributeValid(key, value);327}328}329330331std::string332GNERerouter::getPopUpID() const {333return getTagStr() + ": " + getID();334}335336337std::string338GNERerouter::getHierarchyName() const {339return getTagStr();340}341342// ===========================================================================343// private344// ===========================================================================345346void347GNERerouter::setAttribute(SumoXMLAttr key, const std::string& value) {348switch (key) {349case SUMO_ATTR_EDGES:350throw InvalidArgument(getTagStr() + " cannot be edited");351case SUMO_ATTR_ID:352// update microsimID353setAdditionalID(value);354break;355case SUMO_ATTR_NAME:356myAdditionalName = value;357break;358case SUMO_ATTR_PROB:359myProbability = parse<double>(value);360break;361case SUMO_ATTR_HALTING_TIME_THRESHOLD:362myTimeThreshold = parse<SUMOTime>(value);363break;364case SUMO_ATTR_VTYPES:365myVTypes = parse<std::vector<std::string> >(value);366break;367case SUMO_ATTR_OFF:368myOff = parse<bool>(value);369break;370case SUMO_ATTR_OPTIONAL:371myOptional = parse<bool>(value);372break;373default:374myMoveElementView->setMovingAttribute(key, value);375break;376}377// update boundary (except for template)378if (getID().size() > 0) {379updateCenteringBoundary(true);380}381}382383384void385GNERerouter::rebuildRerouterSymbols(const std::string& value, GNEUndoList* undoList) {386undoList->begin(this, ("change " + getTagStr() + " attribute").c_str());387// drop all additional children388while (getChildAdditionals().size() > 0) {389undoList->add(new GNEChange_Additional(getChildAdditionals().front(), false), true);390}391// get edge vector392const std::vector<GNEEdge*> edges = parse<std::vector<GNEEdge*> >(myNet, value);393// create new VSS Symbols394for (const auto& edge : edges) {395// create VSS Symbol396GNEAdditional* VSSSymbol = new GNERerouterSymbol(this, edge);397// add it using GNEChange_Additional398myNet->getUndoList()->add(new GNEChange_Additional(VSSSymbol, true), true);399}400undoList->end();401}402403404/****************************************************************************/405406407