Path: blob/main/src/netedit/elements/demand/GNEContainer.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 GNEContainer.cpp14/// @author Pablo Alvarez Lopez15/// @date May 201916///17// Representation of containers in netedit18/****************************************************************************/1920#include <microsim/devices/MSDevice_BTreceiver.h>21#include <netedit/changes/GNEChange_Attribute.h>22#include <netedit/elements/moving/GNEMoveElementPlanParent.h>23#include <netedit/GNENet.h>24#include <netedit/GNETagProperties.h>25#include <utils/gui/div/GLHelper.h>26#include <utils/gui/div/GUIDesigns.h>27#include <utils/gui/images/GUITextureSubSys.h>28#include <utils/gui/windows/GUIAppEnum.h>29#include <utils/xml/NamespaceIDs.h>3031#include "GNEContainer.h"32#include "GNERouteHandler.h"3334// ===========================================================================35// FOX callback mapping36// ===========================================================================3738FXDEFMAP(GNEContainer::GNEContainerPopupMenu) containerPopupMenuMap[] = {39FXMAPFUNC(SEL_COMMAND, MID_GNE_CONTAINER_TRANSFORM, GNEContainer::GNEContainerPopupMenu::onCmdTransform),40};4142FXDEFMAP(GNEContainer::GNESelectedContainersPopupMenu) selectedContainersPopupMenuMap[] = {43FXMAPFUNC(SEL_COMMAND, MID_GNE_CONTAINER_TRANSFORM, GNEContainer::GNESelectedContainersPopupMenu::onCmdTransform),44};4546// Object implementation47FXIMPLEMENT(GNEContainer::GNEContainerPopupMenu, GUIGLObjectPopupMenu, containerPopupMenuMap, ARRAYNUMBER(containerPopupMenuMap))48FXIMPLEMENT(GNEContainer::GNESelectedContainersPopupMenu, GUIGLObjectPopupMenu, selectedContainersPopupMenuMap, ARRAYNUMBER(selectedContainersPopupMenuMap))4950// ===========================================================================51// GNEContainer::GNEContainerPopupMenu52// ===========================================================================5354GNEContainer::GNEContainerPopupMenu::GNEContainerPopupMenu(GNEContainer* container, GUIMainWindow& app, GUISUMOAbstractView& parent) :55GUIGLObjectPopupMenu(app, parent, container),56myContainer(container),57myTransformToContainer(nullptr),58myTransformToContainerFlow(nullptr) {59// build common options60container->buildPopUpMenuCommonOptions(this, app, container->myNet->getViewNet(), container->getTagProperty()->getTag(), container->isAttributeCarrierSelected());61// add transform functions only in demand mode62if (myContainer->getNet()->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {63// create menu pane for transform operations64FXMenuPane* transformOperation = new FXMenuPane(this);65this->insertMenuPaneChild(transformOperation);66new FXMenuCascade(this, "transform to", nullptr, transformOperation);67// Create menu comands for all transformations68myTransformToContainer = GUIDesigns::buildFXMenuCommand(transformOperation, "Container", GUIIconSubSys::getIcon(GUIIcon::CONTAINER), this, MID_GNE_CONTAINER_TRANSFORM);69myTransformToContainerFlow = GUIDesigns::buildFXMenuCommand(transformOperation, "ContainerFlow", GUIIconSubSys::getIcon(GUIIcon::CONTAINERFLOW), this, MID_GNE_CONTAINER_TRANSFORM);70// check what menu command has to be disabled71if (myContainer->getTagProperty()->getTag() == SUMO_TAG_CONTAINER) {72myTransformToContainer->disable();73} else if (myContainer->getTagProperty()->getTag() == SUMO_TAG_CONTAINERFLOW) {74myTransformToContainerFlow->disable();75}76}77}787980GNEContainer::GNEContainerPopupMenu::~GNEContainerPopupMenu() {}818283long84GNEContainer::GNEContainerPopupMenu::onCmdTransform(FXObject* obj, FXSelector, void*) {85if (obj == myTransformToContainer) {86GNERouteHandler::transformToContainer(myContainer);87} else if (obj == myTransformToContainerFlow) {88GNERouteHandler::transformToContainerFlow(myContainer);89}90return 1;91}929394// ===========================================================================95// GNEContainer::GNESelectedContainersPopupMenu96// ===========================================================================9798GNEContainer::GNESelectedContainersPopupMenu::GNESelectedContainersPopupMenu(GNEContainer* container, const std::vector<GNEContainer*>& selectedContainer, GUIMainWindow& app, GUISUMOAbstractView& parent) :99GUIGLObjectPopupMenu(app, parent, container),100myContainerTag(container->getTagProperty()->getTag()),101mySelectedContainers(selectedContainer),102myTransformToContainer(nullptr),103myTransformToContainerFlow(nullptr) {104// build common options105container->buildPopUpMenuCommonOptions(this, app, container->myNet->getViewNet(), container->getTagProperty()->getTag(), container->isAttributeCarrierSelected());106// add transform functions only in demand mode107if (container->getNet()->getViewNet()->getEditModes().isCurrentSupermodeDemand()) {108// create menu pane for transform operations109FXMenuPane* transformOperation = new FXMenuPane(this);110this->insertMenuPaneChild(transformOperation);111new FXMenuCascade(this, "transform to", nullptr, transformOperation);112// Create menu comands for all transformations113myTransformToContainer = GUIDesigns::buildFXMenuCommand(transformOperation, "Container", GUIIconSubSys::getIcon(GUIIcon::CONTAINER), this, MID_GNE_CONTAINER_TRANSFORM);114myTransformToContainerFlow = GUIDesigns::buildFXMenuCommand(transformOperation, "ContainerFlow", GUIIconSubSys::getIcon(GUIIcon::CONTAINERFLOW), this, MID_GNE_CONTAINER_TRANSFORM);115}116}117118119GNEContainer::GNESelectedContainersPopupMenu::~GNESelectedContainersPopupMenu() {}120121122long123GNEContainer::GNESelectedContainersPopupMenu::onCmdTransform(FXObject* obj, FXSelector, void*) {124// iterate over all selected containers125for (const auto& container : mySelectedContainers) {126if ((obj == myTransformToContainer) &&127(container->getTagProperty()->getTag() == myContainerTag)) {128GNERouteHandler::transformToContainer(container);129} else if ((obj == myTransformToContainerFlow) &&130(container->getTagProperty()->getTag() == myContainerTag)) {131GNERouteHandler::transformToContainer(container);132}133}134return 1;135}136137// ===========================================================================138// member method definitions139// ===========================================================================140141#ifdef _MSC_VER142#pragma warning(push)143#pragma warning(disable: 4355) // mask warning about "this" in initializers144#endif145GNEContainer::GNEContainer(SumoXMLTag tag, GNENet* net) :146GNEDemandElement(net, tag),147GNEDemandElementFlow(this),148myMoveElementPlanParent(new GNEMoveElementPlanParent(this, departPos, departPosProcedure)) {149// set end and container per hours as default flow values150toggleAttribute(SUMO_ATTR_END, 1);151toggleAttribute(SUMO_ATTR_CONTAINERSPERHOUR, 1);152}153154155GNEContainer::GNEContainer(SumoXMLTag tag, GNENet* net, FileBucket* fileBucket,156GNEDemandElement* pType, const SUMOVehicleParameter& containerparameters) :157GNEDemandElement(containerparameters.id, net, tag, fileBucket),158GNEDemandElementFlow(this, containerparameters),159myMoveElementPlanParent(new GNEMoveElementPlanParent(this, departPos, departPosProcedure)) {160// set parents161setParent<GNEDemandElement*>(pType);162// set manually vtypeID (needed for saving)163vtypeid = pType->getID();164}165#ifdef _MSC_VER166#pragma warning(pop)167#endif168169GNEContainer::~GNEContainer() {}170171172GNEMoveElement*173GNEContainer::getMoveElement() const {174return myMoveElementPlanParent;175}176177178Parameterised*179GNEContainer::getParameters() {180return this;181}182183184const Parameterised*185GNEContainer::getParameters() const {186return this;187}188189190void191GNEContainer::writeDemandElement(OutputDevice& device) const {192// attribute VType musn't be written if is DEFAULT_PEDTYPE_ID193if (getTypeParent()->getID() == DEFAULT_CONTAINERTYPE_ID) {194// unset VType parameter195parametersSet &= ~VEHPARS_VTYPE_SET;196// write container attributes (VType will not be written)197write(device, OptionsCont::getOptions(), myTagProperty->getXMLTag());198// set VType parameter again199parametersSet |= VEHPARS_VTYPE_SET;200} else {201// write container attributes, including VType202write(device, OptionsCont::getOptions(), myTagProperty->getXMLTag(), getTypeParent()->getID());203}204// write parameters205writeParams(device);206// write child demand elements associated to this container (Rides, Walks...)207for (const auto& containerPlan : getChildDemandElements()) {208containerPlan->writeDemandElement(device);209}210// close container tag211device.closeTag();212}213214215GNEDemandElement::Problem216GNEContainer::isDemandElementValid() const {217if (getChildDemandElements().size() == 0) {218return Problem::NO_PLANS;219} else {220return Problem::OK;221}222}223224225std::string226GNEContainer::getDemandElementProblem() const {227if (getChildDemandElements().size() == 0) {228return "Container needs at least one plan";229} else {230return "";231}232}233234235void236GNEContainer::fixDemandElementProblem() {237// nothing to fix238}239240241SUMOVehicleClass242GNEContainer::getVClass() const {243return getParentDemandElements().front()->getVClass();244}245246247const RGBColor&248GNEContainer::getColor() const {249return color;250}251252253void254GNEContainer::updateGeometry() {255// only update geometry of childrens256for (const auto& demandElement : getChildDemandElements()) {257demandElement->updateGeometry();258}259}260261262Position263GNEContainer::getPositionInView() const {264return getAttributePosition(SUMO_ATTR_DEPARTPOS);265}266267268GUIGLObjectPopupMenu*269GNEContainer::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {270// return a GNEContainerPopupMenu271return new GNEContainerPopupMenu(this, app, parent);272}273274275std::string276GNEContainer::getParentName() const {277return getParentDemandElements().front()->getID();278}279280281double282GNEContainer::getExaggeration(const GUIVisualizationSettings& s) const {283return s.containerSize.getExaggeration(s, this, 80);284}285286287Boundary288GNEContainer::getCenteringBoundary() const {289Boundary containerBoundary;290if (getChildDemandElements().size() > 0) {291if (getChildDemandElements().front()->getTagProperty()->isPlanStopContainer()) {292// use boundary of stop center293return getChildDemandElements().front()->getCenteringBoundary();294} else {295containerBoundary.add(getPositionInView());296}297} else {298containerBoundary = Boundary(-0.1, -0.1, 0.1, 0.1);299}300containerBoundary.grow(20);301return containerBoundary;302}303304305void306GNEContainer::splitEdgeGeometry(const double /*splitPosition*/, const GNENetworkElement* /*originalElement*/,307const GNENetworkElement* /*newElement*/, GNEUndoList* /*undoList*/) {308// geometry of this element cannot be splitted309}310311312void313GNEContainer::drawGL(const GUIVisualizationSettings& s) const {314bool drawContainer = true;315// check if container can be drawn316if (!myNet->getViewNet()->getNetworkViewOptions().showDemandElements()) {317drawContainer = false;318} else if (!myNet->getViewNet()->getDataViewOptions().showDemandElements()) {319drawContainer = false;320} else if (!myNet->getViewNet()->getDemandViewOptions().showNonInspectedDemandElements(this)) {321drawContainer = false;322} else if (getChildDemandElements().empty()) {323drawContainer = false;324}325// continue if container can be drawn326if (drawContainer) {327// obtain exaggeration (and add the special containerExaggeration)328const double exaggeration = getExaggeration(s) + 10;329// get detail level330const auto d = s.getDetailLevel(exaggeration);331// obtain position332const Position containerPosition = getAttributePosition(SUMO_ATTR_DEPARTPOS);333if (containerPosition == Position::INVALID) {334return;335}336// draw geometry only if we'rent in drawForObjectUnderCursor mode337if (s.checkDrawContainer(d, isAttributeCarrierSelected())) {338// obtain img file339const std::string file = getTypeParent()->getAttribute(SUMO_ATTR_IMGFILE);340// push draw matrix341GLHelper::pushMatrix();342// Start with the drawing of the area traslating matrix to origin343drawInLayer(getType());344// translate and rotate345glTranslated(containerPosition.x(), containerPosition.y(), 0);346glRotated(90, 0, 0, 1);347// set container color348GLHelper::setColor(getDrawingColor(s));349// set scale350glScaled(exaggeration, exaggeration, 1);351// draw container depending of detail level352switch (s.containerQuality) {353case 0:354case 1:355case 2:356drawAction_drawAsPoly();357break;358case 3:359default:360drawAction_drawAsImage(s);361break;362}363// pop matrix364GLHelper::popMatrix();365// draw line between junctions if container plan isn't valid366for (const auto& containerPlan : getChildDemandElements()) {367if (containerPlan->getTagProperty()->isPlanContainer() && (containerPlan->getParentJunctions().size() > 0) &&368!myNet->getDemandPathManager()->isPathValid(containerPlan)) {369drawJunctionLine(containerPlan);370}371}372// draw stack label373if (myStackedLabelNumber > 0) {374drawStackLabel(myStackedLabelNumber, "container", Position(containerPosition.x() - 2.5, containerPosition.y() - 0.8), -90, 1.3, 5, getExaggeration(s));375} else if (getChildDemandElements().front()->getTagProperty()->getTag() == GNE_TAG_STOPCONTAINER_CONTAINERSTOP) {376// declare counter for stacked containers over stops377int stackedCounter = 0;378// get stoppingPlace379const auto stoppingPlace = getChildDemandElements().front()->getParentAdditionals().front();380// get stacked containers381for (const auto& stopContainer : stoppingPlace->getChildDemandElements()) {382if (stopContainer->getTagProperty()->getTag() == GNE_TAG_STOPCONTAINER_CONTAINERSTOP) {383// get container parent384const auto containerParent = stopContainer->getParentDemandElements().front();385// check if the stop if the first container plan parent386if (stopContainer->getPreviousChildDemandElement(containerParent) == nullptr) {387stackedCounter++;388}389}390}391// if we have more than two stacked elements, draw label392if (stackedCounter > 1) {393drawStackLabel(stackedCounter, "container", Position(containerPosition.x() - 2.5, containerPosition.y() - 0.8), -90, 1.3, 5, getExaggeration(s));394}395}396// draw flow label397if (myTagProperty->isFlow()) {398drawFlowLabel(Position(containerPosition.x() - 1, containerPosition.y() - 4.25), -90, 1.8, 2, getExaggeration(s));399}400// draw name401drawName(containerPosition, s.scale, s.containerName, s.angle);402// draw lock icon403GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), getPositionInView(), exaggeration);404// draw dotted contour405myContainerContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);406}407// calculate contour408myContainerContour.calculateContourRectangleShape(s, d, this, containerPosition, 0.5, 0.18, getType(), -5.5, 0, 0, exaggeration, nullptr);409}410}411412413void414GNEContainer::computePathElement() {415// compute all container plan children (because aren't computed in "computeDemandElements()")416for (const auto& demandElement : getChildDemandElements()) {417demandElement->computePathElement();418}419}420421422void423GNEContainer::drawLanePartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {424// Stops don't use drawJunctionPartialGL425}426427428void429GNEContainer::drawJunctionPartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {430// Stops don't use drawJunctionPartialGL431}432433434GNELane*435GNEContainer::getFirstPathLane() const {436// use path lane of first container plan437return getChildDemandElements().front()->getFirstPathLane();438}439440441GNELane*442GNEContainer::getLastPathLane() const {443// use path lane of first container plan444return getChildDemandElements().front()->getLastPathLane();445}446447448std::string449GNEContainer::getAttribute(SumoXMLAttr key) const {450// declare string error451std::string error;452switch (key) {453case SUMO_ATTR_ID:454return getMicrosimID();455case SUMO_ATTR_TYPE:456return getTypeParent()->getID();457case SUMO_ATTR_COLOR:458if (wasSet(VEHPARS_COLOR_SET)) {459return toString(color);460} else {461return myTagProperty->getDefaultStringValue(SUMO_ATTR_COLOR);462}463case SUMO_ATTR_DEPARTPOS:464if (wasSet(VEHPARS_DEPARTPOS_SET)) {465return getDepartPos();466} else {467return myTagProperty->getDefaultStringValue(SUMO_ATTR_DEPARTPOS);468}469default:470return getFlowAttribute(this, key);471}472}473474475double476GNEContainer::getAttributeDouble(SumoXMLAttr key) const {477switch (key) {478case SUMO_ATTR_DEPARTPOS:479if (departPosProcedure == DepartPosDefinition::GIVEN) {480return departPos;481} else {482return 0;483}484default:485return getFlowAttributeDouble(key);486}487}488489490Position491GNEContainer::getAttributePosition(SumoXMLAttr key) const {492switch (key) {493case SUMO_ATTR_DEPARTPOS: {494// first check number of child demand elements495if (getChildDemandElements().empty()) {496return Position();497}498// get container plan499const GNEDemandElement* containerPlan = getChildDemandElements().front();500// first check if first container plan is a stop501if (containerPlan->getTagProperty()->isPlanStopContainer()) {502// stop center503return containerPlan->getPositionInView();504} else if (containerPlan->getTagProperty()->planFromTAZ()) {505// TAZ506if (containerPlan->getParentAdditionals().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {507return containerPlan->getParentAdditionals().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);508} else {509return containerPlan->getParentAdditionals().front()->getAttributePosition(SUMO_ATTR_CENTER);510}511} else if (containerPlan->getTagProperty()->planFromJunction()) {512// juncrtion513return containerPlan->getParentJunctions().front()->getPositionInView();514} else {515return containerPlan->getAttributePosition(GNE_ATTR_PLAN_GEOMETRY_STARTPOS);516}517}518default:519return getCommonAttributePosition(key);520}521}522523524void525GNEContainer::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {526switch (key) {527case SUMO_ATTR_ID:528case SUMO_ATTR_TYPE:529case SUMO_ATTR_COLOR:530case SUMO_ATTR_DEPARTPOS:531GNEChange_Attribute::changeAttribute(this, key, value, undoList);532break;533default:534setFlowAttribute(this, key, value, undoList);535break;536}537}538539540bool541GNEContainer::isValid(SumoXMLAttr key, const std::string& value) {542// declare string error543std::string error;544switch (key) {545case SUMO_ATTR_ID:546return isValidDemandElementID(NamespaceIDs::containers, value);547case SUMO_ATTR_TYPE:548return (myNet->getAttributeCarriers()->retrieveDemandElements(NamespaceIDs::types, value, false) != nullptr);549case SUMO_ATTR_COLOR:550return canParse<RGBColor>(value);551case SUMO_ATTR_DEPARTPOS: {552double dummyDepartPos;553DepartPosDefinition dummyDepartPosProcedure;554parseDepartPos(value, myTagProperty->getTagStr(), id, dummyDepartPos, dummyDepartPosProcedure, error);555// if error is empty, given value is valid556return error.empty();557}558default:559return isValidFlowAttribute(this, key, value);560}561}562563564void565GNEContainer::enableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {566enableFlowAttribute(this, key, undoList);567}568569570void571GNEContainer::disableAttribute(SumoXMLAttr key, GNEUndoList* undoList) {572disableFlowAttribute(this, key, undoList);573}574575576bool577GNEContainer::isAttributeEnabled(SumoXMLAttr key) const {578return isFlowAttributeEnabled(key);579}580581582std::string583GNEContainer::getPopUpID() const {584return getTagStr();585}586587588std::string589GNEContainer::getHierarchyName() const {590const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();591// special case for Trips and flow592if ((myTagProperty->getTag() == SUMO_TAG_TRIP) || (myTagProperty->getTag() == SUMO_TAG_FLOW)) {593// check if we're inspecting an Edge594if (inspectedElements.getFirstAC() && (inspectedElements.getFirstAC()->getTagProperty()->getTag() == SUMO_TAG_EDGE)) {595// check if edge correspond to a "from", "to" or "via" edge596if (inspectedElements.isACInspected(getParentEdges().front())) {597return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID) + " (from)";598} else if (inspectedElements.isACInspected(getParentEdges().front())) {599return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID) + " (to)";600} else {601// iterate over via602for (const auto& viaEdgeID : via) {603if (viaEdgeID == inspectedElements.getFirstAC()->getID()) {604return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID) + " (via)";605}606}607}608}609}610return getTagStr() + ": " + getAttribute(SUMO_ATTR_ID);611}612613// ===========================================================================614// protected615// ===========================================================================616617RGBColor618GNEContainer::getDrawingColor(const GUIVisualizationSettings& s) const {619// change color620if (drawUsingSelectColor()) {621return s.colorSettings.selectedContainerColor;622} else {623return getColorByScheme(s.containerColorer, this);624}625}626627628void629GNEContainer::drawAction_drawAsPoly() const {630// obtain width and length631const double length = getTypeParent()->getAttributeDouble(SUMO_ATTR_LENGTH);632const double width = getTypeParent()->getAttributeDouble(SUMO_ATTR_WIDTH);633// draw pedestrian shape634glScaled(length * 0.2, width * 0.2, 1);635glBegin(GL_QUADS);636glVertex2d(0, 0.5);637glVertex2d(0, -0.5);638glVertex2d(-1, -0.5);639glVertex2d(-1, 0.5);640glEnd();641GLHelper::setColor(GLHelper::getColor().changedBrightness(-30));642glTranslated(0, 0, .045);643glBegin(GL_QUADS);644glVertex2d(-0.1, 0.4);645glVertex2d(-0.1, -0.4);646glVertex2d(-0.9, -0.4);647glVertex2d(-0.9, 0.4);648glEnd();649}650651652void653GNEContainer::drawAction_drawAsImage(const GUIVisualizationSettings& s) const {654const std::string& file = getTypeParent()->getAttribute(SUMO_ATTR_IMGFILE);655// obtain width and length656const double length = getTypeParent()->getAttributeDouble(SUMO_ATTR_LENGTH);657const double width = getTypeParent()->getAttributeDouble(SUMO_ATTR_WIDTH);658if (file != "") {659// @todo invent an option for controlling whether images should be rotated or not660//if (getVehicleType().getGuiShape() == SVS_CONTAINER) {661// glRotated(RAD2DEG(getAngle() + M_PI / 2.), 0, 0, 1);662//}663int textureID = GUITexturesHelper::getTextureID(file);664if (textureID > 0) {665const double exaggeration = s.containerSize.getExaggeration(s, this);666const double halfLength = length / 2.0 * exaggeration;667const double halfWidth = width / 2.0 * exaggeration;668GUITexturesHelper::drawTexturedBox(textureID, -halfWidth, -halfLength, halfWidth, halfLength);669}670} else {671// fallback if no image is defined672drawAction_drawAsPoly();673}674}675676// ===========================================================================677// private678// ===========================================================================679680GNEContainer::containerPlanSegment::containerPlanSegment(GNEDemandElement* _containerPlan) :681containerPlan(_containerPlan),682edge(nullptr),683arrivalPos(-1) {684}685686687GNEContainer::containerPlanSegment::containerPlanSegment() :688containerPlan(nullptr),689edge(nullptr),690arrivalPos(-1) {691}692693694void695GNEContainer::setAttribute(SumoXMLAttr key, const std::string& value) {696// declare string error697std::string error;698switch (key) {699case SUMO_ATTR_ID:700// update microsimID701setDemandElementID(value);702// update id703id = value;704break;705case SUMO_ATTR_TYPE:706if (getID().size() > 0) {707replaceDemandElementParent(NamespaceIDs::types, value, 0);708// set manually vtypeID (needed for saving)709vtypeid = value;710}711break;712case SUMO_ATTR_COLOR:713if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {714color = parse<RGBColor>(value);715// mark parameter as set716parametersSet |= VEHPARS_COLOR_SET;717} else {718// set default value719color = parse<RGBColor>(myTagProperty->getDefaultStringValue(key));720// unset parameter721parametersSet &= ~VEHPARS_COLOR_SET;722}723break;724case SUMO_ATTR_DEPARTPOS:725if (!value.empty() && (value != myTagProperty->getDefaultStringValue(key))) {726parseDepartPos(value, myTagProperty->getTagStr(), id, departPos, departPosProcedure, error);727// mark parameter as set728parametersSet |= VEHPARS_DEPARTPOS_SET;729} else {730// set default value731parseDepartPos(myTagProperty->getDefaultStringValue(key), myTagProperty->getTagStr(), id, departPos, departPosProcedure, error);732// unset parameter733parametersSet &= ~VEHPARS_DEPARTPOS_SET;734}735// compute container736updateGeometry();737break;738default:739setFlowAttribute(this, key, value);740break;741}742}743744void745GNEContainer::toggleAttribute(SumoXMLAttr key, const bool value) {746// toggle flow attributes747toggleFlowAttribute(key, value);748}749750/****************************************************************************/751752753