Eclipse SUMO - Simulation of Urban MObility
GNEMoveElement.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2022 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 move shape elements
19 /****************************************************************************/
22 #include <netedit/GNEViewNet.h>
23 
24 #include "GNEMoveElement.h"
25 
26 
27 // ===========================================================================
28 // GNEMoveOperation method definitions
29 // ===========================================================================
30 
32  const Position _originalPosition) :
33  moveElement(_moveElement),
34  originalShape({_originalPosition}),
35  shapeToMove({_originalPosition}),
36  allowChangeLane(false),
37  firstGeometryPoint(false),
38 operationType(OperationType::POSITION) {
39 }
40 
41 
43  const PositionVector _originalShape) :
44  moveElement(_moveElement),
45  originalShape(_originalShape),
46  shapeToMove(_originalShape),
47  allowChangeLane(false),
48  firstGeometryPoint(false),
49  operationType(OperationType::ENTIRE_SHAPE) {
50 }
51 
53  const PositionVector _originalShape,
54  const bool _firstGeometryPoint,
55  const OperationType _operationType) :
56  moveElement(_moveElement),
57  originalShape(_originalShape),
58  shapeToMove(_originalShape),
59  allowChangeLane(false),
60  firstGeometryPoint(_firstGeometryPoint),
61  operationType(_operationType) {
62 }
63 
65  const PositionVector _originalShape,
66  const std::vector<int> _originalgeometryPoints,
67  const PositionVector _shapeToMove,
68  const std::vector<int> _geometryPointsToMove) :
69  moveElement(_moveElement),
70  originalShape(_originalShape),
71  originalGeometryPoints(_originalgeometryPoints),
72  shapeToMove(_shapeToMove),
73  geometryPointsToMove(_geometryPointsToMove),
74  allowChangeLane(false),
75  firstGeometryPoint(false),
76  operationType(OperationType::GEOMETRY_POINTS) {
77 }
78 
79 
81  const GNELane* _lane,
82  const double _firstPosition,
83  const bool _allowChangeLane) :
84  moveElement(_moveElement),
85  firstLane(_lane),
86  firstPosition(_firstPosition * _lane->getLengthGeometryFactor()),
87  allowChangeLane(_allowChangeLane),
88  firstGeometryPoint(false),
89  operationType(OperationType::ONE_LANE) {
90 }
91 
92 
94  const GNELane* _lane,
95  const double _firstPosition,
96  const double _secondPosition,
97  const bool _allowChangeLane,
98  const OperationType _operationType) :
99  moveElement(_moveElement),
100  firstLane(_lane),
101  firstPosition(_firstPosition * _lane->getLengthGeometryFactor()),
102  secondPosition(_secondPosition * _lane->getLengthGeometryFactor()),
103  allowChangeLane(_allowChangeLane),
104  firstGeometryPoint(false),
105  operationType(_operationType) {
106 }
107 
108 
110  const GNELane* _firstLane,
111  const double _firstStartPos,
112  const GNELane* _secondLane,
113  const double _secondStartPos,
114  const bool _allowChangeLane,
115  const OperationType _operationType) :
116  moveElement(_moveElement),
117  firstLane(_firstLane),
118  firstPosition((_firstStartPos != INVALID_DOUBLE) ? _firstStartPos * _firstLane->getLengthGeometryFactor() : INVALID_DOUBLE),
119  secondLane(_secondLane),
120  secondPosition((_secondStartPos != INVALID_DOUBLE) ? _secondStartPos * _secondLane->getLengthGeometryFactor() : INVALID_DOUBLE),
121  allowChangeLane(_allowChangeLane),
122  firstGeometryPoint(false),
123  operationType(_operationType) {
124 }
125 
126 
128 
129 // ===========================================================================
130 // GNEMoveOffset method definitions
131 // ===========================================================================
132 
134  x(0),
135  y(0),
136  z(0) {
137 }
138 
139 
140 GNEMoveOffset::GNEMoveOffset(const double x_, const double y_) :
141  x(x_),
142  y(y_),
143  z(0) {
144 }
145 
146 
148  x(0),
149  y(0),
150  z(z_) {
151 }
152 
153 
155 
156 // ===========================================================================
157 // GNEMoveResult method definitions
158 // ===========================================================================
159 
161  operationType(moveOperation->operationType),
162  firstLaneOffset(0),
163  newFirstLane(nullptr),
164  newFirstPos(0),
165  secondLaneOffset(0),
166  newSecondLane(nullptr),
167  newSecondPos(0) {}
168 
169 
171 
172 
173 void
175  firstLaneOffset = 0;
176  newFirstLane = nullptr;
177  secondLaneOffset = 0;
178  newSecondLane = nullptr;
179 }
180 
181 // ===========================================================================
182 // GNEMoveElement method definitions
183 // ===========================================================================
184 
186  myMoveElementLateralOffset(0) {
187 }
188 
189 
191 GNEMoveElement::calculateMoveShapeOperation(const PositionVector originalShape, const Position mousePosition, const double snapRadius, const bool onlyContour) {
192  // calculate squared snapRadius
193  const double squaredSnapRadius = (snapRadius * snapRadius);
194  // declare shape to move
195  PositionVector shapeToMove = originalShape;
196  // obtain nearest index
197  const int nearestIndex = originalShape.indexOfClosest(mousePosition);
198  // obtain nearest position
199  const Position nearestPosition = originalShape.positionAtOffset2D(originalShape.nearest_offset_to_point2D(mousePosition));
200  // check conditions
201  if (nearestIndex == -1) {
202  return nullptr;
203  } else if (nearestPosition == Position::INVALID) {
204  // special case for extremes
205  if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
206  // move extrem without creating new geometry point
207  return new GNEMoveOperation(this, originalShape, {nearestIndex}, shapeToMove, {nearestIndex});
208  } else {
209  return nullptr;
210  }
211  } else if (mousePosition.distanceSquaredTo2D(shapeToMove[nearestIndex]) <= squaredSnapRadius) {
212  // move geometry point without creating new geometry point
213  return new GNEMoveOperation(this, originalShape, {nearestIndex}, shapeToMove, {nearestIndex});
214  } else if (!onlyContour || nearestPosition.distanceSquaredTo2D(mousePosition) <= squaredSnapRadius) {
215  // create new geometry point and keep new index (if we clicked near of shape)
216  const int newIndex = shapeToMove.insertAtClosest(nearestPosition, true);
217  // move after setting new geometry point in shapeToMove
218  return new GNEMoveOperation(this, originalShape, {nearestIndex}, shapeToMove, {newIndex});
219  } else {
220  return nullptr;
221  }
222 }
223 
224 
225 void
226 GNEMoveElement::moveElement(const GNEViewNet* viewNet, GNEMoveOperation* moveOperation, const GNEMoveOffset& offset) {
227  // declare move result
228  GNEMoveResult moveResult(moveOperation);
229  // set geometry points to move
230  moveResult.geometryPointsToMove = moveOperation->geometryPointsToMove;
231  // check if we're moving over a lane shape, an entire shape or only certain geometry point
232  if (moveOperation->firstLane) {
233  // calculate movement over lane
234  if (moveOperation->secondLane) {
236  // move only first position
237  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset,
238  0, moveOperation->firstLane->getLaneShapeLength());
240  // move only two position
241  calculateMoveResult(moveResult, viewNet, moveOperation->secondLane, moveOperation->secondPosition, offset,
242  0, moveOperation->secondLane->getLaneShapeLength());
243  } else {
244  // move both first and second positions
245  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition,
246  moveOperation->secondLane, moveOperation->secondPosition, offset);
247  }
248  // calculate new lane
249  if (moveOperation->allowChangeLane) {
250  calculateNewLane(viewNet, moveOperation->firstLane, moveResult.newFirstLane, moveResult.firstLaneOffset);
251  calculateNewLane(viewNet, moveOperation->secondLane, moveResult.newSecondLane, moveResult.secondLaneOffset);
252  } else {
253  moveResult.clearLanes();
254  }
255  } else {
257  // move first position around the entire lane
258  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset,
259  0, moveOperation->firstLane->getLaneShapeLength());
261  // move first position around [0, secondPosition]
262  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset,
263  0, moveOperation->secondPosition);
265  // move first position around [firstPosition, laneLenght]
266  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->secondPosition, offset,
267  moveOperation->firstPosition, moveOperation->firstLane->getLaneShapeLength());
268  } else {
269  // move both first and second positions
270  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition,
271  moveOperation->secondPosition, offset);
272  }
273  // calculate new lane
274  if (moveOperation->allowChangeLane) {
275  calculateNewLane(viewNet, moveOperation->firstLane, moveResult.newFirstLane, moveResult.firstLaneOffset);
276  } else {
277  moveResult.clearLanes();
278  }
279  }
280  } else if (moveOperation->geometryPointsToMove.size() > 0) {
281  // set values in moveResult
282  moveResult.shapeToUpdate = moveOperation->shapeToMove;
283  // move geometry points
284  for (const auto& geometryPointIndex : moveOperation->geometryPointsToMove) {
285  if (moveResult.shapeToUpdate[geometryPointIndex] != Position::INVALID) {
286  // add offset
287  moveResult.shapeToUpdate[geometryPointIndex].add(offset.x, offset.y, offset.z);
288  // apply snap to active grid
289  moveResult.shapeToUpdate[geometryPointIndex] = viewNet->snapToActiveGrid(moveResult.shapeToUpdate[geometryPointIndex]);
290  } else {
291  throw ProcessError("trying to move an invalid position");
292  }
293  }
294  } else {
295  // set values in moveResult
296  moveResult.shapeToUpdate = moveOperation->shapeToMove;
297  // move entire shape
298  for (auto& geometryPointIndex : moveResult.shapeToUpdate) {
299  if (geometryPointIndex != Position::INVALID) {
300  // add offset
301  geometryPointIndex.add(offset.x, offset.y, offset.z);
302  // apply snap to active grid
303  geometryPointIndex = viewNet->snapToActiveGrid(geometryPointIndex);
304  } else {
305  throw ProcessError("trying to move an invalid position");
306  }
307  }
308  // check if we're adjusting width or height
309  if ((moveOperation->operationType == GNEMoveOperation::OperationType::WIDTH) ||
312  // calculate extrapolate vector
313  moveResult.shapeToUpdate = calculateExtrapolatedVector(moveOperation, moveResult);
314  }
315  }
316  // move shape element
317  moveOperation->moveElement->setMoveShape(moveResult);
318 }
319 
320 
321 void
322 GNEMoveElement::commitMove(const GNEViewNet* viewNet, GNEMoveOperation* moveOperation, const GNEMoveOffset& offset, GNEUndoList* undoList) {
323  // declare move result
324  GNEMoveResult moveResult(moveOperation);
325  // check if we're moving over a lane shape, an entire shape or only certain geometry point
326  if (moveOperation->firstLane) {
327  // calculate original move result
328  moveResult.newFirstLane = moveOperation->firstLane;
329  moveResult.newFirstPos = moveOperation->firstPosition;
330  moveResult.newSecondLane = moveOperation->secondLane;
331  moveResult.newSecondPos = moveOperation->secondPosition;
332  // set original positions in element
333  moveOperation->moveElement->setMoveShape(moveResult);
334  // calculate movement over lane
335  if (moveOperation->secondLane) {
337  // move only first position
338  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset,
339  0, moveOperation->firstLane->getLaneShapeLength());
341  // move only two position
342  calculateMoveResult(moveResult, viewNet, moveOperation->secondLane, moveOperation->secondPosition, offset,
343  0, moveOperation->secondLane->getLaneShapeLength());
344  } else {
345  // move both first and second positions
346  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition,
347  moveOperation->secondLane, moveOperation->secondPosition, offset);
348  }
349  // calculate new lane
350  if (moveOperation->allowChangeLane) {
351  calculateNewLane(viewNet, moveOperation->firstLane, moveResult.newFirstLane, moveResult.firstLaneOffset);
352  calculateNewLane(viewNet, moveOperation->secondLane, moveResult.newSecondLane, moveResult.secondLaneOffset);
353  } else {
354  moveResult.clearLanes();
355  }
356  // calculate new lane
357  if (moveOperation->allowChangeLane) {
358  calculateNewLane(viewNet, moveOperation->firstLane, moveResult.newFirstLane, moveResult.firstLaneOffset);
359  calculateNewLane(viewNet, moveOperation->secondLane, moveResult.newSecondLane, moveResult.secondLaneOffset);
360  } else {
361  moveResult.clearLanes();
362  }
363  } else {
365  // move first position around the entire lane
366  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset,
367  0, moveOperation->firstLane->getLaneShapeLength());
369  // move first position around [0, secondPosition]
370  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition, offset,
371  0, moveOperation->secondPosition);
373  // move first position around [firstPosition, laneLenght]
374  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->secondPosition, offset,
375  moveOperation->firstPosition, moveOperation->firstLane->getLaneShapeLength());
376  } else {
377  // move both first and second positions
378  calculateMoveResult(moveResult, viewNet, moveOperation->firstLane, moveOperation->firstPosition,
379  moveOperation->secondPosition, offset);
380  }
381  // calculate new lane
382  if (moveOperation->allowChangeLane) {
383  calculateNewLane(viewNet, moveOperation->firstLane, moveResult.newFirstLane, moveResult.firstLaneOffset);
384  } else {
385  moveResult.clearLanes();
386  }
387  // calculate new lane
388  if (moveOperation->allowChangeLane) {
389  calculateNewLane(viewNet, moveOperation->firstLane, moveResult.newFirstLane, moveResult.firstLaneOffset);
390  } else {
391  moveResult.clearLanes();
392  }
393  }
394  } else {
395  // set original geometry points to move
396  moveResult.geometryPointsToMove = moveOperation->originalGeometryPoints;
397  // set shapeToUpdate with originalPosOverLanes
398  moveResult.shapeToUpdate = moveOperation->originalShape;
399  // first restore original geometry geometry
400  moveOperation->moveElement->setMoveShape(moveResult);
401  // set new geometry points to move
402  moveResult.geometryPointsToMove = moveOperation->geometryPointsToMove;
403  // set values in moveResult
404  moveResult.shapeToUpdate = moveOperation->shapeToMove;
405  // check if we're moving an entire shape or only certain geometry point
406  if (moveOperation->geometryPointsToMove.size() > 0) {
407  // only move certain geometry points
408  for (const auto& geometryPointIndex : moveOperation->geometryPointsToMove) {
409  if (moveResult.shapeToUpdate[geometryPointIndex] != Position::INVALID) {
410  // add offset
411  moveResult.shapeToUpdate[geometryPointIndex].add(offset.x, offset.y, offset.z);
412  // apply snap to active grid
413  moveResult.shapeToUpdate[geometryPointIndex] = viewNet->snapToActiveGrid(moveResult.shapeToUpdate[geometryPointIndex]);
414  } else {
415  throw ProcessError("trying to move an invalid position");
416  }
417  }
418  // remove double points (only in commitMove)
419  if (moveResult.shapeToUpdate.size() > 2) {
420  moveResult.shapeToUpdate.removeDoublePoints(2);
421  }
422  } else {
423  // move entire shape
424  for (auto& geometryPointIndex : moveResult.shapeToUpdate) {
425  if (geometryPointIndex != Position::INVALID) {
426  // add offset
427  geometryPointIndex.add(offset.x, offset.y, offset.z);
428  // apply snap to active grid
429  geometryPointIndex = viewNet->snapToActiveGrid(geometryPointIndex);
430  } else {
431  throw ProcessError("trying to move an invalid position");
432  }
433  }
434  // check if we're adjusting width or height
435  if ((moveOperation->operationType == GNEMoveOperation::OperationType::WIDTH) ||
438  // calculate extrapolate vector
439  moveResult.shapeToUpdate = calculateExtrapolatedVector(moveOperation, moveResult);
440  }
441  }
442  }
443  // commit move shape
444  moveOperation->moveElement->commitMoveShape(moveResult, undoList);
445 }
446 
447 
448 double
449 GNEMoveElement::calculateLaneOffset(const GNEViewNet* viewNet, const GNELane* lane, const double firstPosition, const double secondPosition,
450  const GNEMoveOffset& offset, const double extremFrom, const double extremTo) {
451  // declare laneOffset
452  double laneOffset = 0;
453  // calculate central position between two given positions
454  const double offsetCentralPosition = (firstPosition + secondPosition) * 0.5;
455  // calculate middle lenght between two given positions
456  const double middleLenght = std::abs(secondPosition - firstPosition) * 0.5;
457  // calculate lane position at offset given by offsetCentralPosition
458  Position laneCentralPosition = lane->getLaneShape().positionAtOffset2D(offsetCentralPosition);
459  // apply offset to positionAtCentralPosition
460  laneCentralPosition.add(offset.x, offset.y, offset.z);
461  // snap to grid
462  laneCentralPosition = viewNet->snapToActiveGrid(laneCentralPosition);
463  // calculate offset over lane using laneCentralPosition
464  const double offsetLaneCentralPositionPerpendicular = lane->getLaneShape().nearest_offset_to_point2D(laneCentralPosition);
465  // check if offset is within lane shape
466  if (offsetLaneCentralPositionPerpendicular == -1) {
467  // calculate non-perpendicular offset over lane using laneCentralPosition
468  const double offsetLaneCentralPosition = lane->getLaneShape().nearest_offset_to_point2D(laneCentralPosition, false);
469  // due laneCentralPosition is out of lane shape, then place positions in extremes
470  if (offsetLaneCentralPosition == 0) {
471  laneOffset = firstPosition;
472  } else {
473  laneOffset = secondPosition - lane->getLaneShape().length2D();
474  }
475  } else {
476  // laneCentralPosition is within of lane shapen, then calculate offset using middlelenght
477  if ((offsetLaneCentralPositionPerpendicular - middleLenght) < extremFrom) {
478  laneOffset = firstPosition + extremFrom;
479  } else if ((offsetLaneCentralPositionPerpendicular + middleLenght) > extremTo) {
480  laneOffset = secondPosition - extremTo;
481  } else {
482  laneOffset = (offsetCentralPosition - offsetLaneCentralPositionPerpendicular);
483  }
484  }
485  return laneOffset;
486 }
487 
488 
489 void
490 GNEMoveElement::calculateMoveResult(GNEMoveResult& moveResult, const GNEViewNet* viewNet, const GNELane* lane,
491  const double pos, const GNEMoveOffset& offset, const double extremFrom, const double extremTo) {
492  // get lane offset
493  const double laneOffset = calculateLaneOffset(viewNet, lane, pos, pos, offset, extremFrom, extremTo);
494  // update moveResult
495  moveResult.newFirstPos = (pos - laneOffset) / lane->getLengthGeometryFactor();
496  moveResult.newSecondPos = 0;
497 }
498 
499 
500 void
501 GNEMoveElement::calculateMoveResult(GNEMoveResult& moveResult, const GNEViewNet* viewNet, const GNELane* lane,
502  const double firstPos, const double secondPos, const GNEMoveOffset& offset) {
503  // get lane offset
504  const double laneOffset = calculateLaneOffset(viewNet, lane, firstPos, secondPos, offset, 0, lane->getLaneShape().length2D());
505  // update moveResult
506  moveResult.newFirstPos = (firstPos - laneOffset) / lane->getLengthGeometryFactor();
507  moveResult.newSecondPos = (secondPos - laneOffset) / lane->getLengthGeometryFactor();
508 }
509 
510 
511 void
512 GNEMoveElement::calculateMoveResult(GNEMoveResult& moveResult, const GNEViewNet* viewNet, const GNELane* firstLane,
513  const double firstPos, const GNELane* secondLane, const double secondPos, const GNEMoveOffset& offset) {
514  // get lane offset of the first lane
515  const double laneOffset = calculateLaneOffset(viewNet, firstLane, firstPos, firstPos, offset, secondLane->getLaneShape().length2D() - firstPos, firstLane->getLaneShape().length2D());
516  // update moveResult
517  moveResult.newFirstPos = (firstPos - laneOffset) / firstLane->getLengthGeometryFactor();
518  moveResult.newSecondPos = (secondPos - laneOffset) / firstLane->getLengthGeometryFactor();
519 }
520 
521 
522 void
523 GNEMoveElement::calculateNewLane(const GNEViewNet* viewNet, const GNELane* originalLane, const GNELane*& newLane, double& laneOffset) {
524  // get cursor position
525  const Position cursorPosition = viewNet->getPositionInformation();
526  // iterate over edge lanes
527  for (const auto& lane : originalLane->getParentEdge()->getLanes()) {
528  // avoid moveOperation lane
529  if (lane != originalLane) {
530  // calculate offset over lane shape
531  const double offSet = lane->getLaneShape().nearest_offset_to_point2D(cursorPosition, true);
532  // calculate position over lane shape
533  const Position posOverLane = lane->getLaneShape().positionAtOffset2D(offSet);
534  // check distance
535  if (posOverLane.distanceSquaredTo2D(cursorPosition) < 1) {
536  // update newlane
537  newLane = lane;
538  // calculate offset over moveOperation lane
539  const double offsetMoveOperationLane = originalLane->getLaneShape().nearest_offset_to_point2D(cursorPosition, true);
540  // calculate position over moveOperation lane
541  const Position posOverMoveOperationLane = originalLane->getLaneShape().positionAtOffset2D(offsetMoveOperationLane);
542  // update moveResult of laneOffset
543  laneOffset = posOverLane.distanceTo2D(posOverMoveOperationLane);
544  // change sign of moveResult laneOffset depending of lane index
545  if (originalLane->getIndex() < newLane->getIndex()) {
546  laneOffset *= -1;
547  }
548  }
549  }
550  }
551 }
552 
553 
556  // get original shape half lenght
557  const double halfLenght = moveOperation->originalShape.length2D() * -0.5;
558  // get original shape and extrapolate
559  PositionVector extendedShape = moveOperation->originalShape;
560  extendedShape.extrapolate2D(10e5);
561  // get geometry point
562  const Position geometryPoint = moveOperation->firstGeometryPoint ? moveResult.shapeToUpdate.front() : moveResult.shapeToUpdate.back();
563  // calculate offsets to first and last positions
564  const double offset = extendedShape.nearest_offset_to_point2D(geometryPoint, false);
565  // calculate extrapolate value
566  double extrapolateValue = (10e5 - offset);
567  // adjust extrapolation
568  if (moveOperation->firstGeometryPoint) {
569  if (extrapolateValue < halfLenght) {
570  extrapolateValue = (halfLenght - POSITION_EPS);
571  }
572  } else {
573  if (extrapolateValue > halfLenght) {
574  extrapolateValue = (halfLenght - POSITION_EPS);
575  }
576  }
577  // restore shape in in moveResult
578  PositionVector extrapolatedShape = moveOperation->shapeToMove;
579  // extrapolate
580  extrapolatedShape.extrapolate2D(extrapolateValue);
581  // check if return reverse
582  if (moveOperation->firstGeometryPoint) {
583  return extrapolatedShape;
584  } else {
585  return extrapolatedShape.reverse();
586  }
587 }
588 
589 /****************************************************************************/
const double INVALID_DOUBLE
Definition: StdDefs.h:63
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:782
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:46
const PositionVector & getLaneShape() const
get elements shape
Definition: GNELane.cpp:131
double getLengthGeometryFactor() const
get length geometry factor
Definition: GNELane.cpp:1713
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:797
double getLaneShapeLength() const
returns the length of the lane's shape
Definition: GNELane.cpp:826
GNEEdge * getParentEdge() const
get arent edge
Definition: GNELane.cpp:113
move element
static PositionVector calculateExtrapolatedVector(const GNEMoveOperation *moveOperation, const GNEMoveResult &moveResult)
calculate width/height shape
virtual void setMoveShape(const GNEMoveResult &moveResult)=0
set move shape
GNEMoveElement()
constructor
GNEMoveOperation * calculateMoveShapeOperation(const PositionVector originalShape, const Position mousePosition, const double snapRadius, const bool onlyContour)
calculate move shape operation
static void calculateMoveResult(GNEMoveResult &moveResult, const GNEViewNet *viewNet, const GNELane *lane, const double pos, const GNEMoveOffset &offset, const double extremFrom, const double extremTo)
calculate single movement over one lane
static void commitMove(const GNEViewNet *viewNet, GNEMoveOperation *moveOperation, const GNEMoveOffset &offset, GNEUndoList *undoList)
commit move element for the given offset
static double calculateLaneOffset(const GNEViewNet *viewNet, const GNELane *lane, const double firstPosition, const double secondPosition, const GNEMoveOffset &offset, const double extremFrom, const double extremTo)
calculate lane offset
virtual void commitMoveShape(const GNEMoveResult &moveResult, GNEUndoList *undoList)=0
commit move shape
static void calculateNewLane(const GNEViewNet *viewNet, const GNELane *originalLane, const GNELane *&newLane, double &laneOffset)
calculate new lane
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)
move offset
const double z
Z.
const double x
X.
const double y
Y.
GNEMoveOffset()
constructor
~GNEMoveOffset()
destructor
move operation
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
GNEMoveOperation(GNEMoveElement *moveElement, const Position originalPosition)
constructor for values with a single position (junctions, E3, ParkingSpaces...)
~GNEMoveOperation()
destructor
const double secondPosition
original second Position
const GNELane * firstLane
original first lane
const GNELane * secondLane
original second 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
move result
const GNELane * newFirstLane
new first Lane
double newFirstPos
new first position
GNEMoveResult(const GNEMoveOperation *moveOperation)
constructor
~GNEMoveResult()
destructor
const GNELane * newSecondLane
new second Lane
void clearLanes()
clear lanes
double firstLaneOffset
lane offset
std::vector< int > geometryPointsToMove
shape points to move (of shapeToMove)
double newSecondPos
new second position
PositionVector shapeToUpdate
shape to update (edited in moveElement)
double secondLaneOffset
lane offset
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.
Position getPositionInformation() const
Returns the cursor's x/y position within the network.
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:257
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:293
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:252
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:125
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
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
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.