Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GUIPolygon.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/****************************************************************************/
21// The GUI-version of a polygon
22/****************************************************************************/
23#include <config.h>
24
25#include <string>
35
36#include "GUIPolygon.h"
37
38#ifndef CALLBACK
39#define CALLBACK
40#endif
41
42// ===========================================================================
43// static members
44// ===========================================================================
45
46// minimum number of extra vertices per shape before tesselation artefacts occur
47// (new vertices are needed for some concave polygons)
48#define MAX_COMBINE_INDEX 1024
49// ring buffer to store temporary vertices (x,y,z) needed by combineCallback
51// array index for above array; incremented inside combineCallback
53GLenum myCurrentType = 0;
54std::vector<Position> myCurrentPoints;
56
57// ===========================================================================
58// callbacks definitions
59// ===========================================================================
60
61void CALLBACK beginCallback(GLenum which) {
62 //std::cout << " beginCallback id=" << Named::getIDSecure(myCurrentTesselated) << " type=" << which << "\n";
63 myCurrentType = which;
64 myCurrentPoints.clear();
65}
66
67
75
76
77void CALLBACK vertexCallback(GLvoid* vertex) {
78 GLdouble* p3 = (GLdouble*) vertex;
79 //std::cout << " vertexCallback id=" << Named::getIDSecure(myCurrentTesselated) << " point=" << p3 << "\n";
80 myCurrentPoints.push_back(Position(p3[0], p3[1], p3[2]));
81}
82
83
84void CALLBACK combineCallback(GLdouble coords[3],
85 GLdouble* vertex_data[4],
86 GLfloat weight[4], GLdouble** dataOut) {
87 UNUSED_PARAMETER(weight);
88 UNUSED_PARAMETER(*vertex_data);
90 myCombineVertices[myCombineIndex][0] = coords[0];
91 myCombineVertices[myCombineIndex][1] = coords[1];
92 myCombineVertices[myCombineIndex][2] = coords[2];
94}
95
96void CALLBACK errorCallback(GLenum errorCode) {
97 const GLubyte* estring;
98
99 estring = gluErrorString(errorCode);
100 fprintf(stderr, "Tessellation Error: %s\n", estring);
101 exit(0);
102}
103
104
105
106static const GLdouble INV_POLY_TEX_DIM = 1.0 / 256.0;
107static const GLdouble xPlane[] = {INV_POLY_TEX_DIM, 0.0, 0.0, 0.0};
108static const GLdouble yPlane[] = {0.0, INV_POLY_TEX_DIM, 0.0, 0.0};
109
110
111// ===========================================================================
112// TesselatedPolygon method definitions
113// ===========================================================================
114
115
116void
118 if (myTesselation.empty()) {
119 myCurrentTesselated = this;
120 // draw the tesselated shape
121 size_t numPoints = shape.size() * 3;
122 for (const PositionVector& hole : myHoles) {
123 numPoints += hole.size() * 3;
124 }
125 double* points = new double[numPoints];
126 GLUtesselator* tobj = gluNewTess();
127#ifdef _MSC_VER
128#pragma warning(push)
129#pragma warning(disable: 4191)
130#endif
131#if defined(__GNUC__) && __GNUC__ >= 8
132#pragma GCC diagnostic push
133#pragma GCC diagnostic ignored "-Wcast-function-type"
134#endif
135 gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(CALLBACK*)()) &vertexCallback);
136 gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(CALLBACK*)()) &beginCallback);
137 gluTessCallback(tobj, GLU_TESS_END, (GLvoid(CALLBACK*)()) &endCallback);
138 //gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (CALLBACK*) ()) &errorCallback);
139 gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(CALLBACK*)()) &combineCallback);
140#if defined(__GNUC__) && __GNUC__ >= 8
141#pragma GCC diagnostic pop
142#endif
143#ifdef _MSC_VER
144#pragma warning(pop)
145#endif
146 gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
147 gluTessBeginPolygon(tobj, nullptr);
148 gluTessBeginContour(tobj);
149 for (int i = 0; i < (int)shape.size(); i++) {
150 points[3 * i] = shape[i].x();
151 points[3 * i + 1] = shape[i].y();
152 points[3 * i + 2] = 0.;
153 gluTessVertex(tobj, points + 3 * i, points + 3 * i);
154 }
155 gluTessEndContour(tobj);
156 size_t startIndex = shape.size() * 3;
157 for (const PositionVector& hole : myHoles) {
158 gluTessBeginContour(tobj);
159 for (int i = 0; i < (int)hole.size(); i++) {
160 points[startIndex + 3 * i] = hole[i].x();
161 points[startIndex + 3 * i + 1] = hole[i].y();
162 points[startIndex + 3 * i + 2] = 0.;
163 gluTessVertex(tobj, points + startIndex + 3 * i, points + startIndex + 3 * i);
164 }
165 startIndex += hole.size() * 3;
166 gluTessEndContour(tobj);
167 }
168 gluTessEndPolygon(tobj);
169 gluDeleteTess(tobj);
170 delete[] points;
171 }
172 for (GLPrimitive& pr : myTesselation) {
173 // XXX change to glDrawArrays
174 glBegin(pr.type);
175 for (const Position& p : pr.vert) {
176 glVertex3d(p.x(), p.y(), p.z());
177 }
178 glEnd();
179 }
180}
181
182// ===========================================================================
183// GUIPolygon method definitions
184// ===========================================================================
185
186GUIPolygon::GUIPolygon(const std::string& id, const std::string& type, const RGBColor& color,
187 const PositionVector& shape, bool geo, bool fill, double lineWidth,
188 double layer, double angle, const std::string& imgFile, const std::string& name):
189 TesselatedPolygon(id, type, color, shape, geo, fill, lineWidth, layer, angle, imgFile, name),
191 myRotatedShape(nullptr) {
192 if (angle != 0.) {
193 setShape(shape);
194 }
195}
196
197
201
202
205 GUISUMOAbstractView& parent) {
206 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);
207 buildPopupHeader(ret, app, false);
208 GUIDesigns::buildFXMenuCommand(ret, "(" + getShapeType() + ")", nullptr, nullptr, 0);
209 new FXMenuSeparator(ret);
213 buildShowParamsPopupEntry(ret, false);
214 buildPositionCopyEntry(ret, app);
215 return ret;
216}
217
218
223 // add items
224 ret->mkItem("type", false, getShapeType());
225 ret->mkItem("layer", false, toString(getShapeLayer()));
226 ret->mkItem("name", false, toString(getShapeName()));
227 ret->closeBuilding(this);
228 return ret;
229}
230
231
232double
236
237
240 const PositionVector& shape = myRotatedShape != nullptr ? *myRotatedShape : myShape;
241 Boundary b;
242 b.add(shape.getBoxBoundary());
243 b.grow(2);
244 return b;
245}
246
247
248void
250 // first check if polygon can be drawn
251 if (myIsActive && checkDraw(s, this, this)) {
252 FXMutexLock locker(myLock);
253 // push name (needed for getGUIGlObjectsUnderCursor(...)
255 // draw inner polygon
256 if (myRotatedShape) {
258 } else {
260 }
261 // pop name
263 }
264}
265
266
267void
269 FXMutexLock locker(myLock);
271 if (getShapeNaviDegree() != 0.) {
272 if (myRotatedShape == nullptr) {
274 }
275 const Position& centroid = myShape.getCentroid();
277 myRotatedShape->sub(centroid);
279 myRotatedShape->add(centroid);
280 } else {
281 delete myRotatedShape;
282 myRotatedShape = nullptr;
283 }
284 myTesselation.clear();
285}
286
287
289GUIPolygon::setColor(const GUIVisualizationSettings& s, const SUMOPolygon* polygon, const GUIGlObject* o, bool disableSelectionColor, int alphaOverride) {
290 const GUIColorer& c = s.polyColorer;
291 const int active = c.getActive();
292 RGBColor color;
293 if (s.netedit && active != 1 && gSelected.isSelected(o->getType(), o->getGlID()) && disableSelectionColor) {
294 // override with special selection colors (unless the color scheme is based on selection)
295 color = RGBColor(0, 0, 204);
296 } else if (active == 0) {
297 color = polygon->getShapeColor();
298 } else if (active == 1) {
299 color = c.getScheme().getColor(gSelected.isSelected(o->getType(), o->getGlID()));
300 } else if (active == 2) {
301 color = c.getScheme().getColor(0);
302 } else {
303 // color randomly (by pointer hash)
304 std::hash<const SUMOPolygon*> ptr_hash;
305 const double hue = (double)(ptr_hash(polygon) % 360); // [0-360]
306 const double sat = (double)((ptr_hash(polygon) / 360) % 67) / 100.0 + 0.33; // [0.33-1]
307 color = RGBColor::fromHSV(hue, sat, 1.);
308 }
309 if (alphaOverride >= 0 && alphaOverride <= 255) {
310 color.setAlpha((unsigned char)alphaOverride);
311 }
312 GLHelper::setColor(color);
313 return color;
314}
315
316
317bool
319 if (o->getExaggeration(s) == 0) {
320 return false;
321 }
322 Boundary boundary = polygon->getShape().getBoxBoundary();
323 if (s.scale * MAX2(boundary.getWidth(), boundary.getHeight()) < s.polySize.minSize) {
324 return false;
325 }
326 if (polygon->getFill()) {
327 if (polygon->getShape().size() < 3) {
328 return false;
329 }
330 } else {
331 if (polygon->getShape().size() < 2) {
332 return false;
333 }
334 }
335 return true;
336}
337
338
339void
341 const PositionVector shape, const double layer, const bool fill,
342 const bool disableSelectionColor, const int alphaOverride, const bool disableText) {
344 glTranslated(0, 0, layer);
345 setColor(s, polygon, o, disableSelectionColor, alphaOverride);
346 int textureID = -1;
347 if (fill) {
348 const std::string& file = polygon->getShapeImgFile();
349 if (file != "") {
350 textureID = GUITexturesHelper::getTextureID(file, true);
351 }
352 }
353 // init generation of texture coordinates
354 if (textureID >= 0) {
355 glEnable(GL_TEXTURE_2D);
356 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
357 glDisable(GL_CULL_FACE);
358 glDisable(GL_DEPTH_TEST); // without DEPTH_TEST vehicles may be drawn below roads
359 glDisable(GL_LIGHTING);
360 glDisable(GL_COLOR_MATERIAL);
361 glDisable(GL_ALPHA_TEST);
362 glEnable(GL_BLEND);
363 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
364 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
365 glBindTexture(GL_TEXTURE_2D, textureID);
366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
367 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
368 // http://www.gamedev.net/topic/133564-glutesselation-and-texture-mapping/
369 glEnable(GL_TEXTURE_GEN_S);
370 glEnable(GL_TEXTURE_GEN_T);
371 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
372 glTexGendv(GL_S, GL_OBJECT_PLANE, xPlane);
373 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
374 glTexGendv(GL_T, GL_OBJECT_PLANE, yPlane);
375 }
376 if (fill) {
377 polygon->drawTesselation(shape);
378 } else {
379 GLHelper::drawLine(shape);
380 GLHelper::drawBoxLines(shape, polygon->getLineWidth() * o->getExaggeration(s));
381 }
382
383 // de-init generation of texture coordinates
384 if (textureID >= 0) {
385 glEnable(GL_DEPTH_TEST);
386 glBindTexture(GL_TEXTURE_2D, 0);
387 glDisable(GL_TEXTURE_2D);
388 glDisable(GL_TEXTURE_GEN_S);
389 glDisable(GL_TEXTURE_GEN_T);
390 }
392 if (s.geometryIndices.show(o)) {
394 }
395 if (!disableText) {
396 const Position& namePos = shape.getPolygonCenter();
397 o->drawName(namePos, s.scale, s.polyName, s.angle);
398 if (s.polyType.show(o)) {
399 const Position p = namePos + Position(0, -0.6 * s.polyType.size / s.scale);
401 }
402 }
403}
404
405/****************************************************************************/
@ GLO_POLYGON
polygon
GUISelectedStorage gSelected
A global holder of selected objects.
GUIIcon
An enumeration of icons used by the gui applications.
Definition GUIIcons.h:33
void CALLBACK errorCallback(GLenum errorCode)
static const GLdouble INV_POLY_TEX_DIM
void CALLBACK combineCallback(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], GLdouble **dataOut)
const TesselatedPolygon * myCurrentTesselated
GLdouble myCombineVertices[MAX_COMBINE_INDEX][3]
#define MAX_COMBINE_INDEX
int myCombineIndex
static const GLdouble yPlane[]
void CALLBACK beginCallback(GLenum which)
GLenum myCurrentType
void CALLBACK endCallback(void)
#define CALLBACK
std::vector< Position > myCurrentPoints
void CALLBACK vertexCallback(GLvoid *vertex)
static const GLdouble xPlane[]
#define DEG2RAD(x)
Definition GeomHelper.h:35
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:75
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
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition GLHelper.cpp:433
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:649
static void pushName(unsigned int name)
push Name
Definition GLHelper.cpp:140
static void popMatrix()
pop matrix
Definition GLHelper.cpp:131
static void drawBoxLines(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double width, int cornerDetail=0, double offset=0)
Draws thick lines.
Definition GLHelper.cpp:348
static void debugVertices(const PositionVector &shape, const GUIVisualizationTextSettings &settings, double scale, double layer=1024)
draw vertex numbers for the given shape (in a random color)
Definition GLHelper.cpp:939
static void popName()
pop Name
Definition GLHelper.cpp:149
static void pushMatrix()
push matrix
Definition GLHelper.cpp:118
static void drawTextSettings(const GUIVisualizationTextSettings &settings, const std::string &text, const Position &pos, const double scale, const double angle=0, const double layer=2048, const int align=0)
Definition GLHelper.cpp:773
static FXMenuCommand * buildFXMenuCommand(FXComposite *p, const std::string &text, FXIcon *icon, FXObject *tgt, FXSelector sel, const bool disable=false)
build menu command
The popup menu of a globject.
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, const GUIMainWindow &app, bool addSeparator=true) const
Builds an entry which allows to copy the cursor position if geo projection is used,...
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
virtual double getExaggeration(const GUIVisualizationSettings &s) const
return exaggeration associated with this GLObject
void buildSelectionPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to (de)select the object.
GUIGlID getGlID() const
Returns the numerical id of the object.
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0, bool forceShow=false) const
draw name of item
A window containing a gl-object's parameter.
void mkItem(const char *name, bool dynamic, ValueSource< T > *src)
Adds a row which obtains its value from a ValueSource.
void closeBuilding(const Parameterised *p=0)
Closes the building of the table.
static void drawInnerPolygon(const GUIVisualizationSettings &s, const TesselatedPolygon *polygon, const GUIGlObject *o, const PositionVector shape, const double layer, const bool fill, const bool disableSelectionColor=false, const int alphaOverride=-1, const bool disableText=false)
draw inner Polygon (before pushName() )
static bool checkDraw(const GUIVisualizationSettings &s, const SUMOPolygon *polygon, const GUIGlObject *o)
check if Polygon can be drawn
virtual void drawGL(const GUIVisualizationSettings &s) const override
Draws the object.
Boundary getCenteringBoundary() const override
Returns the boundary to which the view shall be centered in order to show the object.
PositionVector * myRotatedShape
shape rotated on the centroid, if rotation is needed, nullptr otherwise
Definition GUIPolygon.h:187
~GUIPolygon()
Destructor.
FXMutex myLock
The mutex used to avoid concurrent updates of the shape.
Definition GUIPolygon.h:184
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent) override
Returns an own parameter window.
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent) override
Returns an own popup-menu.
GUIPolygon(const std::string &id, const std::string &type, const RGBColor &color, const PositionVector &shape, bool geo, bool fill, double lineWidth, double layer=0, double angle=0, const std::string &imgFile="", const std::string &name=DEFAULT_NAME)
Constructor.
static RGBColor setColor(const GUIVisualizationSettings &s, const SUMOPolygon *polygon, const GUIGlObject *o, bool disableSelectionColor, int alphaOverride)
set color
double getExaggeration(const GUIVisualizationSettings &s) const override
return exaggeration associated with this GLObject
bool myIsActive
Is the polygon will be drawn or not.
Definition GUIPolygon.h:190
virtual void setShape(const PositionVector &shape) override
set a new shape and update the tesselation
T getColor(const double value) const
bool isSelected(GUIGlObjectType type, GUIGlID id)
Returns the information whether the object with the given type and id is selected.
static int getTextureID(const std::string &filename, const bool mirrorX=false)
return texture id for the given filename (initialize on first use)
Stores the information about how to visualize structures.
double polyCustomLayer
the custom layer for polygons
GUIVisualizationTextSettings geometryIndices
GUIColorer polyColorer
The polygon colorer.
bool polyUseCustomLayer
whether the rendering layer of polygons should be overriden
double scale
information about a lane's width (temporary, used for a single view)
bool netedit
Whether the settings are for Netedit.
GUIVisualizationTextSettings polyName
GUIVisualizationSizeSettings polySize
GUIVisualizationTextSettings polyType
double angle
The current view rotation angle.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
A list of positions.
void rotate2D(double angle)
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
void add(double xoff, double yoff, double zoff)
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
Position getCentroid() const
Returns the centroid (closes the polygon if unclosed)
void sub(const Position &offset)
void setAlpha(unsigned char alpha)
Sets a new alpha value.
Definition RGBColor.cpp:108
static RGBColor fromHSV(double h, double s, double v)
Converts the given hsv-triplet to rgb, inspired by http://alvyray.com/Papers/CG/hsv2rgb....
Definition RGBColor.cpp:403
const PositionVector & getShape() const
Returns the shape of the polygon.
PositionVector myShape
The positions of the polygon.
double getLineWidth() const
Returns whether the polygon is filled.
virtual void setShape(const PositionVector &shape)
Sets the shape of the polygon.
std::vector< PositionVector > myHoles
The collection of the holes of the polygon, each given by a sequence of coodinates.
bool getFill() const
Returns whether the polygon is filled.
const std::string getShapeName() const
Returns the name of the Shape.
Definition Shape.h:108
const std::string & getShapeType() const
Returns the (abstract) type of the Shape.
Definition Shape.h:75
double getShapeLayer() const
Returns the layer of the Shape.
Definition Shape.h:89
const std::string & getShapeImgFile() const
Returns the imgFile of the Shape.
Definition Shape.h:103
const RGBColor & getShapeColor() const
Returns the color of the Shape.
Definition Shape.h:82
double getShapeNaviDegree() const
Returns the angle of the Shape in navigational degrees.
Definition Shape.h:96
std::vector< GLPrimitive > myTesselation
id of the display list for the cached tesselation
Definition GUIPolygon.h:72
void drawTesselation(const PositionVector &shape) const
perform the tesselation / drawing
#define UNUSED_PARAMETER(x)
#define CALLBACK
Definition fxexdefs.h:48
most likely I'm reinventing the wheel here
Definition GUIPolygon.h:37
std::vector< Position > vert
Definition GUIPolygon.h:39
GLenum type
Definition GUIPolygon.h:38
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
double minSize
The minimum size to draw this object.
bool show(const GUIGlObject *o) const
whether to show the text