Path: blob/main/src/netedit/elements/moving/GNEMoveElementShape.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 GNEMoveElementShape.cpp14/// @author Pablo Alvarez Lopez15/// @date Sep 202516///17// Class used for shape elements that can be moved over view18/****************************************************************************/19#include <config.h>2021#include <netedit/changes/GNEChange_Attribute.h>22#include <netedit/frames/common/GNEMoveFrame.h>23#include <netedit/GNENet.h>24#include <netedit/GNETagProperties.h>25#include <netedit/GNEUndoList.h>26#include <netedit/GNEViewParent.h>2728#include "GNEMoveElementShape.h"2930// ===========================================================================31// static members32// ===========================================================================3334PositionVector GNEMoveElementShape::EMPTY_SHAPE;3536// ===========================================================================37// Method definitions38// ===========================================================================3940GNEMoveElementShape::GNEMoveElementShape(GNEAttributeCarrier* element) :41GNEMoveElement(element),42myMovingShape(EMPTY_SHAPE) {43}444546GNEMoveElementShape::GNEMoveElementShape(GNEAttributeCarrier* element, PositionVector& shape, const bool alwaysClosed) :47GNEMoveElement(element),48myMovingShape(shape),49myAlwaysClosed(alwaysClosed) {50}515253GNEMoveElementShape::GNEMoveElementShape(GNEAttributeCarrier* element, PositionVector& shape, const Position& position, const bool alwaysClosed) :54GNEMoveElement(element),55myCenterPosition(position),56myMovingShape(shape),57myAlwaysClosed(alwaysClosed) {58}596061GNEMoveElementShape::~GNEMoveElementShape() {}626364GNEMoveOperation*65GNEMoveElementShape::getMoveOperation() {66// get snap radius67const double snap_radius = myMovedElement->getNet()->getViewNet()->getVisualisationSettings().neteditSizeSettings.polygonGeometryPointRadius;68// check if we're moving center or shape69if (myCenterPosition.distanceSquaredTo2D(myMovedElement->getNet()->getViewNet()->getPositionInformation()) < (snap_radius * snap_radius)) {70// move entire shape71return new GNEMoveOperation(this, myCenterPosition);72} else if (myMovedElement->getNet()->getViewParent()->getMoveFrame()->getNetworkMoveOptions()->getMoveWholePolygons()) {73// move entire shape74return new GNEMoveOperation(this, myMovingShape);75} else {76// calculate move shape operation77return getEditShapeOperation(myMovedElement->getGUIGlObject(), myMovingShape, myAlwaysClosed);78}79}808182void83GNEMoveElementShape::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {84// get original shape85PositionVector shape = myMovingShape;86// check shape size87if (shape.size() > 3) {88// obtain index89int index = shape.indexOfClosest(clickedPosition);90// get last index91const int lastIndex = ((int)shape.size() - 1);92// get snap radius93const double snap_radius = myMovedElement->getNet()->getViewNet()->getVisualisationSettings().neteditSizeSettings.polygonGeometryPointRadius;94// check if we have to create a new index95if ((index != -1) && shape[index].distanceSquaredTo2D(clickedPosition) < (snap_radius * snap_radius)) {96// check if we're deleting the first point97if ((index == 0) || (index == lastIndex)) {98// remove both geometry point99shape.erase(shape.begin() + lastIndex);100shape.erase(shape.begin());101// close shape102shape.closePolygon();103} else {104// remove geometry point105shape.erase(shape.begin() + index);106}107// commit new shape108undoList->begin(myMovedElement, TLF("remove geometry point of %", myMovedElement->getTagStr()));109GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_SHAPE, toString(shape), undoList);110undoList->end();111}112}113}114115116std::string117GNEMoveElementShape::getMovingAttribute(SumoXMLAttr key) const {118return myMovedElement->getCommonAttribute(key);119}120121122double123GNEMoveElementShape::getMovingAttributeDouble(SumoXMLAttr key) const {124return myMovedElement->getCommonAttributeDouble(key);125}126127128Position129GNEMoveElementShape::getMovingAttributePosition(SumoXMLAttr key) const {130return myMovedElement->getCommonAttributePosition(key);131}132133134PositionVector135GNEMoveElementShape::getMovingAttributePositionVector(SumoXMLAttr key) const {136return myMovedElement->getCommonAttributePositionVector(key);137}138139140void141GNEMoveElementShape::setMovingAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {142return myMovedElement->setCommonAttribute(key, value, undoList);143}144145146bool147GNEMoveElementShape::isMovingAttributeValid(SumoXMLAttr key, const std::string& value) const {148return myMovedElement->isCommonAttributeValid(key, value);149}150151152void153GNEMoveElementShape::setMovingAttribute(SumoXMLAttr key, const std::string& value) {154return myMovedElement->setCommonAttribute(key, value);155}156157158void159GNEMoveElementShape::setMoveShape(const GNEMoveResult& moveResult) {160if (moveResult.operationType == GNEMoveOperation::OperationType::POSITION) {161// update new center162myCenterPosition = moveResult.shapeToUpdate.front();163} else if (moveResult.operationType == GNEMoveOperation::OperationType::ENTIRE_SHAPE) {164// update new shape and center165myCenterPosition.add(moveResult.shapeToUpdate.getCentroid() - myMovingShape.getCentroid());166myMovingShape = moveResult.shapeToUpdate;167} else {168// get lastIndex169const int lastIndex = (int)moveResult.shapeToUpdate.size() - 1;170// update new shape171myMovingShape = moveResult.shapeToUpdate;172// adjust first and last position173if (moveResult.geometryPointsToMove.front() == 0) {174myMovingShape[lastIndex] = moveResult.shapeToUpdate[0];175} else if (moveResult.geometryPointsToMove.front() == lastIndex) {176myMovingShape[0] = moveResult.shapeToUpdate[lastIndex];177}178myMovingShape.closePolygon();179}180// update geometry181myMovedElement->updateGeometry();182}183184185void186GNEMoveElementShape::commitMoveShape(const GNEMoveResult& moveResult, GNEUndoList* undoList) {187if (moveResult.operationType == GNEMoveOperation::OperationType::POSITION) {188// commit center189undoList->begin(myMovedElement, TLF("moving center of %", myMovedElement->getTagStr()));190GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_CENTER, toString(moveResult.shapeToUpdate.front()), undoList);191undoList->end();192} else if (moveResult.operationType == GNEMoveOperation::OperationType::ENTIRE_SHAPE) {193// calculate offset between old and new shape194Position newCenter = myCenterPosition;195newCenter.add(moveResult.shapeToUpdate.getCentroid() - myMovingShape.getCentroid());196// commit new shape and center197undoList->begin(myMovedElement, TLF("moving entire shape of %", myMovedElement->getTagStr()));198if (myMovedElement->getTagProperty()->hasAttribute(SUMO_ATTR_CENTER)) {199GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_CENTER, toString(newCenter), undoList);200}201GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_SHAPE, toString(moveResult.shapeToUpdate), undoList);202undoList->end();203} else {204// get lastIndex205const int lastIndex = (int)moveResult.shapeToUpdate.size() - 1;206// close shapeToUpdate207auto closedShape = moveResult.shapeToUpdate;208// adjust first and last position209if (moveResult.geometryPointsToMove.front() == 0) {210closedShape[lastIndex] = moveResult.shapeToUpdate[0];211} else if (moveResult.geometryPointsToMove.front() == lastIndex) {212closedShape[0] = moveResult.shapeToUpdate[lastIndex];213}214// commit new shape215undoList->begin(myMovedElement, TLF("editing shape of %", myMovedElement->getTagStr()));216GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_SHAPE, toString(closedShape), undoList);217undoList->end();218}219}220221/****************************************************************************/222223224