Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 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 =
126 0 : new MFXComboBoxIcon(gf2, 10, false, GUIDesignComboBoxVisibleItemsSmall, this, MID_PRE_DEF,
127 0 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP | LAYOUT_CENTER_Y | COMBOBOX_STATIC);
128 0 : myPredefinedValues->appendIconItem("20 km/h");
129 0 : myPredefinedValues->appendIconItem("40 km/h");
130 0 : myPredefinedValues->appendIconItem("60 km/h");
131 0 : myPredefinedValues->appendIconItem("80 km/h");
132 0 : myPredefinedValues->appendIconItem("100 km/h");
133 0 : myPredefinedValues->appendIconItem("120 km/h");
134 0 : myPredefinedValues->appendIconItem("140 km/h");
135 0 : myPredefinedValues->appendIconItem("160 km/h");
136 0 : myPredefinedValues->appendIconItem("180 km/h");
137 0 : myPredefinedValues->appendIconItem("200 km/h");
138 : }
139 : {
140 : // free
141 : FXHorizontalFrame* gf12 =
142 0 : new FXHorizontalFrame(gp, LAYOUT_TOP | LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 5, 5);
143 : new FXRadioButton(gf12, "Free Entry: ", &myChosenTarget, FXDataTarget::ID_OPTION + 3,
144 : ICON_BEFORE_TEXT | LAYOUT_SIDE_TOP | LAYOUT_CENTER_Y,
145 0 : 0, 0, 0, 0, 2, 2, 0, 0);
146 0 : myUserDefinedSpeed =
147 : new FXRealSpinner(gf12, 10, this, MID_USER_DEF,
148 0 : LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
149 : //myUserDefinedSpeed->setFormatString("%.0f km/h");
150 : //myUserDefinedSpeed->setIncrements(1, 10, 10);
151 0 : myUserDefinedSpeed->setIncrement(10);
152 0 : myUserDefinedSpeed->setRange(0, 300);
153 0 : myUserDefinedSpeed->setValue(myObject->getDefaultSpeed() * 3.6);
154 : }
155 0 : GUIDesigns::buildFXButton(f1, "Close", "", "", nullptr, this, MID_CLOSE,
156 : BUTTON_INITIAL | BUTTON_DEFAULT | FRAME_RAISED | FRAME_THICK | LAYOUT_TOP | LAYOUT_LEFT | LAYOUT_CENTER_X, 0, 0, 0, 0, 30, 30, 4, 4);
157 0 : myObject->setOverriding(true);
158 0 : }
159 :
160 :
161 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::~GUIManip_LaneSpeedTrigger() {}
162 :
163 :
164 : long
165 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdClose(FXObject*, FXSelector, void*) {
166 0 : destroy();
167 0 : return 1;
168 : }
169 :
170 :
171 : long
172 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdUserDef(FXObject*, FXSelector, void*) {
173 0 : mySpeed = myUserDefinedSpeed->getValue() / 3.6;
174 0 : myObject->setOverridingValue(mySpeed);
175 0 : myParent->updateChildren();
176 0 : return 1;
177 : }
178 :
179 :
180 : long
181 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onUpdUserDef(FXObject* sender, FXSelector, void* ptr) {
182 0 : sender->handle(this,
183 0 : myChosenValue != 3 ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
184 : ptr);
185 0 : myParent->updateChildren();
186 0 : return 1;
187 : }
188 :
189 :
190 : long
191 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdPreDef(FXObject*, FXSelector, void*) {
192 0 : mySpeed = ((double)myPredefinedValues->getCurrentItem() * 20. + 20.) / 3.6;
193 0 : myObject->setOverridingValue(mySpeed);
194 0 : myParent->updateChildren();
195 0 : return 1;
196 : }
197 :
198 :
199 : long
200 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onUpdPreDef(FXObject* sender, FXSelector, void* ptr) {
201 0 : sender->handle(this,
202 0 : myChosenValue != 2 ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE),
203 : ptr);
204 0 : myParent->updateChildren();
205 0 : return 1;
206 : }
207 :
208 :
209 : long
210 0 : GUILaneSpeedTrigger::GUIManip_LaneSpeedTrigger::onCmdChangeOption(FXObject*, FXSelector, void*) {
211 0 : myObject->setOverriding(true);
212 0 : switch (myChosenValue) {
213 0 : case 0:
214 0 : mySpeed = myObject->getDefaultSpeed();
215 0 : break;
216 0 : case 1:
217 0 : mySpeed = myObject->getLoadedSpeed();
218 0 : break;
219 0 : case 2:
220 0 : mySpeed = ((double)myPredefinedValues->getCurrentItem() * 20. + 20.) / 3.6;
221 0 : break;
222 0 : case 3:
223 0 : mySpeed = myUserDefinedSpeed->getValue() / 3.6;
224 0 : break;
225 : default:
226 : // hmmm, should not happen
227 : break;
228 : }
229 0 : myObject->setOverridingValue(mySpeed);
230 0 : myParent->updateChildren();
231 0 : if (myChosenValue == 1) {
232 : // !!! lock in between
233 0 : myObject->setOverriding(false);
234 : }
235 0 : return 1;
236 : }
237 :
238 :
239 :
240 : /* -------------------------------------------------------------------------
241 : * GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu - methods
242 : * ----------------------------------------------------------------------- */
243 0 : GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu::GUILaneSpeedTriggerPopupMenu(
244 : GUIMainWindow& app, GUISUMOAbstractView& parent,
245 0 : GUIGlObject& o)
246 0 : : GUIGLObjectPopupMenu(app, parent, o) {}
247 :
248 :
249 0 : GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu::~GUILaneSpeedTriggerPopupMenu() {}
250 :
251 :
252 : long
253 0 : GUILaneSpeedTrigger::GUILaneSpeedTriggerPopupMenu::onCmdOpenManip(FXObject*,
254 : FXSelector,
255 : void*) {
256 0 : static_cast<GUILaneSpeedTrigger*>(myObject)->openManipulator(
257 0 : *myApplication, *myParent);
258 0 : return 1;
259 : }
260 :
261 : // -------------------------------------------------------------------------
262 : // GUILaneSpeedTrigger - methods
263 : // -------------------------------------------------------------------------
264 :
265 100 : GUILaneSpeedTrigger::GUILaneSpeedTrigger(
266 : const std::string& id, const std::vector<MSLane*>& destLanes,
267 100 : const std::string& aXMLFilename) :
268 : MSLaneSpeedTrigger(id, destLanes, aXMLFilename),
269 : GUIGlObject_AbstractAdd(GLO_VSS, id, GUIIconSubSys::getIcon(GUIIcon::VARIABLESPEEDSIGN)),
270 100 : myShowAsKMH(true), myLastValue(-1) {
271 100 : myFGPositions.reserve(destLanes.size());
272 100 : myFGRotations.reserve(destLanes.size());
273 : std::vector<MSLane*>::const_iterator i;
274 212 : for (i = destLanes.begin(); i != destLanes.end(); ++i) {
275 112 : const PositionVector& v = (*i)->getShape();
276 112 : myFGPositions.push_back(v.positionAtOffset(0));
277 112 : myBoundary.add(v.positionAtOffset(0));
278 112 : myFGRotations.push_back(-v.rotationDegreeAtOffset(0));
279 : }
280 100 : }
281 :
282 :
283 200 : GUILaneSpeedTrigger::~GUILaneSpeedTrigger() {}
284 :
285 :
286 : GUIGLObjectPopupMenu*
287 0 : GUILaneSpeedTrigger::getPopUpMenu(GUIMainWindow& app,
288 : GUISUMOAbstractView& parent) {
289 0 : GUIGLObjectPopupMenu* ret = new GUILaneSpeedTriggerPopupMenu(app, parent, *this);
290 0 : buildPopupHeader(ret, app);
291 0 : buildCenterPopupEntry(ret);
292 0 : buildShowManipulatorPopupEntry(ret);
293 0 : buildNameCopyPopupEntry(ret);
294 0 : buildSelectionPopupEntry(ret);
295 0 : buildShowParamsPopupEntry(ret);
296 0 : buildPositionCopyEntry(ret, app);
297 0 : return ret;
298 : }
299 :
300 :
301 : GUIParameterTableWindow*
302 0 : GUILaneSpeedTrigger::getParameterWindow(GUIMainWindow& app,
303 : GUISUMOAbstractView&) {
304 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
305 : // add items
306 0 : ret->mkItem(TL("speed [m/s]"), true,
307 0 : new FunctionBinding<GUILaneSpeedTrigger, double>(this, &GUILaneSpeedTrigger::getCurrentSpeed));
308 : // close building
309 0 : ret->closeBuilding();
310 0 : return ret;
311 : }
312 :
313 :
314 : void
315 20238 : GUILaneSpeedTrigger::drawGL(const GUIVisualizationSettings& s) const {
316 20238 : GLHelper::pushName(getGlID());
317 20238 : GLHelper::pushMatrix();
318 20238 : glTranslated(0, 0, getType());
319 20238 : const double exaggeration = getExaggeration(s);
320 41265 : for (int i = 0; i < (int)myFGPositions.size(); ++i) {
321 21027 : const Position& pos = myFGPositions[i];
322 21027 : double rot = myFGRotations[i];
323 21027 : GLHelper::pushMatrix();
324 21027 : glTranslated(pos.x(), pos.y(), 0);
325 21027 : glRotated(rot, 0, 0, 1);
326 21027 : glTranslated(0, -1.5, 0);
327 21027 : glScaled(exaggeration, exaggeration, 1);
328 : int noPoints = 9;
329 21027 : if (s.scale > 25) {
330 0 : noPoints = (int)(9.0 + s.scale / 10.0);
331 0 : if (noPoints > 36) {
332 : noPoints = 36;
333 : }
334 : }
335 21027 : glColor3d(1, 0, 0);
336 21027 : GLHelper::drawFilledCircle((double) 1.3, noPoints);
337 21027 : if (s.scale >= 5) {
338 0 : glTranslated(0, 0, .1);
339 0 : glColor3d(0, 0, 0);
340 0 : GLHelper::drawFilledCircle((double) 1.1, noPoints);
341 : // draw the speed string
342 : // not if scale to low
343 : // compute
344 0 : double value = (double) getCurrentSpeed();
345 0 : if (myShowAsKMH) {
346 0 : value *= 3.6f;
347 0 : if (((int) value + 1) % 10 == 0) {
348 0 : value = (double)(((int) value + 1) / 10 * 10);
349 : }
350 : }
351 0 : if (value != myLastValue) {
352 0 : myLastValue = value;
353 0 : myLastValueString = toString<double>(myLastValue);
354 0 : std::string::size_type idx = myLastValueString.find('.');
355 0 : if (idx != std::string::npos) {
356 0 : if (idx > myLastValueString.length()) {
357 : idx = myLastValueString.length();
358 : }
359 0 : myLastValueString = myLastValueString.substr(0, idx);
360 : }
361 : }
362 : //draw
363 0 : glColor3d(1, 1, 0);
364 0 : glTranslated(0, 0, .1);
365 0 : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
366 : // draw last value string
367 0 : GLHelper::drawText(myLastValueString.c_str(), Position(0, 0), .1, 1.2, RGBColor(255, 255, 0), 180);
368 : }
369 21027 : GLHelper::popMatrix();
370 : }
371 20238 : GLHelper::popMatrix();
372 20238 : drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
373 20238 : GLHelper::popName();
374 20238 : }
375 :
376 :
377 : double
378 20238 : GUILaneSpeedTrigger::getExaggeration(const GUIVisualizationSettings& s) const {
379 20238 : return s.addSize.getExaggeration(s, this);
380 : }
381 :
382 :
383 : Boundary
384 20338 : GUILaneSpeedTrigger::getCenteringBoundary() const {
385 : Boundary b(myBoundary);
386 20338 : b.grow(20);
387 20338 : return b;
388 0 : }
389 :
390 :
391 : GUIManipulator*
392 0 : GUILaneSpeedTrigger::openManipulator(GUIMainWindow& app,
393 : GUISUMOAbstractView&) {
394 : GUIManip_LaneSpeedTrigger* gui =
395 0 : new GUIManip_LaneSpeedTrigger(app, getFullName(), *this, 0, 0);
396 0 : gui->create();
397 0 : gui->show();
398 0 : return gui;
399 : }
400 :
401 :
402 : /****************************************************************************/
|