Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GUISUMOAbstractView.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/****************************************************************************/
22// The base class for a view
23/****************************************************************************/
24#include <config.h>
25
26#include <iostream>
27#include <utility>
28#include <cmath>
29#include <cassert>
30#include <limits>
31#include <fxkeys.h>
32#ifdef HAVE_GL2PS
33#include <gl2ps.h>
34#endif
65
66#include <unordered_set>
67
68#include "GUISUMOAbstractView.h"
69#include "GUIMainWindow.h"
70#include "GUIGlChildWindow.h"
73
74#ifdef HAVE_GDAL
75#ifdef _MSC_VER
76#pragma warning(push)
77#pragma warning(disable: 4435 5219 5220)
78#endif
79#if __GNUC__ > 3
80#pragma GCC diagnostic push
81#pragma GCC diagnostic ignored "-Wpedantic"
82#endif
83#include <gdal_priv.h>
84#if __GNUC__ > 3
85#pragma GCC diagnostic pop
86#endif
87#ifdef _MSC_VER
88#pragma warning(pop)
89#endif
90#endif
91
92// ===========================================================================
93// debug constants
94// ===========================================================================
95//#define DEBUG_SNAPSHOT
96
97// ===========================================================================
98// static members
99// ===========================================================================
100
101const double GUISUMOAbstractView::SENSITIVITY = 0.1; // meters
102
103// ===========================================================================
104// FOX callback mapping
105// ===========================================================================
106
107FXDEFMAP(GUISUMOAbstractView) GUISUMOAbstractViewMap[] = {
108 FXMAPFUNC(SEL_CONFIGURE, 0, GUISUMOAbstractView::onConfigure),
109 FXMAPFUNC(SEL_PAINT, 0, GUISUMOAbstractView::onPaint),
110 FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, GUISUMOAbstractView::onLeftBtnPress),
111 FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, GUISUMOAbstractView::onLeftBtnRelease),
112 FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, 0, GUISUMOAbstractView::onMiddleBtnPress),
113 FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, 0, GUISUMOAbstractView::onMiddleBtnRelease),
114 FXMAPFUNC(SEL_RIGHTBUTTONPRESS, 0, GUISUMOAbstractView::onRightBtnPress),
115 FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, 0, GUISUMOAbstractView::onRightBtnRelease),
116 FXMAPFUNC(SEL_DOUBLECLICKED, 0, GUISUMOAbstractView::onDoubleClicked),
117 FXMAPFUNC(SEL_MOUSEWHEEL, 0, GUISUMOAbstractView::onMouseWheel),
118 FXMAPFUNC(SEL_MOTION, 0, GUISUMOAbstractView::onMouseMove),
119 FXMAPFUNC(SEL_LEAVE, 0, GUISUMOAbstractView::onMouseLeft),
120 FXMAPFUNC(SEL_KEYPRESS, 0, GUISUMOAbstractView::onKeyPress),
121 FXMAPFUNC(SEL_KEYRELEASE, 0, GUISUMOAbstractView::onKeyRelease),
128};
129
130FXIMPLEMENT_ABSTRACT(GUISUMOAbstractView, FXGLCanvas, GUISUMOAbstractViewMap, ARRAYNUMBER(GUISUMOAbstractViewMap))
131
132// ===========================================================================
133// member method definitions
134// ===========================================================================
135
136GUISUMOAbstractView::GUISUMOAbstractView(FXComposite* p, GUIMainWindow& app, GUIGlChildWindow* parent, const SUMORTree& grid, FXGLVisual* glVis, FXGLCanvas* share) :
137 FXGLCanvas(p, glVis, share, p, MID_GLCANVAS, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0),
138 myApp(&app),
139 myGlChildWindowParent(parent),
140 myGrid(&grid),
141 myMouseHotspotX(app.getDefaultCursor()->getHotX()),
142 myMouseHotspotY(app.getDefaultCursor()->getHotY()),
143 myWindowCursorPositionX(getWidth() / 2),
144 myWindowCursorPositionY(getHeight() / 2) {
145 setTarget(this);
146 enable();
147 flags |= FLAG_ENABLED;
150 myVisualizationSettings->gaming = myApp->isGaming();
151 gSchemeStorage.setViewport(this);
152 myDecals = gSchemeStorage.getDecals();
153}
154
155
157 gSchemeStorage.setDefault(myVisualizationSettings->name);
158 gSchemeStorage.saveViewport(myChanger->getXPos(), myChanger->getYPos(), myChanger->getZPos(), myChanger->getRotation());
159 gSchemeStorage.saveDecals(myDecals);
160 delete myPopup;
161 delete myChanger;
164 // cleanup decals
165 for (auto& decal : myDecals) {
166 delete decal.image;
167 }
168 // remove all elements
169 for (auto& additional : myAdditionallyDrawn) {
170 additional.first->removeActiveAddVisualisation(this, ~0);
171 }
172}
173
174
175bool
179
180
183 return *myChanger;
184}
185
186
187void
189 if (myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->isStaticToolTipEnabled()) {
190 update();
191 }
192}
193
194
199
200
202GUISUMOAbstractView::snapToActiveGrid(const Position& pos, bool snapXY) const {
203 Position result = pos;
204 if (myVisualizationSettings->showGrid) {
205 if (snapXY) {
206 const double xRest = std::fmod(pos.x(), myVisualizationSettings->gridXSize) + (pos.x() < 0 ? myVisualizationSettings->gridXSize : 0);
207 const double yRest = std::fmod(pos.y(), myVisualizationSettings->gridYSize) + (pos.y() < 0 ? myVisualizationSettings->gridYSize : 0);
208 result.setx(pos.x() - xRest + (xRest < myVisualizationSettings->gridXSize * 0.5 ? 0 : myVisualizationSettings->gridXSize));
209 result.sety(pos.y() - yRest + (yRest < myVisualizationSettings->gridYSize * 0.5 ? 0 : myVisualizationSettings->gridYSize));
210 } else {
211 // snapZToActiveGrid uses grid Y Size
212 const double zRest = std::fmod(pos.z(), myVisualizationSettings->gridYSize) + (pos.z() < 0 ? myVisualizationSettings->gridYSize : 0);
213 result.setz(pos.z() - zRest + (zRest < myVisualizationSettings->gridYSize * 0.5 ? 0 : myVisualizationSettings->gridYSize));
214 }
215 }
216 return result;
217}
218
219
222 Boundary bound = myChanger->getViewport();
223 double xNet = bound.xmin() + bound.getWidth() * x / getWidth();
224 // cursor origin is in the top-left corner
225 double yNet = bound.ymin() + bound.getHeight() * (getHeight() - y) / getHeight();
226 // rotate around the viewport center
227 if (myChanger->getRotation() != 0) {
228 return Position(xNet, yNet).rotateAround2D(-DEG2RAD(myChanger->getRotation()), bound.getCenter());
229 } else {
230 return Position(xNet, yNet);
231 }
232}
233
234
235void
236GUISUMOAbstractView::addDecals(const std::vector<Decal>& decals) {
237 myDecals.insert(myDecals.end(), decals.begin(), decals.end());
238}
239
240
241void
244 // set cartesian position
245 myApp->getCartesianLabel()->setText(("x:" + toString(pos.x()) + ", y:" + toString(pos.y())).c_str());
246 // set geo position
248 if (GeoConvHelper::getFinal().usingGeoProjection()) {
249 myApp->getGeoLabel()->setText(("lat:" + toString(pos.y(), gPrecisionGeo) + ", lon:" + toString(pos.x(), gPrecisionGeo)).c_str());
250 } else {
251 myApp->getGeoLabel()->setText(TL("(No projection defined)"));
252 }
253 // if enabled, set test position
254 if (myApp->getTestFrame()) {
255 if (OptionsCont::getOptions().getBool("gui-testing")) {
256 myApp->getTestFrame()->show();
257 // adjust cursor position (24,25) to show exactly the same position as in function netedit.leftClick(match, X, Y)
258 myApp->getTestLabel()->setText(("Test: x:" + toString(getWindowCursorPosition().x() - 24.0) + " y:" + toString(getWindowCursorPosition().y() - 25.0)).c_str());
259 } else {
260 myApp->getTestFrame()->hide();
261 }
262 }
263}
264
265
266int
267GUISUMOAbstractView::doPaintGL(int /*mode*/, const Boundary& /*boundary*/) {
268 return 0;
269}
270
271
272void
275
276
279 return myChanger->getViewport();
280}
281
282
283bool
285 return false;
286}
287
288
289void GUISUMOAbstractView::zoom2Pos(Position& /* camera */, Position& /* lookAt */, double /* zoom */) {
290}
291
292
293void
295 // reset debug counters
298 if (getWidth() == 0 || getHeight() == 0) {
299 return;
300 }
301 const long start = SysUtils::getCurrentMillis();
302
304 centerTo(getTrackedID(), false);
305 }
306 // draw
307 glClearColor(
308 myVisualizationSettings->backgroundColor.red() / 255.f,
309 myVisualizationSettings->backgroundColor.green() / 255.f,
310 myVisualizationSettings->backgroundColor.blue() / 255.f,
311 myVisualizationSettings->backgroundColor.alpha() / 255.f);
312 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
313 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
314
315 if (myVisualizationSettings->dither) {
316 glEnable(GL_DITHER);
317 } else {
318 glDisable(GL_DITHER);
319 }
320 glEnable(GL_BLEND);
321 glDisable(GL_LINE_SMOOTH);
322
323 Boundary bound = applyGLTransform();
324 doPaintGL(GL_RENDER, bound);
328 const long end = SysUtils::getCurrentMillis();
329 myFrameDrawTime = end - start;
330 if (myVisualizationSettings->fps) {
331 drawFPS();
332 }
333 // check if show tooltip
334 if (myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->isStaticToolTipEnabled()) {
336 } else {
337 myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->hideStaticToolTip();
338 }
339 swapBuffers();
340}
341
342
343long
344GUISUMOAbstractView::onCmdCloseLane(FXObject*, FXSelector, void*) {
345 return 1;
346}
347
348
349long
350GUISUMOAbstractView::onCmdCloseEdge(FXObject*, FXSelector, void*) {
351 return 1;
352}
353
354
355long
356GUISUMOAbstractView::onCmdAddRerouter(FXObject*, FXSelector, void*) {
357 return 1;
358}
359
360
361long
362GUISUMOAbstractView::onCmdShowReachability(FXObject*, FXSelector, void*) {
363 return 1;
364}
365
366
367long
368GUISUMOAbstractView::onVisualizationChange(FXObject*, FXSelector, void*) {
369 return 1;
370}
371
372
373GUILane*
375 return nullptr;
376}
377
378
383
384
387 return getObjectAtPosition(getPositionInformation(), sensitivity);
388}
389
390
391std::vector<GUIGlID>
395
396
397
398std::vector<GUIGlObject*>
402
403
404std::vector<GUIGlObject*>
408
409
412 // calculate a boundary for the given position
413 Boundary positionBoundary;
414 positionBoundary.add(pos);
415 positionBoundary.grow(sensitivity);
416 const std::vector<GUIGlID> ids = getObjectsInBoundary(positionBoundary);
417 // Interpret results
418 int idMax = 0;
419 double maxLayer = -std::numeric_limits<double>::max();
420 double minDist = std::numeric_limits<double>::max();
421 // iterate over obtained GUIGlIDs
422 for (const auto& i : ids) {
423 // obtain GUIGlObject
424 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(i);
425 // check that GUIGlObject exist
426 if (o == nullptr) {
427 continue;
428 }
429 // check that GUIGlObject isn't the network
430 if (o->getGlID() == 0) {
431 continue;
432 }
433 //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
434 double layer = o->getClickPriority();
435 double dist = o->getCenter().distanceTo2D(pos);
436 // check whether the current object is above a previous one
437 if (layer > maxLayer) {
438 idMax = i;
439 maxLayer = layer;
440 minDist = dist;
441 } else if (layer == maxLayer && dist < minDist) {
442 idMax = i;
443 minDist = dist;
444 }
445 // unblock object
446 GUIGlObjectStorage::gIDStorage.unblockObject(i);
447 }
448 return idMax;
449}
450
451
452std::vector<GUIGlID>
454 // declare result vector
455 std::vector<GUIGlID> result;
456 // calculate boundary
457 Boundary selection;
458 selection.add(pos);
459 selection.grow(radius);
460 // obtain GUIGlID of objects in boundary
461 const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
462 // iterate over obtained GUIGlIDs
463 for (const auto& i : ids) {
464 // obtain GUIGlObject
465 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(i);
466 // check that GUIGlObject exist
467 if (o == nullptr) {
468 continue;
469 }
470 // check that GUIGlObject isn't the network
471 if (o->getGlID() == 0) {
472 continue;
473 }
474 //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
475 GUIGlObjectType type = o->getType();
476 // avoid network
477 if (type != GLO_NETWORK) {
478 result.push_back(i);
479 }
480 // unblock object
481 GUIGlObjectStorage::gIDStorage.unblockObject(i);
482 }
483 return result;
484}
485
486
487std::vector<GUIGlObject*>
489 // declare result vector
490 std::vector<GUIGlObject*> result;
491 // calculate boundary
492 Boundary selection;
493 selection.add(pos);
494 selection.grow(radius);
495 // obtain GUIGlID of objects in boundary
496 const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
497 // iterate over obtained GUIGlIDs
498 for (const auto& i : ids) {
499 // obtain GUIGlObject
500 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(i);
501 // check that GUIGlObject exist
502 if (o == nullptr) {
503 continue;
504 }
505 // check that GUIGlObject isn't the network
506 if (o->getGlID() == 0) {
507 continue;
508 }
509 result.push_back(o);
510 // unblock object
511 GUIGlObjectStorage::gIDStorage.unblockObject(i);
512 }
513 return result;
514}
515
516
517std::vector<GUIGlID>
519 const int NB_HITS_MAX = 1024 * 1024;
520 // Prepare the selection mode
521 static GUIGlID hits[NB_HITS_MAX];
522 static GLint nb_hits = 0;
523 glSelectBuffer(NB_HITS_MAX, hits);
524 glInitNames();
525
527 Boundary oldViewPort = myChanger->getViewport(false); // backup the actual viewPort
528 myChanger->setViewport(bound);
529 bound = applyGLTransform(false);
530 // enable draw for selecting (to draw objects with less details)
531 myVisualizationSettings->drawForRectangleSelection = true;
532 int hits2 = doPaintGL(GL_SELECT, bound);
533 // reset flags
534 myVisualizationSettings->drawForRectangleSelection = false;
535 // Get the results
536 nb_hits = glRenderMode(GL_RENDER);
537 if (nb_hits == -1) {
538 myApp->setStatusBarText("Selection in boundary failed. Try to select fewer than " + toString(hits2) + " items");
539 }
540 std::vector<GUIGlID> result;
541 GLuint numNames;
542 GLuint* ptr = hits;
543 for (int i = 0; i < nb_hits; ++i) {
544 numNames = *ptr;
545 ptr += 3;
546 for (int j = 0; j < (int)numNames; j++) {
547 result.push_back(*ptr);
548 ptr++;
549 }
550 }
551 // switch viewport back to normal
552 myChanger->setViewport(oldViewPort);
553 return result;
554}
555
556
557std::vector<GUIGlObject*>
558GUISUMOAbstractView::filterInternalLanes(const std::vector<GUIGlObject*>& objects) const {
559 // count number of internal lanes
560 size_t internalLanes = 0;
561 for (const auto& object : objects) {
562 if ((object->getType() == GLO_LANE) && (object->getMicrosimID().find(':') != std::string::npos)) {
563 internalLanes++;
564 }
565 }
566 // if all objects are internal lanes, return it all
567 if (objects.size() == internalLanes || !myVisualizationSettings->drawJunctionShape) {
568 return objects;
569 }
570 // in other case filter internal lanes
571 std::vector<GUIGlObject*> filteredObjects;
572 for (const auto& object : objects) {
573 if ((object->getType() == GLO_LANE) && (object->getMicrosimID().find(':') != std::string::npos)) {
574 continue;
575 }
576 filteredObjects.push_back(object);
577 }
578 return filteredObjects;
579}
580
581
582bool
584 if (idToolTip != GUIGlObject::INVALID_ID) {
585 const GUIGlObject* object = GUIGlObjectStorage::gIDStorage.getObjectBlocking(idToolTip);
586 if (object != nullptr) {
587 myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->showStaticToolTip(object->getFullName().c_str());
588 return true;
589 }
590 }
591 // nothing to show
592 myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->hideStaticToolTip();
593 return false;
594}
595
596
597void
599 // obtain minimum grid
600 const double minimumSizeGrid = (myVisualizationSettings->gridXSize < myVisualizationSettings->gridYSize) ? myVisualizationSettings->gridXSize : myVisualizationSettings->gridYSize;
601 // Check if the distance is enough to draw grid
602 if (myVisualizationSettings->scale * myVisualizationSettings->addSize.getExaggeration(*myVisualizationSettings, nullptr) >= (25 / minimumSizeGrid)) {
603 glEnable(GL_DEPTH_TEST);
604 glLineWidth(1);
605 // get multiplication values (2 is the margin)
606 const int multXmin = (int)(myChanger->getViewport().xmin() / myVisualizationSettings->gridXSize) - 2;
607 const int multYmin = (int)(myChanger->getViewport().ymin() / myVisualizationSettings->gridYSize) - 2;
608 const int multXmax = (int)(myChanger->getViewport().xmax() / myVisualizationSettings->gridXSize) + 2;
609 const int multYmax = (int)(myChanger->getViewport().ymax() / myVisualizationSettings->gridYSize) + 2;
610 // obtain references
611 const double xmin = myVisualizationSettings->gridXSize * multXmin;
612 const double ymin = myVisualizationSettings->gridYSize * multYmin;
613 const double xmax = myVisualizationSettings->gridXSize * multXmax;
614 const double ymax = myVisualizationSettings->gridYSize * multYmax;
615 double xp = xmin;
616 double yp = ymin;
617 // move drawing matrix
618 glTranslated(0, 0, .55);
619 glColor3d(0.5, 0.5, 0.5);
620 // draw horizontal lines
621 glBegin(GL_LINES);
622 while (yp <= ymax) {
623 glVertex2d(xmin, yp);
624 glVertex2d(xmax, yp);
625 yp += myVisualizationSettings->gridYSize;
626 }
627 // draw vertical lines
628 while (xp <= xmax) {
629 glVertex2d(xp, ymin);
630 glVertex2d(xp, ymax);
631 xp += myVisualizationSettings->gridXSize;
632 }
633 glEnd();
634 glTranslated(0, 0, -.55);
635 }
636}
637
638
639void
641 // compute the scale bar length
642 int length = 1;
643 const std::string text("10000000000");
644 int noDigits = 1;
645 int pixelSize = (int) m2p((double) length);
646 while (pixelSize <= 20) {
647 length *= 10;
648 noDigits++;
649 if (noDigits > (int)text.length()) {
650 return;
651 }
652 pixelSize = (int) m2p((double) length);
653 }
654 glLineWidth(1.0);
655
656 glMatrixMode(GL_PROJECTION);
658 glLoadIdentity();
659 glMatrixMode(GL_MODELVIEW);
661 glLoadIdentity();
662
663 // draw the scale bar
664 const double z = -1;
665 glDisable(GL_TEXTURE_2D);
666 glDisable(GL_ALPHA_TEST);
667 glDisable(GL_BLEND);
668 glEnable(GL_DEPTH_TEST);
670 glTranslated(0, 0, z);
671
672 double len = (double) pixelSize / (double)(getWidth() - 1) * (double) 2.0;
673 glColor3d(0, 0, 0);
674 double o = double(15) / double(getHeight());
675 double o2 = o + o;
676 double oo = double(5) / double(getHeight());
677 glBegin(GL_LINES);
678 // vertical
679 glVertex2d(-.98, -1. + o);
680 glVertex2d(-.98 + len, -1. + o);
681 // tick at begin
682 glVertex2d(-.98, -1. + o);
683 glVertex2d(-.98, -1. + o2);
684 // tick at end
685 glVertex2d(-.98 + len, -1. + o);
686 glVertex2d(-.98 + len, -1. + o2);
687 glEnd();
689
690 const double fontHeight = 0.1 * 300. / getHeight();
691 const double fontWidth = 0.1 * 300. / getWidth();
692 // draw 0
693 GLHelper::drawText("0", Position(-.99, -0.99 + o2 + oo), z, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT, fontWidth);
694
695 // draw current scale
696 GLHelper::drawText((text.substr(0, noDigits) + "m").c_str(), Position(-.99 + len, -0.99 + o2 + oo), z, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT, fontWidth);
697
698 // restore matrices
699 glMatrixMode(GL_PROJECTION);
701 glMatrixMode(GL_MODELVIEW);
703}
704
705void
707 if (myVisualizationSettings->showSizeLegend) {
709 }
710 std::string key = "";
711 if (myVisualizationSettings->showColorLegend) {
712 auto const& scheme = myVisualizationSettings->getLaneEdgeScheme();
714 key = myVisualizationSettings->edgeData;
715 } else if (scheme.getName() == GUIVisualizationSettings::SCHEME_NAME_EDGE_PARAM_NUMERICAL) {
716 key = myVisualizationSettings->edgeParam;
717 } else if (scheme.getName() == GUIVisualizationSettings::SCHEME_NAME_LANE_PARAM_NUMERICAL) {
718 key = myVisualizationSettings->laneParam;
719 }
720 displayColorLegend(scheme, false, key);
721 }
722 if (myVisualizationSettings->showVehicleColorLegend) {
723 auto const& scheme = myVisualizationSettings->vehicleColorer.getScheme();
725 key = myVisualizationSettings->vehicleParam;
726 }
727 displayColorLegend(myVisualizationSettings->vehicleColorer.getScheme(), true, key);
728 }
729}
730
731void
732GUISUMOAbstractView::displayColorLegend(const GUIColorScheme& scheme, bool leftSide, const std::string& key) {
733 // compute the scale bar length
734 glLineWidth(1.0);
735 glMatrixMode(GL_PROJECTION);
737 glLoadIdentity();
738 glMatrixMode(GL_MODELVIEW);
740 glLoadIdentity();
741
742 const double z = -1;
743 glEnable(GL_DEPTH_TEST);
744 glEnable(GL_BLEND);
746 glTranslated(0, 0, z);
747
748 const bool fixed = scheme.isFixed();
749 const int numColors = (int)scheme.getColors().size();
750
751 // vertical
752 double right = 0.98;
753 double left = 0.95;
754 double textX = left - 0.01;
755 double textDir = 1;
756 FONSalign textAlign = FONS_ALIGN_RIGHT;
757 const double top = -0.7;
758 const double bot = 0.9;
759 const double dy = (top - bot) / numColors;
760 const double bot2 = fixed ? bot : bot + dy / 2;
761 // legend placement
762 if (leftSide) {
763 right = -right;
764 left = -left;
765 std::swap(right, left);
766 textX = right + 0.01;
767 textDir *= -1;
768 textAlign = FONS_ALIGN_LEFT;
769 }
770 // draw black boundary around legend colors
771 glColor3d(0, 0, 0);
772 glBegin(GL_LINES);
773 glVertex2d(right, top);
774 glVertex2d(right, bot2);
775 glVertex2d(left, bot2);
776 glVertex2d(left, top);
777 glVertex2d(right, top);
778 glVertex2d(left, top);
779 glVertex2d(right, bot2);
780 glVertex2d(left, bot2);
781 glEnd();
782
783 const double fontHeight = 0.20 * 300. / getHeight();
784 const double fontWidth = 0.20 * 300. / getWidth();
785
786 const int fadeSteps = fixed ? 1 : 10;
787 double colorStep = dy / fadeSteps;
788 for (int i = 0; i < numColors; i++) {
789 RGBColor col = scheme.getColors()[i];
790 const double topi = top - i * dy;
791 //const double boti = top - (i + 1) * dy;
792 //std::cout << " col=" << scheme.getColors()[i] << " i=" << i << " topi=" << topi << " boti=" << boti << "\n";
793 if (i + 1 < numColors) {
794 // fade
795 RGBColor col2 = scheme.getColors()[i + 1];
796 double thresh2 = scheme.getThresholds()[i + 1];
797 if (!fixed && thresh2 == GUIVisualizationSettings::MISSING_DATA) {
798 // draw scale end before missing data
800 glBegin(GL_QUADS);
801 glVertex2d(left, topi);
802 glVertex2d(right, topi);
803 glVertex2d(right, topi - 5 * colorStep);
804 glVertex2d(left, topi - 5 * colorStep);
805 glEnd();
806 glColor3d(0, 0, 0);
807 glBegin(GL_LINES);
808 glVertex2d(right, topi - 10 * colorStep);
809 glVertex2d(left, topi - 10 * colorStep);
810 glEnd();
811 glBegin(GL_LINES);
812 glVertex2d(right, topi - 5 * colorStep);
813 glVertex2d(left, topi - 5 * colorStep);
814 glEnd();
815 } else {
816 // fade colors
817 for (double j = 0.0; j < fadeSteps; j++) {
818 GLHelper::setColor(RGBColor::interpolate(col, col2, j / fadeSteps));
819 glBegin(GL_QUADS);
820 glVertex2d(left, topi - j * colorStep);
821 glVertex2d(right, topi - j * colorStep);
822 glVertex2d(right, topi - (j + 1) * colorStep);
823 glVertex2d(left, topi - (j + 1) * colorStep);
824 glEnd();
825 }
826 }
827 } else {
829 glBegin(GL_QUADS);
830 glVertex2d(left, topi);
831 glVertex2d(right, topi);
832 glVertex2d(right, bot2);
833 glVertex2d(left, bot2);
834 glEnd();
835 }
836
837 const double threshold = scheme.getThresholds()[i];
838 std::string name = scheme.getNames()[i];
839 std::string text = fixed || threshold == GUIVisualizationSettings::MISSING_DATA ? name : toString(threshold);
840
841 const double bgShift = 0.0;
842 const double textShift = 0.01;
843 const double textXShift = -0.005;
844
846 glTranslated(0, 0, 0.1);
847 glBegin(GL_QUADS);
848 glVertex2d(textX, topi + fontHeight * bgShift);
849 glVertex2d(textX - textDir * fontWidth * (double)text.size() / 2.1, topi + fontHeight * bgShift);
850 glVertex2d(textX - textDir * fontWidth * (double)text.size() / 2.1, topi + fontHeight * (0.8 + bgShift));
851 glVertex2d(textX, topi + fontHeight * (0.8 + bgShift));
852 glEnd();
853 glTranslated(0, 0, -0.1);
854 GLHelper::drawText(text, Position(textX + textDir * textXShift, topi + textShift), 0, fontHeight, RGBColor::BLACK, 0, textAlign, fontWidth);
855 }
856 // draw scheme name
857 std::string name = scheme.getName();
859 name = "edgeData (" + key + ")";
861 name = "edgeParam (" + key + ")";
863 name = "laneParam (" + key + ")";
865 name = "param (" + key + ")";
867 name = "attribute (" + key + ")";
868 } else if (StringUtils::startsWith(name, "by ")) {
869 name = name.substr(3);
870 }
871 const double topN = -0.8;
872 const double bgShift = 0.0;
874 glTranslated(0, 0, 0.1);
875 glBegin(GL_QUADS);
876 glVertex2d(textX + textDir * 0.04, topN + fontHeight * bgShift - 0.01);
877 glVertex2d(textX + textDir * 0.04 - textDir * fontWidth * (double)name.size() / 2.3, topN + fontHeight * bgShift - 0.01);
878 glVertex2d(textX + textDir * 0.04 - textDir * fontWidth * (double)name.size() / 2.3, topN + fontHeight * (0.8 + bgShift));
879 glVertex2d(textX + textDir * 0.04, topN + fontHeight * (0.8 + bgShift));
880 glEnd();
881 glTranslated(0, 0, -0.1);
882 GLHelper::drawText(name, Position(textX + textDir * 0.04, topN), 0, fontHeight, RGBColor::BLACK, 0, textAlign, fontWidth);
883
885 // restore matrices
886 glMatrixMode(GL_PROJECTION);
888 glMatrixMode(GL_MODELVIEW);
890}
891
892
893double
895 return 1000.0 / MAX2((long)1, myFrameDrawTime);
896}
897
898
903
904
905void
907 glMatrixMode(GL_PROJECTION);
909 glLoadIdentity();
910 glMatrixMode(GL_MODELVIEW);
912 glLoadIdentity();
913 const double fontHeight = 0.2 * 300. / getHeight();
914 const double fontWidth = 0.2 * 300. / getWidth();
915 GLHelper::drawText(toString((int)getFPS()) + " FPS", Position(0.82, 0.88), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
916#ifdef CHECK_ELEMENTCOUNTER
917 GLHelper::drawText(toString(GLHelper::getMatrixCounter()) + " matrix", Position(0.82, 0.79), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
918 GLHelper::drawText(toString(GLHelper::getVertexCounter()) + " vertex", Position(0.82, 0.71), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
919#endif
920 // restore matrices
921 glMatrixMode(GL_PROJECTION);
923 glMatrixMode(GL_MODELVIEW);
925}
926
927
928double
929GUISUMOAbstractView::m2p(double meter) const {
930 return meter * getWidth() / myChanger->getViewport().getWidth();
931}
932
933
934double
935GUISUMOAbstractView::p2m(double pixel) const {
936 return pixel * myChanger->getViewport().getWidth() / getWidth();
937}
938
939
940void
944
945
946void
947GUISUMOAbstractView::centerTo(GUIGlID id, bool applyZoom, double zoomDist) {
948 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id);
949 if (o != nullptr && dynamic_cast<GUIGlObject*>(o) != nullptr) {
950 const Boundary& b = o->getCenteringBoundary();
951 if (b.getCenter() != Position::INVALID) {
952 if (applyZoom && zoomDist < 0) {
953 myChanger->setViewport(b);
954 update(); // only update when centering onto an object once
955 } else {
956 // called during tracking. update is triggered somewhere else
957 myChanger->centerTo(b.getCenter(), zoomDist, applyZoom);
959 }
960 }
961 }
962 GUIGlObjectStorage::gIDStorage.unblockObject(id);
963}
964
965
966void
967GUISUMOAbstractView::centerTo(const Position& pos, bool applyZoom, double zoomDist) {
968 // called during tracking. update is triggered somewhere else
969 myChanger->centerTo(pos, zoomDist, applyZoom);
971}
972
973
974void
976 myChanger->setViewport(bound);
977 update();
978}
979
980
983 return myApp;
984}
985
986
991
992
993void
998
999
1000FXbool
1002 FXbool ret = FXGLCanvas::makeCurrent();
1003 return ret;
1004}
1005
1006
1007long
1008GUISUMOAbstractView::onConfigure(FXObject*, FXSelector, void*) {
1009 if (makeCurrent()) {
1010 glViewport(0, 0, getWidth() - 1, getHeight() - 1);
1011 glClearColor(
1012 myVisualizationSettings->backgroundColor.red() / 255.f,
1013 myVisualizationSettings->backgroundColor.green() / 255.f,
1014 myVisualizationSettings->backgroundColor.blue() / 255.f,
1015 myVisualizationSettings->backgroundColor.alpha() / 255.f);
1016 doInit();
1017 myAmInitialised = true;
1018 makeNonCurrent();
1020 }
1021 return 1;
1022}
1023
1024
1025long
1026GUISUMOAbstractView::onPaint(FXObject*, FXSelector, void*) {
1027 if (!isEnabled() || !myAmInitialised) {
1028 return 1;
1029 }
1030 if (makeCurrent()) {
1031 paintGL();
1032 makeNonCurrent();
1033 }
1034 // run tests
1035 myApp->handle(this, FXSEL(SEL_COMMAND, MID_RUNTESTS), nullptr);
1036 return 1;
1037}
1038
1039
1042 return myPopup;
1043}
1044
1045
1046const Position&
1050
1051
1052void
1054 if (myPopup != nullptr) {
1055 myPopup->removePopupFromObject();
1056 delete myPopup;
1057 myPopupPosition.set(0, 0);
1058 myPopup = nullptr;
1059 myCurrentObjectsDialog.clear();
1060 }
1061}
1062
1063
1064void
1066 // use the same position of old popUp
1067 popUp->move(myPopup->getX(), myPopup->getY());
1068 // delete and replace popup
1069 myPopup->removePopupFromObject();
1070 delete myPopup;
1071 myPopup = popUp;
1072 // create and show popUp
1073 myPopup->create();
1074 myPopup->show();
1075 myChanger->onRightBtnRelease(nullptr);
1076 setFocus();
1077}
1078
1079
1080long
1081GUISUMOAbstractView::onLeftBtnPress(FXObject*, FXSelector, void* ptr) {
1082 destroyPopup();
1083 setFocus();
1084 FXEvent* e = (FXEvent*) ptr;
1085 // check whether the selection-mode is activated
1086 if ((e->state & CONTROLMASK) != 0) {
1087 // toggle selection of object under cursor
1088 if (makeCurrent()) {
1089 int id = getObjectUnderCursor();
1090 if (id != 0) {
1091 gSelected.toggleSelection(id);
1092 }
1093 makeNonCurrent();
1094 if (id != 0) {
1095 // possibly, the selection-coloring is used,
1096 // so we should update the screen again...
1097 update();
1098 }
1099 }
1100 }
1101 if ((e->state & SHIFTMASK) != 0) {
1102 // track vehicle or person under cursor
1103 if (makeCurrent()) {
1104 int id = getObjectUnderCursor();
1105 if (id != 0) {
1106 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id);
1107 if (o != nullptr) {
1108 if (!myApp->isGaming() && (o->getType() == GLO_VEHICLE || o->getType() == GLO_PERSON)) {
1109 startTrack(id);
1110 }
1111 }
1112 }
1113 makeNonCurrent();
1114 }
1115 }
1116 myChanger->onLeftBtnPress(ptr);
1117 grab();
1118 // Check there are double click
1119 if (e->click_count == 2) {
1120 handle(this, FXSEL(SEL_DOUBLECLICKED, 0), ptr);
1121 }
1122 return 1;
1123}
1124
1125
1126long
1127GUISUMOAbstractView::onLeftBtnRelease(FXObject*, FXSelector, void* ptr) {
1128 destroyPopup();
1129 myChanger->onLeftBtnRelease(ptr);
1130 if (myApp->isGaming()) {
1132 }
1133 ungrab();
1134 return 1;
1135}
1136
1137
1138long
1139GUISUMOAbstractView::onMiddleBtnPress(FXObject*, FXSelector, void* ptr) {
1140 destroyPopup();
1141 setFocus();
1142 if (!myApp->isGaming()) {
1143 myChanger->onMiddleBtnPress(ptr);
1144 }
1145 grab();
1146 // enable panning
1147 myPanning = true;
1148 // set cursors
1151 return 1;
1152}
1153
1154
1155long
1156GUISUMOAbstractView::onMiddleBtnRelease(FXObject*, FXSelector, void* ptr) {
1157 destroyPopup();
1158 if (!myApp->isGaming()) {
1159 myChanger->onMiddleBtnRelease(ptr);
1160 }
1161 ungrab();
1162 // disable panning
1163 myPanning = false;
1164 // restore cursors
1167 return 1;
1168}
1169
1170
1171long
1172GUISUMOAbstractView::onRightBtnPress(FXObject*, FXSelector, void* ptr) {
1173 destroyPopup();
1174 if (!myApp->isGaming()) {
1175 myChanger->onRightBtnPress(ptr);
1176 }
1177 grab();
1178 return 1;
1179}
1180
1181
1182long
1183GUISUMOAbstractView::onRightBtnRelease(FXObject* o, FXSelector sel, void* ptr) {
1184 destroyPopup();
1185 onMouseMove(o, sel, ptr);
1186 if (!myChanger->onRightBtnRelease(ptr) && !myApp->isGaming()) {
1187 openObjectDialogAtCursor((FXEvent*)ptr);
1188 }
1189 if (myApp->isGaming()) {
1191 }
1192 ungrab();
1193 return 1;
1194}
1195
1196
1197long
1198GUISUMOAbstractView::onDoubleClicked(FXObject*, FXSelector, void*) {
1199 return 1;
1200}
1201
1202
1203long
1204GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector, void* ptr) {
1205 if (!myApp->isGaming()) {
1206 myChanger->onMouseWheel(ptr);
1207 // upddate viewport
1208 if (myGUIDialogEditViewport != nullptr) {
1209 myGUIDialogEditViewport->setValues(myChanger->getZoom(),
1210 myChanger->getXPos(), myChanger->getYPos(),
1211 myChanger->getRotation());
1212 }
1214 }
1215 return 1;
1216}
1217
1218
1219long
1220GUISUMOAbstractView::onMouseMove(FXObject*, FXSelector, void* ptr) {
1221 // check if popup exist
1222 if (myPopup) {
1223 // check if handle front element
1226 myPopup->handle(this, FXSEL(SEL_COMMAND, MID_CURSORDIALOG_FRONT), nullptr);
1227 destroyPopup();
1228 } else if (!myPopup->shown()) {
1229 destroyPopup();
1230 }
1231 }
1232 if (myPopup == nullptr) {
1233 if (myGUIDialogEditViewport == nullptr || !myGUIDialogEditViewport->haveGrabbed()) {
1234 myChanger->onMouseMove(ptr);
1235 }
1236 if (myGUIDialogEditViewport != nullptr) {
1237 myGUIDialogEditViewport->setValues(myChanger->getZoom(),
1238 myChanger->getXPos(), myChanger->getYPos(),
1239 myChanger->getRotation());
1240 }
1242 }
1243 return 1;
1244}
1245
1246
1247long
1248GUISUMOAbstractView::onMouseLeft(FXObject*, FXSelector, void* /*data*/) {
1249 return 1;
1250}
1251
1252std::vector<GUIGlObject*>
1253GUISUMOAbstractView::filterContextObjects(const std::vector<GUIGlObject*>& objects) {
1254 // assume input is sorted with ComparatorClickPriority
1255 std::vector<GUIGlObject*> result;
1256 for (GUIGlObject* o : objects) {
1257 if (o->getClickPriority() != GUIGlObject::INVALID_PRIORITY && (result.empty() || result.back() != o)) {
1258 result.push_back(o);
1259 }
1260 }
1261 return result;
1262}
1263
1264
1265void
1267 // release the mouse grab
1268 ungrab();
1269 // check if alt key is pressed
1270 const bool altKeyPressed = ((ev->state & ALTMASK) != 0);
1271 // check if SUMO is enabled, initialised and Make OpenGL context current
1272 if (isEnabled() && myAmInitialised && makeCurrent()) {
1273 auto objectsUnderCursor = getGUIGlObjectsUnderCursor();
1274 if (objectsUnderCursor.empty()) {
1275 myPopup = GUIGlObjectStorage::gIDStorage.getNetObject()->getPopUpMenu(*myApp, *this);
1276 } else {
1277 std::sort(objectsUnderCursor.begin(), objectsUnderCursor.end(), ComparatorClickPriority());
1278 std::vector<GUIGlObject*> filtered = filterContextObjects(objectsUnderCursor);
1279 if (filtered.size() > 1 && (altKeyPressed
1280 || filtered[0]->getClickPriority() == filtered[1]->getClickPriority())) {
1281 // open dialog for picking among objects (without duplicates)
1283 } else {
1284 myPopup = objectsUnderCursor.front()->getPopUpMenu(*myApp, *this);
1285 }
1286 }
1288 makeNonCurrent();
1289 }
1290}
1291
1292
1293void
1294GUISUMOAbstractView::openObjectDialog(const std::vector<GUIGlObject*>& objects, const bool filter) {
1295 if (objects.size() > 0) {
1296 // create cursor popup dialog
1297 if (objects.size() == 1) {
1298 myCurrentObjectsDialog = objects;
1299 } else if (filter) {
1300 // declare filtered objects
1301 std::vector<GUIGlObject*> filteredGLObjects;
1302 // fill filtered objects
1303 for (const auto& glObject : objects) {
1304 // compare type with first element type
1305 if (glObject->getType() == objects.front()->getType()) {
1306 filteredGLObjects.push_back(glObject);
1307 }
1308 }
1309 myCurrentObjectsDialog = filteredGLObjects;
1310 } else {
1311 myCurrentObjectsDialog = objects;
1312 }
1313 if (myCurrentObjectsDialog.size() > 1) {
1315 } else {
1316 myPopup = myCurrentObjectsDialog.front()->getPopUpMenu(*myApp, *this);
1317 }
1318 // open popup dialog
1320 }
1321}
1322
1323
1324long
1325GUISUMOAbstractView::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
1326 const FXEvent* e = (FXEvent*) ptr;
1327 // check if process canvas or popup
1328 if (myPopup != nullptr) {
1329 return myPopup->onKeyPress(o, sel, ptr);
1330 } else {
1331 if (e->state & CONTROLMASK) {
1332 if (e->code == FX::KEY_Page_Up) {
1333 myVisualizationSettings->gridXSize *= 2;
1334 myVisualizationSettings->gridYSize *= 2;
1335 update();
1336 return 1;
1337 } else if (e->code == FX::KEY_Page_Down) {
1338 myVisualizationSettings->gridXSize /= 2;
1339 myVisualizationSettings->gridYSize /= 2;
1340 update();
1341 return 1;
1342 }
1343 }
1344 FXGLCanvas::onKeyPress(o, sel, ptr);
1345 return myChanger->onKeyPress(ptr);
1346 }
1347}
1348
1349
1350long
1351GUISUMOAbstractView::onKeyRelease(FXObject* o, FXSelector sel, void* ptr) {
1352 // check if process canvas or popup
1353 if (myPopup != nullptr) {
1354 return myPopup->onKeyRelease(o, sel, ptr);
1355 } else {
1356 FXGLCanvas::onKeyRelease(o, sel, ptr);
1357 return myChanger->onKeyRelease(ptr);
1358 }
1359}
1360
1361// ------------ Dealing with snapshots
1362
1363void
1364GUISUMOAbstractView::addSnapshot(SUMOTime time, const std::string& file, const int w, const int h) {
1365#ifdef DEBUG_SNAPSHOT
1366 std::cout << "add snapshot time=" << time << " file=" << file << "\n";
1367#endif
1368 FXMutexLock lock(mySnapshotsMutex);
1369 mySnapshots[time].push_back(std::make_tuple(file, w, h));
1370}
1371
1372
1373std::string
1374GUISUMOAbstractView::makeSnapshot(const std::string& destFile, const int w, const int h) {
1375 if (w >= 0) {
1376 resize(w, h);
1377 repaint();
1378 }
1379 std::string errorMessage;
1380 FXString ext = FXPath::extension(destFile.c_str());
1381 const bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf";
1382#ifdef HAVE_FFMPEG
1383 const bool useVideo = destFile == "" || ext == "h264" || ext == "hevc" || ext == "mp4";
1384#endif
1385 for (int i = 0; i < 10 && !makeCurrent(); ++i) {
1387 }
1388 // draw
1389 glClearColor(
1390 myVisualizationSettings->backgroundColor.red() / 255.f,
1391 myVisualizationSettings->backgroundColor.green() / 255.f,
1392 myVisualizationSettings->backgroundColor.blue() / 255.f,
1393 myVisualizationSettings->backgroundColor.alpha() / 255.f);
1394 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
1395 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1396
1397 if (myVisualizationSettings->dither) {
1398 glEnable(GL_DITHER);
1399 } else {
1400 glDisable(GL_DITHER);
1401 }
1402 glEnable(GL_BLEND);
1403 glDisable(GL_LINE_SMOOTH);
1404
1406
1407 if (useGL2PS) {
1408#ifdef HAVE_GL2PS
1409 GLint format = GL2PS_PS;
1410 if (ext == "ps") {
1411 format = GL2PS_PS;
1412 } else if (ext == "eps") {
1413 format = GL2PS_EPS;
1414 } else if (ext == "pdf") {
1415 format = GL2PS_PDF;
1416 } else if (ext == "tex") {
1417 format = GL2PS_TEX;
1418 } else if (ext == "svg") {
1419 format = GL2PS_SVG;
1420 } else if (ext == "pgf") {
1421 format = GL2PS_PGF;
1422 } else {
1423 return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'.";
1424 }
1425 FILE* fp = fopen(destFile.c_str(), "wb");
1426 if (fp == 0) {
1427 return "Could not save '" + destFile + "'.\n Could not open file for writing";
1428 }
1430 GLint buffsize = 0, state = GL2PS_OVERFLOW;
1431 GLint viewport[4];
1432 glGetIntegerv(GL_VIEWPORT, viewport);
1433 while (state == GL2PS_OVERFLOW) {
1434 buffsize += 1024 * 1024;
1435 gl2psBeginPage(destFile.c_str(), "sumo-gui; https://sumo.dlr.de", viewport, format, GL2PS_SIMPLE_SORT,
1436 GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT,
1437 GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps");
1438 glMatrixMode(GL_MODELVIEW);
1440 glDisable(GL_TEXTURE_2D);
1441 glDisable(GL_ALPHA_TEST);
1442 glDisable(GL_BLEND);
1443 glEnable(GL_DEPTH_TEST);
1444 // draw decals (if not in grabbing mode)
1445
1446 drawDecals();
1447 if (myVisualizationSettings->showGrid) {
1448 paintGLGrid();
1449 }
1450
1451 glLineWidth(1);
1452 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1453 Boundary viewPort = myChanger->getViewport();
1454 const float minB[2] = { (float)viewPort.xmin(), (float)viewPort.ymin() };
1455 const float maxB[2] = { (float)viewPort.xmax(), (float)viewPort.ymax() };
1457 glEnable(GL_POLYGON_OFFSET_FILL);
1458 glEnable(GL_POLYGON_OFFSET_LINE);
1459 myGrid->Search(minB, maxB, *myVisualizationSettings);
1460
1462 state = gl2psEndPage();
1463 glFinish();
1464 }
1465 GLHelper::setGL2PS(false);
1466 fclose(fp);
1467#else
1468 return "Could not save '" + destFile + "', gl2ps was not enabled at compile time.";
1469#endif
1470 } else {
1471 doPaintGL(GL_RENDER, myChanger->getViewport());
1473 swapBuffers();
1474 glFinish();
1475 FXColor* buf;
1476 FXMALLOC(&buf, FXColor, getWidth()*getHeight());
1477 // read from the back buffer
1478 glReadBuffer(GL_BACK);
1479 // Read the pixels
1480 glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf);
1481 makeNonCurrent();
1482 update();
1483 // mirror
1484 int mwidth = getWidth();
1485 int mheight = getHeight();
1486 FXColor* paa = buf;
1487 FXColor* pbb = buf + mwidth * (mheight - 1);
1488 do {
1489 FXColor* pa = paa;
1490 paa += mwidth;
1491 FXColor* pb = pbb;
1492 pbb -= mwidth;
1493 do {
1494 FXColor t = *pa;
1495 *pa++ = *pb;
1496 *pb++ = t;
1497 } while (pa < paa);
1498 } while (paa < pbb);
1499 try {
1500#ifdef HAVE_FFMPEG
1501 if (useVideo) {
1502 try {
1503 saveFrame(destFile, buf);
1504 errorMessage = "video";
1505 } catch (std::runtime_error& err) {
1506 errorMessage = err.what();
1507 }
1508 } else
1509#endif
1510 if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) {
1511 errorMessage = "Could not save '" + destFile + "'.";
1512 }
1513 } catch (InvalidArgument& e) {
1514 errorMessage = "Could not save '" + destFile + "'.\n" + e.what();
1515 }
1516 FXFREE(&buf);
1517 }
1518 return errorMessage;
1519}
1520
1521
1522void
1523GUISUMOAbstractView::saveFrame(const std::string& destFile, FXColor* buf) {
1524 UNUSED_PARAMETER(destFile);
1525 UNUSED_PARAMETER(buf);
1526}
1527
1528
1529void
1531 const SUMOTime time = getCurrentTimeStep() - DELTA_T;
1532#ifdef DEBUG_SNAPSHOT
1533 std::cout << "check snapshots time=" << time << " registeredTimes=" << mySnapshots.size() << "\n";
1534#endif
1535 FXMutexLock lock(mySnapshotsMutex);
1536 const auto snapIt = mySnapshots.find(time);
1537 if (snapIt == mySnapshots.end()) {
1538 return;
1539 }
1540 std::vector<std::tuple<std::string, int, int> > files = snapIt->second;
1541 lock.unlock();
1542 // decouple map access and painting to avoid deadlock
1543 for (const auto& entry : files) {
1544#ifdef DEBUG_SNAPSHOT
1545 std::cout << "make snapshot time=" << time << " file=" << file << "\n";
1546#endif
1547 const std::string& error = makeSnapshot(std::get<0>(entry), std::get<1>(entry), std::get<2>(entry));
1548 if (error != "" && error != "video") {
1549 WRITE_WARNING(error);
1550 }
1551 }
1552 // synchronization with a waiting run thread
1553 lock.lock();
1554 mySnapshots.erase(time);
1555 mySnapshotCondition.signal();
1556#ifdef DEBUG_SNAPSHOT
1557 std::cout << " files=" << toString(files) << " myApplicationSnapshots=" << joinToString(*myApplicationSnapshots, ",") << "\n";
1558#endif
1559}
1560
1561
1562void
1564 FXMutexLock lock(mySnapshotsMutex);
1565 if (mySnapshots.count(snapshotTime) > 0) {
1567 }
1568}
1569
1570
1573 return 0;
1574}
1575
1576
1577void
1588
1589
1592 if (myGUIDialogEditViewport == nullptr) {
1593 myGUIDialogEditViewport = new GUIDialog_EditViewport(this, TLC("Labels", "Edit Viewport"));
1594 myGUIDialogEditViewport->create();
1595 }
1598}
1599
1600
1602 myGUIDialogEditViewport->setValues(myChanger->getZoom(),
1603 myChanger->getXPos(), myChanger->getYPos(),
1604 myChanger->getRotation());
1605}
1606
1607
1608void
1610 getViewportEditor(); // make sure it exists;
1611 Position p(myChanger->getXPos(), myChanger->getYPos(), myChanger->getZPos());
1612 myGUIDialogEditViewport->setOldValues(p, Position::INVALID, myChanger->getRotation());
1614}
1615
1616
1617void
1618GUISUMOAbstractView::setViewportFromToRot(const Position& lookFrom, const Position& /* lookAt */, double rotation) {
1619 myChanger->setViewportFrom(lookFrom.x(), lookFrom.y(), lookFrom.z());
1620 myChanger->setRotation(rotation);
1621 update();
1622}
1623
1624
1625void
1627 // look straight down
1628 view->setViewportFromToRot(Position(myChanger->getXPos(), myChanger->getYPos(), myChanger->getZPos()),
1629 Position(myChanger->getXPos(), myChanger->getYPos(), 0),
1630 myChanger->getRotation());
1631}
1632
1633
1634bool
1636 return true;
1637}
1638
1639
1644
1645
1650
1651
1652void
1656
1657
1658void
1662
1663
1664double
1666 return myGrid->getWidth();
1667}
1668
1669
1670double
1672 return myGrid->getHeight();
1673}
1674
1675
1676void
1679
1680
1681void
1684
1685
1686GUIGlID
1690
1691
1692void
1695
1696void
1699
1700
1701std::vector<GUISUMOAbstractView::Decal>&
1705
1706
1707FXMutex&
1711
1712
1715 return myGlChildWindowParent->getColoringSchemesCombo();
1716}
1717
1718
1719FXImage*
1721#ifdef HAVE_GDAL
1722 GDALAllRegister();
1723 GDALDataset* poDataset = (GDALDataset*)GDALOpen(d.filename.c_str(), GA_ReadOnly);
1724 if (poDataset == 0) {
1725 return 0;
1726 }
1727 const int xSize = poDataset->GetRasterXSize();
1728 const int ySize = poDataset->GetRasterYSize();
1729 // checking for geodata in the picture and try to adapt position and scale
1730 if (d.width <= 0.) {
1731 double adfGeoTransform[6];
1732 if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
1733 Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
1734 const double horizontalSize = xSize * adfGeoTransform[1];
1735 const double verticalSize = ySize * adfGeoTransform[5];
1736 Position bottomRight(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
1737 if (GeoConvHelper::getFinal().x2cartesian_const(topLeft) && GeoConvHelper::getFinal().x2cartesian_const(bottomRight)) {
1738 //WRITE_MESSAGE("proj: " + toString(poDataset->GetProjectionRef()) + " dim: " + toString(d.width) + "," + toString(d.height) + " center: " + toString(d.centerX) + "," + toString(d.centerY));
1739 } else {
1740 WRITE_WARNINGF(TL("Could not transform coordinates from WGS84 in decal %, assuming UTM."), d.filename);
1741 topLeft = topLeft + GeoConvHelper::getFinal().getOffset();
1742 bottomRight = bottomRight + GeoConvHelper::getFinal().getOffset();
1743 }
1744 d.width = bottomRight.x() - topLeft.x();
1745 d.height = topLeft.y() - bottomRight.y();
1746 d.centerX = (topLeft.x() + bottomRight.x()) / 2;
1747 d.centerY = (topLeft.y() + bottomRight.y()) / 2;
1748 }
1749 }
1750#endif
1751 if (d.width <= 0.) {
1752 d.width = getGridWidth();
1753 d.height = getGridHeight();
1754 }
1755
1756 // trying to read the picture
1757#ifdef HAVE_GDAL
1758 const int picSize = xSize * ySize;
1759 FXColor* result;
1760 if (!FXMALLOC(&result, FXColor, picSize)) {
1761 WRITE_WARNINGF("Could not allocate memory for %.", d.filename);
1762 return 0;
1763 }
1764 for (int j = 0; j < picSize; j++) {
1765 result[j] = GUIDesignTextColorBlack;
1766 }
1767 bool valid = true;
1768 for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
1769 GDALRasterBand* poBand = poDataset->GetRasterBand(i);
1770 int shift = -1;
1771 if (poBand->GetColorInterpretation() == GCI_RedBand) {
1772 shift = 0;
1773 } else if (poBand->GetColorInterpretation() == GCI_GreenBand) {
1774 shift = 1;
1775 } else if (poBand->GetColorInterpretation() == GCI_BlueBand) {
1776 shift = 2;
1777 } else if (poBand->GetColorInterpretation() == GCI_AlphaBand) {
1778 shift = 3;
1779 } else {
1780 valid = false;
1781 break;
1782 }
1783 assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
1784 if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, ((unsigned char*)result) + shift, xSize, ySize, GDT_Byte, 4, 4 * xSize) == CE_Failure) {
1785 valid = false;
1786 break;
1787 }
1788 }
1789 GDALClose(poDataset);
1790 if (valid) {
1791 return new FXImage(getApp(), result, IMAGE_OWNED | IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP, xSize, ySize);
1792 }
1793 FXFREE(&result);
1794#endif
1795 return nullptr;
1796}
1797
1798
1799void
1802 myDecalsLockMutex.lock();
1803 for (auto& decal : myDecals) {
1804 if (decal.skip2D || decal.filename.empty()) {
1805 continue;
1806 }
1807 if (!decal.initialised) {
1808 try {
1809 FXImage* img = checkGDALImage(decal);
1810 if (img == nullptr) {
1811 img = MFXImageHelper::loadImage(getApp(), decal.filename);
1812 }
1814 decal.glID = GUITexturesHelper::add(img);
1815 decal.initialised = true;
1816 decal.image = img;
1817 } catch (InvalidArgument& e) {
1818 WRITE_ERROR("Could not load '" + decal.filename + "'.\n" + e.what());
1819 decal.skip2D = true;
1820 }
1821 }
1823 if (decal.screenRelative) {
1824 Position center = screenPos2NetPos((int)decal.centerX, (int)decal.centerY);
1825 glTranslated(center.x(), center.y(), decal.layer);
1826 } else {
1827 glTranslated(decal.centerX, decal.centerY, decal.layer);
1828 }
1829 glRotated(decal.rot, 0, 0, 1);
1830 glColor3d(1, 1, 1);
1831 double halfWidth = decal.width / 2.;
1832 double halfHeight = decal.height / 2.;
1833 if (decal.screenRelative) {
1834 halfWidth = p2m(halfWidth);
1835 halfHeight = p2m(halfHeight);
1836 }
1837 GUITexturesHelper::drawTexturedBox(decal.glID, -halfWidth, -halfHeight, halfWidth, halfHeight);
1839 }
1840 myDecalsLockMutex.unlock();
1842}
1843
1844
1845void
1847 int x, y;
1848 FXuint b;
1849 myApp->getCursorPosition(x, y, b);
1850 int appX = myApp->getX();
1851 int popX = x + appX;
1852 int popY = y + myApp->getY();
1853 myPopup->setX(popX);
1854 myPopup->setY(popY);
1855 myPopup->create();
1856 myPopup->show();
1857 // TODO: try to stay on screen even on a right secondary screen in multi-monitor setup
1858 const int rootWidth = getApp()->getRootWindow()->getWidth();
1859 const int rootHeight = getApp()->getRootWindow()->getHeight();
1860 if (popX <= rootWidth) {
1861 const int maxX = (appX < 0) ? 0 : rootWidth;
1862 popX = MIN2(popX, maxX - myPopup->getWidth() - 10);
1863 }
1864 popY = MIN2(popY, rootHeight - myPopup->getHeight() - 50);
1865 myPopup->move(popX, popY);
1867 myChanger->onRightBtnRelease(nullptr);
1868 setFocus();
1869}
1870
1871// ------------ Additional visualisations
1872
1873bool
1875 if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1876 myAdditionallyDrawn[which] = 1;
1877 } else {
1878 myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1;
1879 }
1880 update();
1881 return true;
1882}
1883
1884
1885bool
1887 if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1888 return false;
1889 }
1890 int cnt = myAdditionallyDrawn[which];
1891 if (cnt == 1) {
1892 myAdditionallyDrawn.erase(which);
1893 } else {
1894 myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1;
1895 }
1896 update();
1897 return true;
1898}
1899
1900
1901bool
1903 if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1904 return false;
1905 } else {
1906 return true;
1907 }
1908}
1909
1910
1913 Boundary bound = myChanger->getViewport(fixRatio);
1914 glMatrixMode(GL_PROJECTION);
1915 glLoadIdentity();
1916 // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType
1917 // thus, objects with a higher value will be closer (drawn on top)
1918 // // @todo last param should be 0 after modifying all glDraw methods
1919 glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1);
1920 glMatrixMode(GL_MODELVIEW);
1921 glLoadIdentity();
1922 double scaleX = (double)getWidth() / bound.getWidth();
1923 double scaleY = (double)getHeight() / bound.getHeight();
1924 glScaled(scaleX, scaleY, 1);
1925 glTranslated(-bound.xmin(), -bound.ymin(), 0);
1926 // rotate around the center of the screen
1927 //double angle = -90;
1928 if (myChanger->getRotation() != 0) {
1929 glTranslated(bound.getCenter().x(), bound.getCenter().y(), 0);
1930 glRotated(myChanger->getRotation(), 0, 0, 1);
1931 glTranslated(-bound.getCenter().x(), -bound.getCenter().y(), 0);
1932 Boundary rotBound;
1933 double rad = -DEG2RAD(myChanger->getRotation());
1934 rotBound.add(Position(bound.xmin(), bound.ymin()).rotateAround2D(rad, bound.getCenter()));
1935 rotBound.add(Position(bound.xmin(), bound.ymax()).rotateAround2D(rad, bound.getCenter()));
1936 rotBound.add(Position(bound.xmax(), bound.ymin()).rotateAround2D(rad, bound.getCenter()));
1937 rotBound.add(Position(bound.xmax(), bound.ymax()).rotateAround2D(rad, bound.getCenter()));
1938 bound = rotBound;
1939 }
1940 myVisualizationSettings->angle = myChanger->getRotation();
1941 return bound;
1942}
1943
1944
1945double
1947 return myApp->getDelay();
1948}
1949
1950
1951void
1953 myApp->setDelay(delay);
1954}
1955
1956
1957void
1958GUISUMOAbstractView::setBreakpoints(const std::vector<SUMOTime>& breakpoints) {
1959 myApp->setBreakpoints(breakpoints);
1960}
1961
1962
1963void
1965 const GUIVisualizationRainbowSettings& rs, double minValue, double maxValue, bool hasMissingData) {
1966 if (rs.hideMin && rs.hideMax && minValue == std::numeric_limits<double>::infinity()) {
1967 minValue = rs.minThreshold;
1968 maxValue = rs.maxThreshold;
1969 }
1970 if (rs.fixRange) {
1971 if (rs.hideMin) {
1972 minValue = rs.minThreshold;
1973 }
1974 if (rs.hideMax) {
1975 maxValue = rs.maxThreshold;
1976 }
1977 }
1978 if (minValue != std::numeric_limits<double>::infinity()) {
1979 scheme.clear();
1980 // add new thresholds
1986 || hasMissingData) {
1987 scheme.addColor(s.COL_MISSING_DATA, s.MISSING_DATA, "missing data");
1988 }
1989 if (rs.hideMin && !rs.fixRange) {
1990 const double rawRange = maxValue - minValue;
1991 minValue = MAX2(rs.minThreshold + MIN2(1.0, rawRange / 100.0), minValue);
1992 scheme.addColor(RGBColor(204, 204, 204), rs.minThreshold);
1993 }
1994 if (rs.hideMax && !rs.fixRange) {
1995 const double rawRange = maxValue - minValue;
1996 maxValue = MIN2(rs.maxThreshold - MIN2(1.0, rawRange / 100.0), maxValue);
1997 scheme.addColor(RGBColor(204, 204, 204), rs.maxThreshold);
1998 }
1999 const double range = maxValue - minValue;
2000 scheme.addColor(rs.colors.front(), minValue);
2001 const int steps = (int)rs.colors.size() - 1;
2002 if (rs.setNeutral) {
2003 const int steps1 = steps / 2;
2004 const int steps2 = steps - steps1;
2005 const double range1 = rs.neutralThreshold - minValue;
2006 const double range2 = maxValue - rs.neutralThreshold;
2007 for (int i = 1; i < steps1; i++) {
2008 scheme.addColor(rs.colors[i], (minValue + range1 * i / steps1));
2009 }
2010 scheme.addColor(rs.colors[steps1], rs.neutralThreshold);
2011 for (int i = 1; i < steps2; i++) {
2012 scheme.addColor(rs.colors[steps1 + i], (rs.neutralThreshold + range2 * i / steps2));
2013 }
2014 } else {
2015 for (int i = 1; i < steps; i++) {
2016 scheme.addColor(rs.colors[i], (minValue + range * i / steps));
2017 }
2018 }
2019 scheme.addColor(rs.colors.back(), maxValue);
2020 }
2021}
2022
2023
2025 myGLObject(object) {
2026 first = layer;
2027 second.first = object->getType();
2028 second.second = object->getMicrosimID();
2029}
2030
2031
2033 myGLObject(object) {
2034 first = object->getType();
2035 second.first = object->getType();
2036 second.second = object->getMicrosimID();
2037}
2038
2039
2044
2045/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
@ MID_GLCANVAS
GLCanvas - ID.
Definition GUIAppEnum.h:413
@ MID_REACHABILITY
show reachability from a given lane
Definition GUIAppEnum.h:533
@ MID_CLOSE_LANE
close lane
Definition GUIAppEnum.h:669
@ MID_CURSORDIALOG_FRONT
remove/select/mark front element
Definition GUIAppEnum.h:444
@ MID_CLOSE_EDGE
close edge
Definition GUIAppEnum.h:671
@ MID_RUNTESTS
run tests
@ MID_SIMPLE_VIEW_COLORCHANGE
Informs the dialog about a value's change.
Definition GUIAppEnum.h:629
@ MID_ADD_REROUTER
add rerouter
Definition GUIAppEnum.h:673
GUICompleteSchemeStorage gSchemeStorage
@ MOVEVIEW
move view cursor
Definition GUICursors.h:36
@ DEFAULT
default cursor
Definition GUICursors.h:33
#define GUIDesignTextColorBlack
black color (for correct text)
Definition GUIDesigns.h:38
unsigned int GUIGlID
Definition GUIGlObject.h:44
GUIGlObjectType
@ GLO_MAX
empty max
@ GLO_LANE
a lane
@ GLO_VEHICLE
a vehicle
@ GLO_PERSON
a person
@ GLO_NETWORK
The network - empty.
GUISelectedStorage gSelected
A global holder of selected objects.
GUIPropertyScheme< RGBColor > GUIColorScheme
FXDEFMAP(GUISUMOAbstractView) GUISUMOAbstractViewMap[]
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
int gPrecisionGeo
Definition StdDefs.cpp:29
const double SUMO_const_laneWidth
Definition StdDefs.h:52
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition ToString.h:289
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
#define TLC(context, string)
Definition Translation.h:47
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
Position getCenter() const
Returns the center of the boundary.
Definition Boundary.cpp:109
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:75
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:127
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:115
Boundary & grow(double by)
extends the boundary by the given amount
Definition Boundary.cpp:340
double getHeight() const
Returns the height of the boundary (y-axis).
Definition Boundary.cpp:157
double getWidth() const
Returns the width of the boudary (x-axis).
Definition Boundary.cpp:151
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:133
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:121
static void resetVertexCounter()
reset vertex counter
Definition GLHelper.cpp:180
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:653
static void pushName(unsigned int name)
push Name
Definition GLHelper.cpp:144
static void checkCounterMatrix()
check counter matrix (for debug purposes)
Definition GLHelper.cpp:186
static void popMatrix()
pop matrix
Definition GLHelper.cpp:135
static int getMatrixCounter()
get matrix counter
Definition GLHelper.cpp:162
static void checkCounterName()
check counter name (for debug purposes)
Definition GLHelper.cpp:197
static void popName()
pop Name
Definition GLHelper.cpp:153
static void pushMatrix()
push matrix
Definition GLHelper.cpp:122
static void setGL2PS(bool active=true)
set GL2PS
Definition GLHelper.cpp:677
static int getVertexCounter()
get vertex counter
Definition GLHelper.cpp:174
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition GLHelper.cpp:747
static void resetMatrixCounter()
reset matrix counter
Definition GLHelper.cpp:168
Dialog for edit rerouter intervals.
static FXCursor * getCursor(GUICursor which)
returns a cursor previously defined in the enum GUICursor
A dialog to change the viewport.
The dialog to change the view (gui) settings.
The popup menu of a globject.
static const double INVALID_PRIORITY
Definition GUIGlObject.h:74
static const GUIGlID INVALID_ID
Definition GUIGlObject.h:73
virtual double getClickPriority() const
Returns the priority of receiving mouse clicks.
virtual Boundary getCenteringBoundary() const =0
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
virtual Position getCenter() const
GUIGlID getGlID() const
Returns the numerical id of the object.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
Representation of a lane in the micro simulation (gui-version).
Definition GUILane.h:60
const std::vector< double > & getThresholds() const
const std::vector< std::string > & getNames() const
const std::string & getName() const
const std::vector< T > & getColors() const
int addColor(const T &color, const double threshold, const std::string &name="")
MFXComboBoxIcon * getColoringSchemesCombo()
get coloring schemes combo
bool myAmInitialised
Internal information whether doInit() was called.
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.
std::vector< GUIGlObject * > myCurrentObjectsDialog
vector with current objects dialog
std::string makeSnapshot(const std::string &destFile, const int w=-1, const int h=-1)
Takes a snapshots and writes it into the given file.
void updateToolTip()
A method that updates the tooltip.
void addDecals(const std::vector< Decal > &decals)
add decals
virtual void checkSnapshots()
Checks whether it is time for a snapshot.
void showViewschemeEditor()
show viewsscheme editor
GUISUMOAbstractView(FXComposite *p, GUIMainWindow &app, GUIGlChildWindow *parent, const SUMORTree &grid, FXGLVisual *glVis, FXGLCanvas *share)
constructor
static const double SENSITIVITY
virtual long onLeftBtnRelease(FXObject *, FXSelector, void *)
void displayLegend()
Draws a line with ticks, and the length information.
virtual long onVisualizationChange(FXObject *, FXSelector, void *)
hook to react on change in visualization settings
std::vector< GUIGlObject * > getGUIGlObjectsUnderCursor()
returns the GUIGlObject under the cursor using GL_SELECT (including overlapped objects)
long myFrameDrawTime
counter for measuring rendering time
void replacePopup(GUIGLObjectPopupMenu *popUp)
replace PopUp
std::vector< GUIGlID > getObjectsAtPosition(Position pos, double radius)
returns the ids of the object at position within the given (rectangular) radius using GL_SELECT
const SUMORTree * myGrid
The visualization speed-up.
void openObjectDialog(const std::vector< GUIGlObject * > &objects, const bool filter=true)
open object dialog for the given object
virtual void saveFrame(const std::string &destFile, FXColor *buf)
Adds a frame to a video snapshot which will be initialized if necessary.
virtual void recenterView()
recenters the view
virtual SUMOTime getCurrentTimeStep() const
get the current simulation time
void paintGLGrid() const
paints a grid
FXbool makeCurrent()
A reimplementation due to some internal reasons.
int myMouseHotspotX
Offset to the mouse-hotspot from the mouse position.
GUIMainWindow * getMainWindow() const
get main window
bool isInEditMode()
returns true, if the edit button was pressed
void buildMinMaxRainbow(const GUIVisualizationSettings &s, GUIColorScheme &scheme, const GUIVisualizationRainbowSettings &rs, double minValue, double maxValue, bool hasMissingData)
helper function for buildColorRainbow
virtual long onMiddleBtnRelease(FXObject *, FXSelector, void *)
virtual long onMouseMove(FXObject *, FXSelector, void *)
bool myPanning
Panning flag.
bool isAdditionalGLVisualisationEnabled(GUIGlObject *const which) const
Check if an object is added in the additional GL visualitation.
FXMutex myDecalsLockMutex
The mutex to use before accessing the decals list in order to avoid thread conflicts.
FXCondition mySnapshotCondition
the semaphore when waiting for snapshots to finish
virtual GUIGlID getToolTipID()
returns the id of object under cursor to show their tooltip
Position myPopupPosition
The current popup-menu position.
virtual void doInit()
doInit
std::vector< GUIGlObject * > filterContextObjects(const std::vector< GUIGlObject * > &objects)
filter out duplicate and forbidden objects
GUIGlID getObjectUnderCursor(double sensitivity=SENSITIVITY)
returns the id of the front object under the cursor using GL_SELECT
virtual long onCmdCloseEdge(FXObject *, FXSelector, void *)
virtual int doPaintGL(int, const Boundary &)
paint GL
virtual void showViewportEditor()
show viewport editor
const GUIVisualizationSettings & getVisualisationSettings() const
get visualization settings (read only)
void setDelay(double delay)
Sets the delay of the parent application.
Boundary getVisibleBoundary() const
get visible boundary
Position screenPos2NetPos(int x, int y) const
Translate screen position to network position.
void addSnapshot(SUMOTime time, const std::string &file, const int w=-1, const int h=-1)
Sets the snapshot time to file map.
GUIPerspectiveChanger & getChanger() const
get changer
virtual void centerTo(GUIGlID id, bool applyZoom, double zoomDist=20)
centers to the chosen artifact
GUIMainWindow * myApp
The application.
GUIDialog_EditViewport * getViewportEditor()
get the viewport and create it on first access
virtual void zoom2Pos(Position &camera, Position &lookAt, double zoom)
zoom interface for 3D view
GUIGlID getObjectAtPosition(Position pos, double sensitivity=SENSITIVITY)
returns the id of the object at position using GL_SELECT
std::vector< GUIGlID > getObjectsInBoundary(Boundary bound)
returns the ids of all objects in the given boundary
virtual long onCmdCloseLane(FXObject *, FXSelector, void *)
interaction with the simulation
void drawFPS()
Draws frames-per-second indicator.
virtual long onMouseWheel(FXObject *, FXSelector, void *)
double getGridWidth() const
get grid width
std::vector< Decal > & getDecals()
The list of decals to show.
bool removeAdditionalGLVisualisation(GUIGlObject *const which)
Removes an object from the list of objects that show additional things.
GUIGlChildWindow * myGlChildWindowParent
The parent window.
GUIGlChildWindow * getGUIGlChildWindow()
get GUIGlChildWindow
double getDelay() const
Returns the delay of the parent application.
virtual void updatePositionInformationLabel() const
update position information labels
std::vector< GUIGlObject * > getGUIGlObjectsAtPosition(Position pos, double radius)
returns the GUIGlObjects at position within the given (rectangular) radius using GL_SELECT
virtual long onLeftBtnPress(FXObject *, FXSelector, void *)
virtual void setViewportFromToRot(const Position &lookFrom, const Position &lookAt, double rotation)
applies the given viewport settings
double p2m(double pixel) const
pixels-to-meters conversion method
std::vector< Decal > myDecals
The list of decals to show.
const Position & getPopupPosition() const
get position of current popup
double m2p(double meter) const
meter-to-pixels conversion method
virtual GUILane * getLaneUnderCursor()
returns the GUILane at cursor position (implementation depends on view)
virtual void openObjectDialogAtCursor(const FXEvent *ev)
open object dialog at the cursor position
virtual void onGamingClick(Position)
on gaming click
bool myInEditMode
Information whether too-tip informations shall be generated.
GUIVisualizationSettings * editVisualisationSettings() const
edit visualization settings (allow modify VisualizationSetings, use carefully)
GUIVisualizationSettings * myVisualizationSettings
visualization settings
void destroyPopup()
destroys the popup
Position getWindowCursorPosition() const
return windows cursor position
virtual long onKeyPress(FXObject *o, FXSelector sel, void *data)
keyboard functions
GUIDialog_EditViewport * myGUIDialogEditViewport
viewport chooser
void displayColorLegend(const GUIColorScheme &scheme, bool leftSide, const std::string &key)
Draws a legend for the given scheme.
virtual long onMiddleBtnPress(FXObject *, FXSelector, void *)
void paintGL()
FOX needs this.
virtual void stopTrack()
stop track
virtual Position getPositionInformation() const
Returns the cursor's x/y position within the network.
std::vector< GUIGlObject * > getGUIGlObjectsUnderSnappedCursor()
returns the GUIGlObject under the gripped cursor using GL_SELECT (including overlapped objects)
bool showToolTipFor(const GUIGlID idToolTip)
invokes the tooltip for the given object
virtual long onKeyRelease(FXObject *o, FXSelector sel, void *data)
GUIDialog_ViewSettings * myGUIDialogViewSettings
Visualization changer.
virtual void onGamingRightClick(Position)
void setWindowCursorPosition(FXint x, FXint y)
Returns the gl-id of the object under the given coordinates.
double getFPS() const
retrieve FPS
virtual long onCmdShowReachability(FXObject *, FXSelector, void *)
highlight edges according to reachability
std::map< GUIGlObject *, int > myAdditionallyDrawn
List of objects for which GUIGlObject::drawGLAdditional is called.
void drawDecals()
Draws the stored decals.
std::vector< GUIGlID > getObjectsUnderCursor()
returns the id of the objects under the cursor using GL_SELECT (including overlapped objects)
Boundary applyGLTransform(bool fixRatio=true)
applies gl-transformations to fit the Boundary given by myChanger onto the canvas....
virtual void updateViewportValues()
update the viewport chooser with the current view values
FXImage * checkGDALImage(Decal &d)
check whether we can read image data or position with gdal
double getGridHeight() const
get grid height
virtual void startTrack(int)
star track
virtual long onDoubleClicked(FXObject *, FXSelector, void *)
FXMutex & getDecalsLockMutex()
The mutex to use before accessing the decals list in order to avoid thread conflicts.
virtual bool is3DView() const
return whether this is a 3D view
void displayLegends()
Draws the configured legends.
FXMutex mySnapshotsMutex
The mutex to use before accessing the decals list in order to avoid thread conflicts.
virtual long onMouseLeft(FXObject *, FXSelector, void *)
virtual long onRightBtnRelease(FXObject *, FXSelector, void *)
FXint myWindowCursorPositionX
Position of the cursor relative to the window.
GUIPerspectiveChanger * myChanger
The perspective changer.
GUIGLObjectPopupMenu * myPopup
The current popup-menu.
virtual void copyViewportTo(GUISUMOAbstractView *view)
copy the viewport to the given view
void setBreakpoints(const std::vector< SUMOTime > &breakpoints)
Sets the breakpoints of the parent application.
void waitForSnapshots(const SUMOTime snapshotTime)
bool addAdditionalGLVisualisation(GUIGlObject *const which)
Adds an object to call its additional visualisation method.
virtual bool setColorScheme(const std::string &)
set color scheme
GUIGLObjectPopupMenu * getPopup() const
ge the current popup-menu
virtual long onCmdAddRerouter(FXObject *, FXSelector, void *)
std::vector< GUIGlObject * > filterInternalLanes(const std::vector< GUIGlObject * > &objects) const
filter internal lanes in Objects under cursor
virtual long onPaint(FXObject *, FXSelector, void *)
virtual long onRightBtnPress(FXObject *, FXSelector, void *)
virtual ~GUISUMOAbstractView()
destructor
virtual long onConfigure(FXObject *, FXSelector, void *)
mouse functions
std::map< SUMOTime, std::vector< std::tuple< std::string, int, int > > > mySnapshots
Snapshots.
void remove(GUIDialog_EditViewport *)
remove viewport
virtual GUIGlID getTrackedID() const
get tracked id
void openPopupDialog()
open popup dialog
static void drawTexturedBox(int which, double size)
Draws a named texture as a box with the given size.
static GUIGlID add(FXImage *i)
Adds a texture to use.
static int getMaxTextureSize()
return maximum number of pixels in x and y direction
Stores the information about how to visualize structures.
static const std::string SCHEME_NAME_DATA_ATTRIBUTE_NUMERICAL
static const std::string SCHEME_NAME_EDGEDATA_NUMERICAL
static const std::string SCHEME_NAME_LANE_PARAM_NUMERICAL
static const std::string SCHEME_NAME_EDGE_PARAM_NUMERICAL
scheme names
static const std::string SCHEME_NAME_PARAM_NUMERICAL
const Position getOffset() const
Returns the network offset.
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
static FXImage * loadImage(FXApp *a, const std::string &file)
static FXbool scalePower2(FXImage *image, int maxSize=(2<< 29))
static FXbool saveImage(const std::string &file, int width, int height, FXColor *data)
static void sleep(long ms)
static OptionsCont & getOptions()
Retrieves the options.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:323
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition Position.h:273
double x() const
Returns the x-position.
Definition Position.h:52
Position rotateAround2D(double rad, const Position &origin)
rotate this position by rad around origin and return the result
Definition Position.cpp:42
double z() const
Returns the z-position.
Definition Position.h:62
double y() const
Returns the y-position.
Definition Position.h:57
static RGBColor interpolate(const RGBColor &minColor, const RGBColor &maxColor, double weight)
Interpolates between two colors.
Definition RGBColor.cpp:387
static const RGBColor WHITE
Definition RGBColor.h:195
static const RGBColor BLACK
Definition RGBColor.h:196
static const RGBColor RED
named colors
Definition RGBColor.h:188
A RT-tree for efficient storing of SUMO's GL-objects.
Definition SUMORTree.h:66
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition SysUtils.cpp:44
#define UNUSED_PARAMETER(x)
FONSalign
Definition fontstash.h:40
@ FONS_ALIGN_LEFT
Definition fontstash.h:42
@ FONS_ALIGN_RIGHT
Definition fontstash.h:44
comparator for resolving clicks
A decal (an image) that can be shown.
double centerX
The center of the image in x-direction (net coordinates, in m).
double height
The height of the image (net coordinates in y-direction, in m).
double width
The width of the image (net coordinates in x-direction, in m).
double centerY
The center of the image in y-direction (net coordinates, in m).
std::string filename
The path to the file the image is located at.
GUIGlObject * getGLObject() const
get GLObject
LayerObject(double layer, GUIGlObject *object)
constructor for shapes
bool hideMax
whether data above threshold should not be colored
bool setNeutral
whether the scale should be centered at a specific value
bool fixRange
whether the color scale should be fixed to the given min/max values
double minThreshold
threshold below which value should not be colored
std::vector< RGBColor > colors
color steps for the rainbow;
bool hideMin
whether data below threshold should not be colored
double neutralThreshold
neutral point of scale
double maxThreshold
threshold above which value should not be colored