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>
26 #include <utils/geom/GeomHelper.h>
33 #include <utils/gui/div/GLHelper.h>
35 
36 #include "GUIPolygon.h"
37 
38 #ifndef CALLBACK
39 #define CALLBACK
40 #endif
41 
42 //#define GUIPolygon_DEBUG_DRAW_VERTICES
43 
44 // ===========================================================================
45 // callbacks definitions
46 // ===========================================================================
47 
48 void CALLBACK beginCallback(GLenum which) {
49  glBegin(which);
50 }
51 
52 
53 void CALLBACK errorCallback(GLenum errorCode) {
54  const GLubyte* estring;
55 
56  estring = gluErrorString(errorCode);
57  fprintf(stderr, "Tessellation Error: %s\n", estring);
58  exit(0);
59 }
60 
61 
62 void CALLBACK endCallback(void) {
63  glEnd();
64 }
65 
66 
67 void CALLBACK vertexCallback(GLvoid* vertex) {
68  glVertex3dv((GLdouble*) vertex);
69 }
70 
71 
72 void CALLBACK combineCallback(GLdouble coords[3],
73  GLdouble* vertex_data[4],
74  GLfloat weight[4], GLdouble** dataOut) {
75  UNUSED_PARAMETER(weight);
76  UNUSED_PARAMETER(*vertex_data);
77  GLdouble* vertex;
78 
79  vertex = (GLdouble*) malloc(7 * sizeof(GLdouble));
80 
81  vertex[0] = coords[0];
82  vertex[1] = coords[1];
83  vertex[2] = coords[2];
84  *dataOut = vertex;
85 }
86 
87 static const GLdouble INV_POLY_TEX_DIM = 1.0 / 256.0;
88 static const GLdouble xPlane[] = {INV_POLY_TEX_DIM, 0.0, 0.0, 0.0};
89 static const GLdouble yPlane[] = {0.0, INV_POLY_TEX_DIM, 0.0, 0.0};
90 
91 // ===========================================================================
92 // method definitions
93 // ===========================================================================
94 
95 GUIPolygon::GUIPolygon(const std::string& id, const std::string& type, const RGBColor& color,
96  const PositionVector& shape, bool geo, bool fill,
97  double lineWidth, double layer, double angle, const std::string& imgFile,
98  bool relativePath, const std::string& name):
99  SUMOPolygon(id, type, color, shape, geo, fill, lineWidth, layer, angle, imgFile, relativePath, name),
101  myDisplayList(0),
102  myRotatedShape(nullptr) {
103  if (angle != 0.) {
104  setShape(shape);
105  }
106 }
107 
108 
110  delete myRotatedShape;
111 }
112 
113 
116  GUISUMOAbstractView& parent) {
117  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
118  buildPopupHeader(ret, app, false);
119  GUIDesigns::buildFXMenuCommand(ret, "(" + getShapeType() + ")", nullptr, nullptr, 0);
120  new FXMenuSeparator(ret);
124  buildShowParamsPopupEntry(ret, false);
125  buildPositionCopyEntry(ret, false);
126  return ret;
127 }
128 
129 
133  GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
134  // add items
135  ret->mkItem("type", false, getShapeType());
136  ret->mkItem("layer", false, toString(getShapeLayer()));
137  ret->mkItem("name", false, toString(getShapeName()));
138  ret->closeBuilding(this);
139  return ret;
140 }
141 
142 
143 double
145  return s.polySize.getExaggeration(s, this);
146 }
147 
148 
149 Boundary
151  const PositionVector& shape = myRotatedShape != nullptr ? *myRotatedShape : myShape;
152  Boundary b;
153  b.add(shape.getBoxBoundary());
154  b.grow(2);
155  return b;
156 }
157 
158 
159 void
161  // first check if polygon can be drawn
162  if (checkDraw(s, this, this)) {
163  FXMutexLock locker(myLock);
164  //if (myDisplayList == 0 || (!getFill() && myLineWidth != getExaggeration(s))) {
165  // storeTesselation(getExaggeration(s));
166  //}
167  // push name (needed for getGUIGlObjectsUnderCursor(...)
169  // draw inner polygon
170  if (myRotatedShape) {
171  drawInnerPolygon(s, this, this, *myRotatedShape, getFill(), getShapeLayer(), false);
172  } else {
173  drawInnerPolygon(s, this, this, myShape, getFill(), getShapeLayer(), false);
174  }
175  // pop name
177  }
178 }
179 
180 
181 void
183  FXMutexLock locker(myLock);
184  SUMOPolygon::setShape(shape);
185  if (getShapeNaviDegree() != 0.) {
186  if (myRotatedShape == nullptr) {
188  }
189  const Position& centroid = myShape.getCentroid();
191  myRotatedShape->sub(centroid);
193  myRotatedShape->add(centroid);
194  } else {
195  delete myRotatedShape;
196  myRotatedShape = nullptr;
197  }
198  //storeTesselation(myLineWidth);
199 }
200 
201 
202 void
203 GUIPolygon::performTesselation(const bool fill, const PositionVector& shape, const double lineWidth) {
204  if (fill) {
205  // draw the tesselated shape
206  double* points = new double[shape.size() * 3];
207  GLUtesselator* tobj = gluNewTess();
208 #if defined(__GNUC__) && __GNUC__ >= 8
209 #pragma GCC diagnostic push
210 #pragma GCC diagnostic ignored "-Wcast-function-type"
211 #endif
212  gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(CALLBACK*)()) &glVertex3dv);
213  gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(CALLBACK*)()) &beginCallback);
214  gluTessCallback(tobj, GLU_TESS_END, (GLvoid(CALLBACK*)()) &endCallback);
215  //gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (CALLBACK*) ()) &errorCallback);
216  gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(CALLBACK*)()) &combineCallback);
217 #if defined(__GNUC__) && __GNUC__ >= 8
218 #pragma GCC diagnostic pop
219 #endif
220  gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
221  gluTessBeginPolygon(tobj, nullptr);
222  gluTessBeginContour(tobj);
223  for (int i = 0; i != (int)shape.size(); ++i) {
224  points[3 * i] = shape[(int) i].x();
225  points[3 * i + 1] = shape[(int) i].y();
226  points[3 * i + 2] = 0;
227  gluTessVertex(tobj, points + 3 * i, points + 3 * i);
228  }
229  gluTessEndContour(tobj);
230 
231  gluTessEndPolygon(tobj);
232  gluDeleteTess(tobj);
233  delete[] points;
234 
235  } else {
236  GLHelper::drawLine(shape);
237  GLHelper::drawBoxLines(shape, lineWidth);
238  }
239 }
240 
241 
242 void
243 GUIPolygon::storeTesselation(const bool fill, const PositionVector& shape, double lineWidth) const {
244  if (myDisplayList > 0) {
245  glDeleteLists(myDisplayList, 1);
246  }
247  myDisplayList = glGenLists(1);
248  if (myDisplayList == 0) {
249  throw ProcessError("GUIPolygon::storeTesselation() could not create display list");
250  }
251  glNewList(myDisplayList, GL_COMPILE);
252  performTesselation(fill, shape, lineWidth);
253  glEndList();
254 }
255 
256 
257 void
258 GUIPolygon::setColor(const GUIVisualizationSettings& s, const SUMOPolygon* polygon, const GUIGlObject* o, bool disableSelectionColor, int alphaOverride) {
259  const GUIColorer& c = s.polyColorer;
260  const int active = c.getActive();
261  RGBColor color;
262  if (s.netedit && active != 1 && gSelected.isSelected(GLO_POLYGON, o->getGlID()) && disableSelectionColor) {
263  // override with special selection colors (unless the color scheme is based on selection)
264  color = RGBColor(0, 0, 204);
265  } else if (active == 0) {
266  color = polygon->getShapeColor();
267  } else if (active == 1) {
269  } else {
270  color = c.getScheme().getColor(0);
271  }
272  if (alphaOverride >= 0 && alphaOverride <= 255) {
273  color.setAlpha((unsigned char)alphaOverride);
274  }
275  GLHelper::setColor(color);
276 }
277 
278 
279 bool
281  if (o->getExaggeration(s) == 0) {
282  return false;
283  }
284  Boundary boundary = polygon->getShape().getBoxBoundary();
285  if (s.scale * MAX2(boundary.getWidth(), boundary.getHeight()) < s.polySize.minSize) {
286  return false;
287  }
288  if (polygon->getFill()) {
289  if (polygon->getShape().size() < 3) {
290  return false;
291  }
292  } else {
293  if (polygon->getShape().size() < 2) {
294  return false;
295  }
296  }
297  return true;
298 }
299 
300 
301 void
303  const PositionVector shape, const bool drawFill, double layer, bool disableSelectionColor, int alphaOverride) {
305  glTranslated(0, 0, layer);
306  setColor(s, polygon, o, disableSelectionColor, alphaOverride);
307  int textureID = -1;
308  if (drawFill) {
309  const std::string& file = polygon->getShapeImgFile();
310  if (file != "") {
311  textureID = GUITexturesHelper::getTextureID(file, true);
312  }
313  }
314  // init generation of texture coordinates
315  if (textureID >= 0) {
316  glEnable(GL_TEXTURE_2D);
317  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
318  glDisable(GL_CULL_FACE);
319  glDisable(GL_DEPTH_TEST); // without DEPTH_TEST vehicles may be drawn below roads
320  glDisable(GL_LIGHTING);
321  glDisable(GL_COLOR_MATERIAL);
322  glDisable(GL_ALPHA_TEST);
323  glEnable(GL_BLEND);
324  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
325  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
326  glBindTexture(GL_TEXTURE_2D, textureID);
327  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
328  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
329  // http://www.gamedev.net/topic/133564-glutesselation-and-texture-mapping/
330  glEnable(GL_TEXTURE_GEN_S);
331  glEnable(GL_TEXTURE_GEN_T);
332  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
333  glTexGendv(GL_S, GL_OBJECT_PLANE, xPlane);
334  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
335  glTexGendv(GL_T, GL_OBJECT_PLANE, yPlane);
336  }
337  // recall tesselation
338  //glCallList(myDisplayList);
339  performTesselation(drawFill, shape, polygon->getLineWidth() * o->getExaggeration(s));
340  // de-init generation of texture coordinates
341  if (textureID >= 0) {
342  glEnable(GL_DEPTH_TEST);
343  glBindTexture(GL_TEXTURE_2D, 0);
344  glDisable(GL_TEXTURE_2D);
345  glDisable(GL_TEXTURE_GEN_S);
346  glDisable(GL_TEXTURE_GEN_T);
347  }
348 #ifdef GUIPolygon_DEBUG_DRAW_VERTICES
349  GLHelper::debugVertices(shape, 80 / s.scale);
350 #endif
352  const Position& namePos = shape.getPolygonCenter();
353  o->drawName(namePos, s.scale, s.polyName, s.angle);
354  if (s.polyType.show(o)) {
355  const Position p = namePos + Position(0, -0.6 * s.polyType.size / s.scale);
357  }
358 }
359 
360 
361 /****************************************************************************/
@ GLO_POLYGON
a polygon
GUISelectedStorage gSelected
A global holder of selected objects.
void CALLBACK errorCallback(GLenum errorCode)
Definition: GUIPolygon.cpp:53
static const GLdouble INV_POLY_TEX_DIM
Definition: GUIPolygon.cpp:87
void CALLBACK combineCallback(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], GLdouble **dataOut)
Definition: GUIPolygon.cpp:72
static const GLdouble yPlane[]
Definition: GUIPolygon.cpp:89
void CALLBACK beginCallback(GLenum which)
Definition: GUIPolygon.cpp:48
void CALLBACK endCallback(void)
Definition: GUIPolygon.cpp:62
#define CALLBACK
Definition: GUIPolygon.cpp:39
void CALLBACK vertexCallback(GLvoid *vertex)
Definition: GUIPolygon.cpp:67
static const GLdouble xPlane[]
Definition: GUIPolygon.cpp:88
#define DEG2RAD(x)
Definition: GeomHelper.h:35
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MAX2(T a, T b)
Definition: StdDefs.h:80
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:77
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:299
double getHeight() const
Returns the height of the boundary (y-axis)
Definition: Boundary.cpp:159
double getWidth() const
Returns the width of the boudary (x-axis)
Definition: Boundary.cpp:153
static void debugVertices(const PositionVector &shape, double size, double layer=256)
draw vertex numbers for the given shape (in a random color)
Definition: GLHelper.cpp:792
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition: GLHelper.cpp:369
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:507
static void pushName(unsigned int name)
push Name
Definition: GLHelper.cpp:132
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:123
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:277
static void popName()
pop Name
Definition: GLHelper.cpp:141
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:114
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:640
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 buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
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.
virtual double getExaggeration(const GUIVisualizationSettings &s) const =0
return exaggeration asociated 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.
virtual void setShape(const PositionVector &shape)
set a new shape and update the tesselation
Definition: GUIPolygon.cpp:182
static bool checkDraw(const GUIVisualizationSettings &s, const SUMOPolygon *polygon, const GUIGlObject *o)
check if Polygon can be drawn
Definition: GUIPolygon.cpp:280
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GUIPolygon.cpp:115
static void drawInnerPolygon(const GUIVisualizationSettings &s, const SUMOPolygon *polygon, const GUIGlObject *o, const PositionVector shape, const bool drawFill, double layer, bool disableSelectionColor, int alphaOverride=-1)
draw inner Polygon (before pushName() )
Definition: GUIPolygon.cpp:302
void storeTesselation(const bool fill, const PositionVector &shape, double lineWidth) const
store the drawing commands in a display list
Definition: GUIPolygon.cpp:243
PositionVector * myRotatedShape
shape rotated on the centroid, if rotation is needed, nullptr otherwise
Definition: GUIPolygon.h:133
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:95
GLuint myDisplayList
id of the display list for the cached tesselation
Definition: GUIPolygon.h:130
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
Definition: GUIPolygon.cpp:131
~GUIPolygon()
Destructor.
Definition: GUIPolygon.cpp:109
static void performTesselation(const bool fill, const PositionVector &shape, const double lineWidth)
Definition: GUIPolygon.cpp:203
FXMutex myLock
The mutex used to avoid concurrent updates of the shape.
Definition: GUIPolygon.h:127
static void setColor(const GUIVisualizationSettings &s, const SUMOPolygon *polygon, const GUIGlObject *o, bool disableSelectionColor, int alphaOverride)
set color
Definition: GUIPolygon.cpp:258
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GUIPolygon.cpp:150
double getExaggeration(const GUIVisualizationSettings &s) const
return exaggeration asociated with this GLObject
Definition: GUIPolygon.cpp:144
virtual void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GUIPolygon.cpp:160
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.
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
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
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
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:109
const RGBColor & getShapeColor() const
Returns the color of the Shape.
Definition: Shape.h:83
const std::string & getShapeImgFile() const
Returns the imgFile of the Shape.
Definition: Shape.h:104
double getShapeLayer() const
Returns the layer of the Shape.
Definition: Shape.h:90
double getShapeNaviDegree() const
Returns the angle of the Shape in navigational degrees.
Definition: Shape.h:97
const std::string & getShapeType() const
Returns the (abstract) type of the Shape.
Definition: Shape.h:76
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