Eclipse SUMO - Simulation of Urban MObility
GNEConsecutiveSelector.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 // Consecutive lane selector module
19 /****************************************************************************/
20 #include <config.h>
21 
23 #include <netedit/GNENet.h>
24 #include <netedit/GNEViewNet.h>
25 #include <netedit/GNEViewParent.h>
27 #include <utils/gui/div/GLHelper.h>
31 
32 #include "GNEConsecutiveSelector.h"
33 #include "GNEFrame.h"
34 
35 
36 // ===========================================================================
37 // FOX callback mapping
38 // ===========================================================================
39 
40 FXDEFMAP(GNEConsecutiveSelector) ConsecutiveLaneSelectorMap[] = {
45 };
46 
47 // Object implementation
48 FXIMPLEMENT(GNEConsecutiveSelector, MFXGroupBoxModule, ConsecutiveLaneSelectorMap, ARRAYNUMBER(ConsecutiveLaneSelectorMap))
49 
50 // ---------------------------------------------------------------------------
51 // GNEConsecutiveSelector - methods
52 // ---------------------------------------------------------------------------
53 
54 GNEConsecutiveSelector::GNEConsecutiveSelector(GNEFrame* frameParent, const bool allowOneLane) :
55  MFXGroupBoxModule(frameParent, TL("Consecutive lane selector")),
56  myFrameParent(frameParent),
57  myAllowOneLane(allowOneLane) {
58  // create label for route info
59  myInfoPathLabel = new FXLabel(getCollapsableFrame(), "No lanes selected", 0, GUIDesignLabelFrameThicked);
60  // create button for finish route creation
61  myFinishCreationButton = new FXButton(getCollapsableFrame(), TL("Finish path creation"), nullptr, this, MID_GNE_FINISH, GUIDesignButton);
62  myFinishCreationButton->disable();
63  // create button for abort route creation
64  myAbortCreationButton = new FXButton(getCollapsableFrame(), TL("Abort path creation"), nullptr, this, MID_GNE_ABORT, GUIDesignButton);
65  myAbortCreationButton->disable();
66  // create button for remove last inserted lane
67  myRemoveLastInsertedElement = new FXButton(getCollapsableFrame(), TL("Remove last lane"), nullptr, this, MID_GNE_REMOVELAST, GUIDesignButton);
68  myRemoveLastInsertedElement->disable();
69  // create check button
70  myShowCandidateLanes = new FXCheckButton(getCollapsableFrame(), TL("Show candidate lanes"), this, MID_GNE_SHOWCANDIDATES, GUIDesignCheckButton);
71  myShowCandidateLanes->setCheck(TRUE);
72  // create information label
73  new FXLabel(this, "-BACKSPACE: undo click\n-ESC: Abort path creation", 0, GUIDesignLabelFrameInformation);
74 }
75 
76 
78 
79 
80 void
82  // first abort creation
84  // disable buttons
85  myFinishCreationButton->disable();
86  myAbortCreationButton->disable();
87  myRemoveLastInsertedElement->disable();
88  // update lane colors
90  // recalc before show (to avoid graphic problems)
91  recalc();
92  // show modul
93  show();
94 }
95 
96 
97 void
99  // clear path
100  clearPath();
101  // hide modul
102  hide();
103 }
104 
105 
106 const std::vector<std::pair<GNELane*, double> >&
108  return myLanePath;
109 }
110 
111 
112 const std::vector<std::string>
114  std::vector<std::string> laneIDs;
115  for (const auto& lane : myLanePath) {
116  if (laneIDs.empty() || (laneIDs.back() != lane.first->getID())) {
117  laneIDs.push_back(lane.first->getID());
118  }
119  }
120  return laneIDs;
121 }
122 
123 
124 bool
126  // first check if lane is valid
127  if (lane == nullptr) {
128  return false;
129  }
130  // check candidate lane
131  if ((myShowCandidateLanes->getCheck() == TRUE) && !lane->isPossibleCandidate()) {
132  if (lane->isSpecialCandidate() || lane->isConflictedCandidate()) {
133  // Write warning
134  WRITE_WARNING(TL("Invalid lane"));
135  // abort add lane
136  return false;
137  }
138  }
139  // get mouse position
141  // calculate lane offset
142  const double posOverLane = lane->getLaneShape().nearest_offset_to_point2D(mousePos);
143  // All checks ok, then add it in selected elements
144  if (myLanePath.empty()) {
145  myLanePath.push_back(std::make_pair(lane, posOverLane));
146  } else if ((myLanePath.size() == 1) && (myLanePath.front().first == lane)) {
147  if (myAllowOneLane) {
148  myLanePath.push_back(std::make_pair(lane, posOverLane));
149  } else {
150  // Write warning
151  WRITE_WARNING(TL("Lane path needs at least two lanes"));
152  // abort add lane
153  return false;
154  }
155  } else if (myLanePath.back().first == lane) {
156  // only change last position
157  myLanePath.back().second = posOverLane;
158  } else {
159  myLanePath.push_back(std::make_pair(lane, posOverLane));
160  // special case if we clicked over a new lane after a previous double lane
161  if ((myLanePath.size() == 3) && (myLanePath.at(0).first == myLanePath.at(1).first)) {
162  // remove second lane
163  myLanePath.erase(myLanePath.begin() + 1);
164  }
165  }
166  // enable abort route button
167  myAbortCreationButton->enable();
168  // enable finish button
169  myFinishCreationButton->enable();
170  // disable undo/redo
172  // enable or disable remove last lane button
173  if (myLanePath.size() > 1) {
174  myRemoveLastInsertedElement->enable();
175  } else {
176  myRemoveLastInsertedElement->disable();
177  }
178  // update info route label
180  // update lane colors
182  return true;
183 }
184 
185 
186 bool
188  return (myShowCandidateLanes->getCheck() == TRUE);
189 }
190 
191 
192 void
194  // reset all flags
195  for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
196  for (const auto& lane : edge.second->getLanes()) {
197  lane->resetCandidateFlags();
198  }
199  }
200  // set reachability
201  if (myLanePath.size() > 0 && (myShowCandidateLanes->getCheck() == TRUE)) {
202  // first mark all lanes as invalid
203  for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
204  for (const auto& lane : edge.second->getLanes()) {
205  lane->setConflictedCandidate(true);
206  }
207  }
208  // now mark lane paths as valid
209  for (const auto& lane : myLanePath) {
210  // disable conflicted candidate
211  lane.first->setConflictedCandidate(false);
212  if (lane == myLanePath.back()) {
213  lane.first->setSourceCandidate(true);
214  } else {
215  lane.first->setTargetCandidate(true);
216  }
217  }
218  // get parent edge
219  const GNEEdge* edge = myLanePath.back().first->getParentEdge();
220  // iterate over connections
221  for (const auto& connection : edge->getGNEConnections()) {
222  // mark possible candidates
223  if (connection->getLaneFrom() == myLanePath.back().first) {
224  connection->getLaneTo()->setConflictedCandidate(false);
225  connection->getLaneTo()->setPossibleCandidate(true);
226  }
227  }
228  }
229  // update view net
231 }
232 
233 
234 void
236  // Only draw if there is at least one lane
237  if (myLanePath.size() > 0) {
238  // get widths
239  const double lineWidth = 0.35;
240  const double lineWidthin = 0.25;
241  // declare vector with shapes
242  std::vector<PositionVector> shapes;
243  // iterate over lanes (only if there is more than one)
244  if ((myLanePath.size() == 2) && (myLanePath.front().first == myLanePath.back().first)) {
245  // only add first lane shape
246  shapes.push_back(myLanePath.front().first->getLaneShape());
247  // adjust shape
248  shapes.front() = shapes.front().getSubpart(myLanePath.front().second, myLanePath.back().second);
249  } else if (myLanePath.size() > 1) {
250  // get shapes
251  for (int i = 0; i < (int)myLanePath.size(); i++) {
252  // get lane
253  const GNELane* lane = myLanePath.at(i).first;
254  // add lane shape
255  shapes.push_back(lane->getLaneShape());
256  // draw connection between lanes
257  if ((i + 1) < (int)myLanePath.size()) {
258  // get next lane
259  const GNELane* nextLane = myLanePath.at(i + 1).first;
260  if (lane->getLane2laneConnections().exist(nextLane)) {
261  shapes.push_back(lane->getLane2laneConnections().getLane2laneGeometry(nextLane).getShape());
262  } else {
263  shapes.push_back({lane->getLaneShape().back(), nextLane->getLaneShape().front()});
264  }
265  }
266  }
267  // adjust first and last shape
268  shapes.front() = shapes.front().splitAt(myLanePath.front().second).second;
269  shapes.back() = shapes.back().splitAt(myLanePath.back().second).first;
270  }
271  // Add a draw matrix
273  // move to temporal shape
274  glTranslated(0, 0, GLO_TEMPORALSHAPE);
275  // iterate over shapes
276  for (const auto& shape : shapes) {
277  // set extern
279  // draw extern shape
280  GLHelper::drawBoxLines(shape, lineWidth);
281  // push matrix
283  // move to front
284  glTranslated(0, 0, 0.1);
285  // set orange color
287  // draw intern shape
288  GLHelper::drawBoxLines(shape, lineWidthin);
289  // Pop matrix
291  }
292  // draw points
293  const RGBColor pointColor = RGBColor::RED;
294  // positions
295  const Position firstPosition = myLanePath.front().first->getLaneShape().positionAtOffset2D(myLanePath.front().second);
296  const Position secondPosition = myLanePath.back().first->getLaneShape().positionAtOffset2D(myLanePath.back().second);
297  // draw geometry points
298  GUIGeometry::drawGeometryPoints(s, myFrameParent->getViewNet()->getPositionInformation(), {firstPosition, secondPosition},
299  pointColor, RGBColor::WHITE, s.neteditSizeSettings.polylineWidth, 1, false, true);
300  // Pop last matrix
302  }
303 }
304 
305 
306 void
308  // first check that there is elements
309  if (myLanePath.size() > 0) {
310  // unblock undo/redo
312  // clear lanes
313  clearPath();
314  // disable buttons
315  myFinishCreationButton->disable();
316  myAbortCreationButton->disable();
317  myRemoveLastInsertedElement->disable();
318  // update info route label
320  // update reachability
322  // update view (to see the new route)
324  }
325 }
326 
327 
328 void
330  if (myLanePath.size() > 1) {
331  // remove special color of last selected lane
332  myLanePath.back().first->resetCandidateFlags();
333  // remove last lane
334  myLanePath.pop_back();
335  // change last lane flag
336  if ((myLanePath.size() > 0) && myLanePath.back().first->isSourceCandidate()) {
337  myLanePath.back().first->setSourceCandidate(false);
338  myLanePath.back().first->setTargetCandidate(true);
339  }
340  // enable or disable remove last lane button
341  if (myLanePath.size() > 1) {
342  myRemoveLastInsertedElement->enable();
343  } else {
344  myRemoveLastInsertedElement->disable();
345  }
346  // update info route label
348  // update reachability
350  // update view
352  }
353 }
354 
355 
356 long
357 GNEConsecutiveSelector::onCmdCreatePath(FXObject*, FXSelector, void*) {
358  myFrameParent->createPath(false);
359  return 1;
360 }
361 
362 
363 long
364 GNEConsecutiveSelector::onCmdAbortPathCreation(FXObject*, FXSelector, void*) {
365  // just call abort path creation
367  return 1;
368 }
369 
370 
371 long
372 GNEConsecutiveSelector::onCmdRemoveLastElement(FXObject*, FXSelector, void*) {
373  // just call remove last element
375  return 1;
376 }
377 
378 
379 long
380 GNEConsecutiveSelector::onCmdShowCandidateLanes(FXObject*, FXSelector, void*) {
381  // recalc frame
382  recalc();
383  // update lane colors (view will be updated within function)
385  return 1;
386 }
387 
388 
390  myFrameParent(nullptr),
391  myAllowOneLane(false) {
392 }
393 
394 
395 void
397  if (myLanePath.size() > 0) {
398  // declare variables for route info
399  double length = 0;
400  for (const auto& lane : myLanePath) {
401  length += lane.first->getParentEdge()->getNBEdge()->getLength();
402  }
403  // declare ostringstream for label and fill it
404  std::ostringstream information;
405  information
406  << TL("- Selected lanes: ") << toString(myLanePath.size()) << "\n"
407  << TL("- Length: ") << toString(length);
408  // set new label
409  myInfoPathLabel->setText(information.str().c_str());
410  } else {
411  myInfoPathLabel->setText(TL("No lanes selected"));
412  }
413 }
414 
415 
416 void
418  // reset all flags
419  for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
420  for (const auto& lane : edge.second->getLanes()) {
421  lane->resetCandidateFlags();
422  }
423  }
424  // clear path
425  myLanePath.clear();
426  // update info route label
428 }
429 
430 /****************************************************************************/
FXDEFMAP(GNEConsecutiveSelector) ConsecutiveLaneSelectorMap[]
@ MID_GNE_SHOWCANDIDATES
enable or disable show path candidates
Definition: GUIAppEnum.h:928
@ MID_GNE_REMOVELAST
remove last inserted element in path
Definition: GUIAppEnum.h:926
@ MID_GNE_FINISH
finish lane path creation
Definition: GUIAppEnum.h:924
@ MID_GNE_ABORT
abort lane path creation
Definition: GUIAppEnum.h:922
#define GUIDesignButton
Definition: GUIDesigns.h:77
#define GUIDesignLabelFrameThicked
label extended over frame without thick and with text justify to left, used to show information in fr...
Definition: GUIDesigns.h:274
#define GUIDesignCheckButton
checkButton placed in left position
Definition: GUIDesigns.h:169
#define GUIDesignLabelFrameInformation
label extended over frame without thick and with text justify to left, used to show information in fr...
Definition: GUIDesigns.h:271
@ GLO_TEMPORALSHAPE
temporal shape (used in NETEDIT)
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define TL(string)
Definition: MsgHandler.h:282
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:583
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:130
static void drawBoxLines(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double width, int cornerDetail=0, double offset=0)
Draws thick lines.
Definition: GLHelper.cpp:329
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:117
void disableUndoRedo(const std::string &reason)
disable undo-redo giving a string with the reason
void enableUndoRedo()
disable undo-redo
bool isSpecialCandidate() const
check if this element is a special candidate
bool isPossibleCandidate() const
check if this element is a possible candidate
bool isConflictedCandidate() const
check if this element is a conflicted candidate
std::vector< std::pair< GNELane *, double > > myLanePath
vector with lanes and clicked positions
bool addLane(GNELane *lane)
add lane
void abortPathCreation()
abort path creation
FXLabel * myInfoPathLabel
label with path info
GNEFrame * myFrameParent
pointer to frame parent
const bool myAllowOneLane
allow one lane
void updateLaneColors()
update lane colors
void showConsecutiveLaneSelectorModule()
show GNEConsecutiveSelector
long onCmdCreatePath(FXObject *, FXSelector, void *)
void clearPath()
clear lanes (and restore colors)
FXButton * myRemoveLastInsertedElement
button for removing last inserted element
FXCheckButton * myShowCandidateLanes
CheckBox for show candidate lanes.
long onCmdRemoveLastElement(FXObject *, FXSelector, void *)
Called when the user click over button "Remove las inserted lane".
void updateInfoRouteLabel()
update InfoRouteLabel
const std::vector< std::pair< GNELane *, double > > & getLanePath() const
get vector with lanes and clicked positions
void removeLastElement()
remove path element
bool drawCandidateLanesWithSpecialColor() const
draw candidate lanes with special color (Only for candidates, special and conflicted)
void hideConsecutiveLaneSelectorModule()
show GNEConsecutiveSelector
void drawTemporalConsecutiveLanePath(const GUIVisualizationSettings &s) const
draw temporal consecutive lane path
long onCmdShowCandidateLanes(FXObject *, FXSelector, void *)
Called when the user click over check button "show candidate lanes".
const std::vector< std::string > getLaneIDPath() const
get lane IDs
FXButton * myFinishCreationButton
button for finish route creation
long onCmdAbortPathCreation(FXObject *, FXSelector, void *)
Called when the user click over button "Abort route creation".
FXButton * myAbortCreationButton
button for abort route creation
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:53
const std::vector< GNEConnection * > & getGNEConnections() const
returns a reference to the GNEConnection vector
Definition: GNEEdge.cpp:845
GNEViewNet * getViewNet() const
get view net
Definition: GNEFrame.cpp:150
virtual bool createPath(const bool useLastRoute)
create path between two elements
Definition: GNEFrame.cpp:303
bool exist(const GNELane *toLane) const
check if exist a lane2lane geometry for the given toLane
const GUIGeometry & getLane2laneGeometry(const GNELane *toLane) const
get lane2lane geometry
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:142
const GNELane2laneConnection & getLane2laneConnections() const
get Lane2laneConnection struct
Definition: GNELane.cpp:917
const std::map< std::string, GNEEdge * > & getEdges() const
map with the ID and pointer to edges of net
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:132
GNENet * getNet() const
get the net object
GNEViewParent * getViewParent() const
get the net object
void updateViewNet() const
Mark the entire GNEViewNet to be repainted later.
Definition: GNEViewNet.cpp:414
GNEApplicationWindow * getGNEAppWindows() const
get GNE Application Windows
static void drawGeometryPoints(const GUIVisualizationSettings &s, const Position &mousePos, const PositionVector &shape, const RGBColor &geometryPointColor, const RGBColor &textColor, const double radius, const double exaggeration, const bool editingElevation, const bool drawExtremeSymbols)
draw geometry points
const PositionVector & getShape() const
The shape of the additional element.
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.
Stores the information about how to visualize structures.
GUIVisualizationNeteditSizeSettings neteditSizeSettings
netedit size settings
MFXGroupBoxModule (based on FXGroupBox)
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
static const RGBColor WHITE
Definition: RGBColor.h:192
static const RGBColor GREY
Definition: RGBColor.h:194
static const RGBColor ORANGE
Definition: RGBColor.h:191
static const RGBColor RED
named colors
Definition: RGBColor.h:185
static const double polylineWidth
poly line width