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