1 /******************************************************************************
2 * Warmux is a convivial mass murder game.
3 * Copyright (C) 2001-2011 Warmux Team.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 ******************************************************************************
19 * Polygon Generator. Generate various polygon shape on demand (including random one).
20 *****************************************************************************/
21
22 #include <stdlib.h>
23 #include "graphic/polygon.h"
24 #include "graphic/polygon_generator.h"
25 #include "network/randomsync.h"
26 #include "tool/affine_transform.h"
27
28 const int PolygonGenerator::MIN_SPACE_BETWEEN_POINT = 50;
29
GenerateCircle(Double diameter,int nb_point)30 Polygon * PolygonGenerator::GenerateCircle(Double diameter, int nb_point)
31 {
32 return PolygonGenerator::GenerateDentedCircle(diameter, nb_point, ZERO);
33 }
34
GenerateRectangle(Double width,Double height)35 Polygon * PolygonGenerator::GenerateRectangle(Double width, Double height)
36 {
37 Polygon * tmp = new Polygon();
38 tmp->AddPoint(Point2d( width * ONE_HALF, height * ONE_HALF));
39 tmp->AddPoint(Point2d( width * ONE_HALF, -height * ONE_HALF));
40 tmp->AddPoint(Point2d(-width * ONE_HALF, -height * ONE_HALF));
41 tmp->AddPoint(Point2d(-width * ONE_HALF, height * ONE_HALF));
42 return tmp;
43 }
44
GenerateRectangle(const Point2d & orig,const Point2d & size)45 Polygon * PolygonGenerator::GenerateRectangle(const Point2d & orig, const Point2d & size)
46 {
47 Polygon * tmp = new Polygon();
48 tmp->AddPoint(Point2d(orig.x + size.x, orig.y + size.y));
49 tmp->AddPoint(Point2d(orig.x + size.x, orig.y));
50 tmp->AddPoint(Point2d(orig.x, orig.y));
51 tmp->AddPoint(Point2d(orig.x, orig.y + size.y));
52 return tmp;
53 }
54
GenerateRectangle(const Rectanglei & r)55 Polygon * PolygonGenerator::GenerateRectangle(const Rectanglei & r)
56 {
57 return PolygonGenerator::GenerateRectangle(r.GetPosition(), r.GetSize());
58 }
59
GenerateRectangle(const Point2i & orig,const Point2i & size)60 Polygon * PolygonGenerator::GenerateRectangle(const Point2i & orig, const Point2i & size)
61 {
62 return PolygonGenerator::GenerateRectangle((Point2d)orig, (Point2d)size);
63 }
64
GenerateDentedCircle(Double diameter,int nb_point,Double rand_offset)65 Polygon * PolygonGenerator::GenerateDentedCircle(Double diameter, int nb_point, Double rand_offset)
66 {
67 Polygon * tmp = new Polygon();
68 AffineTransform2D trans = AffineTransform2D();
69 Point2d top;
70 for(int i = 0; i < nb_point; i++) {
71 top = Point2d(ZERO, (diameter + RandomSync().GetDouble(-rand_offset, rand_offset)) * ONE_HALF);
72 trans.SetRotation((TWO_PI * -i) / nb_point);
73 tmp->AddPoint(trans * top);
74 }
75 return tmp;
76 }
77
GenerateRoundedRectangle(Double width,Double height,Double edge)78 Polygon * PolygonGenerator::GenerateRoundedRectangle(Double width, Double height, Double edge)
79 {
80 Polygon * tmp = new Polygon();
81 Double edge_vector = edge * ONE_HALF;
82 tmp->AddBezierCurve(Point2d(-width * ONE_HALF + edge, -height * ONE_HALF),
83 Point2d(-edge_vector, 0),
84 Point2d(0, -edge_vector),
85 Point2d(-width * ONE_HALF, -height * ONE_HALF + edge));
86 tmp->AddBezierCurve(Point2d(-width * ONE_HALF, height * ONE_HALF - edge),
87 Point2d(0, edge_vector),
88 Point2d(-edge_vector, 0),
89 Point2d(-width * ONE_HALF + edge, height * ONE_HALF));
90 tmp->AddBezierCurve(Point2d(width * ONE_HALF - edge, height * ONE_HALF),
91 Point2d(edge_vector, 0),
92 Point2d(0, edge_vector),
93 Point2d(width * ONE_HALF, height * ONE_HALF - edge));
94 tmp->AddBezierCurve(Point2d(width * ONE_HALF, -height * ONE_HALF + edge),
95 Point2d(0, -edge_vector),
96 Point2d(edge_vector, 0),
97 Point2d(width * ONE_HALF - edge, -height * ONE_HALF));
98 return tmp;
99 }
100
GenerateRandomShape()101 Polygon * PolygonGenerator::GenerateRandomShape()
102 {
103 Double height = RandomSync().GetDouble(400.0, 600.0);
104 Double width = RandomSync().GetDouble(400.0, 2000.0);
105 return GenerateRandomTrapeze(width, height, RandomSync().GetDouble(10.0, 15.0), RandomSync().GetDouble(10.0, 15.0),
106 RandomSync().GetSign() * RandomSync().GetDouble(0.5, 1.0));
107 }
108
GenerateRandomTrapeze(const Double width,const Double height,const Double x_rand_offset,const Double y_rand_offset,const Double coef)109 Polygon * PolygonGenerator::GenerateRandomTrapeze(const Double width, const Double height,
110 const Double x_rand_offset, const Double y_rand_offset,
111 const Double coef)
112 {
113 Double upper_width, lower_width, upper_offset, lower_offset;
114 int number_of_bottom_point, number_of_side_point;
115 // XXX Unused !?
116 // int number_of_upper_point;
117 Polygon * tmp = new Polygon();
118 number_of_side_point = 1 + (int)RandomSync().GetDouble((height / FOUR) / MIN_SPACE_BETWEEN_POINT,
119 height / MIN_SPACE_BETWEEN_POINT);
120 if(coef > ZERO) {
121 upper_width = width;
122 lower_width = width * coef;
123 upper_offset = RandomSync().GetDouble(ZERO, width - lower_width);
124 lower_offset = ZERO;
125 } else {
126 upper_width = - width * coef;
127 lower_width = width;
128 upper_offset = ZERO;
129 lower_offset = RandomSync().GetDouble(ZERO, width - upper_width);
130 }
131 // XXX Unused !?
132 //number_of_upper_point = RandomSync().GetInt(1 + (int)((upper_width * 0.25) / MIN_SPACE_BETWEEN_POINT),
133 // (int)(upper_width / MIN_SPACE_BETWEEN_POINT));
134 number_of_bottom_point = RandomSync().GetInt(1 + (int)((lower_width / FOUR) / MIN_SPACE_BETWEEN_POINT),
135 (int)((coef * lower_width) / MIN_SPACE_BETWEEN_POINT));
136 tmp->AddRandomCurve(Point2d(upper_offset, ZERO), Point2d(lower_offset, height),
137 x_rand_offset, y_rand_offset, number_of_side_point, false, false);
138 tmp->AddRandomCurve(Point2d(lower_offset, height), Point2d(lower_offset + lower_width, height),
139 x_rand_offset, y_rand_offset, number_of_bottom_point, false, false);
140 tmp->AddRandomCurve(Point2d(lower_offset + lower_width, height), Point2d(upper_offset + upper_width, ZERO),
141 x_rand_offset, y_rand_offset, number_of_side_point, false, false);
142 tmp->AddRandomCurve(Point2d(upper_offset + upper_width, ZERO), Point2d(upper_offset, ZERO),
143 x_rand_offset, y_rand_offset, number_of_side_point, false, false);
144 return tmp;
145 }
146
GeneratePie(Double diameter,int nb_point,Double angle,Double angle_offset)147 Polygon * PolygonGenerator::GeneratePie(Double diameter, int nb_point, Double angle, Double angle_offset)
148 {
149 Polygon * tmp = new Polygon();
150 AffineTransform2D trans = AffineTransform2D();
151 Point2d top;
152 for(int i = 0; i < nb_point; i++) {
153 top = Point2d(ZERO, diameter * ONE_HALF);
154 trans.SetRotation(angle_offset + ((i * angle) / nb_point));
155 tmp->AddPoint(trans * top);
156 }
157 if(angle < TWO_PI)
158 tmp->AddPoint(Point2d(0, 0));
159 return tmp;
160 }
161
GeneratePartialTorus(Double diameter,Double min_diameter,int nb_point,Double angle,Double angle_offset)162 Polygon * PolygonGenerator::GeneratePartialTorus(Double diameter, Double min_diameter, int nb_point, Double angle, Double angle_offset)
163 {
164 if(diameter < min_diameter) {
165 Double tmp = diameter;
166 diameter = min_diameter;
167 min_diameter = tmp;
168 }
169 Polygon * tmp = new Polygon();
170 AffineTransform2D trans = AffineTransform2D();
171 Point2d top = Point2d(0, diameter*ONE_HALF);
172 for(int i = 0; i < nb_point; i++) {
173 trans.SetRotation(angle_offset + ((i * angle) / (nb_point - 1)));
174 tmp->AddPoint(trans * top);
175 }
176 top = Point2d(0, min_diameter*ONE_HALF);
177 for(int i = nb_point - 1; i >= 0; i--) {
178 trans.SetRotation(angle_offset + ((i * angle) / (nb_point - 1)));
179 tmp->AddPoint(trans * top);
180 }
181 return tmp;
182 }
183
GenerateDecoratedBox(Double width,Double height)184 DecoratedBox * PolygonGenerator::GenerateDecoratedBox(Double width, Double height)
185 {
186 DecoratedBox * tmp = new DecoratedBox(width, height);
187
188 return tmp;
189 }
190