Path: blob/main/src/netedit/dialogs/fix/GNEFixDemandElementsDialog.cpp
169684 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 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 GNEFixDemandElementsDialog.cpp14/// @author Pablo Alvarez Lopez15/// @date Jul 201716///17// Dialog used to fix demand elements during saving18/****************************************************************************/1920#include <netedit/GNEApplicationWindow.h>21#include <netedit/GNENet.h>22#include <netedit/GNETagProperties.h>23#include <netedit/GNEUndoList.h>2425#include "GNEFixDemandElementsDialog.h"2627// ===========================================================================28// FOX callback mapping29// ===========================================================================3031FXDEFMAP(GNEFixDemandElementsDialog::FixRouteOptions) FixRouteOptionsMap[] = {32FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_OPERATION, GNEFixDemandElementsDialog::FixRouteOptions::onCmdSelectOption)33};3435FXDEFMAP(GNEFixDemandElementsDialog::FixVehicleOptions) FixVehicleOptionsMap[] = {36FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_OPERATION, GNEFixDemandElementsDialog::FixVehicleOptions::onCmdSelectOption)37};3839FXDEFMAP(GNEFixDemandElementsDialog::FixStopPositionOptions) FixStopPositionOptionsMap[] = {40FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_OPERATION, GNEFixDemandElementsDialog::FixStopPositionOptions::onCmdSelectOption)41};4243FXDEFMAP(GNEFixDemandElementsDialog::FixPlanOptions) FixPlanOptionsMap[] = {44FXMAPFUNC(SEL_COMMAND, MID_CHOOSEN_OPERATION, GNEFixDemandElementsDialog::FixPlanOptions::onCmdSelectOption)45};4647// Object abstract implementation48FXIMPLEMENT(GNEFixDemandElementsDialog::FixRouteOptions, MFXGroupBoxModule, FixRouteOptionsMap, ARRAYNUMBER(FixRouteOptionsMap))49FXIMPLEMENT(GNEFixDemandElementsDialog::FixVehicleOptions, MFXGroupBoxModule, FixVehicleOptionsMap, ARRAYNUMBER(FixVehicleOptionsMap))50FXIMPLEMENT(GNEFixDemandElementsDialog::FixStopPositionOptions, MFXGroupBoxModule, FixStopPositionOptionsMap, ARRAYNUMBER(FixStopPositionOptionsMap))51FXIMPLEMENT(GNEFixDemandElementsDialog::FixPlanOptions, MFXGroupBoxModule, FixPlanOptionsMap, ARRAYNUMBER(FixPlanOptionsMap))5253// ===========================================================================54// member method definitions55// ===========================================================================5657// ---------------------------------------------------------------------------58// GNEFixDemandElementsDialog::FixRouteOptions - methods59// ---------------------------------------------------------------------------6061GNEFixDemandElementsDialog::FixRouteOptions::FixRouteOptions(GNEFixDemandElementsDialog* fixDemandElementsParent) :62FixOptions(fixDemandElementsParent, fixDemandElementsParent->myLeftFrame, TL("Routes")) {63// Remove invalid routes64myRemoveInvalidRoutes = GUIDesigns::buildFXRadioButton(myLeftFrameOptions,65TL("Remove invalid routes"), "",66TL("Remove invalid routes and save"),67this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);68// Save invalid routes69mySaveInvalidRoutes = GUIDesigns::buildFXRadioButton(myLeftFrameOptions,70TL("Save invalid routes"), "",71TL("Save invalid routes"),72this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);73// Select invalid routes74mySelectRouteInvalids = GUIDesigns::buildFXRadioButton(myRightFrameOptions,75TL("Select invalid routes"), "",76TL("Select invalid routes and stop saving"),77this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);78// Remove stops out of route79myRemoveStopsOutOfRoute = GUIDesigns::buildFXCheckButton(myRightFrameOptions,80TL("Remove stops out of route"), "",81TL("Remove stops out of route"),82this, MID_CHOOSEN_OPERATION, GUIDesignCheckButtonFix);83// register options84registerOption(myRemoveInvalidRoutes);85registerOption(mySaveInvalidRoutes);86registerOption(mySelectRouteInvalids);87registerOption(myRemoveStopsOutOfRoute);88// leave option "removeInvalidRoutes" as default89myRemoveInvalidRoutes->setCheck(true);90// ... and remove stops out of route91myRemoveStopsOutOfRoute->setCheck(TRUE);92}939495void96GNEFixDemandElementsDialog::FixRouteOptions::selectInternalTestSolution(const std::string& solution) {97// choose solution98if (solution == "saveRouteInvalids") {99mySaveInvalidRoutes->setCheck(TRUE, TRUE);100} else if (solution == "removeRouteInvalids") {101myRemoveInvalidRoutes->setCheck(TRUE, TRUE);102} else if (solution == "selectRouteInvalids") {103mySelectRouteInvalids->setCheck(TRUE, TRUE);104}105}106107108bool109GNEFixDemandElementsDialog::FixRouteOptions::applyFixOption() {110if (myConflictedElements.size() > 0) {111auto net = myFixElementDialogParent->getApplicationWindow()->getViewNet()->getNet();112auto undoList = myFixElementDialogParent->getApplicationWindow()->getUndoList();113// continue depending of solution114if (myRemoveInvalidRoutes->getCheck() == TRUE) {115// begin undo list116undoList->begin(GUIIcon::ROUTE, TL("delete invalid routes"));117// iterate over invalid routes to delete it118for (const auto& conflictedElement : myConflictedElements) {119// special case for embedded routes120if (conflictedElement.getElement()->getTagProperty()->getTag() == GNE_TAG_ROUTE_EMBEDDED) {121net->deleteDemandElement(conflictedElement.getElement()->getParentDemandElements().front(), undoList);122} else {123net->deleteDemandElement(conflictedElement.getElement(), undoList);124}125}126// end undo list127undoList->end();128} else if (mySelectRouteInvalids->getCheck() == TRUE) {129// begin undo list130undoList->begin(GUIIcon::ROUTE, TL("select invalid routes"));131// iterate over invalid single lane elements to select all elements132for (const auto& conflictedElement : myConflictedElements) {133conflictedElement.getElement()->setAttribute(GNE_ATTR_SELECTED, "true", undoList);134}135// end undo list136undoList->end();137// abort saving138return false;139}140// check if remove stops141if (myRemoveStopsOutOfRoute->getCheck() == TRUE) {142// get all stops to remove143std::vector<GNEDemandElement*> stopsToRemove;144for (const auto& conflictedElement : myConflictedElements) {145const auto invaldstops = conflictedElement.getElement()->getInvalidStops();146// append to stopsToRemove147stopsToRemove.insert(stopsToRemove.end(), invaldstops.begin(), invaldstops.end());148}149// begin undo list150undoList->begin(GUIIcon::STOP, TL("delete invalid stops"));151// remove all152for (const auto& stopToRemove : stopsToRemove) {153net->deleteDemandElement(stopToRemove, undoList);154}155// end undo list156undoList->end();157}158}159return true;160}161162163long164GNEFixDemandElementsDialog::FixRouteOptions::onCmdSelectOption(FXObject* obj, FXSelector, void*) {165if (obj == myRemoveInvalidRoutes) {166myRemoveInvalidRoutes->setCheck(true);167mySaveInvalidRoutes->setCheck(false);168mySelectRouteInvalids->setCheck(false);169} else if (obj == mySaveInvalidRoutes) {170myRemoveInvalidRoutes->setCheck(false);171mySaveInvalidRoutes->setCheck(true);172mySelectRouteInvalids->setCheck(false);173} else if (obj == mySelectRouteInvalids) {174myRemoveInvalidRoutes->setCheck(false);175mySaveInvalidRoutes->setCheck(false);176mySelectRouteInvalids->setCheck(true);177}178return 1;179}180181// ---------------------------------------------------------------------------182// GNEFixDemandElementsDialog::FixVehicleOptions - methods183// ---------------------------------------------------------------------------184185GNEFixDemandElementsDialog::FixVehicleOptions::FixVehicleOptions(GNEFixDemandElementsDialog* fixDemandElementsParent) :186FixOptions(fixDemandElementsParent, fixDemandElementsParent->myLeftFrame, TL("Vehicles")) {187// Remove invalid vehicles188myRemoveInvalidVehicles = GUIDesigns::buildFXRadioButton(myLeftFrameOptions,189TL("Remove invalid vehicles"), "",190TL("Remove invalid vehicles and save"),191this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);192// Save invalid vehicles193mySaveInvalidVehicles = GUIDesigns::buildFXRadioButton(myLeftFrameOptions,194TL("Save invalid vehicles"), "",195TL("Save invalid vehicles"),196this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);197// Select invalid vehicle198mySelectInvalidVehicles = GUIDesigns::buildFXRadioButton(myRightFrameOptions,199TL("Select invalid vehicles"), "",200TL("Select invalid vehicles and stop saving"),201this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);202// Remove stops out of route203myRemoveStopsOutOfVehicle = GUIDesigns::buildFXCheckButton(myRightFrameOptions,204TL("Remove stops out of route"), "",205TL("Remove stops out of vehicle's route"),206this, MID_CHOOSEN_OPERATION, GUIDesignCheckButtonFix);207// register options208registerOption(myRemoveInvalidVehicles);209registerOption(mySaveInvalidVehicles);210registerOption(mySelectInvalidVehicles);211registerOption(myRemoveStopsOutOfVehicle);212// by default remove invalid vehicles213myRemoveInvalidVehicles->setCheck(TRUE);214// ... and remove stops out of route215myRemoveStopsOutOfVehicle->setCheck(TRUE);216}217218219void220GNEFixDemandElementsDialog::FixVehicleOptions::selectInternalTestSolution(const std::string& /*solution*/) {221}222223224bool225GNEFixDemandElementsDialog::FixVehicleOptions::applyFixOption() {226if (myConflictedElements.size() > 0) {227auto net = myFixElementDialogParent->getApplicationWindow()->getViewNet()->getNet();228auto undoList = myFixElementDialogParent->getApplicationWindow()->getUndoList();229// continue depending of solution230if (myRemoveInvalidVehicles->getCheck() == TRUE) {231// begin undo list232undoList->begin(GUIIcon::VEHICLE, TL("delete invalid vehicles"));233// iterate over invalid vehicles to delete it234for (const auto& conflictedElement : myConflictedElements) {235// check that vehicle was not removed previously in cascade236if (net->getAttributeCarriers()->retrieveDemandElement(conflictedElement.getElement()->getTagProperty()->getTag(), conflictedElement.getID(), false) != nullptr) {237net->deleteDemandElement(conflictedElement.getElement(), undoList);238}239}240// end undo list241undoList->end();242} else if (mySelectInvalidVehicles->getCheck() == TRUE) {243// begin undo list244undoList->begin(GUIIcon::ROUTE, TL("select invalid routes"));245// iterate over invalid single lane elements to select all elements246for (const auto& conflictedElement : myConflictedElements) {247conflictedElement.getElement()->setAttribute(GNE_ATTR_SELECTED, "true", undoList);248}249// end undo list250undoList->end();251// abort saving252return false;253}254// check if remove stops255if (myRemoveStopsOutOfVehicle->getCheck() == TRUE) {256// get all stops to remove257std::vector<GNEDemandElement*> stopsToRemove;258for (const auto& conflictedElement : myConflictedElements) {259const auto invaldstops = conflictedElement.getElement()->getInvalidStops();260// append to stopsToRemove261stopsToRemove.insert(stopsToRemove.end(), invaldstops.begin(), invaldstops.end());262}263// begin undo list264undoList->begin(GUIIcon::STOP, TL("delete invalid stops"));265// remove all266for (const auto& stopToRemove : stopsToRemove) {267net->deleteDemandElement(stopToRemove, undoList);268}269// end undo list270undoList->end();271}272}273return true;274}275276277long278GNEFixDemandElementsDialog::FixVehicleOptions::onCmdSelectOption(FXObject* obj, FXSelector, void*) {279if (obj == myRemoveInvalidVehicles) {280myRemoveInvalidVehicles->setCheck(true);281mySaveInvalidVehicles->setCheck(false);282mySelectInvalidVehicles->setCheck(false);283} else if (obj == mySaveInvalidVehicles) {284myRemoveInvalidVehicles->setCheck(false);285mySaveInvalidVehicles->setCheck(true);286mySelectInvalidVehicles->setCheck(false);287} else if (obj == mySelectInvalidVehicles) {288myRemoveInvalidVehicles->setCheck(false);289mySaveInvalidVehicles->setCheck(false);290mySelectInvalidVehicles->setCheck(true);291}292return 1;293}294295// ---------------------------------------------------------------------------296// GNEFixDemandElementsDialog::FixStopPositionOptions - methods297// ---------------------------------------------------------------------------298299GNEFixDemandElementsDialog::FixStopPositionOptions::FixStopPositionOptions(GNEFixDemandElementsDialog* fixDemandElementsParent) :300FixOptions(fixDemandElementsParent, fixDemandElementsParent->myRightFrame, TL("Stop positions")) {301// Activate friendlyPos and save302myActivateFriendlyPosition = GUIDesigns::buildFXRadioButton(myLeftFrameOptions,303TL("Activate friendlyPos"), "",304TL("Activate friendlyPos and save"),305this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);306// Save invalid position307mySaveInvalid = GUIDesigns::buildFXRadioButton(myLeftFrameOptions,308TL("Save invalid stops"), "",309TL("Save elements with invalid positions"),310this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);311// Select invalid Stops312mySelectInvalidStops = GUIDesigns::buildFXRadioButton(myRightFrameOptions,313TL("Select conflicted stops"), "",314TL("Select conflicted stops and abort saving"),315this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);316// Fix positions and save317myFixPositions = GUIDesigns::buildFXRadioButton(myRightFrameOptions,318TL("Fix positions and save"), "",319TL("Fix stop positions and save"),320this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);321// register options322registerOption(myActivateFriendlyPosition);323registerOption(mySaveInvalid);324registerOption(mySelectInvalidStops);325registerOption(myFixPositions);326// leave option "activateFriendlyPositionAndSave" as default327myActivateFriendlyPosition->setCheck(true);328}329330331void332GNEFixDemandElementsDialog::FixStopPositionOptions::selectInternalTestSolution(const std::string& /*solution*/) {333}334335336bool337GNEFixDemandElementsDialog::FixStopPositionOptions::applyFixOption() {338// check options for stops339if (myConflictedElements.size() > 0) {340auto undoList = myFixElementDialogParent->getApplicationWindow()->getUndoList();341// continue depending of solution342if (myActivateFriendlyPosition->getCheck() == TRUE) {343// begin undo list344undoList->begin(GUIIcon::STOP, TLF("change % of invalid stops", toString(SUMO_ATTR_FRIENDLY_POS)));345// iterate over invalid stops to enable friendly position346for (const auto& conflictedElement : myConflictedElements) {347conflictedElement.getElement()->setAttribute(SUMO_ATTR_FRIENDLY_POS, "true", undoList);348}349undoList->end();350} else if (myFixPositions->getCheck() == TRUE) {351undoList->begin(GUIIcon::STOP, TL("fix positions of invalid stops"));352// iterate over invalid stops to fix positions353for (const auto& conflictedElement : myConflictedElements) {354conflictedElement.getElement()->fixDemandElementProblem();355}356undoList->end();357} else if (mySelectInvalidStops->getCheck() == TRUE) {358undoList->begin(GUIIcon::STOP, TL("select invalid stops"));359// iterate over invalid stops to select all elements360for (const auto& conflictedElement : myConflictedElements) {361conflictedElement.getElement()->setAttribute(GNE_ATTR_SELECTED, "true", undoList);362}363// end undo list364undoList->end();365// abort saving366return false;367}368}369return true;370}371372373long374GNEFixDemandElementsDialog::FixStopPositionOptions::onCmdSelectOption(FXObject* obj, FXSelector, void*) {375if (obj == myActivateFriendlyPosition) {376myActivateFriendlyPosition->setCheck(true);377myFixPositions->setCheck(false);378mySaveInvalid->setCheck(false);379mySelectInvalidStops->setCheck(false);380} else if (obj == myFixPositions) {381myActivateFriendlyPosition->setCheck(false);382myFixPositions->setCheck(true);383mySaveInvalid->setCheck(false);384mySelectInvalidStops->setCheck(false);385} else if (obj == mySaveInvalid) {386myActivateFriendlyPosition->setCheck(false);387myFixPositions->setCheck(false);388mySaveInvalid->setCheck(true);389mySelectInvalidStops->setCheck(false);390} else if (obj == mySelectInvalidStops) {391myActivateFriendlyPosition->setCheck(false);392myFixPositions->setCheck(false);393mySaveInvalid->setCheck(false);394mySelectInvalidStops->setCheck(true);395}396return 1;397}398399// ---------------------------------------------------------------------------400// GNEFixDemandElementsDialog::FixPlanOptions - methods401// ---------------------------------------------------------------------------402403GNEFixDemandElementsDialog::FixPlanOptions::FixPlanOptions(GNEFixDemandElementsDialog* fixDemandElementsParent) :404FixOptions(fixDemandElementsParent, fixDemandElementsParent->myRightFrame, TL("Person/container plans")) {405// Delete person plan406myRemoveInvalidPlan = GUIDesigns::buildFXRadioButton(myLeftFrameOptions,407TL("Remove invalid plans"), "",408TL("Remove invalid plans"),409this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);410// Save invalid person plans411mySaveInvalid = GUIDesigns::buildFXRadioButton(myLeftFrameOptions,412TL("Save invalid plans"), "",413TL("Save invalid plans"),414this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);415// Select invalid person plans416mySelectInvalidPlans = GUIDesigns::buildFXRadioButton(myRightFrameOptions,417TL("Select conflicted plans"), "",418TL("Select conflicted plans and abort saving"),419this, MID_CHOOSEN_OPERATION, GUIDesignRadioButtonFix);420// register options421registerOption(myRemoveInvalidPlan);422registerOption(mySaveInvalid);423registerOption(mySelectInvalidPlans);424// set option "activateFriendlyPositionAndSave" as default425myRemoveInvalidPlan->setCheck(true);426}427428429void430GNEFixDemandElementsDialog::FixPlanOptions::selectInternalTestSolution(const std::string& /*solution*/) {431}432433434bool435GNEFixDemandElementsDialog::FixPlanOptions::applyFixOption() {436// check options for person plans437if (myConflictedElements.size() > 0) {438auto net = myFixElementDialogParent->getApplicationWindow()->getViewNet()->getNet();439auto undoList = myFixElementDialogParent->getApplicationWindow()->getUndoList();440// continue depending of solution441if (myRemoveInvalidPlan->getCheck() == TRUE) {442// begin undo list443undoList->begin(GUIIcon::MODEPERSONPLAN, TL("delete invalid person plans"));444// remove all invalid person plans445for (const auto& conflictedElement : myConflictedElements) {446net->deleteDemandElement(conflictedElement.getElement(), undoList);447}448undoList->end();449} else if (mySelectInvalidPlans->getCheck() == TRUE) {450undoList->begin(GUIIcon::MODEPERSONPLAN, TL("select invalid person plans"));451// iterate over invalid person plans to select all elements452for (const auto& conflictedElement : myConflictedElements) {453conflictedElement.getElement()->setAttribute(GNE_ATTR_SELECTED, "true", undoList);454}455// end undo list456undoList->end();457// abort saving458return false;459}460}461return true;462}463464465long466GNEFixDemandElementsDialog::FixPlanOptions::onCmdSelectOption(FXObject* obj, FXSelector, void*) {467if (obj == myRemoveInvalidPlan) {468myRemoveInvalidPlan->setCheck(true);469mySaveInvalid->setCheck(false);470mySelectInvalidPlans->setCheck(false);471} else if (obj == mySaveInvalid) {472myRemoveInvalidPlan->setCheck(false);473mySaveInvalid->setCheck(true);474mySelectInvalidPlans->setCheck(false);475} else if (obj == mySelectInvalidPlans) {476myRemoveInvalidPlan->setCheck(false);477mySaveInvalid->setCheck(false);478mySelectInvalidPlans->setCheck(true);479}480return true;481}482483// ---------------------------------------------------------------------------484// GNEFixDemandElementsDialog - methods485// ---------------------------------------------------------------------------486487GNEFixDemandElementsDialog::GNEFixDemandElementsDialog(GNEApplicationWindow* mainWindow,488const std::vector<GNEDemandElement*>& elements) :489GNEFixElementsDialog(mainWindow, TL("Fix demand elements problems"), GUIIcon::SUPERMODEDEMAND,490DialogType::FIX_DEMANDELEMENTS) {491// create fix route options492myFixRouteOptions = new FixRouteOptions(this);493// create fix vehicle options494myFixVehicleOptions = new FixVehicleOptions(this);495// create fix stops options496myFixStopPositionOptions = new FixStopPositionOptions(this);497// create fix person plans options498myFixPlanOptions = new FixPlanOptions(this);499// split invalidDemandElements in four groups500std::vector<ConflictElement> invalidRoutes, invalidVehicles, invalidStops, invalidPlans;501// fill groups502for (const auto& invalidDemandElement : elements) {503// create conflict element504auto fixElement = ConflictElement(invalidDemandElement,505invalidDemandElement->getID(),506invalidDemandElement->getACIcon(),507invalidDemandElement->getDemandElementProblem());508// add depending of element type509if (invalidDemandElement->getTagProperty()->isRoute()) {510invalidRoutes.push_back(fixElement);511} else if (invalidDemandElement->getTagProperty()->isVehicle()) {512invalidVehicles.push_back(fixElement);513} else if (invalidDemandElement->getTagProperty()->isVehicleStop()) {514invalidStops.push_back(fixElement);515} else {516invalidPlans.push_back(fixElement);517}518}519// fill options520myFixRouteOptions->setInvalidElements(invalidRoutes);521myFixVehicleOptions->setInvalidElements(invalidVehicles);522myFixStopPositionOptions->setInvalidElements(invalidStops);523myFixPlanOptions->setInvalidElements(invalidPlans);524// open modal dialog525openDialog();526}527528529GNEFixDemandElementsDialog::~GNEFixDemandElementsDialog() {530}531532/****************************************************************************/533534535