Shape.cpp
1 //
3 // SFML - Simple and Fast Multimedia Library
4 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
5 //
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors be held liable for any damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 // you must not claim that you wrote the original software.
15 // If you use this software in a product, an acknowledgment
16 // in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 // and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
24 
26 // Headers
28 #include <SFML/Graphics/Shape.hpp>
29 #include <SFML/Graphics/GraphicsContext.hpp>
30 #include <math.h>
31 
32 
33 namespace sf
34 {
39 myOutline (0.f),
40 myIsFillEnabled (true),
41 myIsOutlineEnabled(true),
42 myIsCompiled (false)
43 {
44  // Put a placeholder for the center of the shape
45  myPoints.push_back(Point());
46 }
47 
48 
52 void Shape::AddPoint(float X, float Y, const Color& Col, const Color& OutlineCol)
53 {
54  AddPoint(Vector2f(X, Y), Col, OutlineCol);
55 }
56 
57 
61 void Shape::AddPoint(const Vector2f& Position, const Color& Col, const Color& OutlineCol)
62 {
63  myPoints.push_back(Point(Position, Col, OutlineCol));
64  myIsCompiled = false;
65 }
66 
67 
71 unsigned int Shape::GetNbPoints() const
72 {
73  return static_cast<unsigned int>(myPoints.size() - 1);
74 }
75 
76 
81 void Shape::EnableFill(bool Enable)
82 {
83  myIsFillEnabled = Enable;
84 }
85 
86 
91 void Shape::EnableOutline(bool Enable)
92 {
93  myIsOutlineEnabled = Enable;
94 }
95 
96 
100 void Shape::SetPointPosition(unsigned int Index, const Vector2f& Position)
101 {
102  myPoints[Index + 1].Position = Position;
103  myIsCompiled = false;
104 }
105 
106 
110 void Shape::SetPointPosition(unsigned int Index, float X, float Y)
111 {
112  SetPointPosition(Index, Vector2f(X, Y));
113 }
114 
115 
119 void Shape::SetPointColor(unsigned int Index, const Color& Col)
120 {
121  myPoints[Index + 1].Col = Col;
122  myIsCompiled = false;
123 }
124 
125 
129 void Shape::SetPointOutlineColor(unsigned int Index, const Color& OutlineCol)
130 {
131  myPoints[Index + 1].OutlineCol = OutlineCol;
132  myIsCompiled = false;
133 }
134 
135 
139 void Shape::SetOutlineWidth(float Width)
140 {
141  myOutline = Width;
142 }
143 
144 
148 const Vector2f& Shape::GetPointPosition(unsigned int Index) const
149 {
150  return myPoints[Index + 1].Position;
151 }
152 
153 
157 const Color& Shape::GetPointColor(unsigned int Index) const
158 {
159  return myPoints[Index + 1].Col;
160 }
161 
162 
166 const Color& Shape::GetPointOutlineColor(unsigned int Index) const
167 {
168  return myPoints[Index + 1].OutlineCol;
169 }
170 
171 
176 {
177  return myOutline;
178 }
179 
180 
184 Shape Shape::Line(float P1X, float P1Y, float P2X, float P2Y, float Thickness, const Color& Col, float Outline, const Color& OutlineCol)
185 {
186  Vector2f P1(P1X, P1Y);
187  Vector2f P2(P2X, P2Y);
188 
189  // Compute the extrusion direction
190  Vector2f Normal;
191  ComputeNormal(P1, P2, Normal);
192  Normal *= Thickness / 2;
193 
194  // Create the shape's points
195  Shape S;
196  S.AddPoint(P1 - Normal, Col, OutlineCol);
197  S.AddPoint(P2 - Normal, Col, OutlineCol);
198  S.AddPoint(P2 + Normal, Col, OutlineCol);
199  S.AddPoint(P1 + Normal, Col, OutlineCol);
200  S.SetOutlineWidth(Outline);
201 
202  // Compile it
203  S.Compile();
204 
205  return S;
206 }
207 
208 
212 Shape Shape::Line(const Vector2f& P1, const Vector2f& P2, float Thickness, const Color& Col, float Outline, const Color& OutlineCol)
213 {
214  return Shape::Line(P1.x, P1.y, P2.x, P2.y, Thickness, Col, Outline, OutlineCol);
215 }
216 
217 
221 Shape Shape::Rectangle(float P1X, float P1Y, float P2X, float P2Y, const Color& Col, float Outline, const Color& OutlineCol)
222 {
223  // Create the shape's points
224  Shape S;
225  S.AddPoint(Vector2f(P1X, P1Y), Col, OutlineCol);
226  S.AddPoint(Vector2f(P2X, P1Y), Col, OutlineCol);
227  S.AddPoint(Vector2f(P2X, P2Y), Col, OutlineCol);
228  S.AddPoint(Vector2f(P1X, P2Y), Col, OutlineCol);
229  S.SetOutlineWidth(Outline);
230 
231  // Compile it
232  S.Compile();
233 
234  return S;
235 }
236 
237 
241 Shape Shape::Rectangle(const Vector2f& P1, const Vector2f& P2, const Color& Col, float Outline, const Color& OutlineCol)
242 {
243  return Shape::Rectangle(P1.x, P1.y, P2.x, P2.y, Col, Outline, OutlineCol);
244 }
245 
246 
250 Shape Shape::Circle(float X, float Y, float Radius, const Color& Col, float Outline, const Color& OutlineCol)
251 {
252  static const int NbSegments = 40;
253 
254  // Create the points set
255  Shape S;
256  Vector2f Center(X, Y);
257  for (int i = 0; i < NbSegments; ++i)
258  {
259  float Angle = i * 2 * 3.141592654f / NbSegments;
260  Vector2f Offset(cos(Angle), sin(Angle));
261 
262  S.AddPoint(Center + Offset * Radius, Col, OutlineCol);
263  }
264 
265  // Compile it
266  S.SetOutlineWidth(Outline);
267  S.Compile();
268 
269  return S;
270 }
271 
272 
276 Shape Shape::Circle(const Vector2f& Center, float Radius, const Color& Col, float Outline, const Color& OutlineCol)
277 {
278  return Shape::Circle(Center.x, Center.y, Radius, Col, Outline, OutlineCol);
279 }
280 
281 
286 {
287  // Make sure the shape has at least 3 points (4 if we count the center)
288  if (myPoints.size() < 4)
289  return;
290 
291  // Make sure the shape is compiled
292  if (!myIsCompiled)
293  const_cast<Shape*>(this)->Compile();
294 
295  // Shapes only use color, no texture
296  GLCheck(glDisable(GL_TEXTURE_2D));
297 
298  // Draw the shape
299  if (myIsFillEnabled)
300  {
301  glBegin(GL_TRIANGLE_FAN);
302  {
303  for (std::vector<Point>::const_iterator i = myPoints.begin(); i != myPoints.end(); ++i)
304  {
305  Color PointColor = i->Col * GetColor();
306  glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
307  glVertex2f(i->Position.x, i->Position.y);
308  }
309 
310  // Close the shape by duplicating the first point at the end
311  Color PointColor = myPoints[1].Col * GetColor();
312  glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
313  glVertex2f(myPoints[1].Position.x, myPoints[1].Position.y);
314  }
315  glEnd();
316  }
317 
318  // Draw the outline
319  if (myIsOutlineEnabled)
320  {
321  glBegin(GL_TRIANGLE_STRIP);
322  {
323  for (std::size_t i = 1; i < myPoints.size(); ++i)
324  {
325  Color PointColor = myPoints[i].OutlineCol * GetColor();
326  glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
327  glVertex2f(myPoints[i].Position.x, myPoints[i].Position.y);
328  glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
329  glVertex2f(myPoints[i].Position.x + myPoints[i].Normal.x * myOutline, myPoints[i].Position.y + myPoints[i].Normal.y * myOutline);
330  }
331 
332  // Close the shape by duplicating the first point at the end
333  Color PointColor = myPoints[1].OutlineCol * GetColor();
334  glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
335  glVertex2f(myPoints[1].Position.x, myPoints[1].Position.y);
336  glColor4f(PointColor.r / 255.f, PointColor.g / 255.f, PointColor.b / 255.f, PointColor.a / 255.f);
337  glVertex2f(myPoints[1].Position.x + myPoints[1].Normal.x * myOutline, myPoints[1].Position.y + myPoints[1].Normal.y * myOutline);
338  }
339  glEnd();
340  }
341 }
342 
343 
347 void Shape::Compile()
348 {
349  // Compute the center
350  float NbPoints = static_cast<float>(myPoints.size() - 1);
351  float R = 0, G = 0, B = 0, A = 0;
352  Point Center(Vector2f(0, 0), Color(0, 0, 0, 0));
353  for (std::size_t i = 1; i < myPoints.size(); ++i)
354  {
355  Center.Position += myPoints[i].Position / NbPoints;
356  R += myPoints[i].Col.r / NbPoints;
357  G += myPoints[i].Col.g / NbPoints;
358  B += myPoints[i].Col.b / NbPoints;
359  A += myPoints[i].Col.a / NbPoints;
360  }
361  Center.Col.r = static_cast<Uint8>(R);
362  Center.Col.g = static_cast<Uint8>(G);
363  Center.Col.b = static_cast<Uint8>(B);
364  Center.Col.a = static_cast<Uint8>(A);
365  myPoints[0] = Center;
366 
367  // Compute the outline
368  for (std::size_t i = 1; i < myPoints.size(); ++i)
369  {
370  // Get the two segments shared by the current point
371  Point& P0 = (i == 1) ? myPoints[myPoints.size() - 1] : myPoints[i - 1];
372  Point& P1 = myPoints[i];
373  Point& P2 = (i == myPoints.size() - 1) ? myPoints[1] : myPoints[i + 1];
374 
375  // Compute their normal
376  Vector2f Normal1, Normal2;
377  if (!ComputeNormal(P0.Position, P1.Position, Normal1) || !ComputeNormal(P1.Position, P2.Position, Normal2))
378  continue;
379 
380  // Add them to get the extrusion direction
381  float Factor = 1.f + (Normal1.x * Normal2.x + Normal1.y * Normal2.y);
382  P1.Normal = (Normal1 + Normal2) / Factor;
383 
384  // Make sure it points towards the outside of the shape
385  float Dot = (P1.Position.x - Center.Position.x) * P1.Normal.x + (P1.Position.y - Center.Position.y) * P1.Normal.y;
386  if (Dot < 0)
387  P1.Normal = -P1.Normal;
388  }
389 
390  myIsCompiled = true;
391 }
392 
393 
397 bool Shape::ComputeNormal(const Vector2f& P1, const Vector2f& P2, Vector2f& Normal)
398 {
399  Normal.x = P1.y - P2.y;
400  Normal.y = P2.x - P1.x;
401 
402  float Len = sqrt(Normal.x * Normal.x + Normal.y * Normal.y);
403  if (Len == 0.f)
404  return false;
405 
406  Normal.x /= Len;
407  Normal.y /= Len;
408 
409  return true;
410 }
411 
412 
416 Shape::Point::Point(const Vector2f& Pos, const Color& C, const Color& OutlineC) :
417 Position (Pos),
418 Normal (0.f, 0.f),
419 Col (C),
420 OutlineCol(OutlineC)
421 {
422 
423 }
424 
425 } // namespace sf
Uint8 a
Alpha (transparency) component.
Definition: Color.hpp:119
Shape defines a drawable convex shape ; it also defines helper functions to draw simple shapes like l...
Definition: Shape.hpp:43
void EnableOutline(bool Enable)
Enable or disable drawing the shape outline.
Definition: Shape.cpp:91
float GetOutlineWidth() const
Get the width of the shape outline.
Definition: Shape.cpp:175
const Vector2f & GetPointPosition(unsigned int Index) const
Get the position of a point.
Definition: Shape.cpp:148
void SetPointPosition(unsigned int Index, const Vector2f &Position)
Set the position of a point.
Definition: Shape.cpp:100
void SetPointColor(unsigned int Index, const Color &Col)
Set the color of a point.
Definition: Shape.cpp:119
Shape()
Default constructor.
Definition: Shape.cpp:38
const Color & GetPointColor(unsigned int Index) const
Get the color of a point.
Definition: Shape.cpp:157
T x
X coordinate of the vector.
Definition: Vector2.hpp:59
static Shape Line(float P1X, float P1Y, float P2X, float P2Y, float Thickness, const Color &Col, float Outline=0.f, const Color &OutlineCol=sf::Color(0, 0, 0))
Create a shape made of a single line (use floats)
Definition: Shape.cpp:184
const Color & GetColor() const
Get the color of the object.
Definition: Drawable.cpp:249
Uint8 b
Blue component.
Definition: Color.hpp:118
unsigned int GetNbPoints() const
Get the number of points composing the shape.
Definition: Shape.cpp:71
Uint8 g
Green component.
Definition: Color.hpp:117
const Color & GetPointOutlineColor(unsigned int Index) const
Get the outline color of a point.
Definition: Shape.cpp:166
void AddPoint(float X, float Y, const Color &Col=Color(255, 255, 255), const Color &OutlineCol=Color(0, 0, 0))
Add a point to the shape.
Definition: Shape.cpp:52
static Shape Rectangle(float P1X, float P1Y, float P2X, float P2Y, const Color &Col, float Outline=0.f, const Color &OutlineCol=sf::Color(0, 0, 0))
Create a shape made of a single rectangle (use floats)
Definition: Shape.cpp:221
Color is an utility class for manipulating 32-bits RGBA colors.
Definition: Color.hpp:40
void EnableFill(bool Enable)
Enable or disable filling the shape.
Definition: Shape.cpp:81
void SetPointOutlineColor(unsigned int Index, const Color &OutlineCol)
Set the outline color of a point.
Definition: Shape.cpp:129
static Shape Circle(float X, float Y, float Radius, const Color &Col, float Outline=0.f, const Color &OutlineCol=sf::Color(0, 0, 0))
Create a shape made of a single circle (use floats)
Definition: Shape.cpp:250
T y
Y coordinate of the vector.
Definition: Vector2.hpp:60
Base class for all render targets (window, image, ...)
Uint8 r
Red component.
Definition: Color.hpp:116
virtual void Render(RenderTarget &Target) const
/see Drawable::Render
Definition: Shape.cpp:285
void SetOutlineWidth(float Width)
Change the width of the shape outline.
Definition: Shape.cpp:139