Eclipse SUMO - Simulation of Urban MObility
GUIPolygon.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2001-2022 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// ===========================================================================
44// static members
45// ===========================================================================
46
47// minimum number of extra vertices per shape before tesselation artefacts occur
48// (new vertices are needed for some concave polygons)
49#define MAX_COMBINE_INDEX 1024
50// ring buffer to store temporary vertices (x,y,z) needed by combineCallback
52// array index for above array; incremented inside combineCallback
54GLenum myCurrentType = 0;
55std::vector<Position> myCurrentPoints;
57
58// ===========================================================================
59// callbacks definitions
60// ===========================================================================
61
62void CALLBACK beginCallback(GLenum which) {
63 //std::cout << " beginCallback id=" << Named::getIDSecure(myCurrentTesselated) << " type=" << which << "\n";
64 myCurrentType = which;
65 myCurrentPoints.clear();
66}
67
68
72 glp.type = myCurrentType;
74 myCurrentPoints.clear();
75}
76
77
78void CALLBACK vertexCallback(GLvoid* vertex) {
79 GLdouble* p3 = (GLdouble*) vertex;
80 //std::cout << " vertexCallback id=" << Named::getIDSecure(myCurrentTesselated) << " point=" << p3 << "\n";
81 myCurrentPoints.push_back(Position(p3[0], p3[1], p3[2]));
82}
83
84
85void CALLBACK combineCallback(GLdouble coords[3],
86 GLdouble* vertex_data[4],
87 GLfloat weight[4], GLdouble** dataOut) {
88 UNUSED_PARAMETER(weight);
89 UNUSED_PARAMETER(*vertex_data);
91 myCombineVertices[myCombineIndex][0] = coords[0];
92 myCombineVertices[myCombineIndex][1] = coords[1];
93 myCombineVertices[myCombineIndex][2] = coords[2];
95}
96
97void CALLBACK errorCallback(GLenum errorCode) {
98 const GLubyte* estring;
99
100 estring = gluErrorString(errorCode);
101 fprintf(stderr, "Tessellation Error: %s\n", estring);
102 exit(0);
103}
104
105
106
107static const GLdouble INV_POLY_TEX_DIM = 1.0 / 256.0;
108static const GLdouble xPlane[] = {INV_POLY_TEX_DIM, 0.0, 0.0, 0.0};
109static const GLdouble yPlane[] = {0.0, INV_POLY_TEX_DIM, 0.0, 0.0};
110
111
112// ===========================================================================
113// TesselatedPolygon method definitions
114// ===========================================================================
115
116
117void
119 if (myTesselation.empty()) {
120 myCurrentTesselated = this;
121 // draw the tesselated shape
122 double* points = new double[shape.size() * 3];
123 GLUtesselator* tobj = gluNewTess();
124#ifdef _MSC_VER
125#pragma warning(push)
126#pragma warning(disable: 4191)
127#endif
128#if defined(__GNUC__) && __GNUC__ >= 8
129#pragma GCC diagnostic push
130#pragma GCC diagnostic ignored "-Wcast-function-type"
131#endif
132 gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(CALLBACK*)()) &vertexCallback);
133 gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(CALLBACK*)()) &beginCallback);
134 gluTessCallback(tobj, GLU_TESS_END, (GLvoid(CALLBACK*)()) &endCallback);
135 //gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (CALLBACK*) ()) &errorCallback);
136 gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(CALLBACK*)()) &combineCallback);
137#if defined(__GNUC__) && __GNUC__ >= 8
138#pragma GCC diagnostic pop
139#endif
140#ifdef _MSC_VER
141#pragma warning(pop)
142#endif
143 gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
144 gluTessBeginPolygon(tobj, nullptr);
145 gluTessBeginContour(tobj);
146 for (int i = 0; i < (int)shape.size(); i++) {
147 points[3 * i] = shape[i].x();
148 points[3 * i + 1] = shape[i].y();
149 points[3 * i + 2] = 0.;
150 gluTessVertex(tobj, points + 3 * i, points + 3 * i);
151 }
152 gluTessEndContour(tobj);
153
154 gluTessEndPolygon(tobj);
155 gluDeleteTess(tobj);
156 delete[] points;
157
158 }
159 for (GLPrimitive& pr : myTesselation) {
160 // XXX change to glDrawArrays
161 glBegin(pr.type);
162 for (const Position& p : pr.vert) {
163 glVertex3d(p.x(), p.y(), p.z());
164 }
165 glEnd();
166 }
167}
168
169
170// ===========================================================================
171// GUIPolygon method definitions
172// ===========================================================================
173
174GUIPolygon::GUIPolygon(const std::string& id, const std::string& type, const RGBColor& color,
175 const PositionVector& shape, bool geo, bool fill,
176 double lineWidth, double layer, double angle, const std::string& imgFile,
177 bool relativePath, const std::string& name):
178 TesselatedPolygon(id, type, color, shape, geo, fill, lineWidth, layer, angle, imgFile, relativePath, name),
180 myRotatedShape(nullptr) {
181 if (angle != 0.) {
182 setShape(shape);
183 }
184}
185
186
188 delete myRotatedShape;
189}
190
191
194 GUISUMOAbstractView& parent) {
195 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
196 buildPopupHeader(ret, app, false);
197 GUIDesigns::buildFXMenuCommand(ret, "(" + getShapeType() + ")", nullptr, nullptr, 0);
198 new FXMenuSeparator(ret);
202 buildShowParamsPopupEntry(ret, false);
203 buildPositionCopyEntry(ret, app);
204 return ret;
205}
206
207
212 // add items
213 ret->mkItem("type", false, getShapeType());
214 ret->mkItem("layer", false, toString(getShapeLayer()));
215 ret->mkItem("name", false, toString(getShapeName()));
216 ret->closeBuilding(this);
217 return ret;
218}
219
220
221double
223 return s.polySize.getExaggeration(s, this);
224}
225
226
229 const PositionVector& shape = myRotatedShape != nullptr ? *myRotatedShape : myShape;
230 Boundary b;
231 b.add(shape.getBoxBoundary());
232 b.grow(2);
233 return b;
234}
235
236
237void
239 // first check if polygon can be drawn
240 if (checkDraw(s, this, this)) {
241 FXMutexLock locker(myLock);
242 // push name (needed for getGUIGlObjectsUnderCursor(...)
244 // draw inner polygon
245 if (myRotatedShape) {
247 } else {
248 drawInnerPolygon(s, this, this, myShape, getShapeLayer(), getFill());
249 }
250 // pop name
252 }
253}
254
255
256void
258 FXMutexLock locker(myLock);
260 if (getShapeNaviDegree() != 0.) {
261 if (myRotatedShape == nullptr) {
263 }
264 const Position& centroid = myShape.getCentroid();
266 myRotatedShape->sub(centroid);
268 myRotatedShape->add(centroid);
269 } else {
270 delete myRotatedShape;
271 myRotatedShape = nullptr;
272 }
273 myTesselation.clear();
274}
275
276
278GUIPolygon::setColor(const GUIVisualizationSettings& s, const SUMOPolygon* polygon, const GUIGlObject* o, bool disableSelectionColor, int alphaOverride) {
279 const GUIColorer& c = s.polyColorer;
280 const int active = c.getActive();
281 RGBColor color;
282 if (s.netedit && active != 1 && gSelected.isSelected(o->getType(), o->getGlID()) && disableSelectionColor) {
283 // override with special selection colors (unless the color scheme is based on selection)
284 color = RGBColor(0, 0, 204);
285 } else if (active == 0) {
286 color = polygon->getShapeColor();
287 } else if (active == 1) {
288 color = c.getScheme().getColor(gSelected.isSelected(o->getType(), o->getGlID()));
289 } else if (active == 2) {
290 color = c.getScheme().getColor(0);
291 } else {
292 // color randomly (by pointer hash)
293 std::hash<const SUMOPolygon*> ptr_hash;
294 const double hue = (double)(ptr_hash(polygon) % 360); // [0-360]
295 const double sat = (double)((ptr_hash(polygon) / 360) % 67) / 100.0 + 0.33; // [0.33-1]
296 color = RGBColor::fromHSV(hue, sat, 1.);
297 }
298 if (alphaOverride >= 0 && alphaOverride <= 255) {
299 color.setAlpha((unsigned char)alphaOverride);
300 }
301 GLHelper::setColor(color);
302 return color;
303}
304
305
306bool
308 if (o->getExaggeration(s) == 0) {
309 return false;
310 }
311 Boundary boundary = polygon->getShape().getBoxBoundary();
312 if (s.scale * MAX2(boundary.getWidth(), boundary.getHeight()) < s.polySize.minSize) {
313 return false;
314 }
315 if (polygon->getFill()) {
316 if (polygon->getShape().size() < 3) {
317 return false;
318 }
319 } else {
320 if (polygon->getShape().size() < 2) {
321 return false;
322 }
323 }
324 return true;
325}
326
327
328void
330 const PositionVector shape, const double layer, const bool fill,
331 const bool disableSelectionColor, const int alphaOverride, const bool disableText) {
333 glTranslated(0, 0, layer);
334 setColor(s, polygon, o, disableSelectionColor, alphaOverride);
335 int textureID = -1;
336 if (fill) {
337 const std::string& file = polygon->getShapeImgFile();
338 if (file != "") {
339 textureID = GUITexturesHelper::getTextureID(file, true);
340 }
341 }
342 // init generation of texture coordinates
343 if (textureID >= 0) {
344 glEnable(GL_TEXTURE_2D);
345 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
346 glDisable(GL_CULL_FACE);
347 glDisable(GL_DEPTH_TEST); // without DEPTH_TEST vehicles may be drawn below roads
348 glDisable(GL_LIGHTING);
349 glDisable(GL_COLOR_MATERIAL);
350 glDisable(GL_ALPHA_TEST);
351 glEnable(GL_BLEND);
352 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
353 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
354 glBindTexture(GL_TEXTURE_2D, textureID);
355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
357 // http://www.gamedev.net/topic/133564-glutesselation-and-texture-mapping/
358 glEnable(GL_TEXTURE_GEN_S);
359 glEnable(GL_TEXTURE_GEN_T);
360 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
361 glTexGendv(GL_S, GL_OBJECT_PLANE, xPlane);
362 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
363 glTexGendv(GL_T, GL_OBJECT_PLANE, yPlane);
364 }
365 if (fill) {
366 polygon->drawTesselation(shape);
367 } else {
368 GLHelper::drawLine(shape);
369 GLHelper::drawBoxLines(shape, polygon->getLineWidth() * o->getExaggeration(s));
370 }
371
372 // de-init generation of texture coordinates
373 if (textureID >= 0) {
374 glEnable(GL_DEPTH_TEST);
375 glBindTexture(GL_TEXTURE_2D, 0);
376 glDisable(GL_TEXTURE_2D);
377 glDisable(GL_TEXTURE_GEN_S);
378 glDisable(GL_TEXTURE_GEN_T);
379 }
381 if (s.geometryIndices.show(o)) {
383 }
384 if (!disableText) {
385 const Position& namePos = shape.getPolygonCenter();
386 o->drawName(namePos, s.scale, s.polyName, s.angle);
387 if (s.polyType.show(o)) {
388 const Position p = namePos + Position(0, -0.6 * s.polyType.size / s.scale);
390 }
391 }
392}
393
394/****************************************************************************/
@ GLO_POLYGON
a 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)
Definition: GUIPolygon.cpp:97
static const GLdouble INV_POLY_TEX_DIM
Definition: GUIPolygon.cpp:107
void CALLBACK combineCallback(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], GLdouble **dataOut)
Definition: GUIPolygon.cpp:85
const TesselatedPolygon * myCurrentTesselated
Definition: GUIPolygon.cpp:56
GLdouble myCombineVertices[MAX_COMBINE_INDEX][3]
Definition: GUIPolygon.cpp:51
#define MAX_COMBINE_INDEX
Definition: GUIPolygon.cpp:49
int myCombineIndex
Definition: GUIPolygon.cpp:53
static const GLdouble yPlane[]
Definition: GUIPolygon.cpp:109
void CALLBACK beginCallback(GLenum which)
Definition: GUIPolygon.cpp:62
GLenum myCurrentType
Definition: GUIPolygon.cpp:54
void CALLBACK endCallback(void)
Definition: GUIPolygon.cpp:69
#define CALLBACK
Definition: GUIPolygon.cpp:39
std::vector< Position > myCurrentPoints
Definition: GUIPolygon.cpp:55
void CALLBACK vertexCallback(GLvoid *vertex)
Definition: GUIPolygon.cpp:78
static const GLdouble xPlane[]
Definition: GUIPolygon.cpp:108
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MAX2(T a, T b)
Definition: StdDefs.h:77
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:78
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:300
double getHeight() const
Returns the height of the boundary (y-axis)
Definition: Boundary.cpp:160
double getWidth() const
Returns the width of the boudary (x-axis)
Definition: Boundary.cpp:154
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition: GLHelper.cpp:421
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:583
static void pushName(unsigned int name)
push Name
Definition: GLHelper.cpp:139
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:130
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:329
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:880
static void popName()
pop Name
Definition: GLHelper.cpp:148
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:117
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:716
static FXMenuCommand * buildFXMenuCommand(FXComposite *p, const std::string &text, FXIcon *icon, FXObject *tgt, FXSelector sel)
build menu command
Definition: GUIDesigns.cpp:42
The popup menu of a globject.
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.
Definition: GUIGlObject.h:154
virtual double getExaggeration(const GUIVisualizationSettings &s) const =0
return exaggeration associated with this GLObject
void buildSelectionPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to (de)select the object.
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, const GUIMainWindow &app) const
Builds an entry which allows to copy the cursor position if geo projection is used,...
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GUIGlObject.h:102
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() )
Definition: GUIPolygon.cpp:329
static bool checkDraw(const GUIVisualizationSettings &s, const SUMOPolygon *polygon, const GUIGlObject *o)
check if Polygon can be drawn
Definition: GUIPolygon.cpp:307
virtual void drawGL(const GUIVisualizationSettings &s) const override
Draws the object.
Definition: GUIPolygon.cpp:238
Boundary getCenteringBoundary() const override
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GUIPolygon.cpp:228
PositionVector * myRotatedShape
shape rotated on the centroid, if rotation is needed, nullptr otherwise
Definition: GUIPolygon.h:181
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="", bool relativePath=false, const std::string &name=DEFAULT_NAME)
Constructor.
Definition: GUIPolygon.cpp:174
~GUIPolygon()
Destructor.
Definition: GUIPolygon.cpp:187
FXMutex myLock
The mutex used to avoid concurrent updates of the shape.
Definition: GUIPolygon.h:178
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent) override
Returns an own parameter window.
Definition: GUIPolygon.cpp:209
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent) override
Returns an own popup-menu.
Definition: GUIPolygon.cpp:193
static RGBColor setColor(const GUIVisualizationSettings &s, const SUMOPolygon *polygon, const GUIGlObject *o, bool disableSelectionColor, int alphaOverride)
set color
Definition: GUIPolygon.cpp:278
double getExaggeration(const GUIVisualizationSettings &s) const override
return exaggeration associated with this GLObject
Definition: GUIPolygon.cpp:222
virtual void setShape(const PositionVector &shape) override
set a new shape and update the tesselation
Definition: GUIPolygon.cpp:257
const 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.
GUIVisualizationTextSettings geometryIndices
GUIColorer polyColorer
The polygon colorer.
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
double x() const
Returns the x-position.
Definition: Position.h:55
double z() const
Returns the z-position.
Definition: Position.h:65
double y() const
Returns the y-position.
Definition: Position.h:60
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:371
const PositionVector & getShape() const
Returns whether the shape of the polygon.
Definition: SUMOPolygon.cpp:52
PositionVector myShape
The positions of the polygon.
Definition: SUMOPolygon.h:121
double getLineWidth() const
Returns whether the polygon is filled.
Definition: SUMOPolygon.cpp:64
virtual void setShape(const PositionVector &shape)
Sets the shape of the polygon.
Definition: SUMOPolygon.cpp:82
bool getFill() const
Returns whether the polygon is filled.
Definition: SUMOPolygon.cpp:58
const std::string getShapeName() const
Returns the name of the Shape.
Definition: Shape.h:110
const std::string & getShapeType() const
Returns the (abstract) type of the Shape.
Definition: Shape.h:77
double getShapeLayer() const
Returns the layer of the Shape.
Definition: Shape.h:91
const std::string & getShapeImgFile() const
Returns the imgFile of the Shape.
Definition: Shape.h:105
const RGBColor & getShapeColor() const
Returns the color of the Shape.
Definition: Shape.h:84
double getShapeNaviDegree() const
Returns the angle of the Shape in navigational degrees.
Definition: Shape.h:98
std::vector< GLPrimitive > myTesselation
id of the display list for the cached tesselation
Definition: GUIPolygon.h:74
void drawTesselation(const PositionVector &shape) const
Definition: GUIPolygon.cpp:118
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