Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GNEMoveElement.cpp
Go to the documentation of this file.
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/****************************************************************************/
18// Class used for elements that can be moved
19/****************************************************************************/
20#include <config.h>
21
25
26#include "GNEMoveElement.h"
27
28// ===========================================================================
29// Method definitions
30// ===========================================================================
31
33 myMovedElement(movedElement) {
34}
35
36
38
39
40std::string
42 throw InvalidArgument(myMovedElement->getTagStr() + " doesn't have a moving attribute of type '" + toString(key) + "'");
43}
44
45
46double
48 throw InvalidArgument(myMovedElement->getTagStr() + " doesn't have a moving attribute of type '" + toString(key) + "'");
49}
50
51
52void
53GNEMoveElement::setMovingAttribute(SumoXMLAttr key, const std::string& /*value*/, GNEUndoList* /*undoList*/) {
54 throw InvalidArgument(myMovedElement->getTagStr() + " doesn't have a moving attribute of type '" + toString(key) + "'");
55}
56
57
58bool
59GNEMoveElement::isMovingAttributeValid(SumoXMLAttr key, const std::string& /*value*/) const {
60 throw InvalidArgument(myMovedElement->getTagStr() + " doesn't have a moving attribute of type '" + toString(key) + "'");
61}
62
63
64void
65GNEMoveElement::setMovingAttribute(SumoXMLAttr key, const std::string& /*value*/) {
66 throw InvalidArgument(myMovedElement->getTagStr() + " doesn't have a moving attribute of type '" + toString(key) + "'");
67}
68
69
72 const bool maintainShapeClosed) {
73 // get moved geometry points
74 const auto geometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(obj);
75 // get pos over shape
76 const auto posOverShape = gViewObjectsHandler.getSelectedPositionOverShape(obj);
77 // declare shape to move
78 PositionVector shapeToMove = originalShape;
79 const int lastIndex = (int)shapeToMove.size() - 1;
80 // check if move existent geometry points or create new
81 if (geometryPoints.size() > 0) {
82 // move geometry point without creating new geometry point
83 if (maintainShapeClosed && ((geometryPoints.front() == 0) || (geometryPoints.front() == lastIndex))) {
84 // move first and last point
85 return new GNEMoveOperation(this, originalShape, {0, lastIndex}, shapeToMove, {0, lastIndex});
86 } else {
87 return new GNEMoveOperation(this, originalShape, {geometryPoints.front()}, shapeToMove, {geometryPoints.front()});
88 }
89 } else if (posOverShape != Position::INVALID) {
90 // create new geometry point and keep new index (if we clicked near of shape)
91 const int newIndex = shapeToMove.insertAtClosest(posOverShape, true);
92 return new GNEMoveOperation(this, originalShape, {shapeToMove.indexOfClosest(posOverShape)}, shapeToMove, {newIndex});
93 } else {
94 return nullptr;
95 }
96}
97
98
99void
100GNEMoveElement::moveElement(const GNEViewNet* viewNet, GNEMoveOperation* moveOperation, const GNEMoveOffset& offset) {
101 // declare move result
102 GNEMoveResult moveResult(moveOperation);
103 // set geometry points to move
104 moveResult.geometryPointsToMove = moveOperation->geometryPointsToMove;
105 // check if we're moving over a lane shape, an entire shape or only certain geometry point
106 if (moveOperation->firstLane) {
107 // calculate movement over lane depending if element has more than one lane
108 if (moveOperation->lastLane) {
109 if ((moveOperation->firstPosition != INVALID_DOUBLE) && (moveOperation->lastPosition != INVALID_DOUBLE)) {
110 // move both first and last positions
111 calculateLanePositions(moveResult.newFirstPos, moveResult.newLastPos, viewNet, moveOperation->firstLane,
112 moveOperation->firstPosition, moveOperation->lastLane, moveOperation->lastPosition,
113 moveOperation->clickedFirstLane, offset);
114 } else if (moveOperation->firstPosition != INVALID_DOUBLE) {
115 // move first position
116 calculateLanePosition(moveResult.newFirstPos, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset);
117 } else if (moveOperation->lastPosition != INVALID_DOUBLE) {
118 // move last position
119 calculateLanePosition(moveResult.newLastPos, viewNet, moveOperation->lastLane, moveOperation->lastPosition, offset);
120 }
121 } else {
122 // continue depending if we're moving both positions
123 if ((moveOperation->firstPosition != INVALID_DOUBLE) && (moveOperation->lastPosition != INVALID_DOUBLE)) {
124 // move both first and last positions in the same lane
125 calculateLanePositions(moveResult.newFirstPos, moveResult.newLastPos, viewNet, moveOperation->firstLane,
126 moveOperation->firstPosition, moveOperation->lastPosition, offset);
127 } else if (moveOperation->firstPosition != INVALID_DOUBLE) {
128 // move first position
129 calculateLanePosition(moveResult.newFirstPos, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset);
130 } else if (moveOperation->lastPosition != INVALID_DOUBLE) {
131 // move last position
132 calculateLanePosition(moveResult.newLastPos, viewNet, moveOperation->firstLane, moveOperation->lastPosition, offset);
133 }
134 // calculate new lane
135 if (moveOperation->allowChangeLane) {
136 calculateNewLaneChange(viewNet, moveOperation->firstLane, moveResult.newFirstLane, moveResult.firstLaneOffset);
137 }
138 }
139 } else if (moveOperation->geometryPointsToMove.size() > 0) {
140 // set values in moveResult
141 moveResult.shapeToUpdate = moveOperation->shapeToMove;
142 // move geometry points
143 for (const auto& geometryPointIndex : moveOperation->geometryPointsToMove) {
144 if (moveResult.shapeToUpdate[geometryPointIndex] != Position::INVALID) {
145 // add offset
146 moveResult.shapeToUpdate[geometryPointIndex].add(offset.x, offset.y, offset.z);
147 // apply snap to active grid
148 moveResult.shapeToUpdate[geometryPointIndex] = viewNet->snapToActiveGrid(moveResult.shapeToUpdate[geometryPointIndex]);
149 } else {
150 throw ProcessError("trying to move an invalid position");
151 }
152 }
153 } else {
154 // set values in moveResult
155 moveResult.shapeToUpdate = moveOperation->shapeToMove;
156 // move entire shape
157 for (auto& geometryPointIndex : moveResult.shapeToUpdate) {
158 if (geometryPointIndex != Position::INVALID) {
159 // add offset
160 geometryPointIndex.add(offset.x, offset.y, offset.z);
161 // apply snap to active grid
162 geometryPointIndex = viewNet->snapToActiveGrid(geometryPointIndex);
163 } else {
164 throw ProcessError("trying to move an invalid position");
165 }
166 }
167 // check if we're adjusting width or height
171 // calculate extrapolate vector
172 moveResult.shapeToUpdate = calculateExtrapolatedVector(moveOperation, moveResult);
173 }
174 }
175 // move shape element
176 moveOperation->moveElement->setMoveShape(moveResult);
177}
178
179
180void
181GNEMoveElement::commitMove(const GNEViewNet* viewNet, GNEMoveOperation* moveOperation, const GNEMoveOffset& offset, GNEUndoList* undoList) {
182 // declare move result
183 GNEMoveResult moveResult(moveOperation);
184 // check if we're moving over a lane shape, an entire shape or only certain geometry point
185 if (moveOperation->firstLane) {
186 // calculate original move result
187 moveResult.newFirstLane = moveOperation->firstLane;
188 moveResult.newFirstPos = moveOperation->firstPosition;
189 moveResult.newLastLane = moveOperation->lastLane;
190 moveResult.newLastPos = moveOperation->lastPosition;
191 // set original positions in element
192 moveOperation->moveElement->setMoveShape(moveResult);
193 // calculate movement over lane depending if element has more than one lane
194 if (moveOperation->lastLane) {
195 if ((moveOperation->firstPosition != INVALID_DOUBLE) && (moveOperation->lastPosition != INVALID_DOUBLE)) {
196 // move both first and last positions
197 calculateLanePositions(moveResult.newFirstPos, moveResult.newLastPos, viewNet, moveOperation->firstLane,
198 moveOperation->firstPosition, moveOperation->lastLane, moveOperation->lastPosition,
199 moveOperation->clickedFirstLane, offset);
200 } else if (moveOperation->firstPosition != INVALID_DOUBLE) {
201 // move first position
202 calculateLanePosition(moveResult.newFirstPos, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset);
203 } else if (moveOperation->lastPosition != INVALID_DOUBLE) {
204 // move last position
205 calculateLanePosition(moveResult.newLastPos, viewNet, moveOperation->lastLane, moveOperation->lastPosition, offset);
206 }
207 } else {
208 // continue depending if we're moving both positions
209 if ((moveOperation->firstPosition != INVALID_DOUBLE) && (moveOperation->lastPosition != INVALID_DOUBLE)) {
210 // move both first and last positions in the same lane
211 calculateLanePositions(moveResult.newFirstPos, moveResult.newLastPos, viewNet, moveOperation->firstLane,
212 moveOperation->firstPosition, moveOperation->lastPosition, offset);
213 } else if (moveOperation->firstPosition != INVALID_DOUBLE) {
214 // move first position
215 calculateLanePosition(moveResult.newFirstPos, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset);
216 } else if (moveOperation->lastPosition != INVALID_DOUBLE) {
217 // move last position
218 calculateLanePosition(moveResult.newLastPos, viewNet, moveOperation->firstLane, moveOperation->lastPosition, offset);
219 }
220 // calculate new lane
221 if (moveOperation->allowChangeLane) {
222 calculateNewLaneChange(viewNet, moveOperation->firstLane, moveResult.newFirstLane, moveResult.firstLaneOffset);
223 }
224 }
225 } else {
226 // set original geometry points to move
227 moveResult.geometryPointsToMove = moveOperation->originalGeometryPoints;
228 // set shapeToUpdate with originalPosOverLanes
229 moveResult.shapeToUpdate = moveOperation->originalShape;
230 // first restore original geometry geometry
231 moveOperation->moveElement->setMoveShape(moveResult);
232 // set new geometry points to move
233 moveResult.geometryPointsToMove = moveOperation->geometryPointsToMove;
234 // set values in moveResult
235 moveResult.shapeToUpdate = moveOperation->shapeToMove;
236 // check if we're moving an entire shape or only certain geometry point
237 if (moveOperation->geometryPointsToMove.size() > 0) {
238 // only move certain geometry points
239 for (const auto& geometryPointIndex : moveOperation->geometryPointsToMove) {
240 if (moveResult.shapeToUpdate[geometryPointIndex] != Position::INVALID) {
241 // add offset
242 moveResult.shapeToUpdate[geometryPointIndex].add(offset.x, offset.y, offset.z);
243 // apply snap to active grid
244 moveResult.shapeToUpdate[geometryPointIndex] = viewNet->snapToActiveGrid(moveResult.shapeToUpdate[geometryPointIndex]);
245 } else {
246 throw ProcessError("trying to move an invalid position");
247 }
248 }
249 // remove double points if merge points is enabled (only in commitMove)
250 if (viewNet->getViewParent()->getMoveFrame()->getCommonMoveOptions()->getMergeGeometryPoints() && (moveResult.shapeToUpdate.size() > 2)) {
251 moveResult.shapeToUpdate.removeDoublePoints(2);
252 }
253 } else {
254 // move entire shape
255 for (auto& geometryPointIndex : moveResult.shapeToUpdate) {
256 if (geometryPointIndex != Position::INVALID) {
257 // add offset
258 geometryPointIndex.add(offset.x, offset.y, offset.z);
259 // apply snap to active grid
260 geometryPointIndex = viewNet->snapToActiveGrid(geometryPointIndex);
261 } else {
262 throw ProcessError("trying to move an invalid position");
263 }
264 }
265 // check if we're adjusting width or height
269 // calculate extrapolate vector
270 moveResult.shapeToUpdate = calculateExtrapolatedVector(moveOperation, moveResult);
271 }
272 }
273 }
274 // commit move shape
275 moveOperation->moveElement->commitMoveShape(moveResult, undoList);
276}
277
278
279double
280GNEMoveElement::calculateLaneOffset(const GNEViewNet* viewNet, const GNELane* lane, const double firstPosition, const double lastPosition,
281 const GNEMoveOffset& offset) {
282 // get lane shape lenght
283 const auto laneShapeLength = lane->getLaneShape().length2D();
284 // declare laneOffset
285 double laneOffset = 0;
286 // calculate central position between two given positions
287 const double offsetCentralPosition = (firstPosition + lastPosition) * 0.5;
288 // calculate middle length between two given positions
289 const double middleLength = std::abs(lastPosition - firstPosition) * 0.5;
290 // calculate lane position at offset given by offsetCentralPosition
291 Position laneCentralPosition = lane->getLaneShape().positionAtOffset2D(offsetCentralPosition);
292 // apply offset to positionAtCentralPosition
293 laneCentralPosition.add(offset.x, offset.y, offset.z);
294 // snap to grid
295 laneCentralPosition = viewNet->snapToActiveGrid(laneCentralPosition);
296 // calculate offset over lane using laneCentralPosition
297 const double offsetLaneCentralPositionPerpendicular = lane->getLaneShape().nearest_offset_to_point2D(laneCentralPosition);
298 // check if offset is within lane shape
299 if (offsetLaneCentralPositionPerpendicular == -1) {
300 // calculate non-perpendicular offset over lane using laneCentralPosition
301 const double offsetLaneCentralPosition = lane->getLaneShape().nearest_offset_to_point2D(laneCentralPosition, false);
302 // due laneCentralPosition is out of lane shape, then place positions in extremes
303 if (offsetLaneCentralPosition == 0) {
304 laneOffset = firstPosition;
305 } else {
306 laneOffset = lastPosition - laneShapeLength;
307 }
308 } else {
309 // laneCentralPosition is within of lane shapen, then calculate offset using middlelength
310 if ((offsetLaneCentralPositionPerpendicular - middleLength) < 0) {
311 laneOffset = firstPosition;
312 } else if ((offsetLaneCentralPositionPerpendicular + middleLength) > laneShapeLength) {
313 laneOffset = lastPosition - laneShapeLength;
314 } else {
315 laneOffset = (offsetCentralPosition - offsetLaneCentralPositionPerpendicular);
316 }
317 }
318 return laneOffset;
319}
320
321
322void
323GNEMoveElement::calculateLanePosition(double& posOverLane, const GNEViewNet* viewNet, const GNELane* lane,
324 const double lanePos, const GNEMoveOffset& offset) {
325 // get lane offset
326 const double laneOffset = calculateLaneOffset(viewNet, lane, lanePos, lanePos, offset);
327 // update lane position
328 posOverLane = (lanePos - laneOffset) / lane->getLengthGeometryFactor();
329}
330
331
332void
333GNEMoveElement::calculateLanePositions(double& starPos, double& endPos, const GNEViewNet* viewNet, const GNELane* lane,
334 const double firstPosOverLane, const double lastPosOverLane, const GNEMoveOffset& offset) {
335 // get lane offset
336 const double laneOffset = calculateLaneOffset(viewNet, lane, firstPosOverLane, lastPosOverLane, offset);
337 // update moveResult
338 starPos = (firstPosOverLane - laneOffset) / lane->getLengthGeometryFactor();
339 endPos = (lastPosOverLane - laneOffset) / lane->getLengthGeometryFactor();
340}
341
342
343void
344GNEMoveElement::calculateLanePositions(double& starPos, double& endPos, const GNEViewNet* viewNet, const GNELane* firstLane,
345 const double firstPosOverLane, const GNELane* lastLane, const double lastPosOverLane,
346 const bool firstLaneClicked, const GNEMoveOffset& offset) {
347 // declare offset
348 double laneOffset = 0;
349 // calculate offset depending if we clicked over the first or over the second lane
350 if (firstLaneClicked) {
351 // calculate lane start position for first lane
352 calculateLanePosition(starPos, viewNet, firstLane, firstPosOverLane, offset);
353 // calculate offset
354 laneOffset = (starPos - firstPosOverLane);
355 // set end position
356 endPos = lastPosOverLane + laneOffset;
357 // adjust offset
358 const double lastLaneLength = lastLane->getLaneShape().length2D();
359 if (endPos > lastLaneLength) {
360 laneOffset = (lastLaneLength - lastPosOverLane);
361 }
362 if (endPos < 0) {
363 laneOffset = (0 - lastPosOverLane);
364 }
365 } else {
366 // calculate lane start position for first lane
367 calculateLanePosition(endPos, viewNet, lastLane, lastPosOverLane, offset);
368 // calculate offset
369 laneOffset = (endPos - lastPosOverLane);
370 // set start position
371 starPos = firstPosOverLane + laneOffset;
372 // adjust offset
373 const double firstLaneLength = firstLane->getLaneShape().length2D();
374 if (starPos > firstLaneLength) {
375 laneOffset = (firstLaneLength - firstPosOverLane);
376 }
377 if (starPos < 0) {
378 laneOffset = (0 - firstPosOverLane);
379 }
380 }
381 // set positions with the adjusted offset
382 starPos = firstPosOverLane + laneOffset;
383 endPos = lastPosOverLane + laneOffset;
384}
385
386
387void
388GNEMoveElement::calculateNewLaneChange(const GNEViewNet* viewNet, const GNELane* originalLane, const GNELane*& newLane, double& laneOffset) {
389 // get cursor position
390 const Position cursorPosition = viewNet->getPositionInformation();
391 // iterate over edge lanes
392 for (const auto& lane : originalLane->getParentEdge()->getChildLanes()) {
393 // avoid moveOperation lane
394 if (lane != originalLane) {
395 // calculate offset over lane shape
396 const double offSet = lane->getLaneShape().nearest_offset_to_point2D(cursorPosition, true);
397 // calculate position over lane shape
398 const Position posOverLane = lane->getLaneShape().positionAtOffset2D(offSet);
399 // check distance
400 if (posOverLane.distanceSquaredTo2D(cursorPosition) < 1) {
401 // update newlane
402 newLane = lane;
403 // calculate offset over moveOperation lane
404 const double offsetMoveOperationLane = originalLane->getLaneShape().nearest_offset_to_point2D(cursorPosition, true);
405 // calculate position over moveOperation lane
406 const Position posOverMoveOperationLane = originalLane->getLaneShape().positionAtOffset2D(offsetMoveOperationLane);
407 // update moveResult of laneOffset
408 laneOffset = posOverLane.distanceTo2D(posOverMoveOperationLane);
409 // change sign of moveResult laneOffset depending of lane index
410 if (originalLane->getIndex() < newLane->getIndex()) {
411 laneOffset *= -1;
412 }
413 }
414 }
415 }
416}
417
418
421 // get original shape half length
422 const double halfLength = moveOperation->originalShape.length2D() * -0.5;
423 // get original shape and extrapolate
424 PositionVector extendedShape = moveOperation->originalShape;
425 extendedShape.extrapolate2D(10e5);
426 // get geometry point
427 const Position geometryPoint = moveOperation->firstGeometryPoint ? moveResult.shapeToUpdate.front() : moveResult.shapeToUpdate.back();
428 // calculate offsets to first and last positions
429 const double offset = extendedShape.nearest_offset_to_point2D(geometryPoint, false);
430 // calculate extrapolate value
431 double extrapolateValue = (10e5 - offset);
432 // adjust extrapolation
433 if (moveOperation->firstGeometryPoint) {
434 if (extrapolateValue < halfLength) {
435 extrapolateValue = (halfLength - POSITION_EPS);
436 }
437 } else {
438 if (extrapolateValue > halfLength) {
439 extrapolateValue = (halfLength - POSITION_EPS);
440 }
441 }
442 // restore shape in in moveResult
443 PositionVector extrapolatedShape = moveOperation->shapeToMove;
444 // extrapolate
445 extrapolatedShape.extrapolate2D(extrapolateValue);
446 // check if return reverse
447 if (moveOperation->firstGeometryPoint) {
448 return extrapolatedShape;
449 } else {
450 return extrapolatedShape.reverse();
451 }
452}
453
454/****************************************************************************/
GUIViewObjectsHandler gViewObjectsHandler
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:68
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
const std::string & getTagStr() const
get tag assigned to this object in string format
const GNEHierarchicalContainerChildren< GNELane * > & getChildLanes() const
get child lanes
const PositionVector & getLaneShape() const
get elements shape
Definition GNELane.cpp:232
double getLengthGeometryFactor() const
get length geometry factor
Definition GNELane.cpp:1965
int getIndex() const
returns the index of the lane
Definition GNELane.cpp:624
GNEEdge * getParentEdge() const
get parent edge
Definition GNELane.cpp:214
static PositionVector calculateExtrapolatedVector(const GNEMoveOperation *moveOperation, const GNEMoveResult &moveResult)
calculate width/height shape
virtual void setMoveShape(const GNEMoveResult &moveResult)=0
set move shape
static void calculateLanePositions(double &starPos, double &endPos, const GNEViewNet *viewNet, const GNELane *lane, const double firstPosOverLane, const double lastPosOverLane, const GNEMoveOffset &offset)
calculate lane position over one lane with two positions (stoppingPlaces, E2 single lanes)
GNEAttributeCarrier * myMovedElement
pointer to element
virtual ~GNEMoveElement()
static void commitMove(const GNEViewNet *viewNet, GNEMoveOperation *moveOperation, const GNEMoveOffset &offset, GNEUndoList *undoList)
commit move element for the given offset
static void calculateLanePosition(double &starPos, const GNEViewNet *viewNet, const GNELane *lane, const double posOverLane, const GNEMoveOffset &offset)
calculate lane position over one lane with only one position (accesss, E1, star/end positions,...
virtual double getMovingAttributeDouble(SumoXMLAttr key) const =0
get moving attribute double
virtual void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)=0
commit move shape
virtual std::string getMovingAttribute(SumoXMLAttr key) const =0
get moving attribute
static void calculateNewLaneChange(const GNEViewNet *viewNet, const GNELane *originalLane, const GNELane *&newLane, double &laneOffset)
calculate new lane change
virtual void setMovingAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)=0
set moving attribute (using undo-list)
GNEMoveElement()=delete
invalidate default constructor
GNEMoveOperation * getEditShapeOperation(const GUIGlObject *obj, const PositionVector originalShape, const bool maintainShapeClosed)
calculate move shape operation
virtual bool isMovingAttributeValid(SumoXMLAttr key, const std::string &value) const =0
check if the given moving attribute is valid
static void moveElement(const GNEViewNet *viewNet, GNEMoveOperation *moveOperation, const GNEMoveOffset &offset)
move element the for given offset (note: offset can be X-Y-0, 0-0-Z or X-Y-Z)
static double calculateLaneOffset(const GNEViewNet *viewNet, const GNELane *lane, const double firstPosition, const double lastPosition, const GNEMoveOffset &offset)
calculate lane offset (used in calculateLanePosition)
bool getMergeGeometryPoints() const
check if merge geometry points
CommonMoveOptions * getCommonMoveOptions() const
get common mode options
const double z
Z.
const double x
X.
const double y
Y.
const OperationType operationType
operation type
const PositionVector originalShape
original shape
const std::vector< int > originalGeometryPoints
original shape points to move (of original shape)
const PositionVector shapeToMove
shape to move
const bool clickedFirstLane
@check if clicked the first lane or the last lane (used only in multilane elements like E2)
const GNELane * lastLane
original last lane
const double lastPosition
original last Position
const GNELane * firstLane
original first lane
const std::vector< int > geometryPointsToMove
shape points to move (of shapeToMove)
const double firstPosition
original first Position
const bool allowChangeLane
allow change lane
GNEMoveElement * moveElement
move element
const bool firstGeometryPoint
first position (used for edit with/height
const GNELane * newFirstLane
new first Lane
double newFirstPos
new first position
const GNELane * newLastLane
new last Lane
double firstLaneOffset
lane offset
std::vector< int > geometryPointsToMove
shape points to move (of shapeToMove)
double newLastPos
new last position
PositionVector shapeToUpdate
shape to update (edited in moveElement)
GNEViewParent * getViewParent() const
get the net object
GNEMoveFrame * getMoveFrame() const
get frame for move elements
Position snapToActiveGrid(const Position &pos, bool snapXY=true) const
Returns a position that is mapped to the closest grid point if the grid is active.
virtual Position getPositionInformation() const
Returns the cursor's x/y position within the network.
const Position & getSelectedPositionOverShape(const GUIGlObject *GLObject) const
get position over shape
const std::vector< int > & getSelectedGeometryPoints(const GUIGlObject *GLObject) const
get geometry points for the given glObject
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition Position.h:278
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:323
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition Position.h:273
void add(const Position &pos)
Adds the given position to this one.
Definition Position.h:129
A list of positions.
double length2D() const
Returns the length.
void add(double xoff, double yoff, double zoff)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
int indexOfClosest(const Position &p, bool twoD=false) const
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
int insertAtClosest(const Position &p, bool interpolateZ)
inserts p between the two closest positions
Position positionAtOffset2D(double pos, double lateralOffset=0, bool extrapolateBeyond=false) const
Returns the position at the given length.
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false, int beginOffset=0, int endOffset=0, bool resample=false)
Removes positions if too near.
PositionVector reverse() const
reverse position vector