Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GNEConsecutiveSelector.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// Consecutive lane selector module
19/****************************************************************************/
20
22#include <netedit/GNENet.h>
23#include <netedit/GNEViewNet.h>
30
32#include "GNEFrame.h"
33
34// ===========================================================================
35// FOX callback mapping
36// ===========================================================================
37
44
45// Object implementation
46FXIMPLEMENT(GNEConsecutiveSelector, MFXGroupBoxModule, ConsecutiveLaneSelectorMap, ARRAYNUMBER(ConsecutiveLaneSelectorMap))
47
48// ---------------------------------------------------------------------------
49// GNEConsecutiveSelector - methods
50// ---------------------------------------------------------------------------
51
52GNEConsecutiveSelector::GNEConsecutiveSelector(GNEFrame* frameParent, const bool allowOneLane) :
53 MFXGroupBoxModule(frameParent, TL("Consecutive lane selector")),
54 myFrameParent(frameParent),
55 myAllowOneLane(allowOneLane) {
56 // create label for route info
57 myInfoPathLabel = new FXLabel(getCollapsableFrame(), TL("No lanes selected"), 0, GUIDesignLabelThick(JUSTIFY_LEFT));
58 // create button for finish route creation
59 myFinishCreationButton = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Finish path creation"), "", "", nullptr, this, MID_GNE_FINISH, GUIDesignButton);
60 myFinishCreationButton->disable();
61 // create button for abort route creation
62 myAbortCreationButton = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Abort path creation"), "", "", nullptr, this, MID_GNE_ABORT, GUIDesignButton);
63 myAbortCreationButton->disable();
64 // create button for remove last inserted lane
65 myRemoveLastInsertedElement = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Remove last lane"), "", "", nullptr, this, MID_GNE_REMOVELAST, GUIDesignButton);
66 myRemoveLastInsertedElement->disable();
67 // create check button
68 myShowCandidateLanes = new FXCheckButton(getCollapsableFrame(), TL("Show candidate lanes"), this, MID_GNE_SHOWCANDIDATES, GUIDesignCheckButton);
69 myShowCandidateLanes->setCheck(TRUE);
70 // create information label
71 new FXLabel(this, (TL("-BACKSPACE: undo click") + std::string("\n") + TL("-ESC: Abort path creation")).c_str(), 0, GUIDesignLabelFrameInformation);
72}
73
74
76
77
78void
80 // first abort creation
82 // disable buttons
83 myFinishCreationButton->disable();
84 myAbortCreationButton->disable();
86 // update lane colors
88 // recalc before show (to avoid graphic problems)
89 recalc();
90 // show modul
91 show();
92}
93
94
95void
97 // clear path
98 clearPath();
99 // hide modul
100 hide();
101}
102
103
104const std::vector<std::pair<GNELane*, double> >&
108
109
110const std::vector<std::string>
112 std::vector<std::string> laneIDs;
113 for (const auto& lane : myLanePath) {
114 if (laneIDs.empty() || (laneIDs.back() != lane.first->getID())) {
115 laneIDs.push_back(lane.first->getID());
116 }
117 }
118 return laneIDs;
119}
120
121
122bool
124 // first check if lane is valid
125 if (lane == nullptr) {
126 return false;
127 }
128 // check candidate lane
129 if ((myShowCandidateLanes->getCheck() == TRUE) && !lane->isPossibleCandidate()) {
130 if (lane->isSpecialCandidate() || lane->isConflictedCandidate()) {
131 // Write warning
132 WRITE_WARNING(TL("Invalid lane"));
133 // abort add lane
134 return false;
135 }
136 }
137 // get mouse position
139 // calculate lane offset
140 const double posOverLane = lane->getLaneShape().nearest_offset_to_point2D(mousePos);
141 // All checks ok, then add it in selected elements
142 if (myLanePath.empty()) {
143 myLanePath.push_back(std::make_pair(lane, posOverLane));
144 } else if ((myLanePath.size() == 1) && (myLanePath.front().first == lane)) {
145 if (myAllowOneLane) {
146 myLanePath.push_back(std::make_pair(lane, posOverLane));
147 } else {
148 // Write warning
149 WRITE_WARNING(TL("Lane path needs at least two lanes"));
150 // abort add lane
151 return false;
152 }
153 } else if (myLanePath.back().first == lane) {
154 // only change last position
155 myLanePath.back().second = posOverLane;
156 } else {
157 myLanePath.push_back(std::make_pair(lane, posOverLane));
158 // special case if we clicked over a new lane after a previous double lane
159 if ((myLanePath.size() == 3) && (myLanePath.at(0).first == myLanePath.at(1).first)) {
160 // remove second lane
161 myLanePath.erase(myLanePath.begin() + 1);
162 }
163 }
164 // enable abort route button
165 myAbortCreationButton->enable();
166 // enable finish button
167 myFinishCreationButton->enable();
168 // disable undo/redo temporally
170 // enable or disable remove last lane button
171 if (myLanePath.size() > 1) {
173 } else {
175 }
176 // update info route label
178 // update lane colors
180 return true;
181}
182
183
184bool
188
189
190void
192 // reset all flags
193 for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
194 for (const auto& lane : edge.second->getChildLanes()) {
195 lane->resetCandidateFlags();
196 }
197 }
198 // set reachability
199 if (myLanePath.size() > 0 && (myShowCandidateLanes->getCheck() == TRUE)) {
200 // first mark all lanes as invalid
201 for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
202 for (const auto& lane : edge.second->getChildLanes()) {
203 lane->setConflictedCandidate(true);
204 }
205 }
206 // now mark lane paths as valid
207 for (const auto& lane : myLanePath) {
208 // disable conflicted candidate
209 lane.first->setConflictedCandidate(false);
210 if (lane == myLanePath.back()) {
211 lane.first->setSourceCandidate(true);
212 } else {
213 lane.first->setTargetCandidate(true);
214 }
215 }
216 // get parent edge
217 const GNEEdge* edge = myLanePath.back().first->getParentEdge();
218 // iterate over connections
219 for (const auto& connection : edge->getGNEConnections()) {
220 // mark possible candidates
221 if (connection->getLaneFrom() == myLanePath.back().first) {
222 connection->getLaneTo()->setConflictedCandidate(false);
223 connection->getLaneTo()->setPossibleCandidate(true);
224 }
225 }
226 }
227 // update view net
229}
230
231
232void
234 // Only draw if there is at least one lane
235 if (myLanePath.size() > 0) {
236 // get widths
237 const double lineWidth = 0.35;
238 const double lineWidthin = 0.25;
239 // declare vector with shapes
240 std::vector<PositionVector> shapes;
241 // iterate over lanes (only if there is more than one)
242 if ((myLanePath.size() == 2) && (myLanePath.front().first == myLanePath.back().first)) {
243 // only add first lane shape
244 shapes.push_back(myLanePath.front().first->getLaneShape());
245 // adjust shape
246 shapes.front() = shapes.front().getSubpart(myLanePath.front().second, myLanePath.back().second);
247 } else if (myLanePath.size() > 1) {
248 // get shapes
249 for (int i = 0; i < (int)myLanePath.size(); i++) {
250 // get lane
251 const GNELane* lane = myLanePath.at(i).first;
252 // add lane shape
253 shapes.push_back(lane->getLaneShape());
254 // draw connection between lanes
255 if ((i + 1) < (int)myLanePath.size()) {
256 // get next lane
257 const GNELane* nextLane = myLanePath.at(i + 1).first;
258 if (lane->getLane2laneConnections().exist(nextLane)) {
259 shapes.push_back(lane->getLane2laneConnections().getLane2laneGeometry(nextLane).getShape());
260 } else {
261 shapes.push_back({lane->getLaneShape().back(), nextLane->getLaneShape().front()});
262 }
263 }
264 }
265 // adjust first and last shape
266 shapes.front() = shapes.front().splitAt(myLanePath.front().second).second;
267 shapes.back() = shapes.back().splitAt(myLanePath.back().second).first;
268 }
269 // Add a draw matrix
271 // move to temporal shape
272 glTranslated(0, 0, GLO_TEMPORALSHAPE);
273 // iterate over shapes
274 for (const auto& shape : shapes) {
275 // set extern
277 // draw extern shape
278 GLHelper::drawBoxLines(shape, lineWidth);
279 // push matrix
281 // move to front
282 glTranslated(0, 0, 0.1);
283 // set orange color
285 // draw intern shape
286 GLHelper::drawBoxLines(shape, lineWidthin);
287 // Pop matrix
289 }
290 // draw points
291 if (shapes.size() > 0) {
292 // draw geometry points
294 {shapes.front().front(), shapes.back().back()}, RGBColor::RED,
295 myFrameParent->getViewNet()->getVisualisationSettings().neteditSizeSettings.additionalGeometryPointRadius, 1, false);
296 }
297 // Pop last matrix
299 }
300}
301
302
303void
305 // first check that there is elements
306 if (myLanePath.size() > 0) {
307 // unblock undo/redo
309 // clear lanes
310 clearPath();
311 // disable buttons
312 myFinishCreationButton->disable();
313 myAbortCreationButton->disable();
315 // update info route label
317 // update reachability
319 // update view (to see the new route)
321 }
322}
323
324
325void
327 if (myLanePath.size() > 1) {
328 // remove special color of last selected lane
329 myLanePath.back().first->resetCandidateFlags();
330 // remove last lane
331 myLanePath.pop_back();
332 // change last lane flag
333 if ((myLanePath.size() > 0) && myLanePath.back().first->isSourceCandidate()) {
334 myLanePath.back().first->setSourceCandidate(false);
335 myLanePath.back().first->setTargetCandidate(true);
336 }
337 // enable or disable remove last lane button
338 if (myLanePath.size() > 1) {
340 } else {
342 }
343 // update info route label
345 // update reachability
347 // update view
349 }
350}
351
352
353long
354GNEConsecutiveSelector::onCmdCreatePath(FXObject*, FXSelector, void*) {
356 return 1;
357}
358
359
360long
362 // just call abort path creation
364 return 1;
365}
366
367
368long
370 // just call remove last element
372 return 1;
373}
374
375
376long
378 // recalc frame
379 recalc();
380 // update lane colors (view will be updated within function)
382 return 1;
383}
384
385
387 myFrameParent(nullptr),
388 myAllowOneLane(false) {
389}
390
391
392void
394 if (myLanePath.size() > 0) {
395 // declare variables for route info
396 double length = 0;
397 for (const auto& lane : myLanePath) {
398 length += lane.first->getParentEdge()->getNBEdge()->getLength();
399 }
400 // declare ostringstream for label and fill it
401 std::ostringstream information;
402 information
403 << TL("- Selected lanes: ") << toString(myLanePath.size()) << "\n"
404 << TL("- Length: ") << toString(length);
405 // set new label
406 myInfoPathLabel->setText(information.str().c_str());
407 } else {
408 myInfoPathLabel->setText(TL("No lanes selected"));
409 }
410}
411
412
413void
415 // reset all flags
416 for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
417 for (const auto& lane : edge.second->getChildLanes()) {
418 lane->resetCandidateFlags();
419 }
420 }
421 // clear path
422 myLanePath.clear();
423 // update info route label
425}
426
427/****************************************************************************/
FXDEFMAP(GNEConsecutiveSelector) ConsecutiveLaneSelectorMap[]
@ MID_GNE_SHOWCANDIDATES
enable or disable show path candidates
@ MID_GNE_REMOVELAST
remove last inserted element in path
@ MID_GNE_FINISH
finish lane path creation
@ MID_GNE_ABORT
abort lane path creation
#define GUIDesignButton
Definition GUIDesigns.h:100
#define GUIDesignLabelThick(justify)
label extended over frame with thick and with text justify to left
Definition GUIDesigns.h:251
#define GUIDesignCheckButton
checkButton placed in left position
Definition GUIDesigns.h:194
#define GUIDesignLabelFrameInformation
label extended over frame without thick and with text justify to left, used to show information in fr...
Definition GUIDesigns.h:281
@ GLO_TEMPORALSHAPE
temporal shape (used in netedit)
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:305
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:649
static void popMatrix()
pop matrix
Definition GLHelper.cpp:131
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:348
static void pushMatrix()
push matrix
Definition GLHelper.cpp:118
void enableUndoRedoTemporally()
enable undo-redo temporally (for example, after creating an edge)
void disableUndoRedoTemporally(const std::string &reason)
disable undo-redo temporally giving a string with the reason (for example, if we're creating an edge)
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
void setConflictedCandidate(const bool value)
set element as conflicted candidate
std::vector< std::pair< GNELane *, double > > myLanePath
vector with lanes and clicked positions
void drawTemporalConsecutiveLanePath() const
draw temporal consecutive lane path
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
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:1163
GNEViewNet * getViewNet() const
get view net
Definition GNEFrame.cpp:152
virtual bool createPath(const bool useLastRoute)
create path between two elements
Definition GNEFrame.cpp:239
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:221
const GNELane2laneConnection & getLane2laneConnections() const
get Lane2laneConnection struct
Definition GNELane.cpp:693
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:144
GNENet * getNet() const
get the net object
GNEViewParent * getViewParent() const
get the net object
void updateViewNet(const bool ignoreViewUpdater=true) const
Mark the entire GNEViewNet to be repainted later.
GNEApplicationWindow * getGNEAppWindows() const
get GNE Application Windows
static FXButton * buildFXButton(FXComposite *p, const std::string &text, const std::string &tip, const std::string &help, FXIcon *ic, FXObject *tgt, FXSelector sel, FXuint opts=BUTTON_NORMAL, FXint x=0, FXint y=0, FXint w=0, FXint h=0, FXint pl=DEFAULT_PAD, FXint pr=DEFAULT_PAD, FXint pt=DEFAULT_PAD, FXint pb=DEFAULT_PAD)
build button
static void drawGeometryPoints(const GUIVisualizationSettings::Detail d, const PositionVector &shape, const RGBColor &color, const double radius, const double exaggeration, const bool editingElevation)
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.
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 GREY
Definition RGBColor.h:197
static const RGBColor ORANGE
Definition RGBColor.h:194
static const RGBColor RED
named colors
Definition RGBColor.h:188