Path: blob/main/src/netedit/elements/additional/GNEParkingArea.cpp
169684 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file GNEParkingArea.cpp14/// @author Pablo Alvarez Lopez15/// @date Feb 201816///17// A lane area vehicles can park at (GNE version)18/****************************************************************************/1920#include <netedit/GNENet.h>21#include <netedit/GNETagProperties.h>22#include <netedit/changes/GNEChange_Attribute.h>23#include <utils/gui/div/GLHelper.h>24#include <utils/options/OptionsCont.h>25#include <utils/vehicle/SUMORouteHandler.h>2627#include "GNEParkingArea.h"2829// ===========================================================================30// method definitions31// ===========================================================================3233GNEParkingArea::GNEParkingArea(GNENet* net) :34GNEStoppingPlace(net, SUMO_TAG_PARKING_AREA) {35}363738GNEParkingArea::GNEParkingArea(const std::string& id, GNENet* net, const std::string& filename, GNELane* lane, const double startPos, const double endPos,39const std::string& departPos, const std::string& name, const std::vector<std::string>& badges,40const bool friendlyPosition, const int roadSideCapacity, const bool onRoad, const double width,41const double length, const double angle, const bool lefthand, const Parameterised::Map& parameters) :42GNEStoppingPlace(id, net, filename, SUMO_TAG_PARKING_AREA, lane, startPos,43endPos, name, friendlyPosition, RGBColor::INVISIBLE, angle, parameters),44myDepartPos(departPos),45myRoadSideCapacity(roadSideCapacity),46myOnRoad(onRoad),47myWidth(width),48myLength(length),49myLefthand(lefthand),50myAcceptedBadges(badges) {51// update centering boundary without updating grid52updateCenteringBoundary(false);53}545556GNEParkingArea::~GNEParkingArea() {}575859void60GNEParkingArea::writeAdditional(OutputDevice& device) const {61device.openTag(getTagProperty()->getTag());62// write common attributes63writeStoppingPlaceAttributes(device);64// write specific attributes65if (myRoadSideCapacity != myTagProperty->getDefaultIntValue(SUMO_ATTR_ROADSIDE_CAPACITY)) {66device.writeAttr(SUMO_ATTR_ROADSIDE_CAPACITY, myRoadSideCapacity);67}68if (myOnRoad != myTagProperty->getDefaultBoolValue(SUMO_ATTR_ONROAD)) {69device.writeAttr(SUMO_ATTR_ONROAD, myOnRoad);70}71if (myWidth != myTagProperty->getDefaultDoubleValue(SUMO_ATTR_WIDTH)) {72device.writeAttr(SUMO_ATTR_WIDTH, myWidth);73}74if (myLength != myTagProperty->getDefaultDoubleValue(SUMO_ATTR_LENGTH)) {75device.writeAttr(SUMO_ATTR_LENGTH, myLength);76}77if (myDepartPos != myTagProperty->getDefaultStringValue(SUMO_ATTR_DEPARTPOS)) {78device.writeAttr(SUMO_ATTR_DEPARTPOS, myDepartPos);79}80if (myLefthand != myTagProperty->getDefaultBoolValue(SUMO_ATTR_LEFTHAND)) {81device.writeAttr(SUMO_ATTR_LEFTHAND, myLefthand);82}83if (getAttribute(SUMO_ATTR_ACCEPTED_BADGES) != myTagProperty->getDefaultStringValue(SUMO_ATTR_ACCEPTED_BADGES)) {84device.writeAttr(SUMO_ATTR_ACCEPTED_BADGES, toString(myAcceptedBadges));85}86// write all parking spaces87for (const auto& space : getChildAdditionals()) {88if (space->getTagProperty()->getTag() == SUMO_TAG_PARKING_SPACE) {89space->writeAdditional(device);90}91}92// write parameters (Always after children to avoid problems with additionals.xsd)93writeParams(device);94device.closeTag();95}969798void99GNEParkingArea::updateGeometry() {100// Get value of option "lefthand"101const double offsetSign = OptionsCont::getOptions().getBool("lefthand") != myLefthand ? -1 : 1;102// calculate spaceDim103const double spaceDim = myRoadSideCapacity > 0 ? (getAttributeDouble(SUMO_ATTR_ENDPOS) - getAttributeDouble(SUMO_ATTR_STARTPOS)) / myRoadSideCapacity * getParentLanes().front()->getLengthGeometryFactor() : 7.5;104// calculate length105const double length = (myLength > 0) ? myLength : spaceDim;106// Update common geometry of stopping place107setStoppingPlaceGeometry(myWidth);108// Obtain a copy of the shape109PositionVector tmpShape = myAdditionalGeometry.getShape();110// Move shape to side111tmpShape.move2side(1.5 * offsetSign + myWidth);112// Get position of the sign113mySymbolPosition = tmpShape.getLineCenter();114// clear LotSpaceDefinitions115myLotSpaceDefinitions.clear();116// iterate over117for (int i = 0; i < myRoadSideCapacity; ++i) {118// calculate pos119const Position pos = GeomHelper::calculateLotSpacePosition(myAdditionalGeometry.getShape(), i, spaceDim, myAngle, myWidth, length);120// calculate angle121const double angle = GeomHelper::calculateLotSpaceAngle(myAdditionalGeometry.getShape(), i, spaceDim, myAngle);122// add GNElotEntry123myLotSpaceDefinitions.push_back(GNELotSpaceDefinition(pos.x(), pos.y(), pos.z(), angle, myWidth, length));124}125}126127128void129GNEParkingArea::drawGL(const GUIVisualizationSettings& s) const {130// first check if additional has to be drawn131if (myNet->getViewNet()->getDataViewOptions().showAdditionals()) {132// Obtain exaggeration of the draw133const double parkingAreaExaggeration = getExaggeration(s);134// check if draw moving geometry points135const bool movingGeometryPoints = drawMovingGeometryPoints(false);136// get detail level137const auto d = s.getDetailLevel(parkingAreaExaggeration);138// draw geometry only if we'rent in drawForObjectUnderCursor mode139if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {140// declare colors141RGBColor baseColor, signColor;142// set colors143if (mySpecialColor) {144baseColor = *mySpecialColor;145signColor = baseColor.changedBrightness(-32);146} else if (drawUsingSelectColor()) {147baseColor = s.colorSettings.selectedAdditionalColor;148signColor = baseColor.changedBrightness(-32);149} else {150baseColor = s.colorSettings.parkingAreaColor;151signColor = s.colorSettings.parkingAreaColorSign;152}153// draw parent and child lines154drawParentChildLines(s, s.additionalSettings.connectionColor);155// Add a layer matrix156GLHelper::pushMatrix();157// translate to front158drawInLayer(GLO_PARKING_AREA);159// set base color160GLHelper::setColor(baseColor);161// Draw the area using shape, shapeRotations, shapeLengths and value of exaggeration162GUIGeometry::drawGeometry(d, myAdditionalGeometry, myWidth * 0.5 * MIN2(1.0, parkingAreaExaggeration));163// draw sign164drawSign(s, d, parkingAreaExaggeration, baseColor, signColor, "P");165// Traslate to front166glTranslated(0, 0, 0.1);167// draw lotSpaceDefinitions168if (d <= GUIVisualizationSettings::Detail::AdditionalDetails) {169for (const auto& lsd : myLotSpaceDefinitions) {170GLHelper::drawSpaceOccupancies(parkingAreaExaggeration, lsd.position, lsd.rotation, lsd.width, lsd.length, true);171}172}173// draw geometry points174if (movingGeometryPoints && (myStartPosition != INVALID_DOUBLE)) {175drawLeftGeometryPoint(s, d, myAdditionalGeometry.getShape().front(), myAdditionalGeometry.getShapeRotations().front(), baseColor);176}177if (movingGeometryPoints && (myEndPosition != INVALID_DOUBLE)) {178drawRightGeometryPoint(s, d, myAdditionalGeometry.getShape().back(), myAdditionalGeometry.getShapeRotations().back(), baseColor);179}180// pop layer matrix181GLHelper::popMatrix();182// draw lock icon183GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), getPositionInView(), parkingAreaExaggeration);184// Draw additional ID185drawAdditionalID(s);186// draw additional name187drawAdditionalName(s);188// draw dotted contours189if (movingGeometryPoints) {190myAdditionalContour.drawDottedContourGeometryPoints(s, d, this, myAdditionalGeometry.getShape(), s.neteditSizeSettings.additionalGeometryPointRadius,1911, s.dottedContourSettings.segmentWidthSmall);192} else {193myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);194mySymbolContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidthSmall, true);195}196}197// draw demand element children198drawDemandElementChildren(s);199// calculate contours200calculateStoppingPlaceContour(s, d, myWidth * 0.5, parkingAreaExaggeration, movingGeometryPoints);201}202}203204205std::string206GNEParkingArea::getAttribute(SumoXMLAttr key) const {207switch (key) {208case SUMO_ATTR_DEPARTPOS:209return myDepartPos;210case SUMO_ATTR_ACCEPTED_BADGES:211return joinToString(myAcceptedBadges, " ");212case SUMO_ATTR_ROADSIDE_CAPACITY:213return toString(myRoadSideCapacity);214case SUMO_ATTR_ONROAD:215return toString(myOnRoad);216case SUMO_ATTR_WIDTH:217return toString(myWidth);218case SUMO_ATTR_LENGTH:219return toString(myLength);220case SUMO_ATTR_LEFTHAND:221return toString(myLefthand);222default:223return getStoppingPlaceAttribute(this, key);224}225}226227228double229GNEParkingArea::getAttributeDouble(SumoXMLAttr key) const {230switch (key) {231case SUMO_ATTR_WIDTH:232return myWidth;233case SUMO_ATTR_LENGTH: {234// calculate spaceDim235const double spaceDim = myRoadSideCapacity > 0 ? (getAttributeDouble(SUMO_ATTR_ENDPOS) - getAttributeDouble(SUMO_ATTR_STARTPOS)) / myRoadSideCapacity * getParentLanes().front()->getLengthGeometryFactor() : 7.5;236return (myLength > 0) ? myLength : spaceDim;237}238default:239return getStoppingPlaceAttributeDouble(key);240}241}242243244void245GNEParkingArea::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {246switch (key) {247case SUMO_ATTR_DEPARTPOS:248case SUMO_ATTR_ACCEPTED_BADGES:249case SUMO_ATTR_ROADSIDE_CAPACITY:250case SUMO_ATTR_ONROAD:251case SUMO_ATTR_WIDTH:252case SUMO_ATTR_LENGTH:253case SUMO_ATTR_LEFTHAND:254GNEChange_Attribute::changeAttribute(this, key, value, undoList);255break;256default:257setStoppingPlaceAttribute(key, value, undoList);258break;259}260}261262263bool264GNEParkingArea::isValid(SumoXMLAttr key, const std::string& value) {265switch (key) {266case SUMO_ATTR_DEPARTPOS:267if (value.empty()) {268return true;269} else if (canParse<double>(value)) {270// parse value271const double departPos = parse<double>(value);272if (departPos >= 0) {273if (isTemplate()) {274return true;275} else {276return (departPos <= getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength());277}278} else {279return false;280}281} else {282return false;283}284case SUMO_ATTR_ACCEPTED_BADGES:285return true;286case SUMO_ATTR_ROADSIDE_CAPACITY:287return canParse<int>(value) && (parse<int>(value) >= 0);288case SUMO_ATTR_ONROAD:289return canParse<bool>(value);290case SUMO_ATTR_WIDTH:291return canParse<double>(value) && (parse<double>(value) > 0);292case SUMO_ATTR_LENGTH:293if (value.empty()) {294return true;295} else {296return canParse<double>(value) && (parse<double>(value) > 0);297}298case SUMO_ATTR_LEFTHAND:299return canParse<bool>(value);300default:301return isStoppingPlaceValid(key, value);302}303}304305// ===========================================================================306// protected307// ===========================================================================308309GNEParkingArea::GNELotSpaceDefinition::GNELotSpaceDefinition() :310rotation(0),311width(0),312length(0) {313}314315316GNEParkingArea::GNELotSpaceDefinition::GNELotSpaceDefinition(double x, double y, double z, double rotation_, double width_, double length_) :317position(Position(x, y, z)),318rotation(rotation_),319width(width_),320length(length_) {321}322323// ===========================================================================324// private325// ===========================================================================326327void328GNEParkingArea::setAttribute(SumoXMLAttr key, const std::string& value) {329switch (key) {330case SUMO_ATTR_DEPARTPOS:331myDepartPos = value;332break;333case SUMO_ATTR_ACCEPTED_BADGES:334myAcceptedBadges = GNEAttributeCarrier::parse<std::vector<std::string> >(value);335break;336case SUMO_ATTR_ROADSIDE_CAPACITY:337myRoadSideCapacity = parse<int>(value);338updateCenteringBoundary(false);339break;340case SUMO_ATTR_ONROAD:341myOnRoad = parse<bool>(value);342break;343case SUMO_ATTR_WIDTH:344myWidth = parse<double>(value);345// update geometry of all spaces346for (const auto& space : getChildAdditionals()) {347space->updateGeometry();348}349updateCenteringBoundary(false);350if (!isTemplate()) {351getParentLanes().front()->getParentEdge()->updateCenteringBoundary(true);352}353break;354case SUMO_ATTR_LENGTH:355if (value.empty()) {356myLength = 0;357} else {358myLength = parse<double>(value);359}360// update geometry of all spaces361for (const auto& space : getChildAdditionals()) {362space->updateGeometry();363}364break;365case SUMO_ATTR_LEFTHAND:366myLefthand = parse<bool>(value);367if (!isTemplate()) {368updateGeometry();369}370break;371default:372setStoppingPlaceAttribute(this, key, value);373break;374}375}376377378/****************************************************************************/379380381