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