Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/moving/GNEMoveElementShape.cpp
185790 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file GNEMoveElementShape.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Sep 2025
17
///
18
// Class used for shape elements that can be moved over view
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <netedit/changes/GNEChange_Attribute.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
29
#include "GNEMoveElementShape.h"
30
31
// ===========================================================================
32
// static members
33
// ===========================================================================
34
35
PositionVector GNEMoveElementShape::EMPTY_SHAPE;
36
37
// ===========================================================================
38
// Method definitions
39
// ===========================================================================
40
41
GNEMoveElementShape::GNEMoveElementShape(GNEAttributeCarrier* element) :
42
GNEMoveElement(element),
43
myMovingShape(EMPTY_SHAPE) {
44
}
45
46
47
GNEMoveElementShape::GNEMoveElementShape(GNEAttributeCarrier* element, PositionVector& shape, const bool alwaysClosed) :
48
GNEMoveElement(element),
49
myMovingShape(shape),
50
myAlwaysClosed(alwaysClosed) {
51
}
52
53
54
GNEMoveElementShape::GNEMoveElementShape(GNEAttributeCarrier* element, PositionVector& shape, const Position& position, const bool alwaysClosed) :
55
GNEMoveElement(element),
56
myCenterPosition(position),
57
myMovingShape(shape),
58
myAlwaysClosed(alwaysClosed) {
59
}
60
61
62
GNEMoveElementShape::~GNEMoveElementShape() {}
63
64
65
GNEMoveOperation*
66
GNEMoveElementShape::getMoveOperation() {
67
// get snap radius
68
const double snap_radius = myMovedElement->getNet()->getViewNet()->getVisualisationSettings().neteditSizeSettings.polygonGeometryPointRadius;
69
// check if we're moving center or shape
70
if (myCenterPosition.distanceSquaredTo2D(myMovedElement->getNet()->getViewNet()->getPositionInformation()) < (snap_radius * snap_radius)) {
71
// move entire shape
72
return new GNEMoveOperation(this, myCenterPosition);
73
} else if (myMovedElement->getNet()->getViewParent()->getMoveFrame()->getNetworkMoveOptions()->getMoveWholePolygons()) {
74
// move entire shape
75
return new GNEMoveOperation(this, myMovingShape);
76
} else {
77
// calculate move shape operation
78
return getEditShapeOperation(myMovedElement->getGUIGlObject(), myMovingShape, myAlwaysClosed);
79
}
80
}
81
82
83
void
84
GNEMoveElementShape::removeGeometryPoint(const Position clickedPosition, GNEUndoList* undoList) {
85
// get original shape
86
PositionVector shape = myMovingShape;
87
// check shape size
88
if (shape.size() > 3) {
89
// obtain index
90
int index = shape.indexOfClosest(clickedPosition);
91
// get last index
92
const int lastIndex = ((int)shape.size() - 1);
93
// get snap radius
94
const double snap_radius = myMovedElement->getNet()->getViewNet()->getVisualisationSettings().neteditSizeSettings.polygonGeometryPointRadius;
95
// check if we have to create a new index
96
if ((index != -1) && shape[index].distanceSquaredTo2D(clickedPosition) < (snap_radius * snap_radius)) {
97
// check if we're deleting the first point
98
if ((index == 0) || (index == lastIndex)) {
99
// remove both geometry point
100
shape.erase(shape.begin() + lastIndex);
101
shape.erase(shape.begin());
102
// close shape
103
shape.closePolygon();
104
} else {
105
// remove geometry point
106
shape.erase(shape.begin() + index);
107
}
108
// commit new shape
109
undoList->begin(myMovedElement, TLF("remove geometry point of %", myMovedElement->getTagStr()));
110
GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_SHAPE, toString(shape), undoList);
111
undoList->end();
112
}
113
}
114
}
115
116
117
std::string
118
GNEMoveElementShape::getMovingAttribute(SumoXMLAttr key) const {
119
return myMovedElement->getCommonAttribute(key);
120
}
121
122
123
double
124
GNEMoveElementShape::getMovingAttributeDouble(SumoXMLAttr key) const {
125
return myMovedElement->getCommonAttributeDouble(key);
126
}
127
128
129
Position
130
GNEMoveElementShape::getMovingAttributePosition(SumoXMLAttr key) const {
131
return myMovedElement->getCommonAttributePosition(key);
132
}
133
134
135
PositionVector
136
GNEMoveElementShape::getMovingAttributePositionVector(SumoXMLAttr key) const {
137
return myMovedElement->getCommonAttributePositionVector(key);
138
}
139
140
141
void
142
GNEMoveElementShape::setMovingAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
143
return myMovedElement->setCommonAttribute(key, value, undoList);
144
}
145
146
147
bool
148
GNEMoveElementShape::isMovingAttributeValid(SumoXMLAttr key, const std::string& value) const {
149
return myMovedElement->isCommonAttributeValid(key, value);
150
}
151
152
153
void
154
GNEMoveElementShape::setMovingAttribute(SumoXMLAttr key, const std::string& value) {
155
return myMovedElement->setCommonAttribute(key, value);
156
}
157
158
159
void
160
GNEMoveElementShape::setMoveShape(const GNEMoveResult& moveResult) {
161
if (moveResult.operationType == GNEMoveOperation::OperationType::POSITION) {
162
// update new center
163
myCenterPosition = moveResult.shapeToUpdate.front();
164
} else if (moveResult.operationType == GNEMoveOperation::OperationType::ENTIRE_SHAPE) {
165
// update new shape and center
166
myCenterPosition.add(moveResult.shapeToUpdate.getCentroid() - myMovingShape.getCentroid());
167
myMovingShape = moveResult.shapeToUpdate;
168
} else {
169
// get lastIndex
170
const int lastIndex = (int)moveResult.shapeToUpdate.size() - 1;
171
// update new shape
172
myMovingShape = moveResult.shapeToUpdate;
173
// adjust first and last position
174
if (moveResult.geometryPointsToMove.front() == 0) {
175
myMovingShape[lastIndex] = moveResult.shapeToUpdate[0];
176
} else if (moveResult.geometryPointsToMove.front() == lastIndex) {
177
myMovingShape[0] = moveResult.shapeToUpdate[lastIndex];
178
}
179
myMovingShape.closePolygon();
180
}
181
// update geometry
182
myMovedElement->updateGeometry();
183
}
184
185
186
void
187
GNEMoveElementShape::commitMoveShape(const GNEMoveResult& moveResult, GNEUndoList* undoList) {
188
if (moveResult.operationType == GNEMoveOperation::OperationType::POSITION) {
189
// commit center
190
undoList->begin(myMovedElement, TLF("moving center of %", myMovedElement->getTagStr()));
191
GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_CENTER, toString(moveResult.shapeToUpdate.front()), undoList);
192
undoList->end();
193
} else if (moveResult.operationType == GNEMoveOperation::OperationType::ENTIRE_SHAPE) {
194
// calculate offset between old and new shape
195
Position newCenter = myCenterPosition;
196
newCenter.add(moveResult.shapeToUpdate.getCentroid() - myMovingShape.getCentroid());
197
// commit new shape and center
198
undoList->begin(myMovedElement, TLF("moving entire shape of %", myMovedElement->getTagStr()));
199
if (myMovedElement->getTagProperty()->hasAttribute(SUMO_ATTR_CENTER)) {
200
GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_CENTER, toString(newCenter), undoList);
201
}
202
GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_SHAPE, toString(moveResult.shapeToUpdate), undoList);
203
undoList->end();
204
} else {
205
// get lastIndex
206
const int lastIndex = (int)moveResult.shapeToUpdate.size() - 1;
207
// close shapeToUpdate
208
auto closedShape = moveResult.shapeToUpdate;
209
// adjust first and last position
210
if (moveResult.geometryPointsToMove.front() == 0) {
211
closedShape[lastIndex] = moveResult.shapeToUpdate[0];
212
} else if (moveResult.geometryPointsToMove.front() == lastIndex) {
213
closedShape[0] = moveResult.shapeToUpdate[lastIndex];
214
}
215
// commit new shape
216
undoList->begin(myMovedElement, TLF("editing shape of %", myMovedElement->getTagStr()));
217
GNEChange_Attribute::changeAttribute(myMovedElement, SUMO_ATTR_SHAPE, toString(closedShape), undoList);
218
undoList->end();
219
}
220
}
221
222
/****************************************************************************/
223
224