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-2026 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 delete myPopup;
159 delete myChanger;
162
163 // release GPU textures
164 if (makeCurrent()) {
165 for (auto& decal : myDecals) {
166 if (decal.glID > 0) {
167 queueTextureDelete(static_cast<unsigned int>(decal.glID));
168 }
169 }
171 makeNonCurrent();
172 }
173
174 // remove all elements
175 for (auto& additional : myAdditionallyDrawn) {
176 additional.first->removeActiveAddVisualisation(this, ~0);
177 }
178}
179
180
181bool
185
186
189 return *myChanger;
190}
191
192
193void
195 if (myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->isStaticToolTipEnabled()) {
196 update();
197 }
198}
199
200
205
206
208GUISUMOAbstractView::snapToActiveGrid(const Position& pos, bool snapXY) const {
209 Position result = pos;
210 if (myVisualizationSettings->showGrid) {
211 if (snapXY) {
212 const double xRest = std::fmod(pos.x(), myVisualizationSettings->gridXSize) + (pos.x() < 0 ? myVisualizationSettings->gridXSize : 0);
213 const double yRest = std::fmod(pos.y(), myVisualizationSettings->gridYSize) + (pos.y() < 0 ? myVisualizationSettings->gridYSize : 0);
214 result.setx(pos.x() - xRest + (xRest < myVisualizationSettings->gridXSize * 0.5 ? 0 : myVisualizationSettings->gridXSize));
215 result.sety(pos.y() - yRest + (yRest < myVisualizationSettings->gridYSize * 0.5 ? 0 : myVisualizationSettings->gridYSize));
216 } else {
217 // snapZToActiveGrid uses grid Y Size
218 const double zRest = std::fmod(pos.z(), myVisualizationSettings->gridYSize) + (pos.z() < 0 ? myVisualizationSettings->gridYSize : 0);
219 result.setz(pos.z() - zRest + (zRest < myVisualizationSettings->gridYSize * 0.5 ? 0 : myVisualizationSettings->gridYSize));
220 }
221 }
222 return result;
223}
224
225
228 Boundary bound = myChanger->getViewport();
229 double xNet = bound.xmin() + bound.getWidth() * x / getWidth();
230 // cursor origin is in the top-left corner
231 double yNet = bound.ymin() + bound.getHeight() * (getHeight() - y) / getHeight();
232 // rotate around the viewport center
233 if (myChanger->getRotation() != 0) {
234 return Position(xNet, yNet).rotateAround2D(-DEG2RAD(myChanger->getRotation()), bound.getCenter());
235 } else {
236 return Position(xNet, yNet);
237 }
238}
239
240
241void
242GUISUMOAbstractView::addDecals(const std::vector<Decal>& decals) {
243 // insert decals but avoid duplicates
244 FXMutexLock lock(myDecalsLockMutex);
245 for (const auto& d : decals) {
246 bool found = false;
247 for (const auto& existing : myDecals) {
248 if (existing.filename == d.filename &&
249 existing.centerX == d.centerX &&
250 existing.centerY == d.centerY &&
251 existing.centerZ == d.centerZ) {
252 found = true;
253 break;
254 }
255 }
256 if (!found) {
257 myDecals.push_back(d);
258 myDecals.back().initialised = false;
259 }
260 }
261}
262
263
264void
267 // set cartesian position
268 myApp->getCartesianLabel()->setText(("x:" + toString(pos.x()) + ", y:" + toString(pos.y())).c_str());
269 // set geo position
271 if (GeoConvHelper::getFinal().usingGeoProjection()) {
272 myApp->getGeoLabel()->setText(("lat:" + toString(pos.y(), gPrecisionGeo) + ", lon:" + toString(pos.x(), gPrecisionGeo)).c_str());
273 } else {
274 myApp->getGeoLabel()->setText(TL("(No projection defined)"));
275 }
276 // if enabled, set test position
277 if (myApp->getTestFrame()) {
278 if (OptionsCont::getOptions().getBool("gui-testing")) {
279 myApp->getTestFrame()->show();
280 // adjust cursor position (24,25) to show exactly the same position as in function netedit.leftClick(match, X, Y)
281 myApp->getTestLabel()->setText(("Test: x:" + toString(getWindowCursorPosition().x() - 24.0) + " y:" + toString(getWindowCursorPosition().y() - 25.0)).c_str());
282 } else {
283 myApp->getTestFrame()->hide();
284 }
285 }
286}
287
288
289int
290GUISUMOAbstractView::doPaintGL(int /*mode*/, const Boundary& /*boundary*/) {
291 return 0;
292}
293
294
295void
298
299
302 return myChanger->getViewport();
303}
304
305
306bool
308 return false;
309}
310
311
312void GUISUMOAbstractView::zoom2Pos(Position& /* camera */, Position& /* lookAt */, double /* zoom */) {
313}
314
315
316void
318 // reset debug counters
321 if (getWidth() == 0 || getHeight() == 0) {
322 return;
323 }
324
325 // process pending texture deletions
327
328 const long start = SysUtils::getCurrentMillis();
329
331 centerTo(getTrackedID(), false);
332 }
333 // draw
334 glClearColor(
335 myVisualizationSettings->backgroundColor.red() / 255.f,
336 myVisualizationSettings->backgroundColor.green() / 255.f,
337 myVisualizationSettings->backgroundColor.blue() / 255.f,
338 myVisualizationSettings->backgroundColor.alpha() / 255.f);
339 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
340 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
341
342 if (myVisualizationSettings->dither) {
343 glEnable(GL_DITHER);
344 } else {
345 glDisable(GL_DITHER);
346 }
347 glEnable(GL_BLEND);
348 glDisable(GL_LINE_SMOOTH);
349
350 Boundary bound = applyGLTransform();
351 doPaintGL(GL_RENDER, bound);
355 const long end = SysUtils::getCurrentMillis();
356 myFrameDrawTime = end - start;
357 if (myVisualizationSettings->fps) {
358 drawFPS();
359 }
360 // check if show tooltip
361 if (myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->isStaticToolTipEnabled()) {
363 } else {
364 myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->hideStaticToolTip();
365 }
366 swapBuffers();
367}
368
369
370long
371GUISUMOAbstractView::onCmdCloseLane(FXObject*, FXSelector, void*) {
372 return 1;
373}
374
375
376long
377GUISUMOAbstractView::onCmdCloseEdge(FXObject*, FXSelector, void*) {
378 return 1;
379}
380
381
382long
383GUISUMOAbstractView::onCmdAddRerouter(FXObject*, FXSelector, void*) {
384 return 1;
385}
386
387
388long
389GUISUMOAbstractView::onCmdShowReachability(FXObject*, FXSelector, void*) {
390 return 1;
391}
392
393
394long
395GUISUMOAbstractView::onVisualizationChange(FXObject*, FXSelector, void*) {
396 return 1;
397}
398
399
400GUILane*
402 return nullptr;
403}
404
405
410
411
414 return getObjectAtPosition(getPositionInformation(), sensitivity);
415}
416
417
418std::vector<GUIGlID>
422
423
424
425std::vector<GUIGlObject*>
429
430
431std::vector<GUIGlObject*>
435
436
439 // calculate a boundary for the given position
440 Boundary positionBoundary;
441 positionBoundary.add(pos);
442 positionBoundary.grow(sensitivity);
443 const std::vector<GUIGlID> ids = getObjectsInBoundary(positionBoundary);
444 // Interpret results
445 int idMax = 0;
446 double maxLayer = -std::numeric_limits<double>::max();
447 double minDist = std::numeric_limits<double>::max();
448 // iterate over obtained GUIGlIDs
449 for (const auto& i : ids) {
450 // obtain GUIGlObject
451 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(i);
452 // check that GUIGlObject exist
453 if (o == nullptr) {
454 continue;
455 }
456 // check that GUIGlObject isn't the network
457 if (o->getGlID() == 0) {
458 continue;
459 }
460 //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
461 double layer = o->getClickPriority();
462 double dist = o->getCenter().distanceTo2D(pos);
463 // check whether the current object is above a previous one
464 if (layer > maxLayer) {
465 idMax = i;
466 maxLayer = layer;
467 minDist = dist;
468 } else if (layer == maxLayer && dist < minDist) {
469 idMax = i;
470 minDist = dist;
471 }
472 // unblock object
473 GUIGlObjectStorage::gIDStorage.unblockObject(i);
474 }
475 return idMax;
476}
477
478
479std::vector<GUIGlID>
481 // declare result vector
482 std::vector<GUIGlID> result;
483 // calculate boundary
484 Boundary selection;
485 selection.add(pos);
486 selection.grow(radius);
487 // obtain GUIGlID of objects in boundary
488 const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
489 // iterate over obtained GUIGlIDs
490 for (const auto& i : ids) {
491 // obtain GUIGlObject
492 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(i);
493 // check that GUIGlObject exist
494 if (o == nullptr) {
495 continue;
496 }
497 // check that GUIGlObject isn't the network
498 if (o->getGlID() == 0) {
499 continue;
500 }
501 //std::cout << "point selection hit " << o->getMicrosimID() << "\n";
502 GUIGlObjectType type = o->getType();
503 // avoid network
504 if (type != GLO_NETWORK) {
505 result.push_back(i);
506 }
507 // unblock object
508 GUIGlObjectStorage::gIDStorage.unblockObject(i);
509 }
510 return result;
511}
512
513
514std::vector<GUIGlObject*>
516 // declare result vector
517 std::vector<GUIGlObject*> result;
518 // calculate boundary
519 Boundary selection;
520 selection.add(pos);
521 selection.grow(radius);
522 // obtain GUIGlID of objects in boundary
523 const std::vector<GUIGlID> ids = getObjectsInBoundary(selection);
524 // iterate over obtained GUIGlIDs
525 for (const auto& i : ids) {
526 // obtain GUIGlObject
527 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(i);
528 // check that GUIGlObject exist
529 if (o == nullptr) {
530 continue;
531 }
532 // check that GUIGlObject isn't the network
533 if (o->getGlID() == 0) {
534 continue;
535 }
536 result.push_back(o);
537 // unblock object
538 GUIGlObjectStorage::gIDStorage.unblockObject(i);
539 }
540 return result;
541}
542
543
544std::vector<GUIGlID>
546 const int NB_HITS_MAX = 1024 * 1024;
547 // Prepare the selection mode
548 static GUIGlID hits[NB_HITS_MAX];
549 static GLint nb_hits = 0;
550 glSelectBuffer(NB_HITS_MAX, hits);
551 glInitNames();
552
554 Boundary oldViewPort = myChanger->getViewport(false); // backup the actual viewPort
555 myChanger->setViewport(bound);
556 bound = applyGLTransform(false);
557 // enable draw for selecting (to draw objects with less details)
558 myVisualizationSettings->drawForRectangleSelection = true;
559 int hits2 = doPaintGL(GL_SELECT, bound);
560 // reset flags
561 myVisualizationSettings->drawForRectangleSelection = false;
562 // Get the results
563 nb_hits = glRenderMode(GL_RENDER);
564 if (nb_hits == -1) {
565 myApp->setStatusBarText("Selection in boundary failed. Try to select fewer than " + toString(hits2) + " items");
566 }
567 std::vector<GUIGlID> result;
568 GLuint numNames;
569 GLuint* ptr = hits;
570 for (int i = 0; i < nb_hits; ++i) {
571 numNames = *ptr;
572 ptr += 3;
573 for (int j = 0; j < (int)numNames; j++) {
574 result.push_back(*ptr);
575 ptr++;
576 }
577 }
578 // switch viewport back to normal
579 myChanger->setViewport(oldViewPort);
580 return result;
581}
582
583
584std::vector<GUIGlObject*>
585GUISUMOAbstractView::filterInternalLanes(const std::vector<GUIGlObject*>& objects) const {
586 // count number of internal lanes
587 size_t internalLanes = 0;
588 for (const auto& object : objects) {
589 if ((object->getType() == GLO_LANE) && (object->getMicrosimID().find(':') != std::string::npos)) {
590 internalLanes++;
591 }
592 }
593 // if all objects are internal lanes, return it all
594 if (objects.size() == internalLanes || !myVisualizationSettings->drawJunctionShape) {
595 return objects;
596 }
597 // in other case filter internal lanes
598 std::vector<GUIGlObject*> filteredObjects;
599 for (const auto& object : objects) {
600 if ((object->getType() == GLO_LANE) && (object->getMicrosimID().find(':') != std::string::npos)) {
601 continue;
602 }
603 filteredObjects.push_back(object);
604 }
605 return filteredObjects;
606}
607
608
609bool
611 if (idToolTip != GUIGlObject::INVALID_ID) {
612 const GUIGlObject* object = GUIGlObjectStorage::gIDStorage.getObjectBlocking(idToolTip);
613 if (object != nullptr) {
614 myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->showStaticToolTip(object->getFullName().c_str());
615 return true;
616 }
617 }
618 // nothing to show
619 myGlChildWindowParent->getGUIMainWindowParent()->getStaticTooltipView()->hideStaticToolTip();
620 return false;
621}
622
623
624void
626 // obtain minimum grid
627 const double minimumSizeGrid = (myVisualizationSettings->gridXSize < myVisualizationSettings->gridYSize) ? myVisualizationSettings->gridXSize : myVisualizationSettings->gridYSize;
628 // Check if the distance is enough to draw grid
629 if (myVisualizationSettings->scale * myVisualizationSettings->addSize.getExaggeration(*myVisualizationSettings, nullptr) >= (25 / minimumSizeGrid)) {
630 glEnable(GL_DEPTH_TEST);
631 glLineWidth(1);
632 // get multiplication values (2 is the margin)
633 const int multXmin = (int)(myChanger->getViewport().xmin() / myVisualizationSettings->gridXSize) - 2;
634 const int multYmin = (int)(myChanger->getViewport().ymin() / myVisualizationSettings->gridYSize) - 2;
635 const int multXmax = (int)(myChanger->getViewport().xmax() / myVisualizationSettings->gridXSize) + 2;
636 const int multYmax = (int)(myChanger->getViewport().ymax() / myVisualizationSettings->gridYSize) + 2;
637 // obtain references
638 const double xmin = myVisualizationSettings->gridXSize * multXmin;
639 const double ymin = myVisualizationSettings->gridYSize * multYmin;
640 const double xmax = myVisualizationSettings->gridXSize * multXmax;
641 const double ymax = myVisualizationSettings->gridYSize * multYmax;
642 double xp = xmin;
643 double yp = ymin;
644 // move drawing matrix
645 glTranslated(0, 0, .55);
646 glColor3d(0.5, 0.5, 0.5);
647 // draw horizontal lines
648 glBegin(GL_LINES);
649 while (yp <= ymax) {
650 glVertex2d(xmin, yp);
651 glVertex2d(xmax, yp);
652 yp += myVisualizationSettings->gridYSize;
653 }
654 // draw vertical lines
655 while (xp <= xmax) {
656 glVertex2d(xp, ymin);
657 glVertex2d(xp, ymax);
658 xp += myVisualizationSettings->gridXSize;
659 }
660 glEnd();
661 glTranslated(0, 0, -.55);
662 }
663}
664
665
666void
668 // compute the scale bar length
669 int length = 1;
670 const std::string text("10000000000");
671 int noDigits = 1;
672 int pixelSize = (int) m2p((double) length);
673 while (pixelSize <= 20) {
674 length *= 10;
675 noDigits++;
676 if (noDigits > (int)text.length()) {
677 return;
678 }
679 pixelSize = (int) m2p((double) length);
680 }
681 glLineWidth(1.0);
682
683 glMatrixMode(GL_PROJECTION);
685 glLoadIdentity();
686 glMatrixMode(GL_MODELVIEW);
688 glLoadIdentity();
689
690 // draw the scale bar
691 const double z = -1;
692 glDisable(GL_TEXTURE_2D);
693 glDisable(GL_ALPHA_TEST);
694 glDisable(GL_BLEND);
695 glEnable(GL_DEPTH_TEST);
697 glTranslated(0, 0, z);
698
699 double len = (double) pixelSize / (double)(getWidth() - 1) * (double) 2.0;
700 glColor3d(0, 0, 0);
701 double o = double(15) / double(getHeight());
702 double o2 = o + o;
703 double oo = double(5) / double(getHeight());
704 glBegin(GL_LINES);
705 // vertical
706 glVertex2d(-.98, -1. + o);
707 glVertex2d(-.98 + len, -1. + o);
708 // tick at begin
709 glVertex2d(-.98, -1. + o);
710 glVertex2d(-.98, -1. + o2);
711 // tick at end
712 glVertex2d(-.98 + len, -1. + o);
713 glVertex2d(-.98 + len, -1. + o2);
714 glEnd();
716
717 const double fontHeight = 0.1 * 300. / getHeight();
718 const double fontWidth = 0.1 * 300. / getWidth();
719 // draw 0
720 GLHelper::drawText("0", Position(-.99, -0.99 + o2 + oo), z, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT, fontWidth);
721
722 // draw current scale
723 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);
724
725 // restore matrices
726 glMatrixMode(GL_PROJECTION);
728 glMatrixMode(GL_MODELVIEW);
730}
731
732void
734 if (myVisualizationSettings->showSizeLegend) {
736 }
737 std::string key = "";
738 if (myVisualizationSettings->showColorLegend) {
739 auto const& scheme = myVisualizationSettings->getLaneEdgeScheme();
741 key = myVisualizationSettings->edgeData;
742 } else if (scheme.getName() == GUIVisualizationSettings::SCHEME_NAME_EDGE_PARAM_NUMERICAL) {
743 key = myVisualizationSettings->edgeParam;
744 } else if (scheme.getName() == GUIVisualizationSettings::SCHEME_NAME_LANE_PARAM_NUMERICAL) {
745 key = myVisualizationSettings->laneParam;
746 }
747 displayColorLegend(scheme, false, key);
748 }
749 if (myVisualizationSettings->showVehicleColorLegend) {
750 auto const& scheme = myVisualizationSettings->vehicleColorer.getScheme();
752 key = myVisualizationSettings->vehicleParam;
753 }
754 displayColorLegend(myVisualizationSettings->vehicleColorer.getScheme(), true, key);
755 }
756}
757
758void
759GUISUMOAbstractView::displayColorLegend(const GUIColorScheme& scheme, bool leftSide, const std::string& key) {
760 // compute the scale bar length
761 glLineWidth(1.0);
762 glMatrixMode(GL_PROJECTION);
764 glLoadIdentity();
765 glMatrixMode(GL_MODELVIEW);
767 glLoadIdentity();
768
769 const double z = -1;
770 glEnable(GL_DEPTH_TEST);
771 glEnable(GL_BLEND);
773 glTranslated(0, 0, z);
774
775 const bool fixed = scheme.isFixed();
776 const int numColors = (int)scheme.getColors().size();
777
778 // vertical
779 double right = 0.98;
780 double left = 0.95;
781 double textX = left - 0.01;
782 double textDir = 1;
783 FONSalign textAlign = FONS_ALIGN_RIGHT;
784 const double top = -0.7;
785 const double bot = 0.9;
786 const double dy = (top - bot) / numColors;
787 const double bot2 = fixed ? bot : bot + dy / 2;
788 // legend placement
789 if (leftSide) {
790 right = -right;
791 left = -left;
792 std::swap(right, left);
793 textX = right + 0.01;
794 textDir *= -1;
795 textAlign = FONS_ALIGN_LEFT;
796 }
797 // draw black boundary around legend colors
798 glColor3d(0, 0, 0);
799 glBegin(GL_LINES);
800 glVertex2d(right, top);
801 glVertex2d(right, bot2);
802 glVertex2d(left, bot2);
803 glVertex2d(left, top);
804 glVertex2d(right, top);
805 glVertex2d(left, top);
806 glVertex2d(right, bot2);
807 glVertex2d(left, bot2);
808 glEnd();
809
810 const double fontHeight = 0.20 * 300. / getHeight();
811 const double fontWidth = 0.20 * 300. / getWidth();
812
813 const int fadeSteps = fixed ? 1 : 10;
814 double colorStep = dy / fadeSteps;
815 for (int i = 0; i < numColors; i++) {
816 RGBColor col = scheme.getColors()[i];
817 const double topi = top - i * dy;
818 //const double boti = top - (i + 1) * dy;
819 //std::cout << " col=" << scheme.getColors()[i] << " i=" << i << " topi=" << topi << " boti=" << boti << "\n";
820 if (i + 1 < numColors) {
821 // fade
822 RGBColor col2 = scheme.getColors()[i + 1];
823 double thresh2 = scheme.getThresholds()[i + 1];
824 if (!fixed && thresh2 == GUIVisualizationSettings::MISSING_DATA) {
825 // draw scale end before missing data
827 glBegin(GL_QUADS);
828 glVertex2d(left, topi);
829 glVertex2d(right, topi);
830 glVertex2d(right, topi - 5 * colorStep);
831 glVertex2d(left, topi - 5 * colorStep);
832 glEnd();
833 glColor3d(0, 0, 0);
834 glBegin(GL_LINES);
835 glVertex2d(right, topi - 10 * colorStep);
836 glVertex2d(left, topi - 10 * colorStep);
837 glEnd();
838 glBegin(GL_LINES);
839 glVertex2d(right, topi - 5 * colorStep);
840 glVertex2d(left, topi - 5 * colorStep);
841 glEnd();
842 } else {
843 // fade colors
844 for (double j = 0.0; j < fadeSteps; j++) {
845 GLHelper::setColor(RGBColor::interpolate(col, col2, j / fadeSteps));
846 glBegin(GL_QUADS);
847 glVertex2d(left, topi - j * colorStep);
848 glVertex2d(right, topi - j * colorStep);
849 glVertex2d(right, topi - (j + 1) * colorStep);
850 glVertex2d(left, topi - (j + 1) * colorStep);
851 glEnd();
852 }
853 }
854 } else {
856 glBegin(GL_QUADS);
857 glVertex2d(left, topi);
858 glVertex2d(right, topi);
859 glVertex2d(right, bot2);
860 glVertex2d(left, bot2);
861 glEnd();
862 }
863
864 const double threshold = scheme.getThresholds()[i];
865 std::string name = scheme.getNames()[i];
866 std::string text = fixed || threshold == GUIVisualizationSettings::MISSING_DATA ? name : toString(threshold);
867
868 const double bgShift = 0.0;
869 const double textShift = 0.01;
870 const double textXShift = -0.005;
871
873 glTranslated(0, 0, 0.1);
874 glBegin(GL_QUADS);
875 glVertex2d(textX, topi + fontHeight * bgShift);
876 glVertex2d(textX - textDir * fontWidth * (double)text.size() / 2.1, topi + fontHeight * bgShift);
877 glVertex2d(textX - textDir * fontWidth * (double)text.size() / 2.1, topi + fontHeight * (0.8 + bgShift));
878 glVertex2d(textX, topi + fontHeight * (0.8 + bgShift));
879 glEnd();
880 glTranslated(0, 0, -0.1);
881 GLHelper::drawText(text, Position(textX + textDir * textXShift, topi + textShift), 0, fontHeight, RGBColor::BLACK, 0, textAlign, fontWidth);
882 }
883 // draw scheme name
884 std::string name = scheme.getName();
886 name = "edgeData (" + key + ")";
888 name = "edgeParam (" + key + ")";
890 name = "laneParam (" + key + ")";
892 name = "param (" + key + ")";
894 name = "attribute (" + key + ")";
895 } else if (StringUtils::startsWith(name, "by ")) {
896 name = name.substr(3);
897 }
898 const double topN = -0.8;
899 const double bgShift = 0.0;
901 glTranslated(0, 0, 0.1);
902 glBegin(GL_QUADS);
903 glVertex2d(textX + textDir * 0.04, topN + fontHeight * bgShift - 0.01);
904 glVertex2d(textX + textDir * 0.04 - textDir * fontWidth * (double)name.size() / 2.3, topN + fontHeight * bgShift - 0.01);
905 glVertex2d(textX + textDir * 0.04 - textDir * fontWidth * (double)name.size() / 2.3, topN + fontHeight * (0.8 + bgShift));
906 glVertex2d(textX + textDir * 0.04, topN + fontHeight * (0.8 + bgShift));
907 glEnd();
908 glTranslated(0, 0, -0.1);
909 GLHelper::drawText(name, Position(textX + textDir * 0.04, topN), 0, fontHeight, RGBColor::BLACK, 0, textAlign, fontWidth);
910
912 // restore matrices
913 glMatrixMode(GL_PROJECTION);
915 glMatrixMode(GL_MODELVIEW);
917}
918
919
920double
922 return 1000.0 / MAX2((long)1, myFrameDrawTime);
923}
924
925
930
931
932void
934 glMatrixMode(GL_PROJECTION);
936 glLoadIdentity();
937 glMatrixMode(GL_MODELVIEW);
939 glLoadIdentity();
940 const double fontHeight = 0.2 * 300. / getHeight();
941 const double fontWidth = 0.2 * 300. / getWidth();
942 GLHelper::drawText(toString((int)getFPS()) + " FPS", Position(0.82, 0.88), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
943#ifdef CHECK_ELEMENTCOUNTER
944 GLHelper::drawText(toString(GLHelper::getMatrixCounter()) + " matrix", Position(0.82, 0.79), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
945 GLHelper::drawText(toString(GLHelper::getVertexCounter()) + " vertex", Position(0.82, 0.71), -1, fontHeight, RGBColor::RED, 0, FONS_ALIGN_LEFT, fontWidth);
946#endif
947 // restore matrices
948 glMatrixMode(GL_PROJECTION);
950 glMatrixMode(GL_MODELVIEW);
952}
953
954
955double
956GUISUMOAbstractView::m2p(double meter) const {
957 return meter * getWidth() / myChanger->getViewport().getWidth();
958}
959
960
961double
962GUISUMOAbstractView::p2m(double pixel) const {
963 return pixel * myChanger->getViewport().getWidth() / getWidth();
964}
965
966
967void
971
972
973void
974GUISUMOAbstractView::centerTo(GUIGlID id, bool applyZoom, double zoomDist) {
975 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id);
976 if (o != nullptr && dynamic_cast<GUIGlObject*>(o) != nullptr) {
977 const Boundary& b = o->getCenteringBoundary();
978 if (b.getCenter() != Position::INVALID) {
979 if (applyZoom && zoomDist < 0) {
980 myChanger->setViewport(b);
981 update(); // only update when centering onto an object once
982 } else {
983 // called during tracking. update is triggered somewhere else
984 myChanger->centerTo(b.getCenter(), zoomDist, applyZoom);
986 }
987 }
988 }
989 GUIGlObjectStorage::gIDStorage.unblockObject(id);
990}
991
992
993void
994GUISUMOAbstractView::centerTo(const Position& pos, bool applyZoom) {
995 // called during tracking. update is triggered somewhere else
996 myChanger->centerTo(pos, 20, applyZoom);
998}
999
1000
1001void
1003 myChanger->setViewport(bound);
1004 update();
1005}
1006
1007
1010 return myApp;
1011}
1012
1013
1018
1019
1020void
1025
1026
1027FXbool
1029 FXbool ret = FXGLCanvas::makeCurrent();
1030 return ret;
1031}
1032
1033
1034long
1035GUISUMOAbstractView::onConfigure(FXObject*, FXSelector, void*) {
1036 if (makeCurrent()) {
1037 glViewport(0, 0, getWidth() - 1, getHeight() - 1);
1038 glClearColor(
1039 myVisualizationSettings->backgroundColor.red() / 255.f,
1040 myVisualizationSettings->backgroundColor.green() / 255.f,
1041 myVisualizationSettings->backgroundColor.blue() / 255.f,
1042 myVisualizationSettings->backgroundColor.alpha() / 255.f);
1043 doInit();
1044 myAmInitialised = true;
1045 makeNonCurrent();
1047 }
1048 return 1;
1049}
1050
1051
1052long
1053GUISUMOAbstractView::onPaint(FXObject*, FXSelector, void*) {
1054 if (!isEnabled() || !myAmInitialised) {
1055 return 1;
1056 }
1057 if (makeCurrent()) {
1058 paintGL();
1059 makeNonCurrent();
1060 }
1061 // run tests
1062 myApp->handle(this, FXSEL(SEL_COMMAND, MID_RUNTESTS), nullptr);
1063 return 1;
1064}
1065
1066
1069 return myPopup;
1070}
1071
1072
1073const Position&
1077
1078
1079void
1081 if (myPopup != nullptr) {
1082 myPopup->removePopupFromObject();
1083 delete myPopup;
1084 myPopupPosition.set(0, 0);
1085 myPopup = nullptr;
1086 myCurrentObjectsDialog.clear();
1087 }
1088}
1089
1090
1091void
1093 // use the same position of old popUp
1094 popUp->move(myPopup->getX(), myPopup->getY());
1095 // delete and replace popup
1096 myPopup->removePopupFromObject();
1097 delete myPopup;
1098 myPopup = popUp;
1099 // create and show popUp
1100 myPopup->create();
1101 myPopup->show();
1102 myChanger->onRightBtnRelease(nullptr);
1103 setFocus();
1104}
1105
1106
1107long
1108GUISUMOAbstractView::onLeftBtnPress(FXObject*, FXSelector, void* ptr) {
1109 destroyPopup();
1110 setFocus();
1111 FXEvent* e = (FXEvent*) ptr;
1112 // check whether the selection-mode is activated
1113 if ((e->state & CONTROLMASK) != 0) {
1114 // toggle selection of object under cursor
1115 if (makeCurrent()) {
1116 int id = getObjectUnderCursor();
1117 if (id != 0) {
1118 gSelected.toggleSelection(id);
1119 }
1120 makeNonCurrent();
1121 if (id != 0) {
1122 // possibly, the selection-coloring is used,
1123 // so we should update the screen again...
1124 update();
1125 }
1126 }
1127 }
1128 if ((e->state & SHIFTMASK) != 0) {
1129 // track vehicle or person under cursor
1130 if (makeCurrent()) {
1131 int id = getObjectUnderCursor();
1132 if (id != 0) {
1133 GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id);
1134 if (o != nullptr) {
1135 if (!myApp->isGaming() && (o->getType() == GLO_VEHICLE || o->getType() == GLO_PERSON)) {
1136 startTrack(id);
1137 }
1138 }
1139 }
1140 makeNonCurrent();
1141 }
1142 }
1143 myChanger->onLeftBtnPress(ptr);
1144 grab();
1145 // Check there are double click
1146 if (e->click_count == 2) {
1147 handle(this, FXSEL(SEL_DOUBLECLICKED, 0), ptr);
1148 }
1149 return 1;
1150}
1151
1152
1153long
1154GUISUMOAbstractView::onLeftBtnRelease(FXObject*, FXSelector, void* ptr) {
1155 destroyPopup();
1156 myChanger->onLeftBtnRelease(ptr);
1157 if (myApp->isGaming()) {
1159 }
1160 ungrab();
1161 return 1;
1162}
1163
1164
1165long
1166GUISUMOAbstractView::onMiddleBtnPress(FXObject*, FXSelector, void* ptr) {
1167 destroyPopup();
1168 setFocus();
1169 if (!myApp->isGaming()) {
1170 myChanger->onMiddleBtnPress(ptr);
1171 }
1172 grab();
1173 // enable panning
1174 myPanning = true;
1175 // set cursors
1178 return 1;
1179}
1180
1181
1182long
1183GUISUMOAbstractView::onMiddleBtnRelease(FXObject*, FXSelector, void* ptr) {
1184 destroyPopup();
1185 if (!myApp->isGaming()) {
1186 myChanger->onMiddleBtnRelease(ptr);
1187 }
1188 ungrab();
1189 // disable panning
1190 myPanning = false;
1191 // restore cursors
1194 return 1;
1195}
1196
1197
1198long
1199GUISUMOAbstractView::onRightBtnPress(FXObject*, FXSelector, void* ptr) {
1200 destroyPopup();
1201 if (!myApp->isGaming()) {
1202 myChanger->onRightBtnPress(ptr);
1203 }
1204 grab();
1205 return 1;
1206}
1207
1208
1209long
1210GUISUMOAbstractView::onRightBtnRelease(FXObject* o, FXSelector sel, void* ptr) {
1211 destroyPopup();
1212 onMouseMove(o, sel, ptr);
1213 if (!myChanger->onRightBtnRelease(ptr) && !myApp->isGaming()) {
1214 openObjectDialogAtCursor((FXEvent*)ptr);
1215 }
1216 if (myApp->isGaming()) {
1218 }
1219 ungrab();
1220 return 1;
1221}
1222
1223
1224long
1225GUISUMOAbstractView::onDoubleClicked(FXObject*, FXSelector, void*) {
1226 return 1;
1227}
1228
1229
1230long
1231GUISUMOAbstractView::onMouseWheel(FXObject*, FXSelector, void* ptr) {
1232 if (!myApp->isGaming()) {
1233 myChanger->onMouseWheel(ptr);
1234 // upddate viewport
1235 if (myGUIDialogEditViewport != nullptr) {
1236 myGUIDialogEditViewport->setValues(myChanger->getZoom(),
1237 myChanger->getXPos(), myChanger->getYPos(),
1238 myChanger->getRotation());
1239 }
1241 }
1242 return 1;
1243}
1244
1245
1246long
1247GUISUMOAbstractView::onMouseMove(FXObject*, FXSelector, void* ptr) {
1248 // check if popup exist
1249 if (myPopup) {
1250 // check if handle front element
1253 myPopup->handle(this, FXSEL(SEL_COMMAND, MID_CURSORDIALOG_FRONT), nullptr);
1254 destroyPopup();
1255 } else if (!myPopup->shown()) {
1256 destroyPopup();
1257 }
1258 }
1259 if (myPopup == nullptr) {
1260 if (myGUIDialogEditViewport == nullptr || !myGUIDialogEditViewport->haveGrabbed()) {
1261 myChanger->onMouseMove(ptr);
1262 }
1263 if (myGUIDialogEditViewport != nullptr) {
1264 myGUIDialogEditViewport->setValues(myChanger->getZoom(),
1265 myChanger->getXPos(), myChanger->getYPos(),
1266 myChanger->getRotation());
1267 }
1269 }
1270 return 1;
1271}
1272
1273
1274long
1275GUISUMOAbstractView::onMouseLeft(FXObject*, FXSelector, void* /*data*/) {
1276 return 1;
1277}
1278
1279std::vector<GUIGlObject*>
1280GUISUMOAbstractView::filterContextObjects(const std::vector<GUIGlObject*>& objects) {
1281 // assume input is sorted with ComparatorClickPriority
1282 std::vector<GUIGlObject*> result;
1283 for (GUIGlObject* o : objects) {
1284 if (o->getClickPriority() != GUIGlObject::INVALID_PRIORITY && (result.empty() || result.back() != o)) {
1285 result.push_back(o);
1286 }
1287 }
1288 return result;
1289}
1290
1291
1292void
1294 // release the mouse grab
1295 ungrab();
1296 // check if alt key is pressed
1297 const bool altKeyPressed = ((ev->state & ALTMASK) != 0);
1298 // check if SUMO is enabled, initialised and Make OpenGL context current
1299 if (isEnabled() && myAmInitialised && makeCurrent()) {
1300 auto objectsUnderCursor = getGUIGlObjectsUnderCursor();
1301 if (objectsUnderCursor.empty()) {
1302 myPopup = GUIGlObjectStorage::gIDStorage.getNetObject()->getPopUpMenu(*myApp, *this);
1303 } else {
1304 std::sort(objectsUnderCursor.begin(), objectsUnderCursor.end(), ComparatorClickPriority());
1305 std::vector<GUIGlObject*> filtered = filterContextObjects(objectsUnderCursor);
1306 if (filtered.size() > 1 && (altKeyPressed
1307 || filtered[0]->getClickPriority() == filtered[1]->getClickPriority())) {
1308 // open dialog for picking among objects (without duplicates)
1310 } else {
1311 myPopup = objectsUnderCursor.front()->getPopUpMenu(*myApp, *this);
1312 }
1313 }
1315 makeNonCurrent();
1316 }
1317}
1318
1319
1320void
1321GUISUMOAbstractView::openObjectDialog(const std::vector<GUIGlObject*>& objects, const bool filter) {
1322 if (objects.size() > 0) {
1323 // create cursor popup dialog
1324 if (objects.size() == 1) {
1325 myCurrentObjectsDialog = objects;
1326 } else if (filter) {
1327 // declare filtered objects
1328 std::vector<GUIGlObject*> filteredGLObjects;
1329 // fill filtered objects
1330 for (const auto& glObject : objects) {
1331 // compare type with first element type
1332 if (glObject->getType() == objects.front()->getType()) {
1333 filteredGLObjects.push_back(glObject);
1334 }
1335 }
1336 myCurrentObjectsDialog = filteredGLObjects;
1337 } else {
1338 myCurrentObjectsDialog = objects;
1339 }
1340 if (myCurrentObjectsDialog.size() > 1) {
1342 } else {
1343 myPopup = myCurrentObjectsDialog.front()->getPopUpMenu(*myApp, *this);
1344 }
1345 // open popup dialog
1347 }
1348}
1349
1350
1351long
1352GUISUMOAbstractView::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
1353 const FXEvent* e = (FXEvent*) ptr;
1354 // check if process canvas or popup
1355 if (myPopup != nullptr) {
1356 return myPopup->onKeyPress(o, sel, ptr);
1357 } else {
1358 if (e->state & CONTROLMASK) {
1359 if (e->code == FX::KEY_Page_Up) {
1360 myVisualizationSettings->gridXSize *= 2;
1361 myVisualizationSettings->gridYSize *= 2;
1362 update();
1363 return 1;
1364 } else if (e->code == FX::KEY_Page_Down) {
1365 myVisualizationSettings->gridXSize /= 2;
1366 myVisualizationSettings->gridYSize /= 2;
1367 update();
1368 return 1;
1369 }
1370 }
1371 FXGLCanvas::onKeyPress(o, sel, ptr);
1372 return myChanger->onKeyPress(ptr);
1373 }
1374}
1375
1376
1377long
1378GUISUMOAbstractView::onKeyRelease(FXObject* o, FXSelector sel, void* ptr) {
1379 // check if process canvas or popup
1380 if (myPopup != nullptr) {
1381 return myPopup->onKeyRelease(o, sel, ptr);
1382 } else {
1383 FXGLCanvas::onKeyRelease(o, sel, ptr);
1384 return myChanger->onKeyRelease(ptr);
1385 }
1386}
1387
1388// ------------ Dealing with snapshots
1389
1390void
1391GUISUMOAbstractView::addSnapshot(SUMOTime time, const std::string& file, const int w, const int h) {
1392#ifdef DEBUG_SNAPSHOT
1393 std::cout << "add snapshot time=" << time << " file=" << file << "\n";
1394#endif
1395 FXMutexLock lock(mySnapshotsMutex);
1396 mySnapshots[time].push_back(std::make_tuple(file, w, h));
1397}
1398
1399
1400std::string
1401GUISUMOAbstractView::makeSnapshot(const std::string& destFile, const int w, const int h) {
1402 if (w >= 0) {
1403 resize(w, h);
1404 repaint();
1405 }
1406 std::string errorMessage;
1407 FXString ext = FXPath::extension(destFile.c_str());
1408 const bool useGL2PS = ext == "ps" || ext == "eps" || ext == "pdf" || ext == "svg" || ext == "tex" || ext == "pgf";
1409#ifdef HAVE_FFMPEG
1410 const bool useVideo = destFile == "" || ext == "h264" || ext == "hevc" || ext == "mp4";
1411#endif
1412 for (int i = 0; i < 10 && !makeCurrent(); ++i) {
1414 }
1415 // draw
1416 glClearColor(
1417 myVisualizationSettings->backgroundColor.red() / 255.f,
1418 myVisualizationSettings->backgroundColor.green() / 255.f,
1419 myVisualizationSettings->backgroundColor.blue() / 255.f,
1420 myVisualizationSettings->backgroundColor.alpha() / 255.f);
1421 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
1422 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1423
1424 if (myVisualizationSettings->dither) {
1425 glEnable(GL_DITHER);
1426 } else {
1427 glDisable(GL_DITHER);
1428 }
1429 glEnable(GL_BLEND);
1430 glDisable(GL_LINE_SMOOTH);
1431
1433
1434 if (useGL2PS) {
1435#ifdef HAVE_GL2PS
1436 GLint format = GL2PS_PS;
1437 if (ext == "ps") {
1438 format = GL2PS_PS;
1439 } else if (ext == "eps") {
1440 format = GL2PS_EPS;
1441 } else if (ext == "pdf") {
1442 format = GL2PS_PDF;
1443 } else if (ext == "tex") {
1444 format = GL2PS_TEX;
1445 } else if (ext == "svg") {
1446 format = GL2PS_SVG;
1447 } else if (ext == "pgf") {
1448 format = GL2PS_PGF;
1449 } else {
1450 return "Could not save '" + destFile + "'.\n Unrecognized format '" + std::string(ext.text()) + "'.";
1451 }
1452 FILE* fp = fopen(destFile.c_str(), "wb");
1453 if (fp == 0) {
1454 return "Could not save '" + destFile + "'.\n Could not open file for writing";
1455 }
1457 GLint buffsize = 0, state = GL2PS_OVERFLOW;
1458 GLint viewport[4];
1459 glGetIntegerv(GL_VIEWPORT, viewport);
1460 while (state == GL2PS_OVERFLOW) {
1461 buffsize += 1024 * 1024;
1462 gl2psBeginPage(destFile.c_str(), "sumo-gui; https://sumo.dlr.de", viewport, format, GL2PS_SIMPLE_SORT,
1463 GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT,
1464 GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, "out.eps");
1465 glMatrixMode(GL_MODELVIEW);
1467 glDisable(GL_TEXTURE_2D);
1468 glDisable(GL_ALPHA_TEST);
1469 glDisable(GL_BLEND);
1470 glEnable(GL_DEPTH_TEST);
1471 // draw decals (if not in grabbing mode)
1472
1473 drawDecals();
1474 if (myVisualizationSettings->showGrid) {
1475 paintGLGrid();
1476 }
1477
1478 glLineWidth(1);
1479 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1480 Boundary viewPort = myChanger->getViewport();
1481 const float minB[2] = { (float)viewPort.xmin(), (float)viewPort.ymin() };
1482 const float maxB[2] = { (float)viewPort.xmax(), (float)viewPort.ymax() };
1484 glEnable(GL_POLYGON_OFFSET_FILL);
1485 glEnable(GL_POLYGON_OFFSET_LINE);
1486 myGrid->Search(minB, maxB, *myVisualizationSettings);
1487
1489 state = gl2psEndPage();
1490 glFinish();
1491 }
1492 GLHelper::setGL2PS(false);
1493 fclose(fp);
1494#else
1495 return "Could not save '" + destFile + "', gl2ps was not enabled at compile time.";
1496#endif
1497 } else {
1498 doPaintGL(GL_RENDER, myChanger->getViewport());
1500 swapBuffers();
1501 glFinish();
1502 FXColor* buf;
1503 FXMALLOC(&buf, FXColor, getWidth()*getHeight());
1504 // read from the back buffer
1505 glReadBuffer(GL_BACK);
1506 // Read the pixels
1507 glReadPixels(0, 0, getWidth(), getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)buf);
1508 makeNonCurrent();
1509 update();
1510 // mirror
1511 int mwidth = getWidth();
1512 int mheight = getHeight();
1513 FXColor* paa = buf;
1514 FXColor* pbb = buf + mwidth * (mheight - 1);
1515 do {
1516 FXColor* pa = paa;
1517 paa += mwidth;
1518 FXColor* pb = pbb;
1519 pbb -= mwidth;
1520 do {
1521 FXColor t = *pa;
1522 *pa++ = *pb;
1523 *pb++ = t;
1524 } while (pa < paa);
1525 } while (paa < pbb);
1526 try {
1527#ifdef HAVE_FFMPEG
1528 if (useVideo) {
1529 try {
1530 saveFrame(destFile, buf);
1531 errorMessage = "video";
1532 } catch (std::runtime_error& err) {
1533 errorMessage = err.what();
1534 }
1535 } else
1536#endif
1537 if (!MFXImageHelper::saveImage(destFile, getWidth(), getHeight(), buf)) {
1538 errorMessage = "Could not save '" + destFile + "'.";
1539 }
1540 } catch (InvalidArgument& e) {
1541 errorMessage = "Could not save '" + destFile + "'.\n" + e.what();
1542 }
1543 FXFREE(&buf);
1544 }
1545 return errorMessage;
1546}
1547
1548
1549void
1550GUISUMOAbstractView::saveFrame(const std::string& destFile, FXColor* buf) {
1551 UNUSED_PARAMETER(destFile);
1552 UNUSED_PARAMETER(buf);
1553}
1554
1555
1556void
1558 const SUMOTime time = getCurrentTimeStep() - DELTA_T;
1559#ifdef DEBUG_SNAPSHOT
1560 std::cout << "check snapshots time=" << time << " registeredTimes=" << mySnapshots.size() << "\n";
1561#endif
1562 FXMutexLock lock(mySnapshotsMutex);
1563 const auto snapIt = mySnapshots.find(time);
1564 if (snapIt == mySnapshots.end()) {
1565 return;
1566 }
1567 std::vector<std::tuple<std::string, int, int> > files = snapIt->second;
1568 lock.unlock();
1569 // decouple map access and painting to avoid deadlock
1570 for (const auto& entry : files) {
1571#ifdef DEBUG_SNAPSHOT
1572 std::cout << "make snapshot time=" << time << " file=" << file << "\n";
1573#endif
1574 const std::string& error = makeSnapshot(std::get<0>(entry), std::get<1>(entry), std::get<2>(entry));
1575 if (error != "" && error != "video") {
1576 WRITE_WARNING(error);
1577 }
1578 }
1579 // synchronization with a waiting run thread
1580 lock.lock();
1581 mySnapshots.erase(time);
1582 mySnapshotCondition.signal();
1583#ifdef DEBUG_SNAPSHOT
1584 std::cout << " files=" << toString(files) << " myApplicationSnapshots=" << joinToString(*myApplicationSnapshots, ",") << "\n";
1585#endif
1586}
1587
1588
1589void
1591 FXMutexLock lock(mySnapshotsMutex);
1592 if (mySnapshots.count(snapshotTime) > 0) {
1594 }
1595}
1596
1597
1600 return 0;
1601}
1602
1603
1604void
1615
1616
1619 if (myGUIDialogEditViewport == nullptr) {
1620 myGUIDialogEditViewport = new GUIDialog_EditViewport(this, TLC("Labels", "Edit Viewport"));
1621 myGUIDialogEditViewport->create();
1622 }
1625}
1626
1627
1629 myGUIDialogEditViewport->setValues(myChanger->getZoom(),
1630 myChanger->getXPos(), myChanger->getYPos(),
1631 myChanger->getRotation());
1632}
1633
1634
1635void
1637 getViewportEditor(); // make sure it exists;
1638 Position p(myChanger->getXPos(), myChanger->getYPos(), myChanger->getZPos());
1639 myGUIDialogEditViewport->setOldValues(p, Position::INVALID, myChanger->getRotation());
1641}
1642
1643
1644void
1645GUISUMOAbstractView::setViewportFromToRot(const Position& lookFrom, const Position& /* lookAt */, double rotation) {
1646 myChanger->setViewportFrom(lookFrom.x(), lookFrom.y(), lookFrom.z());
1647 myChanger->setRotation(rotation);
1648 update();
1649}
1650
1651
1652void
1654 // look straight down
1655 view->setViewportFromToRot(Position(myChanger->getXPos(), myChanger->getYPos(), myChanger->getZPos()),
1656 Position(myChanger->getXPos(), myChanger->getYPos(), 0),
1657 myChanger->getRotation());
1658}
1659
1660
1661bool
1663 return true;
1664}
1665
1666
1671
1672
1677
1678
1679void
1683
1684
1685void
1689
1690
1691double
1693 return myGrid->getWidth();
1694}
1695
1696
1697double
1699 return myGrid->getHeight();
1700}
1701
1702
1703void
1706
1707
1708void
1711
1712
1713GUIGlID
1717
1718
1719void
1722
1723void
1726
1727
1728std::vector<GUISUMOAbstractView::Decal>&
1732
1733
1734FXMutex&
1738
1739
1740void
1742 FXMutexLock lock(myTextureDeleteMutex);
1743 myPendingTextureDeletes.push_back(textureId);
1744}
1745
1746
1747void
1749 FXMutexLock lock(myTextureDeleteMutex);
1750 if (!myPendingTextureDeletes.empty()) {
1751 glDeleteTextures(
1752 static_cast<GLsizei>(myPendingTextureDeletes.size()),
1754 );
1756 }
1757}
1758
1759
1760void
1762 FXMutexLock lock(myDecalsLockMutex);
1763 for (auto& decal : myDecals) {
1764 if (decal.glID > 0) {
1765 queueTextureDelete(static_cast<unsigned int>(decal.glID));
1766 decal.glID = -1;
1767 }
1768 decal.initialised = false;
1769 }
1770 myDecals.clear();
1771}
1772
1773
1776 return myGlChildWindowParent->getColoringSchemesCombo();
1777}
1778
1779
1780FXImage*
1782#ifdef HAVE_GDAL
1783 GDALAllRegister();
1784 GDALDataset* poDataset = (GDALDataset*)GDALOpen(d.filename.c_str(), GA_ReadOnly);
1785 if (poDataset == 0) {
1786 return 0;
1787 }
1788 const int xSize = poDataset->GetRasterXSize();
1789 const int ySize = poDataset->GetRasterYSize();
1790 // checking for geodata in the picture and try to adapt position and scale
1791 if (d.width <= 0.) {
1792 double adfGeoTransform[6];
1793 if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
1794 Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
1795 const double horizontalSize = xSize * adfGeoTransform[1];
1796 const double verticalSize = ySize * adfGeoTransform[5];
1797 Position bottomRight(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
1798 if (GeoConvHelper::getFinal().usingGeoProjection() && GeoConvHelper::getFinal().x2cartesian_const(topLeft) && GeoConvHelper::getFinal().x2cartesian_const(bottomRight)) {
1799 //WRITE_MESSAGE("proj: " + toString(poDataset->GetProjectionRef()) + " dim: " + toString(d.width) + "," + toString(d.height) + " center: " + toString(d.centerX) + "," + toString(d.centerY));
1800 } else {
1801 WRITE_WARNINGF(TL("Could not transform coordinates from WGS84 in decal %, assuming UTM."), d.filename);
1802 topLeft = topLeft + GeoConvHelper::getFinal().getOffset();
1803 bottomRight = bottomRight + GeoConvHelper::getFinal().getOffset();
1804 }
1805 d.width = bottomRight.x() - topLeft.x();
1806 d.height = topLeft.y() - bottomRight.y();
1807 d.centerX = (topLeft.x() + bottomRight.x()) / 2;
1808 d.centerY = (topLeft.y() + bottomRight.y()) / 2;
1809 }
1810 }
1811#endif
1812 if (d.width <= 0.) {
1813 d.width = getGridWidth();
1814 d.height = getGridHeight();
1815 }
1816
1817 // trying to read the picture
1818#ifdef HAVE_GDAL
1819 const int picSize = xSize * ySize;
1820 FXColor* result;
1821 if (!FXMALLOC(&result, FXColor, picSize)) {
1822 WRITE_WARNINGF("Could not allocate memory for %.", d.filename);
1823 return 0;
1824 }
1825 for (int j = 0; j < picSize; j++) {
1826 result[j] = GUIDesignTextColorBlack;
1827 }
1828 bool valid = true;
1829 for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
1830 GDALRasterBand* poBand = poDataset->GetRasterBand(i);
1831 int shift = -1;
1832 if (poBand->GetColorInterpretation() == GCI_RedBand) {
1833 shift = 0;
1834 } else if (poBand->GetColorInterpretation() == GCI_GreenBand) {
1835 shift = 1;
1836 } else if (poBand->GetColorInterpretation() == GCI_BlueBand) {
1837 shift = 2;
1838 } else if (poBand->GetColorInterpretation() == GCI_AlphaBand) {
1839 shift = 3;
1840 } else {
1841 valid = false;
1842 break;
1843 }
1844 assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
1845 if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, ((unsigned char*)result) + shift, xSize, ySize, GDT_Byte, 4, 4 * xSize) == CE_Failure) {
1846 valid = false;
1847 break;
1848 }
1849 }
1850 GDALClose(poDataset);
1851 if (valid) {
1852 return new FXImage(getApp(), result, IMAGE_OWNED | IMAGE_KEEP | IMAGE_SHMI | IMAGE_SHMP, xSize, ySize);
1853 }
1854 FXFREE(&result);
1855#endif
1856 return nullptr;
1857}
1858
1859
1860void
1863 myDecalsLockMutex.lock();
1864 for (auto& decal : myDecals) {
1865 if (decal.skip2D || decal.filename.empty()) {
1866 continue;
1867 }
1868 if (!decal.initialised) {
1869 try {
1870 FXImage* img = checkGDALImage(decal);
1871 if (img == nullptr) {
1872 img = MFXImageHelper::loadImage(getApp(), decal.filename);
1873 }
1875 decal.glID = GUITexturesHelper::add(img);
1876 delete img;
1877 decal.initialised = true;
1878 } catch (InvalidArgument& e) {
1879 WRITE_ERROR("Could not load '" + decal.filename + "'.\n" + e.what());
1880 decal.skip2D = true;
1881 }
1882 }
1884 if (decal.screenRelative) {
1885 Position center = screenPos2NetPos((int)decal.centerX, (int)decal.centerY);
1886 glTranslated(center.x(), center.y(), decal.layer);
1887 } else {
1888 glTranslated(decal.centerX, decal.centerY, decal.layer);
1889 }
1890 glRotated(decal.rot, 0, 0, 1);
1891 glColor3d(1, 1, 1);
1892 double halfWidth = decal.width / 2.;
1893 double halfHeight = decal.height / 2.;
1894 if (decal.screenRelative) {
1895 halfWidth = p2m(halfWidth);
1896 halfHeight = p2m(halfHeight);
1897 }
1898 GUITexturesHelper::drawTexturedBox(decal.glID, -halfWidth, -halfHeight, halfWidth, halfHeight);
1900 }
1901 myDecalsLockMutex.unlock();
1903}
1904
1905
1906void
1908 int x, y;
1909 FXuint b;
1910 myApp->getCursorPosition(x, y, b);
1911 int appX = myApp->getX();
1912 int popX = x + appX;
1913 int popY = y + myApp->getY();
1914 myPopup->setX(popX);
1915 myPopup->setY(popY);
1916 myPopup->create();
1917 myPopup->show();
1918 // TODO: try to stay on screen even on a right secondary screen in multi-monitor setup
1919 const int rootWidth = getApp()->getRootWindow()->getWidth();
1920 const int rootHeight = getApp()->getRootWindow()->getHeight();
1921 if (popX <= rootWidth) {
1922 const int maxX = (appX < 0) ? 0 : rootWidth;
1923 popX = MIN2(popX, maxX - myPopup->getWidth() - 10);
1924 }
1925 popY = MIN2(popY, rootHeight - myPopup->getHeight() - 50);
1926 myPopup->move(popX, popY);
1928 myChanger->onRightBtnRelease(nullptr);
1929 setFocus();
1930}
1931
1932// ------------ Additional visualisations
1933
1934bool
1936 if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1937 myAdditionallyDrawn[which] = 1;
1938 } else {
1939 myAdditionallyDrawn[which] = myAdditionallyDrawn[which] + 1;
1940 }
1941 update();
1942 return true;
1943}
1944
1945
1946bool
1948 if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1949 return false;
1950 }
1951 int cnt = myAdditionallyDrawn[which];
1952 if (cnt == 1) {
1953 myAdditionallyDrawn.erase(which);
1954 } else {
1955 myAdditionallyDrawn[which] = myAdditionallyDrawn[which] - 1;
1956 }
1957 update();
1958 return true;
1959}
1960
1961
1962bool
1964 if (myAdditionallyDrawn.find(which) == myAdditionallyDrawn.end()) {
1965 return false;
1966 } else {
1967 return true;
1968 }
1969}
1970
1971
1974 Boundary bound = myChanger->getViewport(fixRatio);
1975 glMatrixMode(GL_PROJECTION);
1976 glLoadIdentity();
1977 // as a rough rule, each GLObject is drawn at z = -GUIGlObjectType
1978 // thus, objects with a higher value will be closer (drawn on top)
1979 // // @todo last param should be 0 after modifying all glDraw methods
1980 glOrtho(0, getWidth(), 0, getHeight(), -GLO_MAX - 1, GLO_MAX + 1);
1981 glMatrixMode(GL_MODELVIEW);
1982 glLoadIdentity();
1983 double scaleX = (double)getWidth() / bound.getWidth();
1984 double scaleY = (double)getHeight() / bound.getHeight();
1985 glScaled(scaleX, scaleY, 1);
1986 glTranslated(-bound.xmin(), -bound.ymin(), 0);
1987 // rotate around the center of the screen
1988 //double angle = -90;
1989 if (myChanger->getRotation() != 0) {
1990 glTranslated(bound.getCenter().x(), bound.getCenter().y(), 0);
1991 glRotated(myChanger->getRotation(), 0, 0, 1);
1992 glTranslated(-bound.getCenter().x(), -bound.getCenter().y(), 0);
1993 Boundary rotBound;
1994 double rad = -DEG2RAD(myChanger->getRotation());
1995 rotBound.add(Position(bound.xmin(), bound.ymin()).rotateAround2D(rad, bound.getCenter()));
1996 rotBound.add(Position(bound.xmin(), bound.ymax()).rotateAround2D(rad, bound.getCenter()));
1997 rotBound.add(Position(bound.xmax(), bound.ymin()).rotateAround2D(rad, bound.getCenter()));
1998 rotBound.add(Position(bound.xmax(), bound.ymax()).rotateAround2D(rad, bound.getCenter()));
1999 bound = rotBound;
2000 }
2001 myVisualizationSettings->angle = myChanger->getRotation();
2002 return bound;
2003}
2004
2005
2006double
2008 return myApp->getDelay();
2009}
2010
2011
2012void
2014 myApp->setDelay(delay);
2015}
2016
2017
2018void
2019GUISUMOAbstractView::setBreakpoints(const std::vector<SUMOTime>& breakpoints) {
2020 myApp->setBreakpoints(breakpoints);
2021}
2022
2023
2024void
2026 const GUIVisualizationRainbowSettings& rs, double minValue, double maxValue, bool hasMissingData) {
2027 if (rs.hideMin && rs.hideMax && minValue == std::numeric_limits<double>::infinity()) {
2028 minValue = rs.minThreshold;
2029 maxValue = rs.maxThreshold;
2030 }
2031 if (rs.fixRange) {
2032 if (rs.hideMin) {
2033 minValue = rs.minThreshold;
2034 }
2035 if (rs.hideMax) {
2036 maxValue = rs.maxThreshold;
2037 }
2038 }
2039 if (minValue != std::numeric_limits<double>::infinity()) {
2040 scheme.clear();
2041 // add new thresholds
2047 || hasMissingData) {
2048 scheme.addColor(s.COL_MISSING_DATA, s.MISSING_DATA, "missing data");
2049 }
2050 if (rs.hideMin && !rs.fixRange) {
2051 const double rawRange = maxValue - minValue;
2052 minValue = MAX2(rs.minThreshold + MIN2(1.0, rawRange / 100.0), minValue);
2053 scheme.addColor(RGBColor(204, 204, 204), rs.minThreshold);
2054 }
2055 if (rs.hideMax && !rs.fixRange) {
2056 const double rawRange = maxValue - minValue;
2057 maxValue = MIN2(rs.maxThreshold - MIN2(1.0, rawRange / 100.0), maxValue);
2058 scheme.addColor(RGBColor(204, 204, 204), rs.maxThreshold);
2059 }
2060 const double range = maxValue - minValue;
2061 scheme.addColor(rs.colors.front(), minValue);
2062 const int steps = (int)rs.colors.size() - 1;
2063 if (rs.setNeutral) {
2064 const int steps1 = steps / 2;
2065 const int steps2 = steps - steps1;
2066 const double range1 = rs.neutralThreshold - minValue;
2067 const double range2 = maxValue - rs.neutralThreshold;
2068 for (int i = 1; i < steps1; i++) {
2069 scheme.addColor(rs.colors[i], (minValue + range1 * i / steps1));
2070 }
2071 scheme.addColor(rs.colors[steps1], rs.neutralThreshold);
2072 for (int i = 1; i < steps2; i++) {
2073 scheme.addColor(rs.colors[steps1 + i], (rs.neutralThreshold + range2 * i / steps2));
2074 }
2075 } else {
2076 for (int i = 1; i < steps; i++) {
2077 scheme.addColor(rs.colors[i], (minValue + range * i / steps));
2078 }
2079 }
2080 scheme.addColor(rs.colors.back(), maxValue);
2081 }
2082}
2083
2084
2086 myGLObject(object) {
2087 first = layer;
2088 second.first = object->getType();
2089 second.second = object->getMicrosimID();
2090}
2091
2092
2094 myGLObject(object) {
2095 first = object->getType();
2096 second.first = object->getType();
2097 second.second = object->getMicrosimID();
2098}
2099
2100
2105
2106/****************************************************************************/
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:314
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
#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 processPendingTextureDeletes()
process pending texture deletions
void replacePopup(GUIGLObjectPopupMenu *popUp)
replace PopUp
FXMutex myTextureDeleteMutex
mutex for pending texture deletes
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 queueTextureDelete(unsigned int textureId)
queue a texture for deletion
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.
void clearDecals()
clear all decals
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
std::vector< unsigned int > myPendingTextureDeletes
texture IDs pending deletion
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:43
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:199
static const RGBColor BLACK
Definition RGBColor.h:200
static const RGBColor RED
named colors
Definition RGBColor.h:192
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:45
#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