Path: blob/main/src/netedit/elements/additional/GNEPoly.cpp
193674 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 GNEPoly.cpp14/// @author Pablo Alvarez Lopez15/// @date Jun 201716///17// A class for visualizing and editing POIS in netedit (adapted from18// GUIPolygon and NLHandler)19/****************************************************************************/2021#include <netedit/changes/GNEChange_Attribute.h>22#include <netedit/elements/moving/GNEMoveElementShape.h>23#include <netedit/frames/common/GNEMoveFrame.h>24#include <netedit/GNENet.h>25#include <netedit/GNETagProperties.h>26#include <netedit/GNEUndoList.h>27#include <netedit/GNEViewParent.h>28#include <utils/gui/div/GLHelper.h>29#include <utils/gui/div/GUIDesigns.h>30#include <utils/gui/div/GUIParameterTableWindow.h>31#include <utils/gui/globjects/GUIGLObjectPopupMenu.h>32#include <utils/gui/images/GUITextureSubSys.h>33#include <utils/xml/NamespaceIDs.h>3435#include "GNEPoly.h"3637// ===========================================================================38// method definitions39// ===========================================================================4041GNEPoly::GNEPoly(SumoXMLTag tag, GNENet* net) :42TesselatedPolygon("", "", RGBColor::BLACK, {}, false, false, 0, 0, 0, "", "", Parameterised::Map()),43GNEAdditional(net, tag),44myMoveElementShape(new GNEMoveElementShape(this)) {45}464748GNEPoly::GNEPoly(const std::string& id, GNENet* net, FileBucket* fileBucket, const std::string& type, const PositionVector& shape,49bool geo, bool fill, double lineWidth, const RGBColor& color, double layer, double angle, const std::string& imgFile,50const std::string& name, const Parameterised::Map& parameters) :51TesselatedPolygon(id, type, color, shape, geo, fill, lineWidth, layer, angle, imgFile, "", parameters),52GNEAdditional(id, net, SUMO_TAG_POLY, fileBucket, name),53myMoveElementShape(new GNEMoveElementShape(this, myShape, false)),54myClosedShape(shape.isClosed()) {55// check if imgFile is valid56if (!imgFile.empty() && GUITexturesHelper::getTextureID(imgFile) == -1) {57setShapeImgFile("");58}59// set GEO shape60myGeoShape = myShape;61if (geo) {62for (int i = 0; i < (int) myGeoShape.size(); i++) {63GeoConvHelper::getFinal().x2cartesian_const(myShape[i]);64}65} else {66for (int i = 0; i < (int) myGeoShape.size(); i++) {67GeoConvHelper::getFinal().cartesian2geo(myGeoShape[i]);68}69}70// update centering boundary without updating grid71updateCenteringBoundary(false);72// update geometry73updateGeometry();74}757677GNEPoly::GNEPoly(SumoXMLTag tag, const std::string& id, GNENet* net, FileBucket* fileBucket, const PositionVector& shape,78bool geo, const std::string& name, const Parameterised::Map& parameters) :79TesselatedPolygon(id, getJuPedSimType(tag), getJuPedSimColor(tag), shape, geo, getJuPedSimFill(tag), 1,80getJuPedSimLayer(tag), 0, "", "", parameters),81GNEAdditional(id, net, tag, fileBucket, name),82myMoveElementShape(new GNEMoveElementShape(this, myShape, (tag == GNE_TAG_JPS_WALKABLEAREA) || (tag == GNE_TAG_JPS_OBSTACLE))),83myClosedShape(shape.isClosed()),84mySimplifiedShape(false) {85// set GEO shape86myGeoShape = myShape;87if (geo) {88for (int i = 0; i < (int) myGeoShape.size(); i++) {89GeoConvHelper::getFinal().x2cartesian_const(myShape[i]);90}91} else {92for (int i = 0; i < (int) myGeoShape.size(); i++) {93GeoConvHelper::getFinal().cartesian2geo(myGeoShape[i]);94}95}96// update centering boundary without updating grid97updateCenteringBoundary(false);98// update geometry99updateGeometry();100}101102103GNEPoly::~GNEPoly() {104delete myMoveElementShape;105}106107108GNEMoveElement*109GNEPoly::getMoveElement() const {110return myMoveElementShape;111}112113114Parameterised*115GNEPoly::getParameters() {116return this;117}118119120const Parameterised*121GNEPoly::getParameters() const {122return this;123}124125126std::string127GNEPoly::generateChildID(SumoXMLTag /*childTag*/) {128return "";129}130131132void133GNEPoly::updateGeometry() {134// just update polygon geometry135myAdditionalGeometry.updateGeometry(myShape);136myTesselation.clear();137}138139140Position141GNEPoly::getPositionInView() const {142return myAdditionalBoundary.getCenter();143}144145146double147GNEPoly::getExaggeration(const GUIVisualizationSettings& s) const {148return s.polySize.getExaggeration(s, this);149}150151152void153GNEPoly::updateCenteringBoundary(const bool updateGrid) {154// Remove object from net155if (updateGrid) {156myNet->removeGLObjectFromGrid(this);157}158// use shape as boundary159myAdditionalBoundary = myShape.getBoxBoundary();160// grow boundary161myAdditionalBoundary.grow(5);162// add object into net163if (updateGrid) {164myNet->addGLObjectIntoGrid(this);165}166}167168169void170GNEPoly::splitEdgeGeometry(const double /*splitPosition*/, const GNENetworkElement* /*originalElement*/, const GNENetworkElement* /*newElement*/, GNEUndoList* /*undoList*/) {171// nothing to split172}173174175void176GNEPoly::writeAdditional(OutputDevice& device) const {177device.openTag(SUMO_TAG_POLY);178// write common additional attributes179writeAdditionalAttributes(device);180// write specific attributes181PositionVector shape = getShape();182if (myGEO) {183device.writeAttr(SUMO_ATTR_GEO, true);184for (int i = 0; i < (int) shape.size(); i++) {185GeoConvHelper::getFinal().cartesian2geo(shape[i]);186}187}188if (getShapeType().size() > 0) {189device.writeAttr(SUMO_ATTR_TYPE, StringUtils::escapeXML(getShapeType()));190}191device.writeAttr(SUMO_ATTR_COLOR, getShapeColor());192device.writeAttr(SUMO_ATTR_FILL, getFill());193if (getLineWidth() != 1) {194device.writeAttr(SUMO_ATTR_LINEWIDTH, getLineWidth());195}196device.writeAttr(SUMO_ATTR_LAYER, getShapeLayer());197198device.setPrecision(gPrecisionGeo);199device.writeAttr(SUMO_ATTR_SHAPE, shape);200device.setPrecision();201if (getShapeNaviDegree() != Shape::DEFAULT_ANGLE) {202device.writeAttr(SUMO_ATTR_ANGLE, getShapeNaviDegree());203}204if (getShapeImgFile() != Shape::DEFAULT_IMG_FILE) {205device.writeAttr(SUMO_ATTR_IMGFILE, getShapeImgFile());206}207writeParams(device);208device.closeTag();209}210211212bool213GNEPoly::isAdditionalValid() const {214return true;215}216217218std::string219GNEPoly::getAdditionalProblem() const {220return "";221}222223224void225GNEPoly::fixAdditionalProblem() {226// nothing to fix227}228229230GUIGlID231GNEPoly::getGlID() const {232return GUIGlObject::getGlID();233}234235236bool237GNEPoly::checkDrawMoveContour() const {238// get edit modes239const auto& editModes = myNet->getViewNet()->getEditModes();240// check if we're in move mode241if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&242!myNet->getViewNet()->getEditNetworkElementShapes().getEditedNetworkElement() &&243(editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {244// only move the first element245return myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() == this;246} else {247return false;248}249}250251252std::string253GNEPoly::getParentName() const {254return myNet->getMicrosimID();255}256257258GUIGLObjectPopupMenu*259GNEPoly::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {260// create popup261GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);262// build common options263buildPopUpMenuCommonOptions(ret, app, myNet->getViewNet(), myTagProperty->getTag(), mySelected);264FXMenuCommand* simplifyShape = GUIDesigns::buildFXMenuCommand(ret, TL("Simplify Shape"), TL("Replace current shape with a rectangle"), nullptr, &parent, MID_GNE_POLYGON_SIMPLIFY_SHAPE);265// disable simplify shape if polygon was already simplified266if (mySimplifiedShape || myShape.size() <= 2) {267simplifyShape->disable();268}269// only allow open/close for non juPedSim polygons270if (!myTagProperty->isJuPedSimElement()) {271if (myShape.isClosed()) {272GUIDesigns::buildFXMenuCommand(ret, TL("Open shape"), TL("Open polygon's shape"), nullptr, &parent, MID_GNE_POLYGON_OPEN);273} else {274GUIDesigns::buildFXMenuCommand(ret, TL("Close shape"), TL("Close polygon's shape"), nullptr, &parent, MID_GNE_POLYGON_CLOSE);275}276}277GUIDesigns::buildFXMenuCommand(ret, TL("Select elements within polygon"), TL("Select elements within polygon boundary"), nullptr, &parent, MID_GNE_POLYGON_SELECT);278if (myShape.size() > 3) {279GUIDesigns::buildFXMenuCommand(ret, TL("Triangulate polygon"), TL("Convert the current polygon in triangles"), nullptr, &parent, MID_GNE_POLYGON_TRIANGULATE);280}281// create a extra FXMenuCommand if mouse is over a vertex282const int index = getVertexIndex(myNet->getViewNet()->getPositionInformation(), false);283if (index != -1) {284// add separator285new FXMenuSeparator(ret);286// check if we're in network mode287if (myNet->getViewNet()->getEditModes().networkEditMode == NetworkEditMode::NETWORK_MOVE) {288GUIDesigns::buildFXMenuCommand(ret, "Set custom Geometry Point", nullptr, &parent, MID_GNE_CUSTOM_GEOMETRYPOINT);289}290FXMenuCommand* removeGeometryPoint = GUIDesigns::buildFXMenuCommand(ret, TL("Remove geometry point"), TL("Remove geometry point under mouse"), nullptr, &parent, MID_GNE_POLYGON_DELETE_GEOMETRY_POINT);291FXMenuCommand* setFirstPoint = GUIDesigns::buildFXMenuCommand(ret, TL("Set first geometry point"), TL("Set first geometry point"), nullptr, &parent, MID_GNE_POLYGON_SET_FIRST_POINT);292// disable setFirstPoint if shape only have three points293if ((myShape.isClosed() && (myShape.size() <= 4)) || (!myShape.isClosed() && (myShape.size() <= 2))) {294removeGeometryPoint->disable();295}296// disable setFirstPoint if mouse is over first point297if (index == 0) {298setFirstPoint->disable();299}300}301return ret;302}303304305void306GNEPoly::drawGL(const GUIVisualizationSettings& s) const {307// first check if poly can be drawn308if (myNet->getViewNet()->getDemandViewOptions().showShapes() &&309myNet->getViewNet()->getDataViewOptions().showShapes() &&310GUIPolygon::checkDraw(s, this, this)) {311// draw boundary312const auto boundary = getCenteringBoundary();313GLHelper::drawBoundary(s, getCenteringBoundary());314// get exaggeration315const double polyExaggeration = getExaggeration(s);316// get detail level317const auto d = s.getDetailLevel(polyExaggeration);318// draw geometry only if we'rent in drawForObjectUnderCursor mode319if (s.checkDrawPoly(boundary, isAttributeCarrierSelected())) {320// get colors321const RGBColor color = isAttributeCarrierSelected() ? s.colorSettings.selectionColor : getShapeColor();322// push layer matrix323GLHelper::pushMatrix();324// translate to front325drawInLayer(s.polyUseCustomLayer ? s.polyCustomLayer : getShapeLayer());326// draw polygon327drawPolygon(s, d, color, polyExaggeration);328// draw contour if don't move whole polygon329if (!myNet->getViewParent()->getMoveFrame()->getNetworkMoveOptions()->getMoveWholePolygons()) {330// get darker color331const RGBColor darkerColor = color.changedBrightness(-32);332// draw contour333drawPolygonContour(s, d, darkerColor, polyExaggeration);334// draw geometry points335drawGeometryPoints(s, d, darkerColor, polyExaggeration);336}337// pop layer matrix338GLHelper::popMatrix();339// draw name and type340drawPolygonNameAndType(s);341// draw lock icon342GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), getPositionInView(), polyExaggeration);343// draw dotted contour344myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);345}346// calculate contour347calculateContourPolygons(s, d, getShapeLayer(), polyExaggeration, getFill());348}349}350351352int353GNEPoly::getVertexIndex(Position pos, bool snapToGrid) {354// check if position has to be snapped to grid355if (snapToGrid) {356pos = myNet->getViewNet()->snapToActiveGrid(pos);357}358// first check if vertex already exists359for (const auto& shapePosition : myShape) {360if (shapePosition.distanceTo2D(pos) < myNet->getViewNet()->getVisualisationSettings().neteditSizeSettings.polygonGeometryPointRadius) {361return myShape.indexOfClosest(shapePosition);362}363}364return -1;365}366367368void369GNEPoly::deleteGeometryPoint(const Position& pos, bool allowUndo) {370if (myShape.size() > 1) {371// obtain index372PositionVector modifiedShape = myShape;373int index = modifiedShape.indexOfClosest(pos);374// remove point dependending of375if (myShape.isClosed() && (index == 0 || index == (int)modifiedShape.size() - 1) && (myShape.size() > 2)) {376modifiedShape.erase(modifiedShape.begin());377modifiedShape.erase(modifiedShape.end() - 1);378modifiedShape.push_back(modifiedShape.front());379} else {380modifiedShape.erase(modifiedShape.begin() + index);381}382// set new shape depending of allowUndo383if (allowUndo) {384myNet->getUndoList()->begin(this, "delete geometry point");385setAttribute(SUMO_ATTR_SHAPE, toString(modifiedShape), myNet->getUndoList());386myNet->getUndoList()->end();387} else {388// first remove object from grid due shape is used for boundary389myNet->removeGLObjectFromGrid(this);390// set new shape391myShape = modifiedShape;392// disable simplified shape flag393mySimplifiedShape = false;394// add object into grid again395myNet->addGLObjectIntoGrid(this);396}397myTesselation.clear();398} else {399WRITE_WARNING(TL("Number of remaining points insufficient"))400}401}402403404bool405GNEPoly::isPolygonClosed() const {406return myShape.isClosed();407}408409410void411GNEPoly::openPolygon(bool allowUndo) {412// only open if shape is closed413if (myShape.isClosed()) {414if (allowUndo) {415myNet->getUndoList()->begin(this, "open polygon");416setAttribute(GNE_ATTR_CLOSE_SHAPE, "false", myNet->getUndoList());417myNet->getUndoList()->end();418} else {419myShape.pop_back();420// disable simplified shape flag421mySimplifiedShape = false;422// update geometry to avoid grabbing Problems423updateGeometry();424}425} else {426WRITE_WARNING(TL("Polygon already opened"))427}428}429430431void432GNEPoly::closePolygon(bool allowUndo) {433// only close if shape is opened434if (!myShape.isClosed()) {435if (allowUndo) {436myNet->getUndoList()->begin(this, "close shape");437setAttribute(GNE_ATTR_CLOSE_SHAPE, "true", myNet->getUndoList());438myNet->getUndoList()->end();439} else {440myShape.closePolygon();441// disable simplified shape flag442mySimplifiedShape = false;443// update geometry to avoid grabbing Problems444updateGeometry();445}446} else {447WRITE_WARNING(TL("Polygon already closed"))448}449}450451452void453GNEPoly::changeFirstGeometryPoint(int oldIndex, bool allowUndo) {454// check that old index is correct455if (oldIndex >= (int)myShape.size()) {456throw InvalidArgument("Invalid old Index");457} else if (oldIndex == 0) {458WRITE_WARNING(TL("Selected point must be different of the first point"))459} else {460// Configure new shape461PositionVector newShape;462for (int i = oldIndex; i < (int)myShape.size(); i++) {463newShape.push_back(myShape[i]);464}465if (myShape.isClosed()) {466for (int i = 1; i < oldIndex; i++) {467newShape.push_back(myShape[i]);468}469newShape.push_back(newShape.front());470} else {471for (int i = 0; i < oldIndex; i++) {472newShape.push_back(myShape[i]);473}474}475// set new rotated shape476if (allowUndo) {477myNet->getUndoList()->begin(this, "change first geometry point");478setAttribute(SUMO_ATTR_SHAPE, toString(newShape), myNet->getUndoList());479myNet->getUndoList()->end();480} else {481// set new shape482myShape = newShape;483// disable simplified shape flag484mySimplifiedShape = false;485// update geometry to avoid grabbing Problems486updateGeometry();487}488}489}490491492void493GNEPoly::simplifyShape(bool allowUndo) {494if (!mySimplifiedShape && myShape.size() > 2) {495const Boundary b = myShape.getBoxBoundary();496// create a square as simplified shape497PositionVector simplifiedShape;498simplifiedShape.push_back(Position(b.xmin(), b.ymin()));499simplifiedShape.push_back(Position(b.xmin(), b.ymax()));500simplifiedShape.push_back(Position(b.xmax(), b.ymax()));501simplifiedShape.push_back(Position(b.xmax(), b.ymin()));502if (myShape.isClosed()) {503simplifiedShape.push_back(simplifiedShape[0]);504}505// set new shape depending of allowUndo506if (allowUndo) {507myNet->getUndoList()->begin(this, "simplify shape");508setAttribute(SUMO_ATTR_SHAPE, toString(simplifiedShape), myNet->getUndoList());509myNet->getUndoList()->end();510} else {511// set new shape512myShape = simplifiedShape;513// update geometry to avoid grabbing Problems514updateGeometry();515}516// change flag after setting simplified shape517mySimplifiedShape = true;518} else {519WRITE_WARNING(TL("Polygon already simplified"))520}521}522523524CommonXMLStructure::SumoBaseObject*525GNEPoly::getSumoBaseObject() const {526CommonXMLStructure::SumoBaseObject* polygonBaseObject = new CommonXMLStructure::SumoBaseObject(nullptr);527polygonBaseObject->setTag(myTagProperty->getTag());528// fill attributes529polygonBaseObject->addStringAttribute(SUMO_ATTR_ID, myID);530polygonBaseObject->addPositionVectorAttribute(SUMO_ATTR_SHAPE, myShape);531polygonBaseObject->addBoolAttribute(SUMO_ATTR_GEO, myGEO);532polygonBaseObject->addBoolAttribute(SUMO_ATTR_FILL, myFill);533polygonBaseObject->addDoubleAttribute(SUMO_ATTR_LINEWIDTH, myLineWidth);534polygonBaseObject->addColorAttribute(SUMO_ATTR_COLOR, getShapeColor());535polygonBaseObject->addStringAttribute(SUMO_ATTR_TYPE, getShapeType());536polygonBaseObject->addDoubleAttribute(SUMO_ATTR_LAYER, getShapeLayer());537polygonBaseObject->addStringAttribute(SUMO_ATTR_IMGFILE, getShapeImgFile());538polygonBaseObject->addDoubleAttribute(SUMO_ATTR_ANGLE, getShapeNaviDegree());539polygonBaseObject->addStringAttribute(SUMO_ATTR_NAME, myAdditionalName);540return polygonBaseObject;541}542543544std::string545GNEPoly::getAttribute(SumoXMLAttr key) const {546switch (key) {547case SUMO_ATTR_ID:548return myID;549case SUMO_ATTR_SHAPE:550if ((GeoConvHelper::getFinal().getProjString() != "!") && myGEO) {551return TL("Using GEO Shape");552} else {553return toString(myShape);554}555case SUMO_ATTR_GEOSHAPE:556if (GeoConvHelper::getFinal().getProjString() != "!") {557return toString(myGeoShape, gPrecisionGeo);558} else {559return TL("No geo-conversion defined");560}561case SUMO_ATTR_COLOR:562return toString(getShapeColor());563case SUMO_ATTR_FILL:564return toString(myFill);565case SUMO_ATTR_LINEWIDTH:566return toString(myLineWidth);567case SUMO_ATTR_LAYER:568return toString(getShapeLayer());569case SUMO_ATTR_TYPE:570return getShapeType();571case SUMO_ATTR_IMGFILE:572return getShapeImgFile();573case SUMO_ATTR_ANGLE:574return toString(getShapeNaviDegree());575case SUMO_ATTR_GEO:576return toString(myGEO);577case SUMO_ATTR_NAME:578return myAdditionalName;579case GNE_ATTR_CLOSE_SHAPE:580return toString(myClosedShape);581default:582return getCommonAttribute(key);583}584}585586587double588GNEPoly::getAttributeDouble(SumoXMLAttr key) const {589return myMoveElementShape->getMovingAttributeDouble(key);590}591592593Position594GNEPoly::getAttributePosition(SumoXMLAttr key) const {595return myMoveElementShape->getMovingAttributePosition(key);596}597598599PositionVector600GNEPoly::getAttributePositionVector(SumoXMLAttr key) const {601return getCommonAttributePositionVector(key);602}603604605void606GNEPoly::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {607if (value == getAttribute(key)) {608return; //avoid needless changes, later logic relies on the fact that attributes have changed609}610switch (key) {611case SUMO_ATTR_ID:612case SUMO_ATTR_SHAPE:613case SUMO_ATTR_GEOSHAPE:614case SUMO_ATTR_COLOR:615case SUMO_ATTR_FILL:616case SUMO_ATTR_LINEWIDTH:617case SUMO_ATTR_LAYER:618case SUMO_ATTR_TYPE:619case SUMO_ATTR_IMGFILE:620case SUMO_ATTR_ANGLE:621case SUMO_ATTR_GEO:622case SUMO_ATTR_NAME:623case GNE_ATTR_CLOSE_SHAPE:624GNEChange_Attribute::changeAttribute(this, key, value, undoList);625break;626default:627setCommonAttribute(key, value, undoList);628break;629}630}631632633bool634GNEPoly::isValid(SumoXMLAttr key, const std::string& value) {635switch (key) {636case SUMO_ATTR_ID:637return isValidAdditionalID(NamespaceIDs::polygons, value);638case SUMO_ATTR_SHAPE:639case SUMO_ATTR_GEOSHAPE:640// empty shapes AREN'T allowed641if (value.empty()) {642return false;643} else {644return canParse<PositionVector>(value);645}646case SUMO_ATTR_COLOR:647return canParse<RGBColor>(value);648case SUMO_ATTR_FILL:649return canParse<bool>(value);650case SUMO_ATTR_LINEWIDTH:651return canParse<double>(value) && (parse<double>(value) >= 0);652case SUMO_ATTR_LAYER:653if (value.empty()) {654return true;655} else {656return canParse<double>(value);657}658case SUMO_ATTR_TYPE:659return true;660case SUMO_ATTR_IMGFILE:661if (value == "") {662return true;663} else {664// check that image can be loaded665return GUITexturesHelper::getTextureID(value) != -1;666}667case SUMO_ATTR_ANGLE:668return canParse<double>(value);669case SUMO_ATTR_GEO:670return canParse<bool>(value);671case SUMO_ATTR_NAME:672return SUMOXMLDefinitions::isValidAttribute(value);673case GNE_ATTR_CLOSE_SHAPE:674return canParse<bool>(value);675default:676return isCommonAttributeValid(key, value);677}678}679680681bool682GNEPoly::isAttributeEnabled(SumoXMLAttr key) const {683switch (key) {684case SUMO_ATTR_SHAPE:685if (GeoConvHelper::getFinal().getProjString() != "!") {686return myGEO == false;687} else {688return true;689}690case SUMO_ATTR_GEO:691return GeoConvHelper::getFinal().getProjString() != "!";692case SUMO_ATTR_GEOSHAPE:693if (GeoConvHelper::getFinal().getProjString() != "!") {694return myGEO == true;695} else {696return false;697}698case GNE_ATTR_CLOSE_SHAPE:699if (isTemplate()) {700return true;701} else {702return myShape.size() > 1;703}704default:705return true;706}707}708709710std::string711GNEPoly::getPopUpID() const {712return getTagStr() + ": " + getID();713}714715716std::string717GNEPoly::getHierarchyName() const {718return getTagStr();719}720721// ===========================================================================722// private723// ===========================================================================724725void726GNEPoly::setAttribute(SumoXMLAttr key, const std::string& value) {727switch (key) {728case SUMO_ATTR_ID: {729// update microsimID730setAdditionalID(value);731// set named ID732myID = value;733break;734}735case SUMO_ATTR_SHAPE: {736// set new shape737myShape = parse<PositionVector>(value);738// set GEO shape739myGeoShape = myShape;740for (int i = 0; i < (int) myGeoShape.size(); i++) {741GeoConvHelper::getFinal().cartesian2geo(myGeoShape[i]);742}743// disable simplified shape flag744mySimplifiedShape = false;745// update geometry746updateGeometry();747// update centering boundary748updateCenteringBoundary(true);749break;750}751case SUMO_ATTR_GEOSHAPE: {752// set new GEO shape753myGeoShape = parse<PositionVector>(value);754// set shape755myShape = myGeoShape ;756for (int i = 0; i < (int) myShape.size(); i++) {757GeoConvHelper::getFinal().x2cartesian_const(myShape[i]);758}759// disable simplified shape flag760mySimplifiedShape = false;761// update geometry762updateGeometry();763// update centering boundary764updateCenteringBoundary(true);765break;766}767case SUMO_ATTR_COLOR:768setShapeColor(parse<RGBColor>(value));769break;770case SUMO_ATTR_FILL:771myFill = parse<bool>(value);772myAdditionalContour.clearContour();773break;774case SUMO_ATTR_LINEWIDTH:775myLineWidth = parse<double>(value);776break;777case SUMO_ATTR_LAYER:778if (value.empty()) {779setShapeLayer(myTagProperty->getDefaultDoubleValue(key));780} else {781setShapeLayer(parse<double>(value));782}783break;784case SUMO_ATTR_TYPE:785setShapeType(value);786break;787case SUMO_ATTR_IMGFILE:788setShapeImgFile(value);789// all textures must be refresh790GUITexturesHelper::clearTextures();791break;792case SUMO_ATTR_ANGLE:793setShapeNaviDegree(parse<double>(value));794break;795case SUMO_ATTR_GEO:796myGEO = parse<bool>(value);797// update centering boundary798updateCenteringBoundary(true);799break;800case SUMO_ATTR_NAME:801myAdditionalName = value;802break;803case GNE_ATTR_CLOSE_SHAPE:804myClosedShape = parse<bool>(value);805if (!isTemplate()) {806if (myClosedShape) {807myShape.closePolygon();808myGeoShape.closePolygon();809810} else {811myShape.openPolygon();812myGeoShape.openPolygon();813}814// disable simplified shape flag815mySimplifiedShape = false;816// update geometry817updateGeometry();818// update centering boundary819updateCenteringBoundary(true);820}821break;822default:823setCommonAttribute(key, value);824break;825}826}827828829void830GNEPoly::drawPolygon(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,831const RGBColor& color, const double exaggeration) const {832// check if we're drawing a polygon or a polyline833if (getFill()) {834// draw inner polygon835GUIPolygon::drawInnerPolygon(s, this, this, myAdditionalGeometry.getShape(), 0, getFill(), myTagProperty->isJuPedSimElement() ? false : drawUsingSelectColor());836} else {837// push matrix838GLHelper::pushMatrix();839// set color840GLHelper::setColor(color);841// draw geometry (polyline)842GUIGeometry::drawGeometry(d, myAdditionalGeometry, s.neteditSizeSettings.polylineWidth * exaggeration);843// pop matrix844GLHelper::popMatrix();845}846}847848849void850GNEPoly::drawPolygonContour(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,851const RGBColor& color, const double exaggeration) const {852// push contour matrix853GLHelper::pushMatrix();854// translate to front855glTranslated(0, 0, 0.1);856// set color857GLHelper::setColor(color);858// draw polygon contour859GUIGeometry::drawGeometry(d, myAdditionalGeometry, s.neteditSizeSettings.polygonContourWidth * exaggeration);860// pop contour matrix861GLHelper::popMatrix();862}863864865void866GNEPoly::drawGeometryPoints(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,867const RGBColor& color, const double exaggeration) const {868// draw shape points only in supermode network869if (myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork()) {870// check if we're in move mode871const bool moveMode = (myNet->getViewNet()->getEditModes().networkEditMode == NetworkEditMode::NETWORK_MOVE);872// get geometry point sizes873const double geometryPointSize = s.neteditSizeSettings.polygonGeometryPointRadius * (moveMode ? 1 : 0.5);874// draw geometry points875GUIGeometry::drawGeometryPoints(d, myAdditionalGeometry.getShape(), color, geometryPointSize, exaggeration,876myNet->getViewNet()->getNetworkViewOptions().editingElevation());877// draw dotted contours for geometry points if we're in move mode878if (moveMode) {879myAdditionalContour.drawDottedContourGeometryPoints(s, d, this, myAdditionalGeometry.getShape(), geometryPointSize,880exaggeration, s.dottedContourSettings.segmentWidthSmall);881}882}883}884885886void887GNEPoly::drawPolygonNameAndType(const GUIVisualizationSettings& s) const {888// get name position889const Position& namePos = myAdditionalGeometry.getShape().getPolygonCenter();890// draw name891drawName(namePos, s.scale, s.polyName, s.angle);892// check if draw poly type893if (s.polyType.show(this)) {894const Position p = namePos + Position(0, -0.6 * s.polyType.size / s.scale);895GLHelper::drawTextSettings(s.polyType, getShapeType(), p, s.scale, s.angle);896}897}898899/****************************************************************************/900901902