Line data Source code
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 : /****************************************************************************/
14 : /// @file GUILaneSpeedTrigger.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Mon, 26.04.2004
19 : ///
20 : // Changes the speed allowed on a set of lanes (gui version)
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <string>
25 : #include <utils/common/MsgHandler.h>
26 : #include <utils/geom/PositionVector.h>
27 : #include <utils/geom/Boundary.h>
28 : #include <utils/gui/div/GLHelper.h>
29 : #include <utils/common/ToString.h>
30 : #include <utils/common/Command.h>
31 : #include <microsim/MSNet.h>
32 : #include <microsim/MSLane.h>
33 : #include <microsim/MSEdge.h>
34 : #include <guisim/GUINet.h>
35 : #include <guisim/GUIEdge.h>
36 : #include "GUILaneSpeedTrigger.h"
37 : #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
38 : #include <utils/gui/windows/GUIAppEnum.h>
39 : #include <gui/GUIGlobals.h>
40 : #include <utils/gui/div/GUIParameterTableWindow.h>
41 : #include <gui/GUIApplicationWindow.h>
42 : #include <microsim/logging/FunctionBinding.h>
43 : #include <utils/gui/div/GUIGlobalSelection.h>
44 : #include <utils/gui/images/GUIIconSubSys.h>
45 : #include <guisim/GUILaneSpeedTrigger.h>
46 : #include <utils/gui/globjects/GLIncludes.h>
47 : #include <utils/gui/div/GUIDesigns.h>
48 :
49 :
50 : // ===========================================================================
51 : // FOX callback mapping
52 : // ===========================================================================
53 : /* -------------------------------------------------------------------------
54 : * GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu - mapping
55 : * ----------------------------------------------------------------------- */
56 : FXDEFMAP(GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu)
57 : GUILaneSpeedTriggerPopupMenuMap[] = {
58 : FXMAPFUNC(SEL_COMMAND, MID_MANIP, GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu::onCmdOpenManip),
59 :
60 : };
61 :
62 : // Object implementation
63 0 : FXIMPLEMENT(GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu, GUIGLObjectPopupMenu, GUILaneSpeedTriggerPopupMenuMap, ARRAYNUMBER(GUILaneSpeedTriggerPopupMenuMap))
64 :
65 :
66 : /* -------------------------------------------------------------------------
67 : * GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger - mapping
68 : * ----------------------------------------------------------------------- */
69 : FXDEFMAP(GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger) GUIManip_LaneSpeedTriggerMap[] = {
70 : FXMAPFUNC(SEL_COMMAND, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::MID_USER_DEF, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdUserDef),
71 : FXMAPFUNC(SEL_UPDATE, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::MID_USER_DEF, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onUpdUserDef),
72 : FXMAPFUNC(SEL_COMMAND, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::MID_PRE_DEF, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdPreDef),
73 : FXMAPFUNC(SEL_UPDATE, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::MID_PRE_DEF, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onUpdPreDef),
74 : FXMAPFUNC(SEL_COMMAND, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::MID_OPTION, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdChangeOption),
75 : FXMAPFUNC(SEL_COMMAND, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::MID_CLOSE, GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdClose),
76 : };
77 :
78 0 : FXIMPLEMENT(GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger, GUIManipulator, GUIManip_LaneSpeedTriggerMap, ARRAYNUMBER(GUIManip_LaneSpeedTriggerMap))
79 :
80 :
81 : // ===========================================================================
82 : // method definitions
83 : // ===========================================================================
84 : /* -------------------------------------------------------------------------
85 : * GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger - methods
86 : * ----------------------------------------------------------------------- */
87 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::GUIManip_LaneSpeedTrigger(
88 : GUIMainWindow& app,
89 : const std::string& name, GUILaneSpeedTrigger& o,
90 0 : int /*xpos*/, int /*ypos*/)
91 : : GUIManipulator(app, name, 0, 0),
92 0 : myParent(&app), myChosenValue(0), myChosenTarget(myChosenValue, nullptr, MID_OPTION),
93 0 : mySpeed(o.getDefaultSpeed()), mySpeedTarget(mySpeed),
94 0 : myObject(&o) {
95 0 : myChosenTarget.setTarget(this);
96 : FXVerticalFrame* f1 =
97 0 : new FXVerticalFrame(this, LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0);
98 :
99 : FXGroupBox* gp = new FXGroupBox(f1, "Change Speed",
100 : GROUPBOX_TITLE_LEFT | FRAME_RIDGE,
101 0 : 0, 0, 0, 0, 4, 4, 1, 1, 2, 0);
102 : {
103 : // default
104 : FXHorizontalFrame* gf1 =
105 0 : new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
106 : new FXRadioButton(gf1, "Default", &myChosenTarget, FXDataTarget::ID_OPTION + 0,
107 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP,
108 0 : 0, 0, 0, 0, 2, 2, 0, 0);
109 : }
110 : {
111 : // loaded
112 : FXHorizontalFrame* gf0 =
113 0 : new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
114 : new FXRadioButton(gf0, "Loaded", &myChosenTarget, FXDataTarget::ID_OPTION + 1,
115 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP,
116 0 : 0, 0, 0, 0, 2, 2, 0, 0);
117 : }
118 : {
119 : // predefined
120 : FXHorizontalFrame* gf2 =
121 0 : new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
122 : new FXRadioButton(gf2, "Predefined: ", &myChosenTarget, FXDataTarget::ID_OPTION + 2,
123 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP | LAYOUT_CENTER_Y,
124 0 : 0, 0, 0, 0, 2, 2, 0, 0);
125 0 : myPredefinedValues = new MFXComboBoxIcon(gf2, nullptr, false, GUIDesignComboBoxVisibleItems, this, MID_PRE_DEF,
126 0 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP | LAYOUT_CENTER_Y | COMBOBOX_STATIC);
127 0 : myPredefinedValues->appendIconItem("20 km/h");
128 0 : myPredefinedValues->appendIconItem("40 km/h");
129 0 : myPredefinedValues->appendIconItem("60 km/h");
130 0 : myPredefinedValues->appendIconItem("80 km/h");
131 0 : myPredefinedValues->appendIconItem("100 km/h");
132 0 : myPredefinedValues->appendIconItem("120 km/h");
133 0 : myPredefinedValues->appendIconItem("140 km/h");
134 0 : myPredefinedValues->appendIconItem("160 km/h");
135 0 : myPredefinedValues->appendIconItem("180 km/h");
136 0 : myPredefinedValues->appendIconItem("200 km/h");
137 : }
138 : {
139 : // free
140 : FXHorizontalFrame* gf12 =
141 0 : new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
142 : new FXRadioButton(gf12, "Free Entry: ", &myChosenTarget, FXDataTarget::ID_OPTION + 3,
143 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP | LAYOUT_CENTER_Y,
144 0 : 0, 0, 0, 0, 2, 2, 0, 0);
145 0 : myUserDefinedSpeed =
146 : new FXRealSpinner(gf12, 10, this, MID_USER_DEF,
147 0 : LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
148 : //myUserDefinedSpeed->setFormatString("%.0f km/h");
149 : //myUserDefinedSpeed->setIncrements(1, 10, 10);
150 0 : myUserDefinedSpeed->setIncrement(10);
151 0 : myUserDefinedSpeed->setRange(0, 300);
152 0 : myUserDefinedSpeed->setValue(myObject->getDefaultSpeed() * 3.6);
153 : }
154 0 : GUIDesigns::buildFXButton(f1, "Close", "", "", nullptr, this, MID_CLOSE,
155 : BUTTON_INITIAL | BUTTON_DEFAULT | FRAME_RAISED | FRAME_THICK | LAYOUT_TOP | LAYOUT_LEFT | LAYOUT_CENTER_X, 0, 0, 0, 0, 30, 30, 4, 4);
156 0 : myObject->setOverriding(true);
157 0 : }
158 :
159 :
160 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::~GUIManip_LaneSpeedTrigger() {}
161 :
162 :
163 : long
164 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdClose(FXObject*, FXSelector, void*) {
165 0 : destroy();
166 0 : return 1;
167 : }
168 :
169 :
170 : long
171 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdUserDef(FXObject*, FXSelector, void*) {
172 0 : mySpeed = myUserDefinedSpeed->getValue() / 3.6;
173 0 : myObject->setOverridingValue(mySpeed);
174 0 : myParent->updateChildren();
175 0 : return 1;
176 : }
177 :
178 :
179 : long
180 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onUpdUserDef(FXObject* sender, FXSelector, void* ptr) {
181 0 : sender->handle(this,
182 0 : myChosenValue != 3 ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
183 : ptr);
184 0 : myParent->updateChildren();
185 0 : return 1;
186 : }
187 :
188 :
189 : long
190 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdPreDef(FXObject*, FXSelector, void*) {
191 0 : mySpeed = ((double)myPredefinedValues->getCurrentItem() * 20. + 20.) / 3.6;
192 0 : myObject->setOverridingValue(mySpeed);
193 0 : myParent->updateChildren();
194 0 : return 1;
195 : }
196 :
197 :
198 : long
199 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onUpdPreDef(FXObject* sender, FXSelector, void* ptr) {
200 0 : sender->handle(this,
201 0 : myChosenValue != 2 ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
202 : ptr);
203 0 : myParent->updateChildren();
204 0 : return 1;
205 : }
206 :
207 :
208 : long
209 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdChangeOption(FXObject*, FXSelector, void*) {
210 0 : myObject->setOverriding(true);
211 0 : switch (myChosenValue) {
212 0 : case 0:
213 0 : mySpeed = myObject->getDefaultSpeed();
214 0 : break;
215 0 : case 1:
216 0 : mySpeed = myObject->getLoadedSpeed();
217 0 : break;
218 0 : case 2:
219 0 : mySpeed = ((double)myPredefinedValues->getCurrentItem() * 20. + 20.) / 3.6;
220 0 : break;
221 0 : case 3:
222 0 : mySpeed = myUserDefinedSpeed->getValue() / 3.6;
223 0 : break;
224 : default:
225 : // hmmm, should not happen
226 : break;
227 : }
228 0 : myObject->setOverridingValue(mySpeed);
229 0 : myParent->updateChildren();
230 0 : if (myChosenValue == 1) {
231 : // !!! lock in between
232 0 : myObject->setOverriding(false);
233 : }
234 0 : return 1;
235 : }
236 :
237 :
238 :
239 : /* -------------------------------------------------------------------------
240 : * GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu - methods
241 : * ----------------------------------------------------------------------- */
242 0 : GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu::GUILaneSpeedTriggerPopupMenu(
243 0 : GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
244 0 : GUIGLObjectPopupMenu(app, parent, o) {}
245 :
246 :
247 0 : GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu::~GUILaneSpeedTriggerPopupMenu() {}
248 :
249 :
250 : long
251 0 : GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu::onCmdOpenManip(FXObject*,
252 : FXSelector,
253 : void*) {
254 0 : static_cast<GUILaneSpeedTrigger*>(myObject)->openManipulator(
255 0 : *myApplication, *myParent);
256 0 : return 1;
257 : }
258 :
259 : // -------------------------------------------------------------------------
260 : // GUILaneSpeedTrigger - methods
261 : // -------------------------------------------------------------------------
262 :
263 100 : GUILaneSpeedTrigger::GUILaneSpeedTrigger(
264 : const std::string& id, const std::vector<MSLane*>& destLanes,
265 100 : const std::string& aXMLFilename) :
266 : MSLaneSpeedTrigger(id, destLanes, aXMLFilename),
267 : GUIGlObject_AbstractAdd(GLO_VSS, id, GUIIconSubSys::getIcon(GUIIcon::VARIABLESPEEDSIGN)),
268 100 : myShowAsKMH(true), myLastValue(-1) {
269 100 : myFGPositions.reserve(destLanes.size());
270 100 : myFGRotations.reserve(destLanes.size());
271 : std::vector<MSLane*>::const_iterator i;
272 212 : for (i = destLanes.begin(); i != destLanes.end(); ++i) {
273 112 : const PositionVector& v = (*i)->getShape();
274 112 : myFGPositions.push_back(v.positionAtOffset(0));
275 112 : myBoundary.add(v.positionAtOffset(0));
276 112 : myFGRotations.push_back(-v.rotationDegreeAtOffset(0));
277 : }
278 100 : }
279 :
280 :
281 200 : GUILaneSpeedTrigger::~GUILaneSpeedTrigger() {}
282 :
283 :
284 : GUIGLObjectPopupMenu*
285 0 : GUILaneSpeedTrigger::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
286 0 : GUIGLObjectPopupMenu* ret = new GUILaneSpeedTriggerPopupMenu(app, parent, this);
287 0 : buildPopupHeader(ret, app);
288 0 : buildCenterPopupEntry(ret);
289 0 : buildShowManipulatorPopupEntry(ret);
290 0 : buildNameCopyPopupEntry(ret);
291 0 : buildSelectionPopupEntry(ret);
292 0 : buildShowParamsPopupEntry(ret);
293 0 : buildPositionCopyEntry(ret, app);
294 0 : return ret;
295 : }
296 :
297 :
298 : GUIParameterTableWindow*
299 0 : GUILaneSpeedTrigger::getParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
300 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
301 : // add items
302 0 : ret->mkItem(TL("speed [m/s]"), true,
303 0 : new FunctionBinding<GUILaneSpeedTrigger, double>(this, &GUILaneSpeedTrigger::getCurrentSpeed));
304 : // close building
305 0 : ret->closeBuilding();
306 0 : return ret;
307 : }
308 :
309 :
310 : void
311 24532 : GUILaneSpeedTrigger::drawGL(const GUIVisualizationSettings& s) const {
312 24532 : GLHelper::pushName(getGlID());
313 24532 : GLHelper::pushMatrix();
314 24532 : glTranslated(0, 0, getType());
315 24532 : const double exaggeration = getExaggeration(s);
316 49877 : for (int i = 0; i < (int)myFGPositions.size(); ++i) {
317 25345 : const Position& pos = myFGPositions[i];
318 25345 : double rot = myFGRotations[i];
319 25345 : GLHelper::pushMatrix();
320 25345 : glTranslated(pos.x(), pos.y(), 0);
321 25345 : glRotated(rot, 0, 0, 1);
322 25345 : glTranslated(0, -1.5, 0);
323 25345 : glScaled(exaggeration, exaggeration, 1);
324 : int noPoints = 9;
325 25345 : if (s.scale > 25) {
326 0 : noPoints = (int)(9.0 + s.scale / 10.0);
327 0 : if (noPoints > 36) {
328 : noPoints = 36;
329 : }
330 : }
331 25345 : glColor3d(1, 0, 0);
332 25345 : GLHelper::drawFilledCircle((double) 1.3, noPoints);
333 25345 : if (s.scale >= 5) {
334 0 : glTranslated(0, 0, .1);
335 0 : glColor3d(0, 0, 0);
336 0 : GLHelper::drawFilledCircle((double) 1.1, noPoints);
337 : // draw the speed string
338 : // not if scale to low
339 : // compute
340 0 : double value = (double) getCurrentSpeed();
341 0 : if (myShowAsKMH) {
342 0 : value *= 3.6f;
343 0 : if (((int) value + 1) % 10 == 0) {
344 0 : value = (double)(((int) value + 1) / 10 * 10);
345 : }
346 : }
347 0 : if (value != myLastValue) {
348 0 : myLastValue = value;
349 0 : myLastValueString = toString<double>(myLastValue);
350 0 : std::string::size_type idx = myLastValueString.find('.');
351 0 : if (idx != std::string::npos) {
352 0 : if (idx > myLastValueString.length()) {
353 : idx = myLastValueString.length();
354 : }
355 0 : myLastValueString = myLastValueString.substr(0, idx);
356 : }
357 : }
358 : //draw
359 0 : glColor3d(1, 1, 0);
360 0 : glTranslated(0, 0, .1);
361 0 : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
362 : // draw last value string
363 0 : GLHelper::drawText(myLastValueString.c_str(), Position(0, 0), .1, 1.2, RGBColor(255, 255, 0), 180);
364 : }
365 25345 : GLHelper::popMatrix();
366 : }
367 24532 : GLHelper::popMatrix();
368 24532 : drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
369 24532 : GLHelper::popName();
370 24532 : }
371 :
372 :
373 : double
374 24532 : GUILaneSpeedTrigger::getExaggeration(const GUIVisualizationSettings& s) const {
375 24532 : return s.addSize.getExaggeration(s, this);
376 : }
377 :
378 :
379 : Boundary
380 24632 : GUILaneSpeedTrigger::getCenteringBoundary() const {
381 : Boundary b(myBoundary);
382 24632 : b.grow(20);
383 24632 : return b;
384 : }
385 :
386 :
387 : GUIManipulator*
388 0 : GUILaneSpeedTrigger::openManipulator(GUIMainWindow& app,
389 : GUISUMOAbstractView&) {
390 : GUIManip_LaneSpeedTrigger* gui =
391 0 : new GUIManip_LaneSpeedTrigger(app, getFullName(), *this, 0, 0);
392 0 : gui->create();
393 0 : gui->show();
394 0 : return gui;
395 : }
396 :
397 :
398 : /****************************************************************************/
|