Shape.cpp
1
2//
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
33namespace sf
34{
39myOutline (0.f),
40myIsFillEnabled (true),
41myIsOutlineEnabled(true),
42myIsCompiled (false)
43{
44 // Put a placeholder for the center of the shape
45 myPoints.push_back(Point());
46}
47
48
52void Shape::AddPoint(float X, float Y, const Color& Col, const Color& OutlineCol)
53{
54 AddPoint(Vector2f(X, Y), Col, OutlineCol);
55}
56
57
61void 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
71unsigned int Shape::GetNbPoints() const
72{
73 return static_cast<unsigned int>(myPoints.size() - 1);
74}
75
76
81void Shape::EnableFill(bool Enable)
82{
83 myIsFillEnabled = Enable;
84}
85
86
91void Shape::EnableOutline(bool Enable)
92{
93 myIsOutlineEnabled = Enable;
94}
95
96
100void Shape::SetPointPosition(unsigned int Index, const Vector2f& Position)
101{
102 myPoints[Index + 1].Position = Position;
103 myIsCompiled = false;
104}
105
106
110void Shape::SetPointPosition(unsigned int Index, float X, float Y)
111{
112 SetPointPosition(Index, Vector2f(X, Y));
113}
114
115
119void Shape::SetPointColor(unsigned int Index, const Color& Col)
120{
121 myPoints[Index + 1].Col = Col;
122 myIsCompiled = false;
123}
124
125
129void Shape::SetPointOutlineColor(unsigned int Index, const Color& OutlineCol)
130{
131 myPoints[Index + 1].OutlineCol = OutlineCol;
132 myIsCompiled = false;
133}
134
135
139void Shape::SetOutlineWidth(float Width)
140{
141 myOutline = Width;
142}
143
144
148const Vector2f& Shape::GetPointPosition(unsigned int Index) const
149{
150 return myPoints[Index + 1].Position;
151}
152
153
157const Color& Shape::GetPointColor(unsigned int Index) const
158{
159 return myPoints[Index + 1].Col;
160}
161
162
166const Color& Shape::GetPointOutlineColor(unsigned int Index) const
167{
168 return myPoints[Index + 1].OutlineCol;
169}
170
171
176{
177 return myOutline;
178}
179
180
184Shape 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
212Shape 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
221Shape 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
241Shape 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
250Shape 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
276Shape 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
285void Shape::Render(RenderTarget&) const
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
347void 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
397bool 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
416Shape::Point::Point(const Vector2f& Pos, const Color& C, const Color& OutlineC) :
417Position (Pos),
418Normal (0.f, 0.f),
419Col (C),
420OutlineCol(OutlineC)
421{
422
423}
424
425} // namespace sf
Color is an utility class for manipulating 32-bits RGBA colors.
Definition Color.hpp:41
Uint8 a
Alpha (transparency) component.
Definition Color.hpp:119
Uint8 g
Green component.
Definition Color.hpp:117
Uint8 b
Blue component.
Definition Color.hpp:118
Uint8 r
Red component.
Definition Color.hpp:116
const Color & GetColor() const
Get the color of the object.
Definition Drawable.cpp:249
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
unsigned int GetNbPoints() const
Get the number of points composing the shape.
Definition Shape.cpp:71
Shape()
Default constructor.
Definition Shape.cpp:38
const Vector2f & GetPointPosition(unsigned int Index) const
Get the position of a point.
Definition Shape.cpp:148
void EnableFill(bool Enable)
Enable or disable filling the shape.
Definition Shape.cpp:81
float GetOutlineWidth() const
Get the width of the shape outline.
Definition Shape.cpp:175
void SetOutlineWidth(float Width)
Change the width of the shape outline.
Definition Shape.cpp:139
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
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
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
void SetPointOutlineColor(unsigned int Index, const Color &OutlineCol)
Set the outline color of a point.
Definition Shape.cpp:129
void SetPointColor(unsigned int Index, const Color &Col)
Set the color of a point.
Definition Shape.cpp:119
const Color & GetPointColor(unsigned int Index) const
Get the color of a point.
Definition Shape.cpp:157
virtual void Render(RenderTarget &Target) const
/see Drawable::Render
Definition Shape.cpp:285
void SetPointPosition(unsigned int Index, const Vector2f &Position)
Set the position of a point.
Definition Shape.cpp:100
void EnableOutline(bool Enable)
Enable or disable drawing the shape outline.
Definition Shape.cpp:91
const Color & GetPointOutlineColor(unsigned int Index) const
Get the outline color of a point.
Definition Shape.cpp:166
T x
X coordinate of the vector.
Definition Vector2.hpp:59
T y
Y coordinate of the vector.
Definition Vector2.hpp:60