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