Eclipse SUMO - Simulation of Urban MObility
GNECrossing.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 class for visualizing Inner Lanes (used when editing traffic lights)
16 /****************************************************************************/
17 
18 
19 // ===========================================================================
20 // included modules
21 // ===========================================================================
22 #include <config.h>
23 
27 #include <utils/gui/div/GLHelper.h>
29 #include <netedit/GNEViewNet.h>
30 #include <netedit/GNEUndoList.h>
31 #include <netedit/GNENet.h>
33 
34 #include "GNECrossing.h"
35 #include "GNEJunction.h"
36 #include "GNEEdge.h"
37 
38 
39 // ===========================================================================
40 // method definitions
41 // ===========================================================================
42 GNECrossing::GNECrossing(GNEJunction* parentJunction, std::vector<NBEdge*> crossingEdges) :
43  GNENetElement(parentJunction->getNet(), parentJunction->getNBNode()->getCrossing(crossingEdges)->id, GLO_CROSSING, SUMO_TAG_CROSSING),
44  myParentJunction(parentJunction),
45  myCrossingEdges(crossingEdges) {
46 }
47 
48 
50 
51 
52 std::string
54  // currently unused
55  return "";
56 }
57 
58 
59 void
61  // first clear geometry
63  // rebuild crossing and walking areas form node parent
65  // obtain shape
66  myGeometry.shape = crossing->customShape.size() > 0 ? crossing->customShape : crossing->shape;
67  // only rebuild shape if junction's shape isn't in Buuble mode
68  if (myParentJunction->getNBNode()->getShape().size() > 0) {
70  }
71 }
72 
73 
76  // currently unused
77  return Position(0, 0);
78 }
79 
80 
83  return myParentJunction;
84 }
85 
86 
87 const std::vector<NBEdge*>&
89  return myCrossingEdges;
90 }
91 
92 
96 }
97 
98 
99 void
101  // only draw if option drawCrossingsAndWalkingareas is enabled and size of shape is greather than 0 and zoom is close enough
103  (myGeometry.shapeRotations.size() > 0) &&
104  (myGeometry.shapeLengths.size() > 0) &&
105  (s.scale > 3.0)) {
108  // push first draw matrix
109  glPushMatrix();
110  // push name
111  glPushName(getGlID());
112  // must draw on top of junction
113  glTranslated(0, 0, GLO_JUNCTION + 0.1);
114  // set color depending of selection and priority
115  if (drawUsingSelectColor()) {
117  } else if (!crossing->valid) {
119  } else if (crossing->priority) {
121  } else {
123  }
124  // traslate to front
125  glTranslated(0, 0, .2);
126  // set default values
127  double length = 0.5;
128  double spacing = 1.0;
129  double halfWidth = crossing->width * 0.5;
130  // push second draw matrix
131  glPushMatrix();
132  // draw on top of of the white area between the rails
133  glTranslated(0, 0, 0.1);
134  for (int i = 0; i < (int)myGeometry.shape.size() - 1; ++i) {
135  // push three draw matrix
136  glPushMatrix();
137  // translate and rotate
138  glTranslated(myGeometry.shape[i].x(), myGeometry.shape[i].y(), 0.0);
139  glRotated(myGeometry.shapeRotations[i], 0, 0, 1);
140  // draw crossing depending if isn't being drawn for selecting
141  if (!s.drawForSelecting) {
142  for (double t = 0; t < myGeometry.shapeLengths[i]; t += spacing) {
143  glBegin(GL_QUADS);
144  glVertex2d(-halfWidth, -t);
145  glVertex2d(-halfWidth, -t - length);
146  glVertex2d(halfWidth, -t - length);
147  glVertex2d(halfWidth, -t);
148  glEnd();
149  }
150  } else {
151  // only draw a single rectangle if it's being drawn only for selecting
152  glBegin(GL_QUADS);
153  glVertex2d(-halfWidth, 0);
154  glVertex2d(-halfWidth, -myGeometry.shapeLengths.back());
155  glVertex2d(halfWidth, -myGeometry.shapeLengths.back());
156  glVertex2d(halfWidth, 0);
157  glEnd();
158  }
159  // pop three draw matrix
160  glPopMatrix();
161  }
162  // pop second draw matrix
163  glPopMatrix();
164  // traslate to back
165  glTranslated(0, 0, -.2);
166  // pop name
167  glPopName();
168  // pop draw matrix
169  glPopMatrix();
170  }
171  // link indices must be drawn in all edit modes if isn't being drawn for selecting
172  if (s.drawLinkTLIndex.show && !s.drawForSelecting) {
173  drawTLSLinkNo(s);
174  }
175  // check if dotted contour has to be drawn
176  if (myNet->getViewNet()->getDottedAC() == this) {
178  }
179  }
180 }
181 
182 
183 void
186  glPushMatrix();
187  glTranslated(0, 0, GLO_JUNCTION + 0.5);
188  PositionVector shape = crossing->shape;
189  shape.extrapolate(0.5); // draw on top of the walking area
190  int linkNo = crossing->tlLinkIndex;
191  int linkNo2 = crossing->tlLinkIndex2 > 0 ? crossing->tlLinkIndex2 : linkNo;
194  glPopMatrix();
195 }
196 
197 
200  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
201  buildPopupHeader(ret, app);
204  // build selection and show parameters menu
207  // build position copy entry
208  buildPositionCopyEntry(ret, false);
209  // create menu commands
210  FXMenuCommand* mcCustomShape = new FXMenuCommand(ret, "Set custom crossing shape", nullptr, &parent, MID_GNE_CROSSING_EDIT_SHAPE);
211  // check if menu commands has to be disabled
213  const bool wrongMode = (editMode == GNE_NMODE_CONNECT || editMode == GNE_NMODE_TLS || editMode == GNE_NMODE_CREATE_EDGE);
214  if (wrongMode) {
215  mcCustomShape->disable();
216  }
217  return ret;
218 }
219 
220 
221 Boundary
223  throw ProcessError("Crossings doesn't have a boundary");
224 }
225 
226 
227 std::string
229  auto crossing = myParentJunction->getNBNode()->getCrossing(myCrossingEdges, (key != SUMO_ATTR_ID));
230  switch (key) {
231  case SUMO_ATTR_ID:
232  // get attribute requieres a special case
233  if (crossing) {
234  return crossing->id;
235  } else {
236  return "Temporal Unreferenced";
237  }
238  case SUMO_ATTR_WIDTH:
239  return toString(crossing->customWidth);
240  case SUMO_ATTR_PRIORITY:
241  return crossing->priority ? "true" : "false";
242  case SUMO_ATTR_EDGES:
243  return toString(crossing->edges);
245  return toString(crossing->customTLIndex);
247  return toString(crossing->customTLIndex2);
249  return toString(crossing->customShape);
250  case GNE_ATTR_SELECTED:
252  case GNE_ATTR_GENERIC:
253  return getGenericParametersStr();
254  default:
255  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
256  }
257 }
258 
259 
260 void
261 GNECrossing::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
262  if (value == getAttribute(key)) {
263  return; //avoid needless changes, later logic relies on the fact that attributes have changed
264  }
265  switch (key) {
266  case SUMO_ATTR_ID:
267  throw InvalidArgument("Modifying attribute '" + toString(key) + "' of " + getTagStr() + " isn't allowed");
268  case SUMO_ATTR_EDGES:
269  case SUMO_ATTR_WIDTH:
270  case SUMO_ATTR_PRIORITY:
274  case GNE_ATTR_SELECTED:
275  case GNE_ATTR_GENERIC:
276  undoList->add(new GNEChange_Attribute(this, myNet, key, value), true);
277  break;
278  default:
279  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
280  }
281 }
282 
283 
284 bool
285 GNECrossing::isValid(SumoXMLAttr key, const std::string& value) {
287  switch (key) {
288  case SUMO_ATTR_ID:
289  return false;
290  case SUMO_ATTR_EDGES:
291  if (canParse<std::vector<GNEEdge*> >(myNet, value, false)) {
292  // parse edges and save their IDs in a set
293  std::vector<GNEEdge*> parsedEdges = parse<std::vector<GNEEdge*> >(myNet, value);
294  EdgeVector nbEdges;
295  for (auto i : parsedEdges) {
296  nbEdges.push_back(i->getNBEdge());
297  }
298  std::sort(nbEdges.begin(), nbEdges.end());
299  //
300  EdgeVector originalEdges = crossing->edges;
301  std::sort(originalEdges.begin(), originalEdges.end());
302  // return true if we're setting the same edges
303  if (toString(nbEdges) == toString(originalEdges)) {
304  return true;
305  } else {
307  }
308  } else {
309  return false;
310  }
311  case SUMO_ATTR_WIDTH:
312  return canParse<double>(value) && ((parse<double>(value) > 0) || (parse<double>(value) == -1)); // kann NICHT 0 sein, oder -1 (bedeutet default)
313  case SUMO_ATTR_PRIORITY:
314  return canParse<bool>(value);
317  return (crossing->tlID != "" && canParse<int>(value)
318  // -1 means that tlLinkIndex2 takes on the same value as tlLinkIndex when setting idnices
319  && ((parse<double>(value) >= 0) || ((parse<double>(value) == -1) && (key == SUMO_ATTR_TLLINKINDEX2)))
320  && myParentJunction->getNBNode()->getControllingTLS().size() > 0
321  && (*myParentJunction->getNBNode()->getControllingTLS().begin())->getMaxValidIndex() >= parse<int>(value));
322  case SUMO_ATTR_CUSTOMSHAPE: {
323  // empty shapes are allowed
324  return canParse<PositionVector>(value);
325  }
326  case GNE_ATTR_SELECTED:
327  return canParse<bool>(value);
328  case GNE_ATTR_GENERIC:
329  return isGenericParametersValid(value);
330  default:
331  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
332  }
333 }
334 
335 
336 std::string
339  std::string result;
340  // Generate an string using the following structure: "key1=value1|key2=value2|...
341  for (auto i : crossing->getParametersMap()) {
342  result += i.first + "=" + i.second + "|";
343  }
344  // remove the last "|"
345  if (!result.empty()) {
346  result.pop_back();
347  }
348  return result;
349 }
350 
351 
352 std::vector<std::pair<std::string, std::string> >
355  std::vector<std::pair<std::string, std::string> > result;
356  // iterate over parameters map and fill result
357  for (auto i : crossing->getParametersMap()) {
358  result.push_back(std::make_pair(i.first, i.second));
359  }
360  return result;
361 }
362 
363 
364 void
365 GNECrossing::setGenericParametersStr(const std::string& value) {
367  // clear parameters
368  crossing->clearParameter();
369  // separate value in a vector of string using | as separator
370  std::vector<std::string> parsedValues;
371  StringTokenizer stValues(value, "|", true);
372  while (stValues.hasNext()) {
373  parsedValues.push_back(stValues.next());
374  }
375  // check that parsed values (A=B)can be parsed in generic parameters
376  for (auto i : parsedValues) {
377  std::vector<std::string> parsedParameters;
378  StringTokenizer stParam(i, "=", true);
379  while (stParam.hasNext()) {
380  parsedParameters.push_back(stParam.next());
381  }
382  // Check that parsed parameters are exactly two and contains valid chracters
383  if (parsedParameters.size() == 2 && SUMOXMLDefinitions::isValidGenericParameterKey(parsedParameters.front()) && SUMOXMLDefinitions::isValidGenericParameterValue(parsedParameters.back())) {
384  crossing->setParameter(parsedParameters.front(), parsedParameters.back());
385  }
386  }
387 }
388 
389 
390 bool
393  if (std::find(crossing->edges.begin(), crossing->edges.end(), edge->getNBEdge()) != crossing->edges.end()) {
394  return true;
395  } else {
396  return false;
397  }
398 }
399 
400 
401 bool
402 GNECrossing::checkEdgeBelong(const std::vector<GNEEdge*>& edges) const {
403  for (auto i : edges) {
404  if (checkEdgeBelong(i)) {
405  return true;
406  }
407  }
408  return false;
409 }
410 
411 // ===========================================================================
412 // private
413 // ===========================================================================
414 
415 void
416 GNECrossing::setAttribute(SumoXMLAttr key, const std::string& value) {
418  switch (key) {
419  case SUMO_ATTR_ID:
420  throw InvalidArgument("Modifying attribute '" + toString(key) + "' of " + getTagStr() + " isn't allowed");
421  case SUMO_ATTR_EDGES: {
422  // obtain GNEEdges
423  std::vector<GNEEdge*> edges = parse<std::vector<GNEEdge*> >(myNet, value);
424  // remove NBEdges of crossing
425  crossing->edges.clear();
426  // set NBEdge of every GNEEdge into Crossing Edges
427  for (auto i : edges) {
428  crossing->edges.push_back(i->getNBEdge());
429  }
430  // sort new edges
431  std::sort(crossing->edges.begin(), crossing->edges.end());
432  // change myCrossingEdges by the new edges
433  myCrossingEdges = crossing->edges;
434  // update geometry of parent junction
436  break;
437  }
438  case SUMO_ATTR_WIDTH:
439  // Change width an refresh element
440  crossing->customWidth = parse<double>(value);
441  break;
442  case SUMO_ATTR_PRIORITY:
443  crossing->priority = parse<bool>(value);
444  break;
446  crossing->customTLIndex = parse<int>(value);
447  // make new value visible immediately
448  crossing->tlLinkIndex = crossing->customTLIndex;
449  break;
451  crossing->customTLIndex2 = parse<int>(value);
452  // make new value visible immediately
453  crossing->tlLinkIndex2 = crossing->customTLIndex2;
454  break;
455  case SUMO_ATTR_CUSTOMSHAPE: {
456  // set custom shape
457  crossing->customShape = parse<PositionVector>(value);
458  break;
459  }
460  case GNE_ATTR_SELECTED:
461  if (parse<bool>(value)) {
463  } else {
465  }
466  break;
467  case GNE_ATTR_GENERIC:
469  break;
470  default:
471  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
472  }
473  // Crossing are a special case and we need ot update geometry of junction instead of crossing
474  if ((key != SUMO_ATTR_ID) && (key != GNE_ATTR_GENERIC) && (key != GNE_ATTR_SELECTED)) {
476  }
477 }
478 
479 /****************************************************************************/
GNECrossing(GNEJunction *parentJunction, std::vector< NBEdge *> edges)
Constructor.
Definition: GNECrossing.cpp:42
a tl-logic
static const RGBColor crossing
color for crossings
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
SumoXMLTag
Numbers representing SUMO-XML - element names.
bool checkEdgeBelong(GNEEdge *edges) const
return true if a edge belongs to crossing&#39;s edges
double scale
information about a lane&#39;s width (temporary, used for a single view)
const std::vector< NBEdge * > & getCrossingEdges() const
get crossingEdges
Definition: GNECrossing.cpp:88
PositionVector shape
The shape of the netElement element.
Definition: GNENetElement.h:57
whether a given shape is user-defined
GNENet * myNet
the net to inform about updates
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
Position getPositionInView() const
Returns position of hierarchical element in view.
Definition: GNECrossing.cpp:75
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
static void drawTextAtEnd(const std::string &text, const PositionVector &shape, double x, double size, RGBColor color)
draw text and the end of shape
Definition: GLHelper.cpp:750
edit junction shape
Definition: GUIAppEnum.h:866
NetworkEditMode
enum for network edit modes
Stores the information about how to visualize structures.
NetElementGeometry myGeometry
netElement geometry
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void setGenericParametersStr(const std::string &value)
set generic parameters in string format
Crossing * getCrossing(const std::string &id) const
return the crossing with the given id
Definition: NBNode.cpp:3116
PositionVector reverse() const
reverse position vector
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
std::string generateChildID(SumoXMLTag childTag)
gererate a new ID for an element child
Definition: GNECrossing.cpp:53
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
bool hasNext()
returns the information whether further substrings exist
std::string getGenericParametersStr() const
return generic parameters in string format
static bool isValidGenericParameterKey(const std::string &value)
whether the given string is a valid key for a generic parameter
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to copy the cursor position if geo projection is used, also builds an entry for copying the geo-position.
generic attribute
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
mode for editing tls
link: the index of the opposite direction link of a pedestrian crossing
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
void updateGeometry()
update pre-computed geometry information
Definition: GNECrossing.cpp:60
NBEdge * getNBEdge() const
returns the internal NBEdge
Definition: GNEEdge.cpp:625
std::vector< double > shapeRotations
The rotations of the single shape parts.
Definition: GNENetElement.h:60
static bool isValidGenericParameterValue(const std::string &value)
whether the given string is a valid value for a generic parameter
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
the edges of a route
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:616
static const RGBColor crossingPriority
color for priority crossing
std::vector< NBEdge * > myCrossingEdges
Crossing Edges (It works as ID because a junction can only ONE Crossing with the same edges) ...
Definition: GNECrossing.h:151
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
A list of positions.
static bool isGenericParametersValid(const std::string &value)
check if given string can be parsed to a map/list of generic parameters
friend class GNEChange_Attribute
declare friend class
mode for creating new edges
GUIVisualizationTextSettings drawLinkTLIndex
GNEJunction * myParentJunction
the parent junction of this crossing
Definition: GNECrossing.h:148
void drawTLSLinkNo(const GUIVisualizationSettings &s) const
draw TLS Link Number
void selectAttributeCarrier(bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
std::vector< double > shapeLengths
The lengths of the single shape parts.
Definition: GNENetElement.h:63
static void drawShapeDottedContourAroundShape(const GUIVisualizationSettings &s, const int type, const PositionVector &shape, const double width)
draw a dotted contour around the given Non closed shape with certain width
Definition: GLHelper.cpp:461
void unselectAttributeCarrier(bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:2143
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:50
static bool canParse(const std::string &string)
true if a value of type T can be parsed from string
RGBColor selectedCrossingColor
crossings selection color
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:331
bool checkCrossingDuplicated(EdgeVector edges)
return true if there already exist a crossing with the same edges as the input
Definition: NBNode.cpp:2404
void updateGeometry()
update pre-computed geometry information
const GNEAttributeCarrier * getDottedAC() const
get AttributeCarrier under cursor
Definition: GNEViewNet.cpp:939
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node) ...
Definition: NBNode.h:322
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
const std::string & getTagStr() const
get tag assigned to this object in string format
static const RGBColor crossingInvalid
color for invalid crossing
element is selected
The popup menu of a globject.
std::vector< std::pair< std::string, std::string > > getGenericParameters() const
return generic parameters as vector of pairs format
crossing between edges for pedestrians
~GNECrossing()
Destructor.
Definition: GNECrossing.cpp:49
bool drawCrossingsAndWalkingareas
whether crosings and walkingareas shall be drawn
mode for connecting lanes
GUIGlID getGlID() const
Returns the numerical id of the object.
A definition of a pedestrian crossing.
Definition: NBNode.h:132
void calculateShapeRotationsAndLengths()
calculate shape rotations and lengths
NetworkEditMode networkEditMode
the current Network edit mode
link: the index of the link within the traffic light
GUIVisualizationColorSettings colorSettings
color settings
bool isValid(SumoXMLAttr key, const std::string &value)
NBNode::Crossing * getNBCrossing() const
get referente to NBode::Crossing
Definition: GNECrossing.cpp:94
bool drawForSelecting
whether drawing is performed for the purpose of selecting objects
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:399
NBNode * getNBNode() const
Return net build node.
void clearGeometry()
reset geometry
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
std::string getAttribute(SumoXMLAttr key) const
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:2067
void clearParameter()
Clears the parameter map.
a junction
GNEJunction * getParentJunction() const
get parent Junction
Definition: GNECrossing.cpp:82