Path: blob/main/src/netedit/elements/demand/GNERouteHandler.cpp
185790 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 GNERouteHandler.cpp14/// @author Pablo Alvarez Lopez15/// @date Jan 201916///17// Builds demand objects for netedit18/****************************************************************************/1920#include <netedit/changes/GNEChange_DemandElement.h>21#include <netedit/dialogs/basic/GNEOverwriteElement.h>22#include <netedit/dialogs/basic/GNEWarningBasicDialog.h>23#include <netedit/frames/common/GNEInspectorFrame.h>24#include <netedit/frames/GNEAttributesEditor.h>25#include <netedit/GNEApplicationWindow.h>26#include <netedit/GNENet.h>27#include <netedit/GNEUndoList.h>28#include <netedit/GNEViewParent.h>29#include <utils/xml/NamespaceIDs.h>3031#include "GNEContainer.h"32#include "GNEPerson.h"33#include "GNEPersonTrip.h"34#include "GNERide.h"35#include "GNERoute.h"36#include "GNERouteRef.h"37#include "GNERouteDistribution.h"38#include "GNERouteHandler.h"39#include "GNEStop.h"40#include "GNEStopPlan.h"41#include "GNETranship.h"42#include "GNETransport.h"43#include "GNEVType.h"44#include "GNEVTypeRef.h"45#include "GNEVTypeDistribution.h"46#include "GNEVehicle.h"47#include "GNEWalk.h"484950// ===========================================================================51// member method definitions52// ===========================================================================5354GNERouteHandler::GNERouteHandler(GNENet* net, FileBucket* bucket, const bool allowUndoRedo, const bool removeEmptyPersons) :55RouteHandler(bucket, false),56myNet(net),57myPlanObject(new CommonXMLStructure::SumoBaseObject(nullptr)),58myAllowUndoRedo(allowUndoRedo),59myRemoveEmptyPersons(removeEmptyPersons) {60}616263GNERouteHandler::~GNERouteHandler() {64// check if clear all parent plan elements without children65if (myRemoveEmptyPersons) {66for (const auto& parentPlanElement : myParentPlanElements) {67if (parentPlanElement->getChildDemandElements().empty()) {68if (myAllowUndoRedo) {69myNet->getUndoList()->begin(parentPlanElement, TLF("delete % '%'", parentPlanElement->getTagStr(), parentPlanElement->getID()));70myNet->getUndoList()->add(new GNEChange_DemandElement(parentPlanElement, false), true);71myNet->getUndoList()->end();72} else {73parentPlanElement->decRef("postParserTasks");74myNet->getAttributeCarriers()->deleteDemandElement(parentPlanElement, false);75}76}77}78}79// update options based in current buckets80myNet->getGNEApplicationWindow()->getFileBucketHandler()->updateOptions();81// delete plan object82delete myPlanObject;83}8485bool86GNERouteHandler::buildVType(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const SUMOVTypeParameter& vTypeParameter) {87// check if loaded type is a default type88if (DEFAULT_VTYPES.count(vTypeParameter.id) > 0) {89// overwrite default vehicle type90return GNEVType::overwriteVType(myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, vTypeParameter.id, false), vTypeParameter, myNet->getUndoList());91} else {92const auto element = retrieveDemandElement(NamespaceIDs::types, vTypeParameter.id);93if (!checkElement(SUMO_TAG_VTYPE, element)) {94return false;95} else if (!checkValidDemandElementID(SUMO_TAG_VTYPE, vTypeParameter.id)) {96return false;97} else {98// create vType/pType using myCurrentVType99GNEDemandElement* vType = new GNEVType(myNet, myFileBucket, vTypeParameter);100// if this vType was created within a vType distribution, we have to create an extra vTypeRef101GNEDemandElement* vTypeRef = nullptr;102GNEDemandElement* distributionParent = nullptr;103if (sumoBaseObject && sumoBaseObject->getParentSumoBaseObject() && (sumoBaseObject->getParentSumoBaseObject()->getTag() == SUMO_TAG_VTYPE_DISTRIBUTION)) {104const auto& vTypeDistributionID = sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID);105distributionParent = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE_DISTRIBUTION, vTypeDistributionID, false);106if (distributionParent) {107// create vType reference without probability108vTypeRef = new GNEVTypeRef(distributionParent, vType);109} else {110WRITE_WARNING(TLF("VType '%' with probability % cannot be referenced with distribution '%'", vTypeParameter.id, toString(vTypeParameter.defaultProbability), vTypeDistributionID));111}112}113if (myAllowUndoRedo) {114myNet->getUndoList()->begin(vType, TLF("add % '%'", vType->getTagStr(), vTypeParameter.id));115myNet->getUndoList()->add(new GNEChange_DemandElement(vType, true), true);116if (vTypeRef) {117myNet->getUndoList()->add(new GNEChange_DemandElement(vTypeRef, true), true);118}119myNet->getUndoList()->end();120} else {121myNet->getAttributeCarriers()->insertDemandElement(vType);122if (vTypeRef) {123distributionParent->addChildElement(vTypeRef);124vType->addChildElement(vTypeRef);125}126vType->incRef("buildVType");127}128return true;129}130}131}132133134bool135GNERouteHandler::buildVTypeRef(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& vTypeID, const double probability) {136const auto distribution = getVTypeDistributionParent(sumoBaseObject);137// the referenced element can be either a vType or a vTypeDistribution138const auto refElement = myNet->getAttributeCarriers()->retrieveDemandElements({SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vTypeID, false);139// check distributions140if (distribution == nullptr) {141return writeErrorInvalidParent(GNE_TAG_VTYPEREF, {SUMO_TAG_VTYPE_DISTRIBUTION});142} else if (refElement) {143// create distributions144GNEDemandElement* vTypeRef = new GNEVTypeRef(distribution, refElement, probability);145if (myAllowUndoRedo) {146myNet->getUndoList()->begin(vTypeRef, TLF("add % '%'", vTypeRef->getTagStr(), distribution->getID()));147myNet->getUndoList()->add(new GNEChange_DemandElement(vTypeRef, true), true);148myNet->getUndoList()->end();149} else {150myNet->getAttributeCarriers()->insertDemandElement(vTypeRef);151distribution->addChildElement(vTypeRef);152refElement->addChildElement(vTypeRef);153vTypeRef->incRef("buildVTypeRef");154}155return true;156} else {157return writeErrorInvalidParent(GNE_TAG_VTYPEREF, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vTypeID);158}159}160161162bool163GNERouteHandler::buildVTypeDistribution(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, const int deterministic) {164// check conditions165const auto element = retrieveDemandElement(NamespaceIDs::types, id);166if (!checkElement(SUMO_TAG_VTYPE_DISTRIBUTION, element)) {167return false;168} else if (!checkValidDemandElementID(SUMO_TAG_VTYPE_DISTRIBUTION, id)) {169return false;170} else {171// create distributions172GNEVTypeDistribution* vTypeDistribution = new GNEVTypeDistribution(id, myNet, myFileBucket, deterministic);173if (myAllowUndoRedo) {174myNet->getUndoList()->begin(vTypeDistribution, TLF("add % '%'", vTypeDistribution->getTagStr(), id));175myNet->getUndoList()->add(new GNEChange_DemandElement(vTypeDistribution, true), true);176myNet->getUndoList()->end();177} else {178myNet->getAttributeCarriers()->insertDemandElement(vTypeDistribution);179vTypeDistribution->incRef("buildVTypeDistribution");180}181return true;182}183}184185186bool187GNERouteHandler::buildRoute(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& id, SUMOVehicleClass vClass,188const std::vector<std::string>& edgeIDs, const RGBColor& color, const int repeat, const SUMOTime cycleTime,189const double probability, const Parameterised::Map& routeParameters) {190// check conditions191const auto element = retrieveDemandElement(NamespaceIDs::routes, id);192if (!checkElement(SUMO_TAG_ROUTE, element)) {193return false;194} else if (!checkValidDemandElementID(SUMO_TAG_ROUTE, id)) {195return false;196} else if (!checkNegative(SUMO_TAG_ROUTE, id, SUMO_ATTR_REPEAT, repeat, true)) {197return false;198} else {199// parse edges200const auto edges = parseEdges(SUMO_TAG_ROUTE, id, edgeIDs);201// check edges202const auto validEdges = GNERoute::isRouteValid(edges);203// continue depending if route is valid204if (validEdges.size() > 0) {205return writeError(TLF("Could not build % with ID '%' in netedit; %.", toString(SUMO_TAG_ROUTE), id, validEdges));206} else {207// create GNERoute208GNEDemandElement* route = new GNERoute(id, myNet, myFileBucket, vClass, edges, color, repeat, cycleTime, probability, routeParameters);209// if this route was created within a route distribution, we have to create an extra routeRef210GNEDemandElement* routeRef = nullptr;211GNEDemandElement* distributionParent = nullptr;212if (sumoBaseObject && sumoBaseObject->getParentSumoBaseObject() && (sumoBaseObject->getParentSumoBaseObject()->getTag() == SUMO_TAG_ROUTE_DISTRIBUTION)) {213const auto& routeDistributionID = sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID);214distributionParent = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_ROUTE_DISTRIBUTION, routeDistributionID, false);215if (distributionParent) {216// create route reference without probability217routeRef = new GNERouteRef(distributionParent, route);218} else {219WRITE_WARNING(TLF("Route '%' with probability % cannot be referenced with distribution '%'", id, toString(probability), routeDistributionID));220}221}222if (myAllowUndoRedo) {223myNet->getUndoList()->begin(route, TLF("add % '%'", route->getTagStr(), id));224myNet->getUndoList()->add(new GNEChange_DemandElement(route, true), true);225if (routeRef) {226myNet->getUndoList()->add(new GNEChange_DemandElement(routeRef, true), true);227}228myNet->getUndoList()->end();229} else {230myNet->getAttributeCarriers()->insertDemandElement(route);231for (const auto& edge : edges) {232edge->addChildElement(route);233}234if (routeRef) {235distributionParent->addChildElement(routeRef);236route->addChildElement(routeRef);237}238route->incRef("buildRoute");239}240return true;241}242}243244}245246247bool248GNERouteHandler::buildRouteRef(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& routeID, const double probability) {249const auto distribution = getRouteDistributionParent(sumoBaseObject);250// the referenced element can be either a route or a routeDistribution251const auto refElement = myNet->getAttributeCarriers()->retrieveDemandElements({SUMO_TAG_ROUTE, SUMO_TAG_ROUTE_DISTRIBUTION}, routeID, false);252// check distributions253if (distribution == nullptr) {254return writeErrorInvalidParent(GNE_TAG_ROUTEREF, {SUMO_TAG_ROUTE_DISTRIBUTION});255} else if (refElement) {256// create distributions257GNEDemandElement* routeRef = new GNERouteRef(distribution, refElement, probability);258if (myAllowUndoRedo) {259myNet->getUndoList()->begin(routeRef, TLF("add % in '%'", routeRef->getTagStr(), distribution->getID()));260myNet->getUndoList()->add(new GNEChange_DemandElement(routeRef, true), true);261myNet->getUndoList()->end();262} else {263myNet->getAttributeCarriers()->insertDemandElement(routeRef);264distribution->addChildElement(routeRef);265refElement->addChildElement(routeRef);266routeRef->incRef("buildRouteRef");267}268return true;269} else {270return writeErrorInvalidParent(GNE_TAG_ROUTEREF, {SUMO_TAG_ROUTE, SUMO_TAG_ROUTE_DISTRIBUTION}, routeID);271}272}273274275bool276GNERouteHandler::buildRouteDistribution(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id) {277// check conditions278const auto element = retrieveDemandElement(NamespaceIDs::routes, id);279if (!checkElement(SUMO_TAG_ROUTE_DISTRIBUTION, element)) {280return false;281} else if (!checkValidDemandElementID(SUMO_TAG_ROUTE_DISTRIBUTION, id)) {282return false;283} else {284// create distributions285GNERouteDistribution* routeDistribution = new GNERouteDistribution(id, myNet, myFileBucket);286if (myAllowUndoRedo) {287myNet->getUndoList()->begin(routeDistribution, TLF("add % '%'", routeDistribution->getTagStr(), id));288myNet->getUndoList()->add(new GNEChange_DemandElement(routeDistribution, true), true);289myNet->getUndoList()->end();290} else {291myNet->getAttributeCarriers()->insertDemandElement(routeDistribution);292routeDistribution->incRef("buildRouteDistribution");293}294return true;295}296}297298299bool300GNERouteHandler::buildVehicleOverRoute(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters) {301// check conditions302const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);303if (!checkElement(SUMO_TAG_VEHICLE, element)) {304return false;305} else if (!checkValidDemandElementID(SUMO_TAG_VEHICLE, vehicleParameters.id)) {306return false;307} else {308// obtain routes and vtypes309GNEDemandElement* type = getType(vehicleParameters.vtypeid);310GNEDemandElement* route = getRoute(vehicleParameters.routeid);311if (type == nullptr) {312return writeErrorInvalidParent(SUMO_TAG_VEHICLE, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);313} else if (route == nullptr) {314return writeErrorInvalidParent(SUMO_TAG_VEHICLE, vehicleParameters.id, {SUMO_TAG_ROUTE, SUMO_TAG_ROUTE_DISTRIBUTION}, vehicleParameters.routeid);315} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && (vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN) && ((int)route->getParentEdges().front()->getChildLanes().size() < vehicleParameters.departLane)) {316return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));317} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {318return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));319} else {320// create vehicle using vehicleParameters321GNEDemandElement* vehicle = new GNEVehicle(SUMO_TAG_VEHICLE, myNet, myFileBucket, type, route, vehicleParameters);322if (myAllowUndoRedo) {323myNet->getUndoList()->begin(vehicle, TLF("add % '%'", vehicle->getTagStr(), vehicleParameters.id));324myNet->getUndoList()->add(new GNEChange_DemandElement(vehicle, true), true);325myNet->getUndoList()->end();326} else {327myNet->getAttributeCarriers()->insertDemandElement(vehicle);328// set vehicle as child of type and Route329type->addChildElement(vehicle);330route->addChildElement(vehicle);331vehicle->incRef("buildVehicleOverRoute");332}333return true;334}335}336}337338339bool340GNERouteHandler::buildVehicleEmbeddedRoute(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,341const std::vector<std::string>& edgeIDs, const RGBColor& color, const int repeat, const SUMOTime cycleTime,342const Parameterised::Map& routeParameters) {343// check conditions344const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);345if (!checkElement(GNE_TAG_VEHICLE_WITHROUTE, element)) {346return false;347} else if (!checkValidDemandElementID(GNE_TAG_VEHICLE_WITHROUTE, vehicleParameters.id)) {348return false;349} else {350// parse route edges351const auto edges = parseEdges(GNE_TAG_ROUTE_EMBEDDED, vehicleParameters.id, edgeIDs);352// check edges353const auto validEdges = GNERoute::isRouteValid(edges);354// continue depending if route is valid355if (validEdges.size() > 0) {356return writeError(TLF("Could not build % with ID '%' in netedit; %.", toString(GNE_TAG_VEHICLE_WITHROUTE), vehicleParameters.id, validEdges));357} else {358// obtain type359GNEDemandElement* type = getType(vehicleParameters.vtypeid);360if (type == nullptr) {361return writeErrorInvalidParent(GNE_TAG_VEHICLE_WITHROUTE, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);362} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && (vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN) && ((int)edges.front()->getChildLanes().size() < vehicleParameters.departLane)) {363return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));364} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {365return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));366} else {367// create vehicle using vehicleParameters368GNEDemandElement* vehicle = new GNEVehicle(GNE_TAG_VEHICLE_WITHROUTE, myNet, myFileBucket, type, vehicleParameters);369// create embedded route370GNEDemandElement* route = new GNERoute(vehicle, edges, color, repeat, cycleTime, routeParameters);371if (myAllowUndoRedo) {372myNet->getUndoList()->begin(vehicle, TLF("add % '%'", vehicle->getTagStr(), vehicleParameters.id));373myNet->getUndoList()->add(new GNEChange_DemandElement(vehicle, true), true);374myNet->getUndoList()->add(new GNEChange_DemandElement(route, true), true);375myNet->getUndoList()->end();376} else {377myNet->getAttributeCarriers()->insertDemandElement(vehicle);378myNet->getAttributeCarriers()->insertDemandElement(route);379type->addChildElement(vehicle);380vehicle->addChildElement(route);381for (const auto& edge : edges) {382edge->addChildElement(route);383}384vehicle->incRef("buildVehicleEmbeddedRoute");385route->incRef("buildVehicleEmbeddedRoute");386}387return true;388}389}390}391}392393394bool395GNERouteHandler::buildFlowOverRoute(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters) {396// check conditions397const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);398if (!checkElement(GNE_TAG_FLOW_ROUTE, element)) {399return false;400} else if (!checkValidDemandElementID(GNE_TAG_FLOW_ROUTE, vehicleParameters.id)) {401return false;402} else {403// obtain routes and vtypes404GNEDemandElement* type = getType(vehicleParameters.vtypeid);405GNEDemandElement* route = getRoute(vehicleParameters.routeid);406if (type == nullptr) {407return writeErrorInvalidParent(SUMO_TAG_VEHICLE, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);408} else if (route == nullptr) {409return writeErrorInvalidParent(SUMO_TAG_VEHICLE, vehicleParameters.id, {SUMO_TAG_ROUTE, SUMO_TAG_ROUTE_DISTRIBUTION}, vehicleParameters.routeid);410} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && (vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN) && ((int)route->getParentEdges().front()->getChildLanes().size() < vehicleParameters.departLane)) {411return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));412} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {413return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));414} else {415// create flow or trips using vehicleParameters416GNEDemandElement* flow = new GNEVehicle(GNE_TAG_FLOW_ROUTE, myNet, myFileBucket, type, route, vehicleParameters);417if (myAllowUndoRedo) {418myNet->getUndoList()->begin(flow, TLF("add % '%'", flow->getTagStr(), vehicleParameters.id));419myNet->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);420myNet->getUndoList()->end();421} else {422myNet->getAttributeCarriers()->insertDemandElement(flow);423// set flow as child of type and Route424type->addChildElement(flow);425route->addChildElement(flow);426flow->incRef("buildFlowOverRoute");427}428return true;429}430}431}432433434bool435GNERouteHandler::buildFlowEmbeddedRoute(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,436const std::vector<std::string>& edgeIDs, const RGBColor& color, const int repeat, const SUMOTime cycleTime,437const Parameterised::Map& routeParameters) {438// check conditions439const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);440if (!checkElement(GNE_TAG_FLOW_WITHROUTE, element)) {441return false;442} else if (!checkValidDemandElementID(GNE_TAG_FLOW_WITHROUTE, vehicleParameters.id)) {443return false;444} else {445// parse route edges446const auto edges = parseEdges(GNE_TAG_FLOW_WITHROUTE, vehicleParameters.id, edgeIDs);447// check edges448const auto validEdges = GNERoute::isRouteValid(edges);449// continue depending if route is valid450if (validEdges.size() > 0) {451return writeError(TLF("Could not build % with ID '%' in netedit; %.", toString(GNE_TAG_FLOW_WITHROUTE), vehicleParameters.id, validEdges));452} else {453// obtain type454GNEDemandElement* type = getType(vehicleParameters.vtypeid);455if (type == nullptr) {456return writeErrorInvalidParent(GNE_TAG_FLOW_WITHROUTE, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);457} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && (vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN) && ((int)edges.front()->getChildLanes().size() < vehicleParameters.departLane)) {458return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));459} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {460return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));461} else {462// create vehicle using vehicleParameters463GNEDemandElement* vehicle = new GNEVehicle(GNE_TAG_FLOW_WITHROUTE, myNet, myFileBucket, type, vehicleParameters);464// create embedded route465GNEDemandElement* route = new GNERoute(vehicle, edges, color, repeat, cycleTime, routeParameters);466if (myAllowUndoRedo) {467myNet->getUndoList()->begin(vehicle, TLF("add % '%'", vehicle->getTagStr(), vehicleParameters.id));468myNet->getUndoList()->add(new GNEChange_DemandElement(vehicle, true), true);469myNet->getUndoList()->add(new GNEChange_DemandElement(route, true), true);470myNet->getUndoList()->end();471} else {472myNet->getAttributeCarriers()->insertDemandElement(vehicle);473myNet->getAttributeCarriers()->insertDemandElement(route);474type->addChildElement(vehicle);475vehicle->addChildElement(route);476for (const auto& edge : edges) {477edge->addChildElement(route);478}479vehicle->incRef("buildFlowEmbeddedRoute");480route->incRef("buildFlowEmbeddedRoute");481}482return true;483}484}485}486}487488489bool490GNERouteHandler::buildTrip(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const SUMOVehicleParameter& vehicleParameters,491const std::string& fromEdgeID, const std::string& toEdgeID) {492// check conditions493const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);494if (!checkElement(SUMO_TAG_TRIP, element)) {495return false;496} else if (!checkValidDemandElementID(SUMO_TAG_TRIP, vehicleParameters.id)) {497return false;498} else {499// set via attribute500if (sumoBaseObject && sumoBaseObject->hasStringListAttribute(SUMO_ATTR_VIA)) {501vehicleParameters.via = sumoBaseObject->getStringListAttribute(SUMO_ATTR_VIA);502}503// parse edges504const auto fromEdge = parseEdge(SUMO_TAG_TRIP, vehicleParameters.id, fromEdgeID, sumoBaseObject, true);505const auto toEdge = parseEdge(SUMO_TAG_TRIP, vehicleParameters.id, toEdgeID, sumoBaseObject, false);506if (!fromEdge || !toEdge) {507return false;508} else {509// obtain type510GNEDemandElement* type = getType(vehicleParameters.vtypeid);511if (type == nullptr) {512return writeErrorInvalidParent(SUMO_TAG_TRIP, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);513} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && ((vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN)) && ((int)fromEdge->getChildLanes().size() < vehicleParameters.departLane)) {514return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));515} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {516return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));517} else if (!checkViaAttribute(SUMO_TAG_TRIP, vehicleParameters.id, vehicleParameters.via)) {518return false;519} else {520// create trip or flow using tripParameters521GNEDemandElement* trip = new GNEVehicle(SUMO_TAG_TRIP, myNet, myFileBucket, type, fromEdge, toEdge, vehicleParameters);522if (myAllowUndoRedo) {523myNet->getUndoList()->begin(trip, TLF("add % '%'", trip->getTagStr(), vehicleParameters.id));524myNet->getUndoList()->add(new GNEChange_DemandElement(trip, true), true);525myNet->getUndoList()->end();526} else {527myNet->getAttributeCarriers()->insertDemandElement(trip);528// set vehicle as child of type529type->addChildElement(trip);530trip->incRef("buildTrip");531// add reference in all edges532fromEdge->addChildElement(trip);533toEdge->addChildElement(trip);534}535return true;536}537}538}539}540541542bool543GNERouteHandler::buildTripJunctions(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,544const std::string& fromJunctionID, const std::string& toJunctionID) {545// check conditions546const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);547if (!checkElement(GNE_TAG_TRIP_JUNCTIONS, element)) {548return false;549} else if (!checkValidDemandElementID(GNE_TAG_TRIP_JUNCTIONS, vehicleParameters.id)) {550return false;551} else {552// parse junctions553const auto fromJunction = parseJunction(GNE_TAG_TRIP_JUNCTIONS, vehicleParameters.id, fromJunctionID);554const auto toJunction = parseJunction(GNE_TAG_TRIP_JUNCTIONS, vehicleParameters.id, toJunctionID);555if (!fromJunction || !toJunction) {556return false;557} else {558// obtain type559GNEDemandElement* type = getType(vehicleParameters.vtypeid);560if (type == nullptr) {561return writeErrorInvalidParent(GNE_TAG_TRIP_JUNCTIONS, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);562} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && ((vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN)) && (vehicleParameters.departLane > 0)) {563return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));564} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {565return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));566} else {567// create trip using vehicleParameters568GNEDemandElement* flow = new GNEVehicle(GNE_TAG_TRIP_JUNCTIONS, myNet, myFileBucket, type, fromJunction, toJunction, vehicleParameters);569if (myAllowUndoRedo) {570myNet->getUndoList()->begin(flow, TLF("add % '%'", flow->getTagStr(), vehicleParameters.id));571myNet->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);572myNet->getUndoList()->end();573} else {574myNet->getAttributeCarriers()->insertDemandElement(flow);575// set vehicle as child of type576type->addChildElement(flow);577flow->incRef("buildFlow");578// add reference in all junctions579fromJunction->addChildElement(flow);580toJunction->addChildElement(flow);581}582return true;583}584}585}586}587588589bool590GNERouteHandler::buildTripTAZs(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,591const std::string& fromTAZID, const std::string& toTAZID) {592// check conditions593const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);594if (!checkElement(GNE_TAG_TRIP_TAZS, element)) {595return false;596} else if (!checkValidDemandElementID(GNE_TAG_TRIP_TAZS, vehicleParameters.id)) {597return false;598} else {599// parse TAZs600const auto fromTAZ = parseTAZ(GNE_TAG_TRIP_TAZS, vehicleParameters.id, fromTAZID);601const auto toTAZ = parseTAZ(GNE_TAG_TRIP_TAZS, vehicleParameters.id, toTAZID);602if (!fromTAZ || !toTAZ) {603return false;604} else {605// obtain type606GNEDemandElement* type = getType(vehicleParameters.vtypeid);607if (type == nullptr) {608return writeErrorInvalidParent(GNE_TAG_TRIP_TAZS, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);609} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && ((vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN)) && (vehicleParameters.departLane > 0)) {610return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));611} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {612return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));613} else {614// create trip using vehicleParameters615GNEDemandElement* flow = new GNEVehicle(GNE_TAG_TRIP_TAZS, myNet, myFileBucket, type, fromTAZ, toTAZ, vehicleParameters);616if (myAllowUndoRedo) {617myNet->getUndoList()->begin(flow, TLF("add % '%'", flow->getTagStr(), vehicleParameters.id));618myNet->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);619myNet->getUndoList()->end();620} else {621myNet->getAttributeCarriers()->insertDemandElement(flow);622// set vehicle as child of type623type->addChildElement(flow);624flow->incRef("buildFlow");625// add reference in all TAZs626fromTAZ->addChildElement(flow);627toTAZ->addChildElement(flow);628}629return true;630}631}632}633}634635636bool637GNERouteHandler::buildFlow(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const SUMOVehicleParameter& vehicleParameters,638const std::string& fromEdgeID, const std::string& toEdgeID) {639// check conditions640const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);641if (!checkElement(SUMO_TAG_FLOW, element)) {642return false;643} else if (!checkValidDemandElementID(SUMO_TAG_FLOW, vehicleParameters.id)) {644return false;645} else {646// set via attribute647if (sumoBaseObject && sumoBaseObject->hasStringListAttribute(SUMO_ATTR_VIA)) {648vehicleParameters.via = sumoBaseObject->getStringListAttribute(SUMO_ATTR_VIA);649}650// parse edges651const auto fromEdge = parseEdge(SUMO_TAG_FLOW, vehicleParameters.id, fromEdgeID, sumoBaseObject, true);652const auto toEdge = parseEdge(SUMO_TAG_FLOW, vehicleParameters.id, toEdgeID, sumoBaseObject, false);653if (!fromEdge || !toEdge) {654return false;655} else {656// obtain type657GNEDemandElement* type = getType(vehicleParameters.vtypeid);658if (type == nullptr) {659return writeErrorInvalidParent(SUMO_TAG_FLOW, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);660} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && (vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN) && ((int)fromEdge->getChildLanes().size() < vehicleParameters.departLane)) {661return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));662} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {663return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));664} else if (!checkViaAttribute(SUMO_TAG_FLOW, vehicleParameters.id, vehicleParameters.via)) {665return false;666} else {667// create trip or flow using tripParameters668GNEDemandElement* flow = new GNEVehicle(SUMO_TAG_FLOW, myNet, myFileBucket, type, fromEdge, toEdge, vehicleParameters);669if (myAllowUndoRedo) {670myNet->getUndoList()->begin(flow, TLF("add % '%'", flow->getTagStr(), vehicleParameters.id));671myNet->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);672myNet->getUndoList()->end();673} else {674myNet->getAttributeCarriers()->insertDemandElement(flow);675// set vehicle as child of type676type->addChildElement(flow);677flow->incRef("buildFlow");678// add reference in all edges679fromEdge->addChildElement(flow);680toEdge->addChildElement(flow);681}682return true;683}684}685}686}687688689bool690GNERouteHandler::buildFlowJunctions(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,691const std::string& fromJunctionID, const std::string& toJunctionID) {692// check conditions693const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);694if (!checkElement(GNE_TAG_FLOW_JUNCTIONS, element)) {695return false;696} else if (!checkValidDemandElementID(GNE_TAG_FLOW_JUNCTIONS, vehicleParameters.id)) {697return false;698} else {699// parse junctions700const auto fromJunction = parseJunction(GNE_TAG_FLOW_JUNCTIONS, vehicleParameters.id, fromJunctionID);701const auto toJunction = parseJunction(GNE_TAG_FLOW_JUNCTIONS, vehicleParameters.id, toJunctionID);702if (!fromJunction || !toJunction) {703return false;704} else {705// obtain type706GNEDemandElement* type = getType(vehicleParameters.vtypeid);707if (type == nullptr) {708return writeErrorInvalidParent(GNE_TAG_FLOW_JUNCTIONS, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);709} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && ((vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN)) && (vehicleParameters.departLane > 0)) {710return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));711} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {712return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));713} else {714// create flow using vehicleParameters715GNEDemandElement* flow = new GNEVehicle(GNE_TAG_FLOW_JUNCTIONS, myNet, myFileBucket, type, fromJunction, toJunction, vehicleParameters);716if (myAllowUndoRedo) {717myNet->getUndoList()->begin(flow, TLF("add % '%'", flow->getTagStr(), vehicleParameters.id));718myNet->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);719myNet->getUndoList()->end();720} else {721myNet->getAttributeCarriers()->insertDemandElement(flow);722// set vehicle as child of type723type->addChildElement(flow);724flow->incRef("buildFlow");725// add reference in all junctions726fromJunction->addChildElement(flow);727toJunction->addChildElement(flow);728}729return true;730}731}732}733}734735736bool737GNERouteHandler::buildFlowTAZs(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,738const std::string& fromTAZID, const std::string& toTAZID) {739// check conditions740const auto element = retrieveDemandElement(NamespaceIDs::vehicles, vehicleParameters.id);741if (!checkElement(GNE_TAG_FLOW_TAZS, element)) {742return false;743} else if (!checkValidDemandElementID(GNE_TAG_FLOW_TAZS, vehicleParameters.id)) {744return false;745} else {746// parse TAZs747const auto fromTAZ = parseTAZ(GNE_TAG_FLOW_TAZS, vehicleParameters.id, fromTAZID);748const auto toTAZ = parseTAZ(GNE_TAG_FLOW_TAZS, vehicleParameters.id, toTAZID);749if (!fromTAZ || !toTAZ) {750return false;751} else {752// obtain type753GNEDemandElement* type = getType(vehicleParameters.vtypeid);754if (type == nullptr) {755return writeErrorInvalidParent(GNE_TAG_FLOW_TAZS, vehicleParameters.id, {SUMO_TAG_VTYPE, SUMO_TAG_VTYPE_DISTRIBUTION}, vehicleParameters.vtypeid);756} else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && ((vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN)) && (vehicleParameters.departLane > 0)) {757return writeError(TLF("Invalid % used in % '%'. % is greater than number of lanes", toString(SUMO_ATTR_DEPARTLANE), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departLane)));758} else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (type->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {759return writeError(TLF("Invalid % used in % '%'. % is greater than type %", toString(SUMO_ATTR_DEPARTSPEED), toString(vehicleParameters.tag), vehicleParameters.id, toString(vehicleParameters.departSpeed), toString(SUMO_ATTR_MAXSPEED)));760} else {761// create flow using vehicleParameters762GNEDemandElement* flow = new GNEVehicle(GNE_TAG_FLOW_TAZS, myNet, myFileBucket, type, fromTAZ, toTAZ, vehicleParameters);763if (myAllowUndoRedo) {764myNet->getUndoList()->begin(flow, TLF("add % '%'", flow->getTagStr(), vehicleParameters.id));765myNet->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);766myNet->getUndoList()->end();767} else {768myNet->getAttributeCarriers()->insertDemandElement(flow);769// set vehicle as child of type770type->addChildElement(flow);771flow->incRef("buildFlow");772// add reference in all TAZs773fromTAZ->addChildElement(flow);774toTAZ->addChildElement(flow);775}776return true;777}778}779}780}781782783bool784GNERouteHandler::buildPerson(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& personParameters) {785// check conditions786const auto element = retrieveDemandElement(NamespaceIDs::persons, personParameters.id);787if (!checkElement(SUMO_TAG_PERSON, element)) {788return false;789} else if (!checkValidDemandElementID(SUMO_TAG_PERSON, personParameters.id)) {790return false;791} else {792// obtain type793GNEDemandElement* type = getType(personParameters.vtypeid);794if (type == nullptr) {795return writeErrorInvalidParent(SUMO_TAG_PERSON, personParameters.id, {SUMO_TAG_VTYPE}, personParameters.vtypeid);796} else {797// create person using personParameters798GNEDemandElement* person = new GNEPerson(SUMO_TAG_PERSON, myNet, myFileBucket, type, personParameters);799if (myAllowUndoRedo) {800myNet->getUndoList()->begin(person, TLF("add % '%'", person->getTagStr(), personParameters.id));801myNet->getUndoList()->add(new GNEChange_DemandElement(person, true), true);802myNet->getUndoList()->end();803} else {804myNet->getAttributeCarriers()->insertDemandElement(person);805// set person as child of type806type->addChildElement(person);807person->incRef("buildPerson");808}809// save in parent plan elements810myParentPlanElements.insert(person);811return true;812}813}814}815816817bool818GNERouteHandler::buildPersonFlow(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& personFlowParameters) {819// check conditions820const auto element = retrieveDemandElement(NamespaceIDs::persons, personFlowParameters.id);821if (!checkElement(SUMO_TAG_PERSONFLOW, element)) {822return false;823} else if (!checkValidDemandElementID(SUMO_TAG_PERSONFLOW, personFlowParameters.id)) {824return false;825} else {826// obtain type827GNEDemandElement* type = getType(personFlowParameters.vtypeid);828if (type == nullptr) {829return writeErrorInvalidParent(SUMO_TAG_PERSONFLOW, personFlowParameters.id, {SUMO_TAG_VTYPE}, personFlowParameters.vtypeid);830} else {831// create personFlow using personFlowParameters832GNEDemandElement* personFlow = new GNEPerson(SUMO_TAG_PERSONFLOW, myNet, myFileBucket, type, personFlowParameters);833if (myAllowUndoRedo) {834myNet->getUndoList()->begin(personFlow, TLF("add % '%'", personFlow->getTagStr(), personFlowParameters.id));835myNet->getUndoList()->add(new GNEChange_DemandElement(personFlow, true), true);836myNet->getUndoList()->end();837} else {838myNet->getAttributeCarriers()->insertDemandElement(personFlow);839// set personFlow as child of type840type->addChildElement(personFlow);841personFlow->incRef("buildPersonFlow");842}843// save in parent plan elements844myParentPlanElements.insert(personFlow);845return true;846}847}848}849850851bool852GNERouteHandler::buildPersonTrip(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const CommonXMLStructure::PlanParameters& planParameters,853const double arrivalPos, const std::vector<std::string>& types, const std::vector<std::string>& modes,854const std::vector<std::string>& lines, const double walkFactor, const std::string& group) {855// get values856GNEDemandElement* personParent = getPersonParent(sumoBaseObject);857const auto personTripTag = planParameters.getPersonTripTag();858GNEPlanParents planParents = GNEPlanParents(planParameters, myNet->getAttributeCarriers());859// check conditions860if (personParent == nullptr) {861return writeErrorInvalidParent(SUMO_TAG_PERSONTRIP, {SUMO_TAG_PERSON});862} else if (personTripTag == SUMO_TAG_NOTHING) {863return false;864} else if (planParents.checkIntegrity(personTripTag, personParent, planParameters)) {865// build person trip866GNEDemandElement* personTrip = new GNEPersonTrip(personTripTag, personParent, planParents,867arrivalPos, types, modes, lines, walkFactor, group);868// continue depending of undo.redo869if (myAllowUndoRedo) {870myNet->getUndoList()->begin(personTrip, TLF("add % in '%'", personTrip->getTagStr(), personParent->getID()));871myNet->getUndoList()->add(new GNEChange_DemandElement(personTrip, true), true);872myNet->getUndoList()->end();873} else {874myNet->getAttributeCarriers()->insertDemandElement(personTrip);875// set child references876personParent->addChildElement(personTrip);877planParents.addDemandElementChild(personTrip);878personTrip->incRef("buildPersonTrip");879}880return true;881} else {882return false;883}884}885886887bool888GNERouteHandler::buildWalk(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const CommonXMLStructure::PlanParameters& planParameters,889const double arrivalPos, const double speed, const SUMOTime duration) {890// get values891GNEDemandElement* personParent = getPersonParent(sumoBaseObject);892const auto walkTag = planParameters.getWalkTag();893GNEPlanParents planParents = GNEPlanParents(planParameters, myNet->getAttributeCarriers());894// check conditions895if (personParent == nullptr) {896return writeErrorInvalidParent(SUMO_TAG_WALK, {SUMO_TAG_PERSON});897} else if (walkTag == SUMO_TAG_NOTHING) {898return false;899} else if (!checkNegative(SUMO_TAG_WALK, personParent->getID(), SUMO_ATTR_SPEED, speed, true)) {900return false;901} else if (!checkNegative(SUMO_TAG_WALK, personParent->getID(), SUMO_ATTR_DURATION, duration, true)) {902return false;903} else if (planParents.checkIntegrity(walkTag, personParent, planParameters)) {904// build person trip905GNEDemandElement* walk = new GNEWalk(walkTag, personParent, planParents, arrivalPos, speed, duration);906// continue depending of undo.redo907if (myAllowUndoRedo) {908myNet->getUndoList()->begin(walk, TLF("add % in '%'", walk->getTagStr(), personParent->getID()));909myNet->getUndoList()->add(new GNEChange_DemandElement(walk, true), true);910myNet->getUndoList()->end();911} else {912myNet->getAttributeCarriers()->insertDemandElement(walk);913// set child references914personParent->addChildElement(walk);915planParents.addDemandElementChild(walk);916walk->incRef("buildWalk");917}918return true;919} else {920return false;921}922}923924925bool926GNERouteHandler::buildRide(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const CommonXMLStructure::PlanParameters& planParameters,927const double arrivalPos, const std::vector<std::string>& lines, const std::string& group) {928// get values929GNEDemandElement* personParent = getPersonParent(sumoBaseObject);930const auto rideTag = planParameters.getRideTag();931GNEPlanParents planParents = GNEPlanParents(planParameters, myNet->getAttributeCarriers());932// check conditions933if (personParent == nullptr) {934return writeErrorInvalidParent(SUMO_TAG_RIDE, {SUMO_TAG_PERSON});935} else if (rideTag == SUMO_TAG_NOTHING) {936return false;937} else if (planParents.checkIntegrity(rideTag, personParent, planParameters)) {938// build ride939GNEDemandElement* ride = new GNERide(rideTag, personParent, planParents, arrivalPos, lines, group);940// continue depending of undo-redo941if (myAllowUndoRedo) {942myNet->getUndoList()->begin(ride, TLF("add % in '%'", ride->getTagStr(), personParent->getID()));943myNet->getUndoList()->add(new GNEChange_DemandElement(ride, true), true);944myNet->getUndoList()->end();945} else {946myNet->getAttributeCarriers()->insertDemandElement(ride);947// set child references948personParent->addChildElement(ride);949planParents.addDemandElementChild(ride);950ride->incRef("buildRide");951}952return true;953} else {954return false;955}956}957958959bool960GNERouteHandler::buildContainer(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& containerParameters) {961// check conditions962const auto element = retrieveDemandElement(NamespaceIDs::containers, containerParameters.id);963if (!checkElement(SUMO_TAG_CONTAINER, element)) {964return false;965} else if (!checkValidDemandElementID(SUMO_TAG_CONTAINER, containerParameters.id)) {966return false;967} else {968// obtain type969GNEDemandElement* type = getType(containerParameters.vtypeid);970if (type == nullptr) {971return writeError(TLF("Invalid vehicle type '%' used in % '%'.", containerParameters.vtypeid, toString(containerParameters.tag), containerParameters.id));972} else {973// create container using containerParameters974GNEDemandElement* container = new GNEContainer(SUMO_TAG_CONTAINER, myNet, myFileBucket, type, containerParameters);975if (myAllowUndoRedo) {976myNet->getUndoList()->begin(container, TLF("add % '%'", container->getTagStr(), container->getID()));977myNet->getUndoList()->add(new GNEChange_DemandElement(container, true), true);978myNet->getUndoList()->end();979} else {980myNet->getAttributeCarriers()->insertDemandElement(container);981// set container as child of type982type->addChildElement(container);983container->incRef("buildContainer");984}985// save in parent plan elements986myParentPlanElements.insert(container);987return true;988}989}990}991992993bool994GNERouteHandler::buildContainerFlow(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& containerFlowParameters) {995// check conditions996const auto element = retrieveDemandElement(NamespaceIDs::containers, containerFlowParameters.id);997if (!checkElement(SUMO_TAG_CONTAINERFLOW, element)) {998return false;999} else if (!checkValidDemandElementID(SUMO_TAG_CONTAINERFLOW, containerFlowParameters.id)) {1000return false;1001} else {1002// obtain type1003GNEDemandElement* type = getType(containerFlowParameters.vtypeid);1004if (type == nullptr) {1005return writeError(TLF("Invalid vehicle type '%' used in % '%'.", containerFlowParameters.vtypeid, toString(containerFlowParameters.tag), containerFlowParameters.id));1006} else {1007// create containerFlow using containerFlowParameters1008GNEDemandElement* containerFlow = new GNEContainer(SUMO_TAG_CONTAINERFLOW, myNet, myFileBucket, type, containerFlowParameters);1009if (myAllowUndoRedo) {1010myNet->getUndoList()->begin(containerFlow, TLF("add % '%'", containerFlow->getTagStr(), containerFlow->getID()));1011myNet->getUndoList()->add(new GNEChange_DemandElement(containerFlow, true), true);1012myNet->getUndoList()->end();1013} else {1014myNet->getAttributeCarriers()->insertDemandElement(containerFlow);1015// set containerFlow as child of type1016type->addChildElement(containerFlow);1017containerFlow->incRef("buildContainerFlow");1018}1019// save in parent plan elements1020myParentPlanElements.insert(containerFlow);1021return true;1022}1023}1024}102510261027bool1028GNERouteHandler::buildTransport(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const CommonXMLStructure::PlanParameters& planParameters,1029const double arrivalPos, const std::vector<std::string>& lines, const std::string& group) {1030// get values1031GNEDemandElement* containerParent = getContainerParent(sumoBaseObject);1032const auto transportTag = planParameters.getTransportTag();1033GNEPlanParents planParents = GNEPlanParents(planParameters, myNet->getAttributeCarriers());1034// check conditions1035if (containerParent == nullptr) {1036return writeErrorInvalidParent(SUMO_TAG_TRANSPORT, {SUMO_TAG_CONTAINER});1037} else if (transportTag == SUMO_TAG_NOTHING) {1038return false;1039} else if (planParents.checkIntegrity(transportTag, containerParent, planParameters)) {1040// build transport1041GNEDemandElement* transport = new GNETransport(transportTag, containerParent, planParents, arrivalPos, lines, group);1042// continue depending of undo-redo1043if (myAllowUndoRedo) {1044myNet->getUndoList()->begin(transport, TLF("add % in '%'", transport->getTagStr(), containerParent->getID()));1045myNet->getUndoList()->add(new GNEChange_DemandElement(transport, true), true);1046myNet->getUndoList()->end();1047} else {1048myNet->getAttributeCarriers()->insertDemandElement(transport);1049// set child references1050containerParent->addChildElement(transport);1051planParents.addDemandElementChild(transport);1052transport->incRef("buildTransport");1053}1054return true;1055} else {1056return false;1057}1058}105910601061bool1062GNERouteHandler::buildTranship(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const CommonXMLStructure::PlanParameters& planParameters,1063const double arrivalPosition, const double departPosition, const double speed, const SUMOTime duration) {1064// get values1065GNEDemandElement* containerParent = getContainerParent(sumoBaseObject);1066const auto transhipTag = planParameters.getTranshipTag();1067GNEPlanParents planParents = GNEPlanParents(planParameters, myNet->getAttributeCarriers());1068// check conditions1069if (containerParent == nullptr) {1070return writeErrorInvalidParent(SUMO_TAG_TRANSHIP, {SUMO_TAG_CONTAINER});1071} else if (transhipTag == SUMO_TAG_NOTHING) {1072return false;1073} else if (!checkNegative(SUMO_TAG_TRANSHIP, containerParent->getID(), SUMO_ATTR_SPEED, speed, true)) {1074return false;1075} else if (!checkNegative(SUMO_TAG_TRANSHIP, containerParent->getID(), SUMO_ATTR_DURATION, duration, true)) {1076return false;1077} else if (planParents.checkIntegrity(transhipTag, containerParent, planParameters)) {1078// build tranship1079GNEDemandElement* tranship = new GNETranship(transhipTag, containerParent, planParents,1080departPosition, arrivalPosition, speed, duration);1081// continue depending of undo-redo1082if (myAllowUndoRedo) {1083myNet->getUndoList()->begin(tranship, TLF("add % in '%'", tranship->getTagStr(), containerParent->getID()));1084myNet->getUndoList()->add(new GNEChange_DemandElement(tranship, true), true);1085myNet->getUndoList()->end();1086} else {1087myNet->getAttributeCarriers()->insertDemandElement(tranship);1088// set child references1089containerParent->addChildElement(tranship);1090planParents.addDemandElementChild(tranship);1091tranship->incRef("buildTranship");1092}1093return true;1094} else {1095return false;1096}1097}109810991100bool1101GNERouteHandler::buildPersonStop(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const CommonXMLStructure::PlanParameters& planParameters,1102const double endPos, const SUMOTime duration, const SUMOTime until,1103const std::string& actType, const bool friendlyPos, const int parameterSet) {1104// get values1105GNEDemandElement* personParent = getPersonParent(sumoBaseObject);1106const auto personStopTag = planParameters.getPersonStopTag();1107GNEPlanParents planParents = GNEPlanParents(planParameters, myNet->getAttributeCarriers());1108// check conditions1109if (personParent == nullptr) {1110return writeErrorInvalidParent(SUMO_TAG_STOP, {SUMO_TAG_PERSON});1111} else if (personStopTag == SUMO_TAG_NOTHING) {1112return false;1113} else if (planParents.checkIntegrity(personStopTag, personParent, planParameters)) {1114// build person stop1115GNEDemandElement* stopPlan = new GNEStopPlan(personStopTag, personParent, planParents,1116endPos, duration, until, actType, friendlyPos, parameterSet);1117// continue depending of undo-redo1118if (myAllowUndoRedo) {1119myNet->getUndoList()->begin(stopPlan, TLF("add % in '%'", stopPlan->getTagStr(), personParent->getID()));1120myNet->getUndoList()->add(new GNEChange_DemandElement(stopPlan, true), true);1121myNet->getUndoList()->end();1122} else {1123myNet->getAttributeCarriers()->insertDemandElement(stopPlan);1124// set child references1125personParent->addChildElement(stopPlan);1126planParents.addDemandElementChild(stopPlan);1127stopPlan->incRef("buildPersonStop");1128}1129return true;1130} else {1131return false;1132}1133}113411351136bool1137GNERouteHandler::buildContainerStop(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const CommonXMLStructure::PlanParameters& planParameters,1138const double endPos, const SUMOTime duration,1139const SUMOTime until, const std::string& actType, const bool friendlyPos, const int parameterSet) {1140// get values1141GNEDemandElement* containerParent = getContainerParent(sumoBaseObject);1142const auto containerStopTag = planParameters.getContainerStopTag();1143GNEPlanParents planParents = GNEPlanParents(planParameters, myNet->getAttributeCarriers());1144// check conditions1145if (containerParent == nullptr) {1146return writeErrorInvalidParent(SUMO_TAG_STOP, {SUMO_TAG_CONTAINER});1147} else if (containerStopTag == SUMO_TAG_NOTHING) {1148return false;1149} else if (planParents.checkIntegrity(containerStopTag, containerParent, planParameters)) {1150// build container stop1151GNEDemandElement* stopPlan = new GNEStopPlan(containerStopTag, containerParent, planParents,1152endPos, duration, until, actType, friendlyPos, parameterSet);1153// continue depending of undo-redo1154if (myAllowUndoRedo) {1155myNet->getUndoList()->begin(stopPlan, TLF("add % in '%'", stopPlan->getTagStr(), containerParent->getID()));1156myNet->getUndoList()->add(new GNEChange_DemandElement(stopPlan, true), true);1157myNet->getUndoList()->end();1158} else {1159myNet->getAttributeCarriers()->insertDemandElement(stopPlan);1160// set child references1161containerParent->addChildElement(stopPlan);1162planParents.addDemandElementChild(stopPlan);1163stopPlan->incRef("buildContainerStop");1164}1165return true;1166} else {1167return false;1168}1169}117011711172bool1173GNERouteHandler::buildStop(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const CommonXMLStructure::PlanParameters& planParameters,1174const SUMOVehicleParameter::Stop& stopParameters) {1175// get obj parent1176const auto objParent = sumoBaseObject->getParentSumoBaseObject();1177// continue depending of objParent1178if (objParent == nullptr) {1179return writeErrorInvalidParent(SUMO_TAG_STOP, {SUMO_TAG_VEHICLE});1180} else if ((objParent->getTag() == SUMO_TAG_PERSON) || (objParent->getTag() == SUMO_TAG_PERSONFLOW)) {1181return buildPersonStop(sumoBaseObject, planParameters, stopParameters.endPos,1182stopParameters.duration, stopParameters.until, stopParameters.actType, stopParameters.friendlyPos, stopParameters.parametersSet);1183} else if ((objParent->getTag() == SUMO_TAG_CONTAINER) || (objParent->getTag() == SUMO_TAG_CONTAINERFLOW)) {1184return buildContainerStop(sumoBaseObject, planParameters, stopParameters.endPos,1185stopParameters.duration, stopParameters.until, stopParameters.actType, stopParameters.friendlyPos, stopParameters.parametersSet);1186} else {1187// get vehicle tag1188SumoXMLTag vehicleTag = objParent->getTag();1189if (vehicleTag == SUMO_TAG_VEHICLE) {1190// check if vehicle is placed over route or with embedded route1191if (!objParent->hasStringAttribute(SUMO_ATTR_ROUTE)) {1192vehicleTag = GNE_TAG_VEHICLE_WITHROUTE;1193}1194} else if (vehicleTag == SUMO_TAG_FLOW) {1195if (objParent->hasStringAttribute(SUMO_ATTR_ROUTE)) {1196vehicleTag = GNE_TAG_FLOW_ROUTE;1197} else if (objParent->hasStringAttribute(SUMO_ATTR_FROM) && objParent->hasStringAttribute(SUMO_ATTR_TO)) {1198vehicleTag = SUMO_TAG_FLOW;1199} else {1200vehicleTag = GNE_TAG_FLOW_WITHROUTE;1201}1202}1203// get stop parent1204GNEDemandElement* stopParent = myNet->getAttributeCarriers()->retrieveDemandElement(vehicleTag, objParent->getStringAttribute(SUMO_ATTR_ID), false);1205// check if stopParent exist1206if (stopParent) {1207// flag for waypoint (is like a stop, but with extra attribute speed)1208bool waypoint = false;1209// abool waypoints for person and containers1210if (!stopParent->getTagProperty()->isPerson() && !stopParent->getTagProperty()->isContainer()) {1211waypoint = (sumoBaseObject->getStopParameter().parametersSet & STOP_SPEED_SET) || (sumoBaseObject->getStopParameter().speed > 0);1212}1213// declare pointers to parent elements1214GNEAdditional* stoppingPlace = nullptr;1215GNELane* lane = nullptr;1216GNEEdge* edge = nullptr;1217// declare stopTagType1218SumoXMLTag stopTagType = SUMO_TAG_NOTHING;1219// check conditions1220if (stopParameters.busstop.size() > 0) {1221stoppingPlace = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, stopParameters.busstop, false);1222stopTagType = waypoint ? GNE_TAG_WAYPOINT_BUSSTOP : GNE_TAG_STOP_BUSSTOP;1223// check if is a train stop1224if (stoppingPlace == nullptr) {1225stoppingPlace = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRAIN_STOP, stopParameters.busstop, false);1226stopTagType = waypoint ? GNE_TAG_WAYPOINT_TRAINSTOP : GNE_TAG_STOP_TRAINSTOP;1227}1228// containers cannot stops in busStops1229if (stopParent->getTagProperty()->isContainer()) {1230return writeError(TL("Containers don't support stops at busStops or trainStops"));1231}1232} else if (stopParameters.containerstop.size() > 0) {1233stoppingPlace = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CONTAINER_STOP, stopParameters.containerstop, false);1234stopTagType = waypoint ? GNE_TAG_WAYPOINT_CONTAINERSTOP : GNE_TAG_STOP_CONTAINERSTOP;1235// persons cannot stops in containerStops1236if (stopParent->getTagProperty()->isPerson()) {1237return writeError(TL("Persons don't support stops at containerStops"));1238}1239} else if (stopParameters.chargingStation.size() > 0) {1240stoppingPlace = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CHARGING_STATION, stopParameters.chargingStation, false);1241stopTagType = waypoint ? GNE_TAG_WAYPOINT_CHARGINGSTATION : GNE_TAG_STOP_CHARGINGSTATION;1242// check person and containers1243if (stopParent->getTagProperty()->isPerson()) {1244return writeError(TL("Persons don't support stops at chargingStations"));1245} else if (stopParent->getTagProperty()->isContainer()) {1246return writeError(TL("Containers don't support stops at chargingStations"));1247}1248} else if (stopParameters.parkingarea.size() > 0) {1249stoppingPlace = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_PARKING_AREA, stopParameters.parkingarea, false);1250stopTagType = waypoint ? GNE_TAG_WAYPOINT_PARKINGAREA : GNE_TAG_STOP_PARKINGAREA;1251// check person and containers1252if (stopParent->getTagProperty()->isPerson()) {1253return writeError(TL("Persons don't support stops at parkingAreas"));1254} else if (stopParent->getTagProperty()->isContainer()) {1255return writeError(TL("Containers don't support stops at parkingAreas"));1256}1257} else if (stopParameters.lane.size() > 0) {1258lane = myNet->getAttributeCarriers()->retrieveLane(stopParameters.lane, false);1259stopTagType = waypoint ? GNE_TAG_WAYPOINT_LANE : GNE_TAG_STOP_LANE;1260} else if (stopParameters.edge.size() > 0) {1261edge = myNet->getAttributeCarriers()->retrieveEdge(stopParameters.edge, false);1262// check vehicles1263if (stopParent->getTagProperty()->isVehicle()) {1264return writeError(TL("vehicles don't support stops at edges"));1265}1266}1267// overwrite lane with edge parent if we're handling a personStop1268if (lane && (stopParent->getTagProperty()->isPerson() || stopParent->getTagProperty()->isContainer())) {1269edge = lane->getParentEdge();1270lane = nullptr;1271}1272// check if values are correct1273if (stoppingPlace && lane && edge) {1274return writeError(TL("A stop must be defined either over a stoppingPlace, a edge or a lane"));1275} else if (!stoppingPlace && !lane && !edge) {1276return writeError(TL("A stop requires only a stoppingPlace, edge or lane"));1277} else if (stoppingPlace) {1278// create stop using stopParameters and stoppingPlace1279GNEDemandElement* stop = nullptr;1280if (stopParent->getTagProperty()->isPerson()) {1281if (stoppingPlace->getTagProperty()->getTag() == SUMO_TAG_BUS_STOP) {1282stop = new GNEStop(GNE_TAG_STOPPERSON_BUSSTOP, stopParent, stoppingPlace, stopParameters);1283} else {1284stop = new GNEStop(GNE_TAG_STOPPERSON_TRAINSTOP, stopParent, stoppingPlace, stopParameters);1285}1286} else if (stopParent->getTagProperty()->isContainer()) {1287stop = new GNEStop(GNE_TAG_STOPCONTAINER_CONTAINERSTOP, stopParent, stoppingPlace, stopParameters);1288} else {1289stop = new GNEStop(stopTagType, stopParent, stoppingPlace, stopParameters);1290}1291// add it depending of undoDemandElements1292if (myAllowUndoRedo) {1293myNet->getUndoList()->begin(stop, TLF("add % in '%'", stop->getTagStr(), stopParent->getID()));1294myNet->getUndoList()->add(new GNEChange_DemandElement(stop, true), true);1295myNet->getUndoList()->end();1296} else {1297myNet->getAttributeCarriers()->insertDemandElement(stop);1298stoppingPlace->addChildElement(stop);1299stopParent->addChildElement(stop);1300stop->incRef("buildStoppingPlaceStop");1301}1302return true;1303} else if (lane) {1304// create stop using stopParameters and lane (only for vehicles)1305GNEDemandElement* stop = new GNEStop(stopTagType, stopParent, lane, stopParameters);1306// add it depending of undoDemandElements1307if (myAllowUndoRedo) {1308myNet->getUndoList()->begin(stop, TLF("add % in '%'", stop->getTagStr(), stopParent->getID()));1309myNet->getUndoList()->add(new GNEChange_DemandElement(stop, true), true);1310myNet->getUndoList()->end();1311} else {1312myNet->getAttributeCarriers()->insertDemandElement(stop);1313lane->addChildElement(stop);1314stopParent->addChildElement(stop);1315stop->incRef("buildLaneStop");1316}1317return true;1318} else {1319return false;1320}1321} else {1322return false;1323}1324}1325}132613271328bool1329GNERouteHandler::buildPersonPlan(const GNEDemandElement* planTemplate, GNEDemandElement* personParent,1330GNEAttributesEditor* personPlanAttributesEditor, GNEPlanCreator* planCreator,1331const bool centerAfterCreation) {1332// first check if person is valid1333if (personParent == nullptr) {1334return false;1335}1336// clear and set person object1337myPlanObject->clear();1338myPlanObject->setTag(personParent->getTagProperty()->getTag());1339myPlanObject->addStringAttribute(SUMO_ATTR_ID, personParent->getID());1340// declare personPlan object1341CommonXMLStructure::SumoBaseObject* personPlanObject = new CommonXMLStructure::SumoBaseObject(myPlanObject);1342// get person plan attributes1343personPlanAttributesEditor->fillSumoBaseObject(personPlanObject);1344// get attributes1345const std::vector<std::string> types = personPlanObject->hasStringListAttribute(SUMO_ATTR_VTYPES) ? personPlanObject->getStringListAttribute(SUMO_ATTR_VTYPES) :1346personPlanObject->hasStringAttribute(SUMO_ATTR_VTYPES) ? GNEAttributeCarrier::parse<std::vector<std::string> >(personPlanObject->getStringAttribute(SUMO_ATTR_VTYPES)) :1347std::vector<std::string>();1348const std::vector<std::string> modes = personPlanObject->hasStringListAttribute(SUMO_ATTR_MODES) ? personPlanObject->getStringListAttribute(SUMO_ATTR_MODES) :1349personPlanObject->hasStringAttribute(SUMO_ATTR_MODES) ? GNEAttributeCarrier::parse<std::vector<std::string> >(personPlanObject->getStringAttribute(SUMO_ATTR_MODES)) :1350std::vector<std::string>();1351const std::vector<std::string> lines = personPlanObject->hasStringListAttribute(SUMO_ATTR_LINES) ? personPlanObject->getStringListAttribute(SUMO_ATTR_LINES) :1352personPlanObject->hasStringAttribute(SUMO_ATTR_LINES) ? GNEAttributeCarrier::parse<std::vector<std::string> >(personPlanObject->getStringAttribute(SUMO_ATTR_LINES)) :1353std::vector<std::string>();1354const double arrivalPos = personPlanObject->hasDoubleAttribute(SUMO_ATTR_ARRIVALPOS) ? personPlanObject->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS) :1355personPlanObject->hasStringAttribute(SUMO_ATTR_ARRIVALPOS) ? GNEAttributeCarrier::parse<double>(personPlanObject->getStringAttribute(SUMO_ATTR_ARRIVALPOS)) :1356-1;1357const double endPos = personPlanObject->hasDoubleAttribute(SUMO_ATTR_ENDPOS) ? personPlanObject->getDoubleAttribute(SUMO_ATTR_ENDPOS) :1358personPlanObject->hasStringAttribute(SUMO_ATTR_ENDPOS) ? GNEAttributeCarrier::parse<double>(personPlanObject->getStringAttribute(SUMO_ATTR_ENDPOS)) :1359planCreator->getClickedPositionOverLane();1360const SUMOTime duration = personPlanObject->hasTimeAttribute(SUMO_ATTR_DURATION) ? personPlanObject->getTimeAttribute(SUMO_ATTR_DURATION) :1361personPlanObject->hasStringAttribute(SUMO_ATTR_DURATION) ? GNEAttributeCarrier::parse<SUMOTime>(personPlanObject->getStringAttribute(SUMO_ATTR_DURATION)) :13620;1363const SUMOTime until = personPlanObject->hasTimeAttribute(SUMO_ATTR_UNTIL) ? personPlanObject->getTimeAttribute(SUMO_ATTR_UNTIL) :1364personPlanObject->hasStringAttribute(SUMO_ATTR_UNTIL) ? GNEAttributeCarrier::parse<SUMOTime>(personPlanObject->getStringAttribute(SUMO_ATTR_UNTIL)) :13650;1366const std::string actType = personPlanObject->hasStringAttribute(SUMO_ATTR_ACTTYPE) ? personPlanObject->getStringAttribute(SUMO_ATTR_ACTTYPE) : "";1367const bool friendlyPos = personPlanObject->hasBoolAttribute(SUMO_ATTR_FRIENDLY_POS) ? personPlanObject->getBoolAttribute(SUMO_ATTR_FRIENDLY_POS) :1368personPlanObject->hasStringAttribute(SUMO_ATTR_FRIENDLY_POS) ? GNEAttributeCarrier::parse<bool>(personPlanObject->getStringAttribute(SUMO_ATTR_FRIENDLY_POS)) :1369false;1370const double walkFactor = personPlanObject->hasDoubleAttribute(SUMO_ATTR_WALKFACTOR) ? personPlanObject->getDoubleAttribute(SUMO_ATTR_WALKFACTOR) : 0;1371const std::string group = personPlanObject->hasStringAttribute(SUMO_ATTR_GROUP) ? personPlanObject->getStringAttribute(SUMO_ATTR_GROUP) : "";1372const double speed = personPlanObject->hasDoubleAttribute(SUMO_ATTR_SPEED) ? personPlanObject->getDoubleAttribute(SUMO_ATTR_SPEED) : 0;1373// build depending of plan type1374if (planTemplate->getTagProperty()->isPlanWalk()) {1375buildWalk(personPlanObject, planCreator->getPlanParameteres(), arrivalPos, speed, duration);1376} else if (planTemplate->getTagProperty()->isPlanPersonTrip()) {1377buildPersonTrip(personPlanObject, planCreator->getPlanParameteres(), arrivalPos, types, modes, lines, walkFactor, group);1378} else if (planTemplate->getTagProperty()->isPlanRide()) {1379buildRide(personPlanObject, planCreator->getPlanParameteres(), arrivalPos, lines, group);1380} else if (planTemplate->getTagProperty()->isPlanStopPerson()) {1381// set specific stop parameters1382int parameterSet = 0;1383if (personPlanObject->hasTimeAttribute(SUMO_ATTR_DURATION)) {1384parameterSet |= STOP_DURATION_SET;1385}1386if (personPlanObject->hasTimeAttribute(SUMO_ATTR_UNTIL)) {1387parameterSet |= STOP_UNTIL_SET;1388}1389buildPersonStop(personPlanObject, planCreator->getPlanParameteres(), endPos, duration, until, actType, friendlyPos, parameterSet);1390}1391// get person1392const auto person = myNet->getAttributeCarriers()->retrieveDemandElement(personPlanObject->getParentSumoBaseObject()->getTag(),1393personPlanObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);1394if (person) {1395// center view after creation1396if (centerAfterCreation && !myNet->getViewNet()->getVisibleBoundary().around(person->getPositionInView())) {1397myNet->getViewNet()->centerTo(person->getPositionInView(), false);1398}1399}1400delete personPlanObject;1401return true;1402}140314041405bool1406GNERouteHandler::buildContainerPlan(const GNEDemandElement* planTemplate, GNEDemandElement* containerParent,1407GNEAttributesEditor* containerPlanAttributesEditor, GNEPlanCreator* planCreator,1408const bool centerAfterCreation) {1409// first check if container is valid1410if (containerParent == nullptr) {1411return false;1412}1413// clear and set container object1414myPlanObject->clear();1415myPlanObject->setTag(containerParent->getTagProperty()->getTag());1416myPlanObject->addStringAttribute(SUMO_ATTR_ID, containerParent->getID());1417// declare containerPlan object1418CommonXMLStructure::SumoBaseObject* containerPlanObject = new CommonXMLStructure::SumoBaseObject(myPlanObject);1419// get container plan attributes1420containerPlanAttributesEditor->fillSumoBaseObject(containerPlanObject);1421// get attributes1422const double speed = containerPlanObject->hasDoubleAttribute(SUMO_ATTR_SPEED) ? containerPlanObject->getDoubleAttribute(SUMO_ATTR_SPEED) :1423containerPlanObject->hasStringAttribute(SUMO_ATTR_SPEED) ? GNEAttributeCarrier::parse<double>(containerPlanObject->getStringAttribute(SUMO_ATTR_SPEED)) :14240;1425const std::vector<std::string> lines = containerPlanObject->hasStringListAttribute(SUMO_ATTR_LINES) ? containerPlanObject->getStringListAttribute(SUMO_ATTR_LINES) :1426containerPlanObject->hasStringAttribute(SUMO_ATTR_LINES) ? GNEAttributeCarrier::parse<std::vector<std::string> >(containerPlanObject->getStringAttribute(SUMO_ATTR_LINES)) :1427std::vector<std::string>();1428const double departPos = containerPlanObject->hasDoubleAttribute(SUMO_ATTR_DEPARTPOS) ? containerPlanObject->getDoubleAttribute(SUMO_ATTR_DEPARTPOS) :1429containerPlanObject->hasStringAttribute(SUMO_ATTR_DEPARTPOS) ? GNEAttributeCarrier::parse<double>(containerPlanObject->getStringAttribute(SUMO_ATTR_DEPARTPOS)) :1430-1;1431const double arrivalPos = containerPlanObject->hasDoubleAttribute(SUMO_ATTR_ARRIVALPOS) ? containerPlanObject->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS) :1432containerPlanObject->hasStringAttribute(SUMO_ATTR_ARRIVALPOS) ? GNEAttributeCarrier::parse<double>(containerPlanObject->getStringAttribute(SUMO_ATTR_ARRIVALPOS)) :1433-1;1434const double endPos = containerPlanObject->hasDoubleAttribute(SUMO_ATTR_ENDPOS) ? containerPlanObject->getDoubleAttribute(SUMO_ATTR_ENDPOS) :1435containerPlanObject->hasStringAttribute(SUMO_ATTR_ENDPOS) ? GNEAttributeCarrier::parse<double>(containerPlanObject->getStringAttribute(SUMO_ATTR_ENDPOS)) :1436planCreator->getClickedPositionOverLane();1437const SUMOTime duration = containerPlanObject->hasTimeAttribute(SUMO_ATTR_DURATION) ? containerPlanObject->getTimeAttribute(SUMO_ATTR_DURATION) :1438containerPlanObject->hasStringAttribute(SUMO_ATTR_DURATION) ? GNEAttributeCarrier::parse<SUMOTime>(containerPlanObject->getStringAttribute(SUMO_ATTR_DURATION)) :14390;1440const SUMOTime until = containerPlanObject->hasTimeAttribute(SUMO_ATTR_UNTIL) ? containerPlanObject->getTimeAttribute(SUMO_ATTR_UNTIL) :1441containerPlanObject->hasStringAttribute(SUMO_ATTR_UNTIL) ? GNEAttributeCarrier::parse<SUMOTime>(containerPlanObject->getStringAttribute(SUMO_ATTR_UNTIL)) :14420;1443const std::string actType = containerPlanObject->hasStringAttribute(SUMO_ATTR_ACTTYPE) ? containerPlanObject->getStringAttribute(SUMO_ATTR_ACTTYPE) : "";1444const bool friendlyPos = containerPlanObject->hasBoolAttribute(SUMO_ATTR_FRIENDLY_POS) ? containerPlanObject->getBoolAttribute(SUMO_ATTR_FRIENDLY_POS) :1445containerPlanObject->hasStringAttribute(SUMO_ATTR_FRIENDLY_POS) ? GNEAttributeCarrier::parse<bool>(containerPlanObject->getStringAttribute(SUMO_ATTR_FRIENDLY_POS)) :1446false;1447const std::string group = containerPlanObject->hasStringAttribute(SUMO_ATTR_GROUP) ? containerPlanObject->getStringAttribute(SUMO_ATTR_GROUP) : "";1448// build depending of plan type1449if (planTemplate->getTagProperty()->isPlanTranship()) {1450buildTranship(containerPlanObject, planCreator->getPlanParameteres(), arrivalPos, departPos, speed, duration);1451} else if (planTemplate->getTagProperty()->isPlanTransport()) {1452buildTransport(containerPlanObject, planCreator->getPlanParameteres(), arrivalPos, lines, group);1453} else if (planTemplate->getTagProperty()->isPlanStopContainer()) {1454// set stops specific parameters1455int parameterSet = 0;1456if (containerPlanObject->hasTimeAttribute(SUMO_ATTR_DURATION)) {1457parameterSet |= STOP_DURATION_SET;1458}1459if (containerPlanObject->hasTimeAttribute(SUMO_ATTR_UNTIL)) {1460parameterSet |= STOP_UNTIL_SET;1461}1462buildContainerStop(containerPlanObject, planCreator->getPlanParameteres(), endPos, duration, until, actType, friendlyPos, parameterSet);1463}1464// get container1465const auto container = myNet->getAttributeCarriers()->retrieveDemandElement(containerPlanObject->getParentSumoBaseObject()->getTag(),1466containerPlanObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);1467if (container) {1468// center view after creation1469if (centerAfterCreation && !myNet->getViewNet()->getVisibleBoundary().around(container->getPositionInView())) {1470myNet->getViewNet()->centerTo(container->getPositionInView(), false);1471}1472}1473delete containerPlanObject;1474return true;1475}147614771478void1479GNERouteHandler::duplicatePlan(const GNEDemandElement* originalPlan, GNEDemandElement* newParent) {1480const auto tagProperty = originalPlan->getTagProperty();1481// clear and set container object1482myPlanObject->clear();1483myPlanObject->setTag(newParent->getTagProperty()->getTag());1484myPlanObject->addStringAttribute(SUMO_ATTR_ID, newParent->getID());1485// declare personPlan object for adding all attributes1486CommonXMLStructure::SumoBaseObject* planObject = new CommonXMLStructure::SumoBaseObject(myPlanObject);1487planObject->setTag(tagProperty->getTag());1488// declare parameters1489CommonXMLStructure::PlanParameters planParameters;1490// from-to elements1491if (tagProperty->planFromEdge()) {1492planParameters.fromEdge = originalPlan->getAttribute(SUMO_ATTR_FROM);1493}1494if (tagProperty->planToEdge()) {1495planParameters.toEdge = originalPlan->getAttribute(SUMO_ATTR_TO);1496}1497if (tagProperty->planFromJunction()) {1498planParameters.fromJunction = originalPlan->getAttribute(SUMO_ATTR_FROM_JUNCTION);1499}1500if (tagProperty->planToJunction()) {1501planParameters.toJunction = originalPlan->getAttribute(SUMO_ATTR_TO_JUNCTION);1502}1503if (tagProperty->planFromTAZ()) {1504planParameters.fromTAZ = originalPlan->getAttribute(SUMO_ATTR_FROM_TAZ);1505}1506if (tagProperty->planToTAZ()) {1507planParameters.toTAZ = originalPlan->getAttribute(SUMO_ATTR_TO_TAZ);1508}1509if (tagProperty->planFromBusStop()) {1510planParameters.fromBusStop = originalPlan->getAttribute(GNE_ATTR_FROM_BUSSTOP);1511}1512if (tagProperty->planToBusStop()) {1513planParameters.toBusStop = originalPlan->getAttribute(SUMO_ATTR_BUS_STOP);1514}1515if (tagProperty->planFromTrainStop()) {1516planParameters.fromTrainStop = originalPlan->getAttribute(GNE_ATTR_FROM_TRAINSTOP);1517}1518if (tagProperty->planToTrainStop()) {1519planParameters.toTrainStop = originalPlan->getAttribute(SUMO_ATTR_TRAIN_STOP);1520}1521if (tagProperty->planFromContainerStop()) {1522planParameters.fromContainerStop = originalPlan->getAttribute(GNE_ATTR_FROM_CONTAINERSTOP);1523}1524if (tagProperty->planToContainerStop()) {1525planParameters.toContainerStop = originalPlan->getAttribute(SUMO_ATTR_CONTAINER_STOP);1526}1527// single elements1528if (tagProperty->planEdge()) {1529planParameters.toEdge = originalPlan->getAttribute(SUMO_ATTR_EDGE);1530}1531if (tagProperty->planBusStop()) {1532planParameters.toBusStop = originalPlan->getAttribute(SUMO_ATTR_BUS_STOP);1533}1534if (tagProperty->planTrainStop()) {1535planParameters.toTrainStop = originalPlan->getAttribute(SUMO_ATTR_TRAIN_STOP);1536}1537if (tagProperty->planContainerStop()) {1538planParameters.toContainerStop = originalPlan->getAttribute(SUMO_ATTR_CONTAINER_STOP);1539}1540// route1541if (tagProperty->planRoute()) {1542planParameters.toRoute = originalPlan->getAttribute(SUMO_ATTR_ROUTE);1543}1544// path1545if (tagProperty->planConsecutiveEdges()) {1546planParameters.consecutiveEdges = GNEAttributeCarrier::parse<std::vector<std::string> >(originalPlan->getAttribute(SUMO_ATTR_EDGES));1547}1548// other elements1549planObject->addTimeAttribute(SUMO_ATTR_DURATION, 60);1550planObject->addTimeAttribute(SUMO_ATTR_UNTIL, 0);1551planObject->addDoubleAttribute(SUMO_ATTR_DEPARTPOS, 0);1552planObject->addDoubleAttribute(SUMO_ATTR_ARRIVALPOS, -1);1553planObject->addDoubleAttribute(SUMO_ATTR_ENDPOS, 0);1554planObject->addDoubleAttribute(SUMO_ATTR_SPEED, 1.39);1555planObject->addBoolAttribute(SUMO_ATTR_FRIENDLY_POS, false);1556// add rest of attributes1557for (const auto& attrProperty : tagProperty->getAttributeProperties()) {1558if (!planObject->hasStringAttribute(attrProperty->getAttr())) {1559if (attrProperty->isFloat()) {1560if (!originalPlan->getAttribute(attrProperty->getAttr()).empty()) {1561planObject->addDoubleAttribute(attrProperty->getAttr(), originalPlan->getAttributeDouble(attrProperty->getAttr()));1562}1563} else if (attrProperty->isSUMOTime()) {1564if (!originalPlan->getAttribute(attrProperty->getAttr()).empty()) {1565planObject->addTimeAttribute(attrProperty->getAttr(), GNEAttributeCarrier::parse<SUMOTime>(originalPlan->getAttribute(attrProperty->getAttr())));1566}1567} else if (attrProperty->isBool()) {1568planObject->addBoolAttribute(attrProperty->getAttr(), GNEAttributeCarrier::parse<bool>(originalPlan->getAttribute(attrProperty->getAttr())));1569} else if (attrProperty->isList()) {1570planObject->addStringListAttribute(attrProperty->getAttr(), GNEAttributeCarrier::parse<std::vector<std::string> >(originalPlan->getAttribute(attrProperty->getAttr())));1571} else {1572planObject->addStringAttribute(attrProperty->getAttr(), originalPlan->getAttribute(attrProperty->getAttr()));1573}1574}1575}1576// create plan1577if (tagProperty->isPlanPersonTrip()) {1578buildPersonTrip(planObject, planParameters,1579planObject->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),1580planObject->getStringListAttribute(SUMO_ATTR_VTYPES),1581planObject->getStringListAttribute(SUMO_ATTR_MODES),1582planObject->getStringListAttribute(SUMO_ATTR_LINES),1583planObject->getDoubleAttribute(SUMO_ATTR_WALKFACTOR),1584planObject->getStringAttribute(SUMO_ATTR_GROUP));1585} else if (tagProperty->isPlanWalk()) {1586buildWalk(planObject, planParameters,1587planObject->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),1588planObject->getDoubleAttribute(SUMO_ATTR_SPEED),1589planObject->getTimeAttribute(SUMO_ATTR_DURATION));1590} else if (tagProperty->isPlanRide()) {1591buildRide(planObject, planParameters,1592planObject->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),1593planObject->getStringListAttribute(SUMO_ATTR_LINES),1594planObject->getStringAttribute(SUMO_ATTR_GROUP));1595} else if (tagProperty->isPlanStopPerson()) {1596// set parameters1597int parameterSet = 0;1598if (planObject->hasTimeAttribute(SUMO_ATTR_DURATION)) {1599parameterSet |= STOP_DURATION_SET;1600}1601if (planObject->hasTimeAttribute(SUMO_ATTR_UNTIL)) {1602parameterSet |= STOP_UNTIL_SET;1603}1604buildPersonStop(planObject, planParameters,1605planObject->getDoubleAttribute(SUMO_ATTR_ENDPOS),1606planObject->getTimeAttribute(SUMO_ATTR_DURATION),1607planObject->getTimeAttribute(SUMO_ATTR_UNTIL),1608planObject->getStringAttribute(SUMO_ATTR_ACTTYPE),1609planObject->getBoolAttribute(SUMO_ATTR_FRIENDLY_POS),1610parameterSet);1611} else if (tagProperty->isPlanTransport()) {1612buildTransport(planObject, planParameters,1613planObject->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),1614planObject->getStringListAttribute(SUMO_ATTR_LINES),1615planObject->getStringAttribute(SUMO_ATTR_GROUP));1616} else if (tagProperty->isPlanTranship()) {1617buildTranship(planObject, planParameters,1618planObject->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS),1619planObject->getDoubleAttribute(SUMO_ATTR_DEPARTPOS),1620planObject->getDoubleAttribute(SUMO_ATTR_SPEED),1621planObject->getTimeAttribute(SUMO_ATTR_DURATION));1622} else if (tagProperty->isPlanStopContainer()) {1623// set parameters1624int parameterSet = 0;1625if (planObject->hasTimeAttribute(SUMO_ATTR_DURATION)) {1626parameterSet |= STOP_DURATION_SET;1627}1628if (planObject->hasTimeAttribute(SUMO_ATTR_UNTIL)) {1629parameterSet |= STOP_UNTIL_SET;1630}1631buildContainerStop(planObject, planParameters,1632planObject->getDoubleAttribute(SUMO_ATTR_ENDPOS),1633planObject->getTimeAttribute(SUMO_ATTR_DURATION),1634planObject->getTimeAttribute(SUMO_ATTR_UNTIL),1635planObject->getStringAttribute(SUMO_ATTR_ACTTYPE),1636planObject->getBoolAttribute(SUMO_ATTR_FRIENDLY_POS),1637parameterSet);1638} else {1639throw ProcessError("Invalid plan for duplicating");1640}1641}164216431644bool1645GNERouteHandler::checkViaAttribute(const SumoXMLTag tag, const std::string& id, const std::vector<std::string>& via) {1646for (const auto& edgeID : via) {1647if (myNet->getAttributeCarriers()->retrieveEdge(edgeID, false) == nullptr) {1648return writeError(TLF("Could not build % with ID '%' in netedit; via % with ID '%' doesn't exist.", toString(tag), id, toString(SUMO_TAG_EDGE), edgeID));1649}1650}1651return true;1652}165316541655void1656GNERouteHandler::transformToVehicle(GNEVehicle* originalVehicle, bool createEmbeddedRoute) {1657auto GNEApp = originalVehicle->getNet()->getGNEApplicationWindow();1658// get pointer to net1659GNENet* net = originalVehicle->getNet();1660// check if transform after creation1661const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalVehicle);1662// declare route handler1663GNERouteHandler routeHandler(net, originalVehicle->getFileBucket(), GNEApp->isUndoRedoAllowed(), true);1664// make a copy of the vehicle parameters1665SUMOVehicleParameter vehicleParameters = *originalVehicle;1666// obtain vClass1667const auto vClass = originalVehicle->getVClass();1668// set "yellow" as original route color1669RGBColor routeColor = RGBColor::YELLOW;1670// declare edges1671GNEDemandElement* originalRoute = nullptr;1672std::vector<GNEEdge*> routeEdges;1673// obtain edges depending of tag1674if (originalVehicle->getTagProperty()->vehicleRoute()) {1675// get route edges1676originalRoute = originalVehicle->getParentDemandElements().at(1);1677} else if (originalVehicle->getTagProperty()->vehicleRouteEmbedded()) {1678// get embedded route edges1679routeEdges = originalVehicle->getChildDemandElements().front()->getParentEdges();1680} else if (originalVehicle->getTagProperty()->vehicleEdges()) {1681// calculate path using from-via-to edges1682routeEdges = originalVehicle->getNet()->getDemandPathManager()->getPathCalculator()->calculateDijkstraPath(originalVehicle->getVClass(), originalVehicle->getParentEdges());1683}1684// declare edge IDs1685std::vector<std::string> edgeIDs;1686for (const auto& edge : routeEdges) {1687edgeIDs.push_back(edge->getID());1688}1689// only continue if edges are valid1690if (!originalRoute && routeEdges.empty()) {1691// declare header1692const std::string header = "Problem transforming to vehicle";1693// declare message1694const std::string message = "Vehicle cannot be transformed. Invalid number of edges";1695// open message box1696GNEWarningBasicDialog(GNEApp, header, message);1697} else {1698// begin undo-redo operation1699net->getViewNet()->getUndoList()->begin(originalVehicle, "transform " + originalVehicle->getTagStr() + " to " + toString(SUMO_TAG_VEHICLE));1700// first delete vehicle1701net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());1702// check if new vehicle must have an embedded route1703if (createEmbeddedRoute) {1704// change tag in vehicle parameters1705vehicleParameters.tag = GNE_TAG_VEHICLE_WITHROUTE;1706// build embedded route1707if (originalRoute) {1708for (const auto& edge : originalRoute->getParentEdges()) {1709edgeIDs.push_back(edge->getID());1710}1711routeHandler.buildVehicleEmbeddedRoute(nullptr, vehicleParameters, edgeIDs, RGBColor::INVISIBLE, 0, 0, {});1712} else {1713routeHandler.buildVehicleEmbeddedRoute(nullptr, vehicleParameters, edgeIDs, RGBColor::INVISIBLE, 0, 0, {});1714}1715} else if (originalRoute) {1716// set route ID in vehicle parameters1717vehicleParameters.routeid = originalRoute->getID();1718// create vehicle1719routeHandler.buildVehicleOverRoute(nullptr, vehicleParameters);1720} else {1721// change tag in vehicle parameters1722vehicleParameters.tag = SUMO_TAG_VEHICLE;1723// generate route ID1724const std::string routeID = net->getAttributeCarriers()->generateDemandElementID(SUMO_TAG_ROUTE);1725// build route1726routeHandler.buildRoute(nullptr, routeID, vClass, edgeIDs, routeColor, 0, 0, DEFAULT_VEH_PROB, {});1727// set route ID in vehicle parameters1728vehicleParameters.routeid = routeID;1729// create vehicle1730routeHandler.buildVehicleOverRoute(nullptr, vehicleParameters);1731}1732// end undo-redo operation1733net->getViewNet()->getUndoList()->end();1734// check if inspect1735if (inspectAfterTransform) {1736// get created element1737auto transformedVehicle = net->getAttributeCarriers()->retrieveDemandElement(vehicleParameters.tag, vehicleParameters.id);1738// inspect it1739net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(transformedVehicle);1740}1741}1742}174317441745void1746GNERouteHandler::transformToRouteFlow(GNEVehicle* originalVehicle, bool createEmbeddedRoute) {1747auto GNEApp = originalVehicle->getNet()->getGNEApplicationWindow();1748// get pointer to net1749GNENet* net = originalVehicle->getNet();1750// check if transform after creation1751const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalVehicle);1752// declare route handler1753GNERouteHandler routeHandler(net, originalVehicle->getFileBucket(), GNEApp->isUndoRedoAllowed(), true);1754// obtain vehicle parameters1755SUMOVehicleParameter vehicleParameters = *originalVehicle;1756// obtain vClass1757const auto vClass = originalVehicle->getVClass();1758// set "yellow" as original route color1759RGBColor routeColor = RGBColor::YELLOW;1760// declare edges1761GNEDemandElement* originalRoute = nullptr;1762std::vector<GNEEdge*> routeEdges;1763// obtain edges depending of tag1764if (originalVehicle->getTagProperty()->vehicleRoute()) {1765// get original route1766originalRoute = originalVehicle->getParentDemandElements().back();1767} else if (originalVehicle->getTagProperty()->vehicleRouteEmbedded()) {1768// get embedded route edges1769routeEdges = originalVehicle->getChildDemandElements().front()->getParentEdges();1770} else if (originalVehicle->getTagProperty()->vehicleEdges()) {1771// calculate path using from-via-to edges1772routeEdges = originalVehicle->getNet()->getDemandPathManager()->getPathCalculator()->calculateDijkstraPath(originalVehicle->getVClass(), originalVehicle->getParentEdges());1773}1774// declare edge IDs1775std::vector<std::string> edgeIDs;1776for (const auto& edge : routeEdges) {1777edgeIDs.push_back(edge->getID());1778}1779// only continue if edges are valid1780if (!originalRoute && routeEdges.empty()) {1781// declare header1782const std::string header = "Problem transforming to vehicle";1783// declare message1784const std::string message = "Vehicle cannot be transformed. Invalid number of edges";1785// open message box1786GNEWarningBasicDialog(GNEApp, header, message);1787} else {1788// begin undo-redo operation1789net->getViewNet()->getUndoList()->begin(originalVehicle, "transform " + originalVehicle->getTagStr() + " to " + toString(GNE_TAG_FLOW_ROUTE));1790// first delete vehicle1791net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());1792// change depart1793if (!originalVehicle->getTagProperty()->isFlow()) {1794// get template flow1795const auto templateFlow = net->getViewNet()->getNet()->getACTemplates()->getTemplateAC(GNE_TAG_FLOW_ROUTE);1796// set flow parameters1797vehicleParameters.repetitionEnd = vehicleParameters.depart + string2time("3600");1798vehicleParameters.repetitionNumber = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(SUMO_ATTR_NUMBER));1799vehicleParameters.repetitionOffset = string2time(templateFlow->getAttribute(SUMO_ATTR_PERIOD));1800vehicleParameters.repetitionProbability = GNEAttributeCarrier::parse<double>(templateFlow->getAttribute(SUMO_ATTR_PROB));1801// by default, number and end enabled1802vehicleParameters.parametersSet = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(GNE_ATTR_FLOWPARAMETERS));1803}1804// check if new vehicle must have an embedded route1805if (createEmbeddedRoute) {1806// change tag in vehicle parameters1807vehicleParameters.tag = GNE_TAG_FLOW_WITHROUTE;1808// build embedded route1809if (originalRoute) {1810for (const auto& edge : originalRoute->getParentEdges()) {1811edgeIDs.push_back(edge->getID());1812}1813routeHandler.buildFlowEmbeddedRoute(nullptr, vehicleParameters, edgeIDs, RGBColor::INVISIBLE, 0, 0, {});1814} else {1815routeHandler.buildFlowEmbeddedRoute(nullptr, vehicleParameters, edgeIDs, RGBColor::INVISIBLE, 0, 0, {});1816}1817} else if (originalRoute) {1818// set route ID in vehicle parameters1819vehicleParameters.routeid = originalRoute->getID();1820// create vehicle1821routeHandler.buildFlowOverRoute(nullptr, vehicleParameters);1822} else {1823// change tag in vehicle parameters1824vehicleParameters.tag = GNE_TAG_FLOW_ROUTE;1825// generate a new route id1826const std::string routeID = net->getAttributeCarriers()->generateDemandElementID(SUMO_TAG_ROUTE);1827// build route1828routeHandler.buildRoute(nullptr, routeID, vClass, edgeIDs, routeColor, 0, 0, DEFAULT_VEH_PROB, {});1829// set route ID in vehicle parameters1830vehicleParameters.routeid = routeID;1831// create vehicle1832routeHandler.buildFlowOverRoute(nullptr, vehicleParameters);1833}18341835// end undo-redo operation1836net->getViewNet()->getUndoList()->end();1837// check if inspect1838if (inspectAfterTransform) {1839// get created element1840auto transformedVehicle = net->getAttributeCarriers()->retrieveDemandElement(vehicleParameters.tag, vehicleParameters.id);1841// inspect it1842net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(transformedVehicle);1843}1844}1845}184618471848void1849GNERouteHandler::transformToTrip(GNEVehicle* originalVehicle) {1850auto GNEApp = originalVehicle->getNet()->getGNEApplicationWindow();1851// get pointer to net1852GNENet* net = originalVehicle->getNet();1853// check if transform after creation1854const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalVehicle);1855// declare route handler1856GNERouteHandler routeHandler(net, originalVehicle->getFileBucket(), GNEApp->isUndoRedoAllowed(), true);1857// obtain vehicle parameters1858SUMOVehicleParameter vehicleParameters = *originalVehicle;1859// get route1860GNEDemandElement* route = nullptr;1861// declare edges1862std::vector<GNEEdge*> edges;1863// obtain edges depending of tag1864if (originalVehicle->getTagProperty()->vehicleRoute()) {1865// set route1866route = originalVehicle->getParentDemandElements().back();1867// get route edges1868edges = route->getParentEdges();1869} else if (originalVehicle->getTagProperty()->vehicleRouteEmbedded()) {1870// get embedded route edges1871edges = originalVehicle->getChildDemandElements().front()->getParentEdges();1872} else if (originalVehicle->getTagProperty()->vehicleEdges()) {1873// just take parent edges (from and to)1874edges = originalVehicle->getParentEdges();1875}1876// only continue if edges are valid1877if (edges.size() < 2) {1878// declare header1879const std::string header = "Problem transforming to vehicle";1880// declare message1881const std::string message = "Vehicle cannot be transformed. Invalid number of edges";1882// open message box1883GNEWarningBasicDialog(GNEApp, header, message);1884} else {1885// begin undo-redo operation1886net->getViewNet()->getUndoList()->begin(originalVehicle, "transform " + originalVehicle->getTagStr() + " to " + toString(SUMO_TAG_TRIP));1887// first delete vehicle1888net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());1889// check if route has to be deleted1890if (route && route->getChildDemandElements().empty()) {1891net->deleteDemandElement(route, net->getViewNet()->getUndoList());1892}1893// change tag in vehicle parameters1894vehicleParameters.tag = SUMO_TAG_TRIP;1895// create trip1896routeHandler.buildTrip(nullptr, vehicleParameters, edges.front()->getID(), edges.back()->getID());1897// end undo-redo operation1898net->getViewNet()->getUndoList()->end();1899// check if inspect1900if (inspectAfterTransform) {1901// get created element1902auto transformedVehicle = net->getAttributeCarriers()->retrieveDemandElement(vehicleParameters.tag, vehicleParameters.id);1903// inspect it1904net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(transformedVehicle);1905}1906}1907}190819091910void1911GNERouteHandler::transformToFlow(GNEVehicle* originalVehicle) {1912auto GNEApp = originalVehicle->getNet()->getGNEApplicationWindow();1913// get pointer to net1914GNENet* net = originalVehicle->getNet();1915// check if transform after creation1916const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalVehicle);1917// declare route handler1918GNERouteHandler routeHandler(net, originalVehicle->getFileBucket(), GNEApp->isUndoRedoAllowed(), true);1919// obtain vehicle parameters1920SUMOVehicleParameter vehicleParameters = *originalVehicle;1921// declare route1922GNEDemandElement* route = nullptr;1923// declare edges1924std::vector<GNEEdge*> edges;1925// obtain edges depending of tag1926if (originalVehicle->getTagProperty()->vehicleRoute()) {1927// set route1928route = originalVehicle->getParentDemandElements().back();1929// get route edges1930edges = route->getParentEdges();1931} else if (originalVehicle->getTagProperty()->vehicleRouteEmbedded()) {1932// get embedded route edges1933edges = originalVehicle->getChildDemandElements().front()->getParentEdges();1934} else if (originalVehicle->getTagProperty()->vehicleEdges()) {1935// just take parent edges (from and to)1936edges = originalVehicle->getParentEdges();1937}1938// only continue if edges are valid1939if (edges.empty()) {1940// declare header1941const std::string header = "Problem transforming to vehicle";1942// declare message1943const std::string message = "Vehicle cannot be transformed. Invalid number of edges";1944// open message box1945GNEWarningBasicDialog(GNEApp, header, message);1946} else {1947// begin undo-redo operation1948net->getViewNet()->getUndoList()->begin(originalVehicle, "transform " + originalVehicle->getTagStr() + " to " + toString(SUMO_TAG_VEHICLE));1949// first delete vehicle1950net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());1951// check if route has to be deleted1952if (route && route->getChildDemandElements().empty()) {1953net->deleteDemandElement(route, net->getViewNet()->getUndoList());1954}1955// change depart1956if (!originalVehicle->getTagProperty()->isFlow()) {1957// get template flow1958const auto templateFlow = net->getViewNet()->getNet()->getACTemplates()->getTemplateAC(GNE_TAG_FLOW_ROUTE);1959// set flow parameters1960vehicleParameters.repetitionEnd = vehicleParameters.depart + string2time("3600");1961vehicleParameters.repetitionNumber = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(SUMO_ATTR_NUMBER));1962vehicleParameters.repetitionOffset = string2time(templateFlow->getAttribute(SUMO_ATTR_PERIOD));1963vehicleParameters.repetitionProbability = GNEAttributeCarrier::parse<double>(templateFlow->getAttribute(SUMO_ATTR_PROB));1964// by default, number and end enabled1965vehicleParameters.parametersSet = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(GNE_ATTR_FLOWPARAMETERS));1966}1967// change tag in vehicle parameters1968vehicleParameters.tag = SUMO_TAG_FLOW;1969// create flow1970routeHandler.buildFlow(nullptr, vehicleParameters, edges.front()->getID(), edges.back()->getID());1971// end undo-redo operation1972net->getViewNet()->getUndoList()->end();1973// check if inspect1974if (inspectAfterTransform) {1975// get created element1976auto transformedVehicle = net->getAttributeCarriers()->retrieveDemandElement(vehicleParameters.tag, vehicleParameters.id);1977// inspect it1978net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(transformedVehicle);1979}1980}1981}198219831984void1985GNERouteHandler::transformToTripJunctions(GNEVehicle* originalVehicle) {1986auto GNEApp = originalVehicle->getNet()->getGNEApplicationWindow();1987// only continue if number of junctions are valid1988if (originalVehicle->getParentJunctions().empty()) {1989// declare header1990const std::string header = "Problem transforming to trip over junctions";1991// declare message1992const std::string message = "Vehicle cannot be transformed. Invalid number of junctions";1993// open message box1994GNEWarningBasicDialog(GNEApp, header, message);1995} else {1996// get pointer to net1997GNENet* net = originalVehicle->getNet();1998// get TAZs before deleting vehicle1999const auto fromJunction = originalVehicle->getParentJunctions().front()->getID();2000const auto toJunction = originalVehicle->getParentJunctions().back()->getID();2001// check if transform after creation2002const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalVehicle);2003// declare route handler2004GNERouteHandler routeHandler(net, originalVehicle->getFileBucket(), GNEApp->isUndoRedoAllowed(), true);2005// obtain vehicle parameters2006SUMOVehicleParameter vehicleParameters = *originalVehicle;2007// begin undo-redo operation2008net->getViewNet()->getUndoList()->begin(originalVehicle, "transform " + originalVehicle->getTagStr() + " to " + toString(GNE_TAG_TRIP_JUNCTIONS));2009// first delete vehicle2010net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());2011// change tag in vehicle parameters2012vehicleParameters.tag = GNE_TAG_TRIP_JUNCTIONS;2013// create trip2014routeHandler.buildTripJunctions(nullptr, vehicleParameters, fromJunction, toJunction);2015// end undo-redo operation2016net->getViewNet()->getUndoList()->end();2017// check if inspect2018if (inspectAfterTransform) {2019// get created element2020auto transformedVehicle = net->getAttributeCarriers()->retrieveDemandElement(vehicleParameters.tag, vehicleParameters.id);2021// inspect it2022net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(transformedVehicle);2023}2024}2025}202620272028void2029GNERouteHandler::transformToFlowJunctions(GNEVehicle* originalVehicle) {2030auto GNEApp = originalVehicle->getNet()->getGNEApplicationWindow();2031// only continue if number of junctions are valid2032if (originalVehicle->getParentJunctions().empty()) {2033// declare header2034const std::string header = "Problem transforming to flow over junctions";2035// declare message2036const std::string message = "Vehicle cannot be transformed. Invalid number of junctions";2037// open message box2038GNEWarningBasicDialog(GNEApp, header, message);2039} else {2040// get pointer to net2041GNENet* net = originalVehicle->getNet();2042// get TAZs before deleting vehicle2043const auto fromJunction = originalVehicle->getParentJunctions().front()->getID();2044const auto toJunction = originalVehicle->getParentJunctions().back()->getID();2045// check if transform after creation2046const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalVehicle);2047// declare route handler2048GNERouteHandler routeHandler(net, originalVehicle->getFileBucket(), GNEApp->isUndoRedoAllowed(), true);2049// obtain vehicle parameters2050SUMOVehicleParameter vehicleParameters = *originalVehicle;2051// begin undo-redo operation2052net->getViewNet()->getUndoList()->begin(originalVehicle, "transform " + originalVehicle->getTagStr() + " to " + toString(GNE_TAG_FLOW_JUNCTIONS));2053// first delete vehicle2054net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());2055// get template flow2056const auto templateFlow = net->getViewNet()->getNet()->getACTemplates()->getTemplateAC(GNE_TAG_FLOW_JUNCTIONS);2057// set flow parameters2058vehicleParameters.repetitionEnd = vehicleParameters.depart + string2time("3600");2059vehicleParameters.repetitionNumber = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(SUMO_ATTR_NUMBER));2060vehicleParameters.repetitionOffset = string2time(templateFlow->getAttribute(SUMO_ATTR_PERIOD));2061vehicleParameters.repetitionProbability = GNEAttributeCarrier::parse<double>(templateFlow->getAttribute(SUMO_ATTR_PROB));2062// by default, number and end enabled2063vehicleParameters.parametersSet = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(GNE_ATTR_FLOWPARAMETERS));2064// change tag in vehicle parameters2065vehicleParameters.tag = GNE_TAG_FLOW_JUNCTIONS;2066// create flow2067routeHandler.buildFlowJunctions(nullptr, vehicleParameters, fromJunction, toJunction);2068// end undo-redo operation2069net->getViewNet()->getUndoList()->end();2070// check if inspect2071if (inspectAfterTransform) {2072// get created element2073auto transformedVehicle = net->getAttributeCarriers()->retrieveDemandElement(vehicleParameters.tag, vehicleParameters.id);2074// inspect it2075net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(transformedVehicle);2076}2077}2078}207920802081void2082GNERouteHandler::transformToTripTAZs(GNEVehicle* originalVehicle) {2083auto GNEApp = originalVehicle->getNet()->getGNEApplicationWindow();2084// only continue if number of junctions are valid2085if (originalVehicle->getParentAdditionals().empty()) {2086// declare header2087const std::string header = "Problem transforming to trip over TAZs";2088// declare message2089const std::string message = "Vehicle cannot be transformed. Invalid number of TAZs";2090// open message box2091GNEWarningBasicDialog(GNEApp, header, message);2092} else {2093// get pointer to net2094GNENet* net = originalVehicle->getNet();2095// get TAZs before deleting vehicle2096const auto fromTAZ = originalVehicle->getParentAdditionals().front()->getID();2097const auto toTAZ = originalVehicle->getParentAdditionals().back()->getID();2098// check if transform after creation2099const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalVehicle);2100// declare route handler2101GNERouteHandler routeHandler(net, originalVehicle->getFileBucket(), GNEApp->isUndoRedoAllowed(), true);2102// obtain vehicle parameters2103SUMOVehicleParameter vehicleParameters = *originalVehicle;2104// begin undo-redo operation2105net->getViewNet()->getUndoList()->begin(originalVehicle, "transform " + originalVehicle->getTagStr() + " to " + toString(GNE_TAG_TRIP_TAZS));2106// first delete vehicle2107net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());2108// change tag in vehicle parameters2109vehicleParameters.tag = GNE_TAG_TRIP_TAZS;2110// create trip2111routeHandler.buildTripTAZs(nullptr, vehicleParameters, fromTAZ, toTAZ);2112// end undo-redo operation2113net->getViewNet()->getUndoList()->end();2114// check if inspect2115if (inspectAfterTransform) {2116// get created element2117auto transformedVehicle = net->getAttributeCarriers()->retrieveDemandElement(vehicleParameters.tag, vehicleParameters.id);2118// inspect it2119net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(transformedVehicle);2120}2121}2122}212321242125void2126GNERouteHandler::transformToFlowTAZs(GNEVehicle* originalVehicle) {2127auto GNEApp = originalVehicle->getNet()->getGNEApplicationWindow();2128// only continue if number of junctions are valid2129if (originalVehicle->getParentAdditionals().empty()) {2130// declare header2131const std::string header = "Problem transforming to flow over TAZs";2132// declare message2133const std::string message = "Vehicle cannot be transformed. Invalid number of TAZs";2134// open message box2135GNEWarningBasicDialog(GNEApp, header, message);2136} else {2137// get pointer to net2138GNENet* net = originalVehicle->getNet();2139// get TAZs before deleting vehicle2140const auto fromTAZ = originalVehicle->getParentAdditionals().front()->getID();2141const auto toTAZ = originalVehicle->getParentAdditionals().back()->getID();2142// check if transform after creation2143const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalVehicle);2144// declare route handler2145GNERouteHandler routeHandler(net, originalVehicle->getFileBucket(), GNEApp->isUndoRedoAllowed(), true);2146// obtain vehicle parameters2147SUMOVehicleParameter vehicleParameters = *originalVehicle;2148// begin undo-redo operation2149net->getViewNet()->getUndoList()->begin(originalVehicle, "transform " + originalVehicle->getTagStr() + " to " + toString(GNE_TAG_FLOW_TAZS));2150// first delete vehicle2151net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());2152// get template flow2153const auto templateFlow = net->getViewNet()->getNet()->getACTemplates()->getTemplateAC(GNE_TAG_FLOW_TAZS);2154// set flow parameters2155vehicleParameters.repetitionEnd = vehicleParameters.depart + string2time("3600");2156vehicleParameters.repetitionNumber = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(SUMO_ATTR_NUMBER));2157vehicleParameters.repetitionOffset = string2time(templateFlow->getAttribute(SUMO_ATTR_PERIOD));2158vehicleParameters.repetitionProbability = GNEAttributeCarrier::parse<double>(templateFlow->getAttribute(SUMO_ATTR_PROB));2159// by default, number and end enabled2160vehicleParameters.parametersSet = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(GNE_ATTR_FLOWPARAMETERS));2161// change tag in vehicle parameters2162vehicleParameters.tag = GNE_TAG_FLOW_TAZS;2163// create flow2164routeHandler.buildFlowTAZs(nullptr, vehicleParameters, fromTAZ, toTAZ);2165// end undo-redo operation2166net->getViewNet()->getUndoList()->end();2167// check if inspect2168if (inspectAfterTransform) {2169// get created element2170auto transformedVehicle = net->getAttributeCarriers()->retrieveDemandElement(vehicleParameters.tag, vehicleParameters.id);2171// inspect it2172net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(transformedVehicle);2173}2174}2175}217621772178void2179GNERouteHandler::transformToPerson(GNEPerson* originalPerson) {2180// get pointer to net2181GNENet* net = originalPerson->getNet();2182// check if transform after creation2183const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalPerson);2184// declare route handler2185GNERouteHandler routeHandler(net, originalPerson->getFileBucket(), net->getGNEApplicationWindow()->isUndoRedoAllowed(), false);2186// obtain person parameters2187SUMOVehicleParameter personParameters = *originalPerson;2188// save ID2189const auto ID = personParameters.id;2190// set dummy ID2191personParameters.id = "%dummyID%";2192// begin undo-redo operation2193net->getViewNet()->getUndoList()->begin(originalPerson, "transform " + originalPerson->getTagStr() + " to " + toString(SUMO_TAG_PERSON));2194// create personFlow and get it2195routeHandler.buildPerson(nullptr, personParameters);2196auto newPerson = net->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_PERSON, "%dummyID%");2197// duplicate plans in new person2198for (const auto& personPlan : originalPerson->getChildDemandElements()) {2199routeHandler.duplicatePlan(personPlan, newPerson);2200}2201// delete original person plan2202net->deleteDemandElement(originalPerson, net->getViewNet()->getUndoList());2203// restore ID of new person plan2204newPerson->setAttribute(SUMO_ATTR_ID, ID, net->getViewNet()->getUndoList());2205// finish undoList2206net->getViewNet()->getUndoList()->end();2207// check if inspect2208if (inspectAfterTransform) {2209net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(newPerson);2210}2211}221222132214void2215GNERouteHandler::transformToPersonFlow(GNEPerson* originalPerson) {2216// get pointer to net2217GNENet* net = originalPerson->getNet();2218// check if transform after creation2219const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalPerson);2220// declare route handler2221GNERouteHandler routeHandler(net, originalPerson->getFileBucket(), net->getGNEApplicationWindow()->isUndoRedoAllowed(), false);2222// obtain person parameters2223SUMOVehicleParameter personParameters = *originalPerson;2224// get person plans2225const auto personPlans = originalPerson->getChildDemandElements();2226// save ID2227const auto ID = personParameters.id;2228// set dummy ID2229personParameters.id = "%dummyID%";2230// begin undo-redo operation2231net->getViewNet()->getUndoList()->begin(originalPerson, "transform " + originalPerson->getTagStr() + " to " + toString(SUMO_TAG_PERSONFLOW));2232// create personFlow and get it2233routeHandler.buildPersonFlow(nullptr, personParameters);2234auto newPerson = net->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_PERSONFLOW, "%dummyID%");2235// move all person plans to new person2236for (const auto& personPlan : personPlans) {2237routeHandler.duplicatePlan(personPlan, newPerson);2238}2239// delete original person plan2240net->deleteDemandElement(originalPerson, net->getViewNet()->getUndoList());2241// restore ID of new person plan2242newPerson->setAttribute(SUMO_ATTR_ID, ID, net->getViewNet()->getUndoList());2243// enable attributes2244newPerson->enableAttribute(SUMO_ATTR_END, net->getViewNet()->getUndoList());2245newPerson->enableAttribute(SUMO_ATTR_PERSONSPERHOUR, net->getViewNet()->getUndoList());2246// finish undoList2247net->getViewNet()->getUndoList()->end();2248// check if inspect2249if (inspectAfterTransform) {2250net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(newPerson);2251}2252}225322542255void2256GNERouteHandler::transformToContainer(GNEContainer* originalContainer) {2257// get pointer to net2258GNENet* net = originalContainer->getNet();2259// check if transform after creation2260const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalContainer);2261// declare route handler2262GNERouteHandler routeHandler(net, originalContainer->getFileBucket(), net->getGNEApplicationWindow()->isUndoRedoAllowed(), false);2263// obtain container parameters2264SUMOVehicleParameter containerParameters = *originalContainer;2265// get container plans2266const auto containerPlans = originalContainer->getChildDemandElements();2267// save ID2268const auto ID = containerParameters.id;2269// set dummy ID2270containerParameters.id = "%dummyID%";2271// begin undo-redo operation2272net->getViewNet()->getUndoList()->begin(originalContainer, "transform " + originalContainer->getTagStr() + " to " + toString(SUMO_TAG_CONTAINER));2273// create containerFlow2274routeHandler.buildContainer(nullptr, containerParameters);2275// move all container plans to new container2276for (const auto& containerPlan : containerPlans) {2277containerPlan->setAttribute(GNE_ATTR_PARENT, "%dummyID%", net->getViewNet()->getUndoList());2278}2279// delete original container plan2280net->deleteDemandElement(originalContainer, net->getViewNet()->getUndoList());2281// restore ID of new container plan2282auto newContainer = net->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_CONTAINER, "%dummyID%");2283newContainer->setAttribute(SUMO_ATTR_ID, ID, net->getViewNet()->getUndoList());2284// finish undoList2285net->getViewNet()->getUndoList()->end();2286// check if inspect2287if (inspectAfterTransform) {2288net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(newContainer);2289}2290}229122922293void2294GNERouteHandler::transformToContainerFlow(GNEContainer* originalContainer) {2295// get pointer to net2296GNENet* net = originalContainer->getNet();2297// check if transform after creation2298const bool inspectAfterTransform = net->getViewNet()->getInspectedElements().isACInspected(originalContainer);2299// declare route handler2300GNERouteHandler routeHandler(net, originalContainer->getFileBucket(), net->getGNEApplicationWindow()->isUndoRedoAllowed(), false);2301// obtain container parameters2302SUMOVehicleParameter containerParameters = *originalContainer;2303// get container plans2304const auto containerPlans = originalContainer->getChildDemandElements();2305// save ID2306const auto ID = containerParameters.id;2307// set dummy ID2308containerParameters.id = "%dummyID%";2309// begin undo-redo operation2310net->getViewNet()->getUndoList()->begin(originalContainer, "transform " + originalContainer->getTagStr() + " to " + toString(SUMO_TAG_CONTAINERFLOW));2311// create containerFlow2312routeHandler.buildContainerFlow(nullptr, containerParameters);2313// move all container plans to new container2314for (const auto& containerPlan : containerPlans) {2315containerPlan->setAttribute(GNE_ATTR_PARENT, "%dummyID%", net->getViewNet()->getUndoList());2316}2317// delete original container plan2318net->deleteDemandElement(originalContainer, net->getViewNet()->getUndoList());2319// restore ID of new container plan2320auto newContainer = net->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_CONTAINERFLOW, "%dummyID%");2321newContainer->setAttribute(SUMO_ATTR_ID, ID, net->getViewNet()->getUndoList());2322// enable attributes2323newContainer->enableAttribute(SUMO_ATTR_END, net->getViewNet()->getUndoList());2324newContainer->enableAttribute(SUMO_ATTR_CONTAINERSPERHOUR, net->getViewNet()->getUndoList());2325// finish undoList2326net->getViewNet()->getUndoList()->end();2327// check if inspect2328if (inspectAfterTransform) {2329net->getViewNet()->getViewParent()->getInspectorFrame()->inspectElement(newContainer);2330}2331}233223332334bool2335GNERouteHandler::canReverse(const GNEDemandElement* element) {2336// continue depending of element2337if (element->getTagProperty()->getTag() == SUMO_TAG_ROUTE) {2338return canReverse(element->getNet(), SVC_PEDESTRIAN, element->getParentEdges());2339} else if (element->getTagProperty()->vehicleRoute()) {2340return canReverse(element->getNet(), element->getVClass(), element->getParentDemandElements().at(1)->getParentEdges());2341} else if (element->getTagProperty()->vehicleRouteEmbedded()) {2342return canReverse(element->getNet(), element->getVClass(), element->getChildDemandElements().front()->getParentEdges());2343} else if (element->getTagProperty()->vehicleEdges()) {2344return canReverse(element->getNet(), element->getVClass(), element->getParentEdges());2345} else if (element->getTagProperty()->vehicleJunctions()) {2346return (element->getNet()->getDemandPathManager()->getPathCalculator()->calculateDijkstraPath(element->getVClass(),2347element->getParentJunctions().back(), element->getParentJunctions().front()).size() > 0);2348} else if (element->getTagProperty()->vehicleTAZs()) {2349return true;2350} else {2351return false;2352}2353}235423552356bool2357GNERouteHandler::canReverse(GNENet* net, SUMOVehicleClass vClass, const std::vector<GNEEdge*>& edges) {2358if (edges.empty()) {2359return false;2360} else {2361// obtain opposite edges2362std::vector<GNEEdge*> reverseEdges;2363for (const auto& edge : edges) {2364const auto oppositeEdges = edge->getOppositeEdges();2365// stop if there isn't opposite edges for the current edge2366if (oppositeEdges.empty()) {2367return false;2368} else {2369reverseEdges.push_back(oppositeEdges.front());2370}2371}2372// reverse edges2373std::reverse(reverseEdges.begin(), reverseEdges.end());2374// now check if exist a path2375return (net->getDemandPathManager()->getPathCalculator()->calculateDijkstraPath(vClass, edges).size() > 0);2376}2377}237823792380void2381GNERouteHandler::reverse(GNEDemandElement* element) {2382// get undo list2383auto undoList = element->getNet()->getUndoList();2384// continue depending of element2385if (element->getTagProperty()->vehicleRoute()) {2386// reverse parent route2387reverse(element->getParentDemandElements().at(1));2388} else if (element->getTagProperty()->vehicleRouteEmbedded()) {2389// reverse embedded route2390reverse(element->getChildDemandElements().front());2391} else if (element->getTagProperty()->vehicleJunctions()) {2392// get from to junctions2393const auto fromJunction = element->getAttribute(SUMO_ATTR_FROM_JUNCTION);2394const auto toJunction = element->getAttribute(SUMO_ATTR_TO_JUNCTION);2395// swap both attributes2396element->setAttribute(SUMO_ATTR_FROM_JUNCTION, toJunction, undoList);2397element->setAttribute(SUMO_ATTR_TO_JUNCTION, fromJunction, undoList);2398} else if (element->getTagProperty()->vehicleTAZs()) {2399// get from to TAZs2400const auto fromTAZ = element->getAttribute(SUMO_ATTR_FROM_TAZ);2401const auto toTAZ = element->getAttribute(SUMO_ATTR_TO_TAZ);2402// swap both attributes2403element->setAttribute(SUMO_ATTR_FROM_TAZ, toTAZ, undoList);2404element->setAttribute(SUMO_ATTR_TO_TAZ, fromTAZ, undoList);2405} else {2406// extract and reverse opposite edges2407std::vector<GNEEdge*> oppositeEdges;2408for (const auto& edge : element->getParentEdges()) {2409oppositeEdges.push_back(edge->getOppositeEdges().front());2410}2411std::reverse(oppositeEdges.begin(), oppositeEdges.end());2412if (element->isRoute()) {2413element->setAttribute(SUMO_ATTR_EDGES, GNEAttributeCarrier::parseIDs(oppositeEdges), undoList);2414} else {2415// set from and to2416element->setAttribute(SUMO_ATTR_FROM, oppositeEdges.front()->getID(), undoList);2417element->setAttribute(SUMO_ATTR_TO, oppositeEdges.back()->getID(), undoList);2418// check if add via attribute2419oppositeEdges.erase(oppositeEdges.begin());2420oppositeEdges.pop_back();2421if (oppositeEdges.size() > 0) {2422element->setAttribute(SUMO_ATTR_VIA, GNEAttributeCarrier::parseIDs(oppositeEdges), undoList);2423}2424}2425}2426}242724282429void2430GNERouteHandler::addReverse(GNEDemandElement* element) {2431GNEDemandElement* elementCopy = nullptr;2432if (element->getTagProperty()->getTag() == SUMO_TAG_ROUTE) {2433// make a copy of the route and reverse2434elementCopy = GNERoute::copyRoute(dynamic_cast<GNERoute*>(element));2435} else if (element->getTagProperty()->isVehicle()) {2436// make a copy of the vehicle2437elementCopy = GNEVehicle::copyVehicle(dynamic_cast<GNEVehicle*>(element));2438}2439// reverse copied element2440reverse(elementCopy);2441}24422443// ===========================================================================2444// protected2445// ===========================================================================24462447GNEJunction*2448GNERouteHandler::parseJunction(const SumoXMLTag tag, const std::string& id, const std::string& junctionID) {2449GNEJunction* junction = myNet->getAttributeCarriers()->retrieveJunction(junctionID, false);2450// empty junctions aren't allowed. If junction is empty, write error, clear junctions and stop2451if (junction == nullptr) {2452writeErrorInvalidParent(tag, id, {SUMO_TAG_JUNCTION}, junctionID);2453}2454return junction;2455}245624572458GNEAdditional*2459GNERouteHandler::parseTAZ(const SumoXMLTag tag, const std::string& id, const std::string& TAZID) {2460GNEAdditional* TAZ = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TAZ, TAZID, false);2461// empty TAZs aren't allowed. If TAZ is empty, write error, clear TAZs and stop2462if (TAZ == nullptr) {2463writeErrorInvalidParent(tag, id, {SUMO_TAG_TAZ}, TAZID);2464}2465return TAZ;2466}246724682469GNEEdge*2470GNERouteHandler::parseEdge(const SumoXMLTag tag, const std::string& id, const std::string& edgeID,2471const CommonXMLStructure::SumoBaseObject* sumoBaseObject,2472const bool firstEdge) {2473GNEEdge* edge = nullptr;2474if (edgeID.empty()) {2475if (sumoBaseObject->getSumoBaseObjectChildren().size() > 0) {2476const auto frontTag = sumoBaseObject->getSumoBaseObjectChildren().front()->getTag();2477const auto backTag = sumoBaseObject->getSumoBaseObjectChildren().back()->getTag();2478if (firstEdge && ((frontTag == SUMO_TAG_STOP) || (frontTag == SUMO_TAG_TRAIN_STOP) ||2479(frontTag == SUMO_TAG_CONTAINER_STOP) || (frontTag == SUMO_TAG_CHARGING_STATION) ||2480(frontTag == SUMO_TAG_PARKING_AREA))) {2481edge = parseStopEdge(sumoBaseObject->getSumoBaseObjectChildren().front());2482} else if (!firstEdge && ((backTag == SUMO_TAG_STOP) || (backTag == SUMO_TAG_TRAIN_STOP) ||2483(backTag == SUMO_TAG_CONTAINER_STOP) || (backTag == SUMO_TAG_CHARGING_STATION) ||2484(backTag == SUMO_TAG_PARKING_AREA))) {2485edge = parseStopEdge(sumoBaseObject->getSumoBaseObjectChildren().back());2486}2487}2488} else {2489edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);2490}2491// write info if edge doesn't exist2492if (edge == nullptr) {2493writeErrorInvalidParent(tag, id, {SUMO_TAG_EDGE}, edgeID);2494}2495return edge;2496}249724982499GNEEdge*2500GNERouteHandler::parseStopEdge(const CommonXMLStructure::SumoBaseObject* sumoBaseObject) const {2501if (sumoBaseObject->hasStringAttribute(SUMO_ATTR_EDGE)) {2502return myNet->getAttributeCarriers()->retrieveEdge(sumoBaseObject->getStringAttribute(SUMO_ATTR_EDGE), false);2503} else if (sumoBaseObject->hasStringAttribute(SUMO_ATTR_LANE)) {2504return parseEdgeFromLaneID(sumoBaseObject->getStringAttribute(SUMO_ATTR_LANE));2505} else if (sumoBaseObject->hasStringAttribute(SUMO_ATTR_BUS_STOP)) {2506const auto busStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, sumoBaseObject->getStringAttribute(SUMO_ATTR_BUS_STOP), false);2507const auto trainStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRAIN_STOP, sumoBaseObject->getStringAttribute(SUMO_ATTR_BUS_STOP), false);2508if (busStop != nullptr) {2509return busStop->getParentLanes().front()->getParentEdge();2510} else if (trainStop != nullptr) {2511return trainStop->getParentLanes().front()->getParentEdge();2512} else {2513return nullptr;2514}2515} else if (sumoBaseObject->hasStringAttribute(SUMO_ATTR_TRAIN_STOP)) {2516const auto busStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, sumoBaseObject->getStringAttribute(SUMO_ATTR_TRAIN_STOP), false);2517const auto trainStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRAIN_STOP, sumoBaseObject->getStringAttribute(SUMO_ATTR_TRAIN_STOP), false);2518if (busStop != nullptr) {2519return busStop->getParentLanes().front()->getParentEdge();2520} else if (trainStop != nullptr) {2521return trainStop->getParentLanes().front()->getParentEdge();2522} else {2523return nullptr;2524}2525} else if (sumoBaseObject->hasStringAttribute(SUMO_ATTR_CONTAINER_STOP)) {2526const auto containerStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CONTAINER_STOP, sumoBaseObject->getStringAttribute(SUMO_ATTR_CONTAINER_STOP), false);2527if (containerStop != nullptr) {2528return containerStop->getParentLanes().front()->getParentEdge();2529} else {2530return nullptr;2531}25322533} else if (sumoBaseObject->hasStringAttribute(SUMO_ATTR_CHARGING_STATION)) {2534const auto containerStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CHARGING_STATION, sumoBaseObject->getStringAttribute(SUMO_ATTR_CHARGING_STATION), false);2535if (containerStop != nullptr) {2536return containerStop->getParentLanes().front()->getParentEdge();2537} else {2538return nullptr;2539}25402541} else if (sumoBaseObject->hasStringAttribute(SUMO_ATTR_PARKING_AREA)) {2542const auto parkingArea = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_PARKING_AREA, sumoBaseObject->getStringAttribute(SUMO_ATTR_PARKING_AREA), false);2543if (parkingArea != nullptr) {2544return parkingArea->getParentLanes().front()->getParentEdge();2545} else {2546return nullptr;2547}2548} else {2549return nullptr;2550}2551}255225532554GNEEdge*2555GNERouteHandler::parseEdgeFromLaneID(const std::string& laneID) const {2556std::string edgeID = laneID;2557for (int i = ((int)laneID.size() - 1); (i >= 0) && (laneID[i + 1] != '_'); i--) {2558edgeID.pop_back();2559}2560return myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);2561}256225632564std::vector<GNEEdge*>2565GNERouteHandler::parseEdges(const SumoXMLTag tag, const std::string& id, const std::vector<std::string>& edgeIDs) {2566std::vector<GNEEdge*> edges;2567for (const auto& edgeID : edgeIDs) {2568GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);2569// empty edges aren't allowed. If edge is empty, write error, clear edges and stop2570if (edge == nullptr) {2571writeError(TLF("Could not build % with ID '%' in netedit; % with ID '%' doesn't exist.", toString(tag), id, toString(SUMO_TAG_EDGE), edgeID));2572edges.clear();2573return edges;2574} else {2575edges.push_back(edge);2576}2577}2578return edges;2579}258025812582GNEDemandElement*2583GNERouteHandler::getType(const std::string& id) const {2584GNEDemandElement* type = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, id, false);2585if (type == nullptr) {2586return myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE_DISTRIBUTION, id, false);2587} else {2588return type;2589}2590}259125922593GNEDemandElement*2594GNERouteHandler::getRoute(const std::string& id) const {2595GNEDemandElement* type = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_ROUTE, id, false);2596if (type == nullptr) {2597return myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_ROUTE_DISTRIBUTION, id, false);2598} else {2599return type;2600}2601}260226032604GNEDemandElement*2605GNERouteHandler::getPersonParent(const CommonXMLStructure::SumoBaseObject* sumoBaseObject) const {2606// check that sumoBaseObject has parent2607if (sumoBaseObject->getParentSumoBaseObject() == nullptr) {2608return nullptr;2609}2610if ((sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_PERSON) &&2611(sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_PERSONFLOW)) {2612return nullptr;2613}2614// try it with person2615GNEDemandElement* personParent = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_PERSON, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);2616// if empty, try it with personFlow2617if (personParent == nullptr) {2618return myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_PERSONFLOW, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);2619} else {2620return personParent;2621}2622}262326242625GNEDemandElement*2626GNERouteHandler::getContainerParent(const CommonXMLStructure::SumoBaseObject* sumoBaseObject) const {2627// check that sumoBaseObject has parent2628if (sumoBaseObject->getParentSumoBaseObject() == nullptr) {2629return nullptr;2630}2631if ((sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_CONTAINER) &&2632(sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_CONTAINERFLOW)) {2633return nullptr;2634}2635// try it with container2636GNEDemandElement* containerParent = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_CONTAINER, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);2637// if empty, try it with containerFlow2638if (containerParent == nullptr) {2639return myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_CONTAINERFLOW, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);2640} else {2641return containerParent;2642}2643}264426452646GNEDemandElement*2647GNERouteHandler::getRouteDistributionParent(const CommonXMLStructure::SumoBaseObject* sumoBaseObject) const {2648// check that sumoBaseObject has parent2649if (sumoBaseObject->getParentSumoBaseObject() == nullptr) {2650return nullptr;2651}2652if (sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_ROUTE_DISTRIBUTION) {2653return nullptr;2654}2655return myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_ROUTE_DISTRIBUTION, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);2656}265726582659GNEDemandElement*2660GNERouteHandler::getVTypeDistributionParent(const CommonXMLStructure::SumoBaseObject* sumoBaseObject) const {2661// check that sumoBaseObject has parent2662if (sumoBaseObject->getParentSumoBaseObject() == nullptr) {2663return nullptr;2664}2665if (sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_VTYPE_DISTRIBUTION) {2666return nullptr;2667}2668return myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE_DISTRIBUTION, sumoBaseObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);2669}267026712672bool2673GNERouteHandler::getDistributionElements(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, SumoXMLTag distributionElementTag,2674const std::vector<std::string>& distributionElementIDs, const std::vector<double>& probabilities,2675std::vector<const GNEDemandElement*>& elements) {2676// get distribution tag and ID2677std::string distributionTag = toString(sumoBaseObject->getTag());2678std::string distributionID = sumoBaseObject->getStringAttribute(SUMO_ATTR_ID);2679// first parse vType IDs2680for (const auto& distributionElementID : distributionElementIDs) {2681auto distributionElement = myNet->getAttributeCarriers()->retrieveDemandElement(distributionElementTag, distributionElementID, false);2682if (distributionElement) {2683elements.push_back(distributionElement);2684} else {2685return writeError(TLF("% with id '%' doesn't exist in % '%'", toString(distributionElementTag), distributionElementID, distributionTag, distributionID));2686}2687}2688// check probabilities2689for (const auto& probability : probabilities) {2690if (probability < 0) {2691return writeError(TLF("invalid probability % in % '%'", toString(probability), distributionTag, distributionID));2692}2693}2694// check that number of elements and probabilities is the same2695if (elements.size() != probabilities.size()) {2696return writeError(TLF("Invalid type distribution probabilities in % '%'. Must have the same number of elements", distributionTag, distributionID));2697} else {2698return true;2699}2700}270127022703GNEDemandElement*2704GNERouteHandler::retrieveDemandElement(const std::vector<SumoXMLTag> tags, const std::string& id) {2705for (const auto& tag : tags) {2706// retrieve demand element2707auto demandElement = myNet->getAttributeCarriers()->retrieveDemandElement(tag, id, false);2708if (demandElement) {2709return demandElement;2710}2711}2712return nullptr;2713}271427152716bool2717GNERouteHandler::checkElement(const SumoXMLTag tag, GNEDemandElement* demandElement) {2718if (demandElement) {2719if (myOverwriteElements) {2720// delete element2721myNet->deleteDemandElement(demandElement, myNet->getUndoList());2722} else if (myRemainElements) {2723// duplicated demand2724return writeWarningDuplicated(tag, demandElement->getID(), demandElement->getTagProperty()->getTag());2725} else {2726// open overwrite dialog2727GNEOverwriteElement overwriteElementDialog(this, demandElement);2728// continue depending of result2729if (overwriteElementDialog.getResult() == GNEOverwriteElement::Result::ACCEPT) {2730// delete element2731myNet->deleteDemandElement(demandElement, myNet->getUndoList());2732} else if (overwriteElementDialog.getResult() == GNEOverwriteElement::Result::CANCEL) {2733// duplicated demand2734return writeWarningDuplicated(tag, demandElement->getID(), demandElement->getTagProperty()->getTag());2735} else {2736return false;2737}2738}2739}2740return true;2741}27422743/****************************************************************************/274427452746