Path: blob/main/src/netedit/elements/additional/GNEAccess.cpp
193871 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file GNEAccess.cpp14/// @author Pablo Alvarez Lopez15/// @date Jun 201816///17//18/****************************************************************************/19#include <config.h>2021#include <netedit/changes/GNEChange_Attribute.h>22#include <netedit/elements/moving/GNEMoveElementLaneSingle.h>23#include <netedit/GNENet.h>24#include <netedit/GNETagProperties.h>25#include <utils/gui/div/GLHelper.h>26#include <utils/xml/NamespaceIDs.h>2728#include "GNEAccess.h"29#include "GNEAdditionalHandler.h"3031// ===========================================================================32// member method definitions33// ===========================================================================3435GNEAccess::GNEAccess(GNENet* net) :36GNEAdditional(net, SUMO_TAG_ACCESS),37myMoveElementLaneSingle(new GNEMoveElementLaneSingle(this, SUMO_ATTR_POSITION, myPosOverLane, myFriendlyPos,38GNEMoveElementLaneSingle::PositionType::SINGLE)) {39}404142GNEAccess::GNEAccess(GNEAdditional* busStop, GNELane* lane, const double pos, const std::string& specialPos,43const bool friendlyPos, const double length, const Parameterised::Map& parameters) :44GNEAdditional(busStop, SUMO_TAG_ACCESS, ""),45Parameterised(parameters),46myPosOverLane(pos),47myFriendlyPos(friendlyPos),48myMoveElementLaneSingle(new GNEMoveElementLaneSingle(this, SUMO_ATTR_POSITION, myPosOverLane, myFriendlyPos,49GNEMoveElementLaneSingle::PositionType::SINGLE)),50mySpecialPosition(specialPos),51myLength(length) {52// set parents53setParent<GNELane*>(lane);54setParent<GNEAdditional*>(busStop);55// update centering boundary without updating grid56updateCenteringBoundary(false);57}585960GNEAccess::~GNEAccess() {61delete myMoveElementLaneSingle;62}636465GNEMoveElement*66GNEAccess::getMoveElement() const {67return myMoveElementLaneSingle;68}697071Parameterised*72GNEAccess::getParameters() {73return this;74}757677const Parameterised*78GNEAccess::getParameters() const {79return this;80}818283void84GNEAccess::updateGeometry() {85// set start position86double fixedPositionOverLane;87if (myPosOverLane < 0) {88fixedPositionOverLane = 0;89} else if (myPosOverLane > getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength()) {90fixedPositionOverLane = getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();91} else {92fixedPositionOverLane = myPosOverLane;93}94// update geometry95myAdditionalGeometry.updateGeometry(getParentLanes().front()->getLaneShape(), fixedPositionOverLane * getParentLanes().front()->getLengthGeometryFactor(), myMoveElementLaneSingle->myMovingLateralOffset);96}979899Position100GNEAccess::getPositionInView() const {101return myAdditionalGeometry.getShape().getPolygonCenter();102}103104105void106GNEAccess::updateCenteringBoundary(const bool /*updateGrid*/) {107// nothing to update108}109110111void112GNEAccess::splitEdgeGeometry(const double splitPosition, const GNENetworkElement* /*originalElement*/, const GNENetworkElement* newElement, GNEUndoList* undoList) {113if (splitPosition < myPosOverLane) {114// change lane115setAttribute(SUMO_ATTR_LANE, newElement->getID(), undoList);116// now adjust start position117setAttribute(SUMO_ATTR_POSITION, toString(myPosOverLane - splitPosition), undoList);118}119}120121122bool123GNEAccess::isAccessPositionFixed() const {124// with friendly position enabled position are "always fixed"125if (myFriendlyPos) {126return true;127} else {128if (myPosOverLane != INVALID_DOUBLE) {129return (myPosOverLane >= 0) && (myPosOverLane <= getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength());130} else {131return false;132}133}134}135136137void138GNEAccess::writeAdditional(OutputDevice& device) const {139device.openTag(SUMO_TAG_ACCESS);140// write common additional attributes141writeAdditionalAttributes(device);142// write move attributes143myMoveElementLaneSingle->writeMoveAttributes(device);144// write specific attributes145if (myLength != -1) {146device.writeAttr(SUMO_ATTR_LENGTH, myLength);147}148device.closeTag();149}150151152bool153GNEAccess::isAdditionalValid() const {154// only movement problems155return myMoveElementLaneSingle->isMoveElementValid();156}157158159std::string160GNEAccess::getAdditionalProblem() const {161// only movement problems162return myMoveElementLaneSingle->getMovingProblem();163}164165166void167GNEAccess::fixAdditionalProblem() {168// only movement problems169myMoveElementLaneSingle->fixMovingProblem();170}171172173bool174GNEAccess::checkDrawMoveContour() const {175// get edit modes176const auto& editModes = myNet->getViewNet()->getEditModes();177// check if we're in move mode178if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&179!myNet->getViewNet()->getEditNetworkElementShapes().getEditedNetworkElement() &&180(editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {181// only move the first element182return myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() == this;183} else {184return false;185}186}187188189GNEEdge*190GNEAccess::getEdge() const {191return getParentLanes().front()->getParentEdge();192}193194195std::string196GNEAccess::getParentName() const {197return getParentAdditionals().at(0)->getID();198}199200201void202GNEAccess::drawGL(const GUIVisualizationSettings& s) const {203// first check if additional has to be drawn204if (myNet->getViewNet()->getDataViewOptions().showAdditionals()) {205// Obtain exaggeration206const double accessExaggeration = getExaggeration(s);207// adjust radius depending of mode and distance to mouse position208double radius = 0.5;209if (myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork() &&210myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(myAdditionalGeometry.getShape().front()) < 1) {211radius = 1;212}213// get detail level214const auto d = s.getDetailLevel(1);215// draw geometry only if we'rent in drawForObjectUnderCursor mode216if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {217// get color218RGBColor accessColor;219if (drawUsingSelectColor()) {220accessColor = s.colorSettings.selectedAdditionalColor;221} else if (!getParentAdditionals().front()->getAttribute(SUMO_ATTR_COLOR).empty()) {222accessColor = parse<RGBColor>(getParentAdditionals().front()->getAttribute(SUMO_ATTR_COLOR));223} else if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_CONTAINER_STOP) {224accessColor = s.colorSettings.containerStopColor;225} else {226accessColor = s.colorSettings.busStopColor;227}228// draw parent and child lines229drawParentChildLines(s, accessColor);230// push layer matrix231GLHelper::pushMatrix();232// translate to front233drawInLayer(GLO_ACCESS);234// set color235GLHelper::setColor(accessColor);236// translate to geometry position237glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), 0);238// draw circle239GLHelper::drawFilledCircleDetailled(d, radius * accessExaggeration);240// pop layer matrix241GLHelper::popMatrix();242// draw lock icon243GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), myAdditionalGeometry.getShape().front(), accessExaggeration, 0.3);244// draw dotted contour245myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidthSmall, true);246}247// calculate contour248myAdditionalContour.calculateContourCircleShape(s, d, this, myAdditionalGeometry.getShape().front(), radius, getType(),249accessExaggeration, getParentLanes().front()->getParentEdge());250}251}252253254std::string255GNEAccess::getAttribute(SumoXMLAttr key) const {256switch (key) {257case SUMO_ATTR_ID:258return getParentAdditionals().front()->getID();259case SUMO_ATTR_POSITION:260if (myPosOverLane == INVALID_DOUBLE) {261return mySpecialPosition;262} else {263return myMoveElementLaneSingle->getMovingAttribute(key);264}265case SUMO_ATTR_LENGTH:266if (myLength == -1) {267return "";268} else {269return toString(myLength);270}271case GNE_ATTR_PARENT:272if (isTemplate()) {273return "";274} else {275return getParentAdditionals().at(0)->getID();276}277case GNE_ATTR_SHIFTLANEINDEX:278return "";279default:280return myMoveElementLaneSingle->getMovingAttribute(key);281}282}283284285double286GNEAccess::getAttributeDouble(SumoXMLAttr key) const {287return myMoveElementLaneSingle->getMovingAttributeDouble(key);288}289290291Position292GNEAccess::getAttributePosition(SumoXMLAttr key) const {293return myMoveElementLaneSingle->getMovingAttributePosition(key);294}295296297PositionVector298GNEAccess::getAttributePositionVector(SumoXMLAttr key) const {299return getCommonAttributePositionVector(key);300}301302303void304GNEAccess::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {305switch (key) {306case SUMO_ATTR_LENGTH:307case GNE_ATTR_PARENT:308case GNE_ATTR_SHIFTLANEINDEX:309GNEChange_Attribute::changeAttribute(this, key, value, undoList);310break;311default:312myMoveElementLaneSingle->setMovingAttribute(key, value, undoList);313break;314}315}316317318bool319GNEAccess::isValid(SumoXMLAttr key, const std::string& value) {320switch (key) {321case SUMO_ATTR_LANE: {322// check lane323if (!myMoveElementLaneSingle->isMovingAttributeValid(key, value)) {324return false;325} else {326// check if exist another access for the same parent in the given edge327const auto lane = myNet->getAttributeCarriers()->retrieveLane(value);328return GNEAdditionalHandler::accessExists(getParentAdditionals().at(0), lane->getParentEdge());329}330}331case SUMO_ATTR_POSITION:332if (value.empty() || (value == "random") || (value == "doors") || (value == "carriage")) {333return true;334} else {335return myMoveElementLaneSingle->isMovingAttributeValid(key, value);336}337case SUMO_ATTR_LENGTH:338if (canParse<double>(value)) {339const double valueDouble = parse<double>(value);340return (valueDouble == -1) || (valueDouble >= 0);341} else {342return false;343}344case GNE_ATTR_PARENT:345return (myNet->getAttributeCarriers()->retrieveAdditionals(NamespaceIDs::busStops, value, false) != nullptr);346default:347return myMoveElementLaneSingle->isMovingAttributeValid(key, value);348}349}350351352std::string353GNEAccess::getPopUpID() const {354return getTagStr();355}356357358std::string359GNEAccess::getHierarchyName() const {360return getTagStr() + ": " + getParentLanes().front()->getParentEdge()->getID();361}362363// ===========================================================================364// private365// ===========================================================================366367void368GNEAccess::setAttribute(SumoXMLAttr key, const std::string& value) {369switch (key) {370case SUMO_ATTR_LANE:371replaceAdditionalParentLanes(value);372break;373case SUMO_ATTR_POSITION:374if (value.empty()) {375myPosOverLane = 0;376} else if (value == "random" || value == "doors" || value == "carriage") {377myPosOverLane = INVALID_DOUBLE;378mySpecialPosition = value;379} else {380myMoveElementLaneSingle->setMovingAttribute(key, value);381}382break;383case SUMO_ATTR_LENGTH:384if (value.empty()) {385myLength = myTagProperty->getDefaultDoubleValue(key);386} else {387myLength = parse<double>(value);388}389break;390case GNE_ATTR_PARENT:391if (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, value, false) != nullptr) {392replaceAdditionalParent(SUMO_TAG_BUS_STOP, value, 0);393} else if (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRAIN_STOP, value, false) != nullptr) {394replaceAdditionalParent(SUMO_TAG_TRAIN_STOP, value, 0);395} else {396replaceAdditionalParent(SUMO_TAG_CONTAINER_STOP, value, 0);397}398break;399case GNE_ATTR_SHIFTLANEINDEX:400shiftLaneIndex();401break;402default:403myMoveElementLaneSingle->setMovingAttribute(key, value);404break;405}406}407408/****************************************************************************/409410411