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-2024 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
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// ===========================================================================
184// GUIPolygon method definitions
185// ===========================================================================
186
187GUIPolygon::GUIPolygon(const std::string& id, const std::string& type, const RGBColor& color,
188 const PositionVector& shape, bool geo, bool fill,
189 double lineWidth, double layer, double angle, const std::string& imgFile,
190 bool relativePath, const std::string& name):
191 TesselatedPolygon(id, type, color, shape, geo, fill, lineWidth, layer, angle, imgFile, relativePath, name),
193 myRotatedShape(nullptr) {
194 if (angle != 0.) {
195 setShape(shape);
196 }
197}
198
199
203
204
207 GUISUMOAbstractView& parent) {
208 GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
209 buildPopupHeader(ret, app, false);
210 GUIDesigns::buildFXMenuCommand(ret, "(" + getShapeType() + ")", nullptr, nullptr, 0);
211 new FXMenuSeparator(ret);
215 buildShowParamsPopupEntry(ret, false);
216 buildPositionCopyEntry(ret, app);
217 return ret;
218}
219
220
225 // add items
226 ret->mkItem("type", false, getShapeType());
227 ret->mkItem("layer", false, toString(getShapeLayer()));
228 ret->mkItem("name", false, toString(getShapeName()));
229 ret->closeBuilding(this);
230 return ret;
231}
232
233
234double
238
239
242 const PositionVector& shape = myRotatedShape != nullptr ? *myRotatedShape : myShape;
243 Boundary b;
244 b.add(shape.getBoxBoundary());
245 b.grow(2);
246 return b;
247}
248
249
250void
252 // first check if polygon can be drawn
253 if (myIsActive && checkDraw(s, this, this)) {
254 FXMutexLock locker(myLock);
255 // push name (needed for getGUIGlObjectsUnderCursor(...)
257 // draw inner polygon
258 if (myRotatedShape) {
260 } else {
262 }
263 // pop name
265 }
266}
267
268
269void
271 FXMutexLock locker(myLock);
273 if (getShapeNaviDegree() != 0.) {
274 if (myRotatedShape == nullptr) {
276 }
277 const Position& centroid = myShape.getCentroid();
279 myRotatedShape->sub(centroid);
281 myRotatedShape->add(centroid);
282 } else {
283 delete myRotatedShape;
284 myRotatedShape = nullptr;
285 }
286 myTesselation.clear();
287}
288
289
291GUIPolygon::setColor(const GUIVisualizationSettings& s, const SUMOPolygon* polygon, const GUIGlObject* o, bool disableSelectionColor, int alphaOverride) {
292 const GUIColorer& c = s.polyColorer;
293 const int active = c.getActive();
294 RGBColor color;
295 if (s.netedit && active != 1 && gSelected.isSelected(o->getType(), o->getGlID()) && disableSelectionColor) {
296 // override with special selection colors (unless the color scheme is based on selection)
297 color = RGBColor(0, 0, 204);
298 } else if (active == 0) {
299 color = polygon->getShapeColor();
300 } else if (active == 1) {
301 color = c.getScheme().getColor(gSelected.isSelected(o->getType(), o->getGlID()));
302 } else if (active == 2) {
303 color = c.getScheme().getColor(0);
304 } else {
305 // color randomly (by pointer hash)
306 std::hash<const SUMOPolygon*> ptr_hash;
307 const double hue = (double)(ptr_hash(polygon) % 360); // [0-360]
308 const double sat = (double)((ptr_hash(polygon) / 360) % 67) / 100.0 + 0.33; // [0.33-1]
309 color = RGBColor::fromHSV(hue, sat, 1.);
310 }
311 if (alphaOverride >= 0 && alphaOverride <= 255) {
312 color.setAlpha((unsigned char)alphaOverride);
313 }
314 GLHelper::setColor(color);
315 return color;
316}
317
318
319bool
321 if (o->getExaggeration(s) == 0) {
322 return false;
323 }
324 Boundary boundary = polygon->getShape().getBoxBoundary();
325 if (s.scale * MAX2(boundary.getWidth(), boundary.getHeight()) < s.polySize.minSize) {
326 return false;
327 }
328 if (polygon->getFill()) {
329 if (polygon->getShape().size() < 3) {
330 return false;
331 }
332 } else {
333 if (polygon->getShape().size() < 2) {
334 return false;
335 }
336 }
337 return true;
338}
339
340
341void
343 const PositionVector shape, const double layer, const bool fill,
344 const bool disableSelectionColor, const int alphaOverride, const bool disableText) {
346 glTranslated(0, 0, layer);
347 setColor(s, polygon, o, disableSelectionColor, alphaOverride);
348 int textureID = -1;
349 if (fill) {
350 const std::string& file = polygon->getShapeImgFile();
351 if (file != "") {
352 textureID = GUITexturesHelper::getTextureID(file, true);
353 }
354 }
355 // init generation of texture coordinates
356 if (textureID >= 0) {
357 glEnable(GL_TEXTURE_2D);
358 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
359 glDisable(GL_CULL_FACE);
360 glDisable(GL_DEPTH_TEST); // without DEPTH_TEST vehicles may be drawn below roads
361 glDisable(GL_LIGHTING);
362 glDisable(GL_COLOR_MATERIAL);
363 glDisable(GL_ALPHA_TEST);
364 glEnable(GL_BLEND);
365 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
366 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
367 glBindTexture(GL_TEXTURE_2D, textureID);
368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
370 // http://www.gamedev.net/topic/133564-glutesselation-and-texture-mapping/
371 glEnable(GL_TEXTURE_GEN_S);
372 glEnable(GL_TEXTURE_GEN_T);
373 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
374 glTexGendv(GL_S, GL_OBJECT_PLANE, xPlane);
375 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
376 glTexGendv(GL_T, GL_OBJECT_PLANE, yPlane);
377 }
378 if (fill) {
379 polygon->drawTesselation(shape);
380 } else {
381 GLHelper::drawLine(shape);
382 GLHelper::drawBoxLines(shape, polygon->getLineWidth() * o->getExaggeration(s));
383 }
384
385 // de-init generation of texture coordinates
386 if (textureID >= 0) {
387 glEnable(GL_DEPTH_TEST);
388 glBindTexture(GL_TEXTURE_2D, 0);
389 glDisable(GL_TEXTURE_2D);
390 glDisable(GL_TEXTURE_GEN_S);
391 glDisable(GL_TEXTURE_GEN_T);
392 }
394 if (s.geometryIndices.show(o)) {
396 }
397 if (!disableText) {
398 const Position& namePos = shape.getPolygonCenter();
399 o->drawName(namePos, s.scale, s.polyName, s.angle);
400 if (s.polyType.show(o)) {
401 const Position p = namePos + Position(0, -0.6 * s.polyType.size / s.scale);
403 }
404 }
405}
406
407/****************************************************************************/
@ 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
#define UNUSED_PARAMETER(x)
Definition StdDefs.h:30
T MAX2(T a, T b)
Definition StdDefs.h:82
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:343
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:438
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:654
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:347
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:953
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:787
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 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.
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.
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:190
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.
~GUIPolygon()
Destructor.
FXMutex myLock
The mutex used to avoid concurrent updates of the shape.
Definition GUIPolygon.h:187
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent) override
Returns an own parameter window.
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent) override
Returns an own popup-menu.
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:193
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:371
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: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
perform the tesselation / drawing
#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