Eclipse SUMO - Simulation of Urban MObility
GNEStoppingPlace.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-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
15 // A abstract class to define common parameters of lane area in which vehicles can halt (GNE version)
16 /****************************************************************************/
17 
18 // ===========================================================================
19 // included modules
20 // ===========================================================================
21 
22 #include <netedit/GNENet.h>
23 #include <netedit/GNEUndoList.h>
24 #include <netedit/GNEViewNet.h>
30 
31 #include "GNEStoppingPlace.h"
32 
33 // ===========================================================================
34 // static members
35 // ===========================================================================
36 
37 const double GNEStoppingPlace::myCircleWidth = 1.1;
38 const double GNEStoppingPlace::myCircleWidthSquared = 1.21;
39 const double GNEStoppingPlace::myCircleInWidth = 0.9;
40 const double GNEStoppingPlace::myCircleInText = 1.6;
41 
42 // ===========================================================================
43 // member method definitions
44 // ===========================================================================
45 
46 GNEStoppingPlace::GNEStoppingPlace(const std::string& id, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, GNELane* lane, const std::string& startPos, const std::string& endPos,
47  const std::string& name, bool friendlyPosition, bool blockMovement) :
48  GNEAdditional(id, viewNet, type, tag, name, blockMovement, {}, {lane}, {}, {}, {}, {}, {}, {}, {}, {}),
49  myStartPosition(startPos),
50  myEndPosition(endPos),
51 myFriendlyPosition(friendlyPosition) {
52 }
53 
54 
56 
57 
58 bool
60  // with friendly position enabled position are "always fixed"
61  if (myFriendlyPosition) {
62  return true;
63  } else {
64  // obtain lane length
65  double laneLenght = getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength() * getLaneParents().front()->getLengthGeometryFactor();
66  // calculate start and end positions
67  double startPos = canParse<double>(myStartPosition) ? parse<double>(myStartPosition) : 0;
68  double endPos = canParse<double>(myEndPosition) ? parse<double>(myEndPosition) : laneLenght;
69  // check if position has to be fixed
70  if (startPos < 0) {
71  startPos += laneLenght;
72  }
73  if (endPos < 0) {
74  endPos += laneLenght;
75  }
76  // check values
77  if (myStartPosition.empty() && myEndPosition.empty()) {
78  return true;
79  } else if (myStartPosition.empty()) {
80  return (endPos <= getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength());
81  } else if (myEndPosition.empty()) {
82  return (startPos >= 0);
83  } else {
84  return ((startPos >= 0) && (endPos <= getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength()) && ((endPos - startPos) >= POSITION_EPS));
85  }
86  }
87 }
88 
89 
90 std::string
92  // calculate start and end positions
93  double startPos = canParse<double>(myStartPosition) ? parse<double>(myStartPosition) : 0;
94  double endPos = canParse<double>(myEndPosition) ? parse<double>(myEndPosition) : getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength();
95  // obtain lane lenght
96  double laneLenght = getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength();
97  // check if position has to be fixed
98  if (startPos < 0) {
99  startPos += laneLenght;
100  }
101  if (endPos < 0) {
102  endPos += laneLenght;
103  }
104  // declare variables
105  std::string errorStart, separator, errorEnd;
106  // check positions over lane
107  if (startPos < 0) {
108  errorStart = (toString(SUMO_ATTR_STARTPOS) + " < 0");
109  } else if (startPos > getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength()) {
110  errorStart = (toString(SUMO_ATTR_STARTPOS) + " > lanes's length");
111  }
112  if (endPos < 0) {
113  errorEnd = (toString(SUMO_ATTR_ENDPOS) + " < 0");
114  } else if (endPos > getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength()) {
115  errorEnd = (toString(SUMO_ATTR_ENDPOS) + " > lanes's length");
116  }
117  // check separator
118  if ((errorStart.size() > 0) && (errorEnd.size() > 0)) {
119  separator = " and ";
120  }
121  return errorStart + separator + errorEnd;
122 }
123 
124 
125 void
127  // declare new start and end position
128  std::string newStartPos = myStartPosition;
129  std::string newEndPos = myEndPosition;
130  // fix start and end positions using fixStoppinPlacePosition
131  fixStoppinPlacePosition(newStartPos, newEndPos, getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength(), true);
132  // set new start and end positions
135 }
136 
137 
138 bool
139 GNEStoppingPlace::checkStoppinPlacePosition(const std::string& startPosStr, const std::string& endPosStr, const double laneLength, const bool friendlyPos) {
140  // obtain start and end position in double format, depending if it can be parsed to double
141  double startPos = GNEAttributeCarrier::canParse<double>(startPosStr) ? GNEAttributeCarrier::parse<double>(startPosStr) : 0;
142  double endPos = GNEAttributeCarrier::canParse<double>(endPosStr) ? GNEAttributeCarrier::parse<double>(endPosStr) : laneLength;
143  // return check stop pos (note: this is the same function of SUMORouteHandler::checkStopPos)
144  if (POSITION_EPS > laneLength) {
145  return false;
146  }
147  if (startPos < 0) {
148  startPos += laneLength;
149  }
150  if (endPos < 0) {
151  endPos += laneLength;
152  }
153  if (endPos < POSITION_EPS || endPos > laneLength) {
154  if (!friendlyPos) {
155  return false;
156  }
157  }
158  if (startPos < 0 || startPos > endPos - POSITION_EPS) {
159  if (!friendlyPos) {
160  return false;
161  }
162  }
163  return true;
164 }
165 
166 
167 bool
168 GNEStoppingPlace::fixStoppinPlacePosition(std::string& startPosStr, std::string& endPosStr, const double laneLength, const bool friendlyPos) {
169  // obtain start and end position in double format
170  double startPos = fabs(canParse<double>(startPosStr) ? parse<double>(startPosStr) : 0);
171  double endPos = fabs(parse<double>(endPosStr) ? parse<double>(endPosStr) : laneLength);
172  double minLength = POSITION_EPS + 0.01;
173  // return check stop pos (note: this is the same function of SUMORouteHandler::checkStopPos)
174  if (minLength > laneLength) {
175  return false;
176  }
177  if (startPos < 0) {
178  startPos += laneLength;
179  }
180  if (endPos < 0) {
181  endPos += laneLength;
182  }
183  if (endPos < minLength || endPos > laneLength) {
184  if (!friendlyPos) {
185  return false;
186  }
187  if (endPos < minLength) {
188  endPos = minLength;
189  }
190  if (endPos > laneLength) {
191  endPos = laneLength;
192  }
193  }
194  if (startPos < 0 || startPos > endPos - minLength) {
195  if (!friendlyPos) {
196  return false;
197  }
198  if (startPos < 0) {
199  startPos = 0;
200  }
201  if (startPos > endPos - minLength) {
202  startPos = endPos - minLength;
203  }
204  }
205  startPosStr = toString(startPos);
206  endPosStr = toString(endPos);
207  return true;
208 }
209 
210 
211 Position
213  // calculate start and end positions as absolute values
214  double startPos = fabs(canParse<double>(myStartPosition) ? parse<double>(myStartPosition) : 0);
215  double endPos = fabs(canParse<double>(myEndPosition) ? parse<double>(myEndPosition) : getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength());
216  // obtain position in view depending if both positions are defined
217  if (myStartPosition.empty() && myEndPosition.empty()) {
218  return getLaneParents().front()->getGeometry().shape.positionAtOffset(getLaneParents().front()->getGeometry().shape.length() / 2);
219  } else if (myStartPosition.empty()) {
220  return getLaneParents().front()->getGeometry().shape.positionAtOffset(endPos);
221  } else if (myEndPosition.empty()) {
222  return getLaneParents().front()->getGeometry().shape.positionAtOffset(startPos);
223  } else {
224  return getLaneParents().front()->getGeometry().shape.positionAtOffset((startPos + endPos) / 2.0);
225  }
226 }
227 
228 
229 void
231  // only move if at leats start or end positions is defined
232  if (!myStartPosition.empty() || !myEndPosition.empty()) {
233  // Calculate new position using old position
234  Position newPosition = myMove.originalViewPosition;
235  newPosition.add(offset);
236  // filtern position using snap to active grid
237  newPosition = myViewNet->snapToActiveGrid(newPosition);
238  double offsetLane = getLaneParents().front()->getGeometry().shape.nearest_offset_to_point2D(newPosition, false) - getLaneParents().front()->getGeometry().shape.nearest_offset_to_point2D(myMove.originalViewPosition, false);
239  // check if both position has to be moved
240  if (!myStartPosition.empty() && !myEndPosition.empty()) {
241  // calculate stoppingPlace lenght and lane lenght (After apply geometry factor)
242  double stoppingPlaceLenght = fabs(parse<double>(myMove.secondOriginalPosition) - parse<double>(myMove.firstOriginalLanePosition));
243  double laneLengt = getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength() * getLaneParents().front()->getLengthGeometryFactor();
244  // avoid changing stopping place's lenght
245  if ((parse<double>(myMove.firstOriginalLanePosition) + offsetLane) < 0) {
246  myStartPosition = "0";
247  myEndPosition = toString(stoppingPlaceLenght);
248  } else if ((parse<double>(myMove.secondOriginalPosition) + offsetLane) > laneLengt) {
249  myStartPosition = toString(laneLengt - stoppingPlaceLenght);
250  myEndPosition = toString(laneLengt);
251  } else {
252  myStartPosition = toString(parse<double>(myMove.firstOriginalLanePosition) + offsetLane);
253  myEndPosition = toString(parse<double>(myMove.secondOriginalPosition) + offsetLane);
254  }
255  } else {
256  // check if start position must be moved
257  if (!myStartPosition.empty()) {
258  myStartPosition = toString(parse<double>(myMove.firstOriginalLanePosition) + offsetLane);
259  }
260  // check if start position must be moved
261  if (!myEndPosition.empty()) {
262  myEndPosition = toString(parse<double>(myMove.secondOriginalPosition) + offsetLane);
263  }
264  }
265  // update demand element children
266  for (const auto& i : getDemandElementChildren()) {
267  // if child is a person plan, update geometry of their person parent
268  if (i->getTagProperty().isPersonPlan()) {
269  i->getDemandElementParents().front()->markSegmentGeometryDeprecated();
270  i->getDemandElementParents().front()->updateGeometry();
271  } else {
272  i->markSegmentGeometryDeprecated();
273  i->updateGeometry();
274  }
275  }
276  // Update geometry
277  updateGeometry();
278  }
279 }
280 
281 
282 void
284  // only commit geometry moving if at leats start or end positions is defined
285  if (!myStartPosition.empty() || !myEndPosition.empty()) {
286  undoList->p_begin("position of " + getTagStr());
287  if (!myStartPosition.empty()) {
289  }
290  if (!myEndPosition.empty()) {
292  }
293  undoList->p_end();
294  // update demand element children
295  for (const auto& i : getDemandElementChildren()) {
296  // if child is a person plan, update geometry of their person parent
297  if (i->getTagProperty().isPersonPlan()) {
298  i->getDemandElementParents().front()->markSegmentGeometryDeprecated();
299  i->getDemandElementParents().front()->updateGeometry();
300  } else {
301  i->markSegmentGeometryDeprecated();
302  i->updateGeometry();
303  }
304  }
305  }
306 }
307 
308 
309 double
311  if (canParse<double>(myStartPosition)) {
312  return parse<double>(myStartPosition);
313  } else {
314  return 0;
315  }
316 }
317 
318 
319 double
321  if (canParse<double>(myEndPosition)) {
322  return parse<double>(myEndPosition);
323  } else {
324  return getLaneParents().front()->getLaneShapeLength();
325  }
326 }
327 
328 
329 std::string
331  return getLaneParents().front()->getMicrosimID();
332 }
333 
334 
335 void
337  // Clear all containers
339 
340  // Get value of option "lefthand"
341  double offsetSign = OptionsCont::getOptions().getBool("lefthand") ? -1 : 1;
342 
343  // Get shape of lane parent
344  myGeometry.shape = getLaneParents().front()->getGeometry().shape;
345 
346  // Move shape to side
347  myGeometry.shape.move2side(movingToSide * offsetSign);
348 
349  // Cut shape using as delimitators fixed start position and fixed end position
351 
352  // Get calculate lenghts and rotations
354 }
355 
356 
357 double
359  if (myStartPosition.empty()) {
360  return 0;
361  } else {
362  double fixedPos = parse<double>(myStartPosition);
363  const double len = getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength();
364  if (fixedPos < 0) {
365  fixedPos += len;
366  }
367  return fixedPos * getLaneParents().front()->getLengthGeometryFactor();
368  }
369 }
370 
371 
372 double
374  if (myEndPosition.empty()) {
375  return getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength();
376  } else {
377  double fixedPos = parse<double>(myEndPosition);
378  const double len = getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength();
379  if (fixedPos < 0) {
380  fixedPos += len;
381  }
382  return fixedPos * getLaneParents().front()->getLengthGeometryFactor();
383  }
384 }
385 
386 
387 std::string
389  return getTagStr() + ": " + getID();
390 }
391 
392 
393 std::string
395  return getTagStr();
396 }
397 
398 /****************************************************************************/
SumoXMLTag
Numbers representing SUMO-XML - element names.
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.
GUIGlObjectType
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:127
std::string secondOriginalPosition
value for saving second original position over lane before moving
std::string getHierarchyName() const
get Hierarchy Name (Used in AC Hierarchy)
std::string getPopUpID() const
get PopPup ID (Used in AC Hierarchy)
static const double myCircleWidthSquared
squared circle width resolution for all stopping places
static const double myCircleInWidth
inner circle width resolution for all stopping places
Position getPositionInView() const
Returns position of additional in view.
static bool checkStoppinPlacePosition(const std::string &startPosStr, const std::string &endPosStr, const double laneLength, const bool friendlyPos)
check if the position of an stoppingPlace over a lane is valid (without modifications) ...
void clearGeometry()
reset geometry
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:46
bool myFriendlyPosition
Flag for friendly position.
Position originalViewPosition
value for saving first original position over lane before moving
void p_begin(const std::string &description)
Begin undo command sub-group. This begins a new group of commands that are treated as a single comman...
Definition: GNEUndoList.cpp:73
std::string myStartPosition
The relative start position this stopping place is located at (optional, if empty takes 0) ...
static const double myCircleInText
text inner circle width resolution for all stopping places
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
std::string getParentName() const
Returns the name of the parent object (if any)
virtual void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)=0
method for setting the attribute and letting the object perform additional changes ...
bool isAdditionalValid() const
check if current additional is valid to be writed into XML (by default true, can be reimplemented in ...
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
const std::vector< GNEDemandElement * > & getDemandElementChildren() const
return vector of demand elements that have as Parent this edge (For example, Calibrators) ...
double getEndGeometryPositionOverLane() const
get end position over lane that is applicable to the shape
GNEViewNet * myViewNet
The GNEViewNet this additional element belongs.
AdditionalMove myMove
variable AdditionalMove
double getEndPosition() const
get end Position
void p_add(GNEChange_Attribute *cmd)
special method, avoid empty changes, always execute
GNEUndoList * getUndoList() const
get the undoList object
Definition: GNEViewNet.cpp:933
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
void fixAdditionalProblem()
fix additional problem
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise, the sub-group will be added as a new command into parent group. A matching begin() must have been called previously.
Definition: GNEUndoList.cpp:80
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
PositionVector shape
The shape of the additional element.
Definition: GNEAdditional.h:68
double getStartGeometryPositionOverLane() const
get start position over lane that is applicable to the shape
friend class GNEChange_Attribute
declare friend class
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
const std::vector< GNELane * > & getLaneParents() const
get lanes of VSS
#define POSITION_EPS
Definition: config.h:169
GNEStoppingPlace(const std::string &id, GNEViewNet *viewNet, GUIGlObjectType type, SumoXMLTag tag, GNELane *lane, const std::string &startPos, const std::string &endPos, const std::string &name, bool friendlyPosition, bool blockMovement)
Constructor.
void commitGeometryMoving(GNEUndoList *undoList)
commit geometry changes in the attributes of an element after use of moveGeometry(...)
~GNEStoppingPlace()
Destructor.
const std::string getID() const
function to support debugging
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
static const double myCircleWidth
circle width resolution for all stopping places
void calculateShapeRotationsAndLengths()
calculate shape rotations and lenghts
double getStartPosition() const
get start Position
std::string getAdditionalProblem() const
return a string with the current additional problem
void setStoppingPlaceGeometry(double movingToSide)
set geometry common to all stopping places
An Element which don&#39;t belongs to GNENet but has influency in the simulation.
Definition: GNEAdditional.h:47
AdditionalGeometry myGeometry
geometry to be precomputed in updateGeometry(...)
const std::string & getTagStr() const
get tag assigned to this object in string format
virtual void updateGeometry()=0
update pre-computed geometry information
static bool fixStoppinPlacePosition(std::string &startPosStr, std::string &endPosStr, const double laneLength, const bool friendlyPos)
check if the position of an stoppingPlace over a la can be fixed
GNENet * getNet() const
get the net object
Definition: GNEViewNet.cpp:927
std::string myEndPosition
The position this stopping place is located at (optional, if empty takes the lane lenght) ...
std::string firstOriginalLanePosition
value for saving first original position over lane before moving
void moveGeometry(const Position &offset)
change the position of the element geometry without saving in undoList