"Fossies" - the Fresh Open Source Software Archive 
Member "libgd-2.3.3/src/gd_matrix.c" (11 Sep 2021, 8734 Bytes) of package /linux/www/libgd-2.3.3.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "gd_matrix.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.3.2_vs_2.3.3.
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif /* HAVE_CONFIG_H */
4
5 #include "gd.h"
6 #include <math.h>
7
8 #ifndef M_PI
9 # define M_PI 3.14159265358979323846
10 #endif
11
12 /**
13 * Title: Matrix
14 * Group: Affine Matrix
15 *
16 * Matrix functions to initialize, transform and various other operations
17 * on these matrices.
18 * They can be used with gdTransformAffineCopy and are also used in various
19 * transformations functions in GD.
20 *
21 * matrix are create using a 6 elements double array:
22 * (start code)
23 * matrix[0] == xx
24 * matrix[1] == yx
25 * matrix[2] == xy
26 * matrix[3] == xy
27 * matrix[4] == x0
28 * matrix[5] == y0
29 * (end code)
30 * where the transformation of a given point (x,y) is given by:
31 *
32 * (start code)
33 * x_new = xx * x + xy * y + x0;
34 * y_new = yx * x + yy * y + y0;
35 * (end code)
36 */
37
38 /**
39 * Function: gdAffineApplyToPointF
40 * Applies an affine transformation to a point (floating point
41 * gdPointF)
42 *
43 *
44 * Parameters:
45 * dst - Where to store the resulting point
46 * affine - Source Point
47 * flip_horz - affine matrix
48 *
49 * Returns:
50 * GD_TRUE if the affine is rectilinear or GD_FALSE
51 */
52 BGD_DECLARE(int) gdAffineApplyToPointF (gdPointFPtr dst, const gdPointFPtr src,
53 const double affine[6])
54 {
55 double x = src->x;
56 double y = src->y;
57 dst->x = x * affine[0] + y * affine[2] + affine[4];
58 dst->y = x * affine[1] + y * affine[3] + affine[5];
59 return GD_TRUE;
60 }
61
62 /**
63 * Function: gdAffineInvert
64 * Find the inverse of an affine transformation.
65 *
66 * All non-degenerate affine transforms are invertible. Applying the
67 * inverted matrix will restore the original values. Multiplying <src>
68 * by <dst> (commutative) will return the identity affine (rounding
69 * error possible).
70 *
71 * Parameters:
72 * dst - Where to store the resulting affine transform
73 * src_affine - Original affine matrix
74 * flip_horz - Whether or not to flip horizontally
75 * flip_vert - Whether or not to flip vertically
76 *
77 * See also:
78 * <gdAffineIdentity>
79 *
80 * Returns:
81 * GD_TRUE on success or GD_FALSE on failure
82 */
83 BGD_DECLARE(int) gdAffineInvert (double dst[6], const double src[6])
84 {
85 double r_det = (src[0] * src[3] - src[1] * src[2]);
86
87 if (!isfinite(r_det)) {
88 return GD_FALSE;
89 }
90 if (r_det == 0) {
91 return GD_FALSE;
92 }
93
94 r_det = 1.0 / r_det;
95 dst[0] = src[3] * r_det;
96 dst[1] = -src[1] * r_det;
97 dst[2] = -src[2] * r_det;
98 dst[3] = src[0] * r_det;
99 dst[4] = -src[4] * dst[0] - src[5] * dst[2];
100 dst[5] = -src[4] * dst[1] - src[5] * dst[3];
101 return GD_TRUE;
102 }
103
104 /**
105 * Function: gdAffineFlip
106 * Flip an affine transformation horizontally or vertically.
107 *
108 * Flips the affine transform, giving GD_FALSE for <flip_horz> and
109 * <flip_vert> will clone the affine matrix. GD_TRUE for both will
110 * copy a 180° rotation.
111 *
112 * Parameters:
113 * dst - Where to store the resulting affine transform
114 * src_affine - Original affine matrix
115 * flip_h - Whether or not to flip horizontally
116 * flip_v - Whether or not to flip vertically
117 *
118 * Returns:
119 * GD_TRUE on success or GD_FALSE
120 */
121 BGD_DECLARE(int) gdAffineFlip (double dst[6], const double src[6], const int flip_h, const int flip_v)
122 {
123 dst[0] = flip_h ? - src[0] : src[0];
124 dst[1] = flip_h ? - src[1] : src[1];
125 dst[2] = flip_v ? - src[2] : src[2];
126 dst[3] = flip_v ? - src[3] : src[3];
127 dst[4] = flip_h ? - src[4] : src[4];
128 dst[5] = flip_v ? - src[5] : src[5];
129 return GD_TRUE;
130 }
131
132 /**
133 * Function: gdAffineConcat
134 * Concat (Multiply) two affine transformation matrices.
135 *
136 * Concats two affine transforms together, i.e. the result
137 * will be the equivalent of doing first the transformation m1 and then
138 * m2. All parameters can be the same matrix (safe to call using
139 * the same array for all three arguments).
140 *
141 * Parameters:
142 * dst - Where to store the resulting affine transform
143 * m1 - First affine matrix
144 * m2 - Second affine matrix
145 *
146 * Returns:
147 * GD_TRUE on success or GD_FALSE
148 */
149 BGD_DECLARE(int) gdAffineConcat (double dst[6], const double m1[6], const double m2[6])
150 {
151 double dst0, dst1, dst2, dst3, dst4, dst5;
152
153 dst0 = m1[0] * m2[0] + m1[1] * m2[2];
154 dst1 = m1[0] * m2[1] + m1[1] * m2[3];
155 dst2 = m1[2] * m2[0] + m1[3] * m2[2];
156 dst3 = m1[2] * m2[1] + m1[3] * m2[3];
157 dst4 = m1[4] * m2[0] + m1[5] * m2[2] + m2[4];
158 dst5 = m1[4] * m2[1] + m1[5] * m2[3] + m2[5];
159 dst[0] = dst0;
160 dst[1] = dst1;
161 dst[2] = dst2;
162 dst[3] = dst3;
163 dst[4] = dst4;
164 dst[5] = dst5;
165 return GD_TRUE;
166 }
167
168 /**
169 * Function: gdAffineIdentity
170 * Set up the identity matrix.
171 *
172 * Parameters:
173 * dst - Where to store the resulting affine transform
174 *
175 * Returns:
176 * GD_TRUE on success or GD_FALSE
177 */
178 BGD_DECLARE(int) gdAffineIdentity (double dst[6])
179 {
180 dst[0] = 1;
181 dst[1] = 0;
182 dst[2] = 0;
183 dst[3] = 1;
184 dst[4] = 0;
185 dst[5] = 0;
186 return GD_TRUE;
187 }
188
189 /**
190 * Function: gdAffineScale
191 * Set up a scaling matrix.
192 *
193 * Parameters:
194 * scale_x - X scale factor
195 * scale_y - Y scale factor
196 *
197 * Returns:
198 * GD_TRUE on success or GD_FALSE
199 */
200 BGD_DECLARE(int) gdAffineScale (double dst[6], const double scale_x, const double scale_y)
201 {
202 dst[0] = scale_x;
203 dst[1] = 0;
204 dst[2] = 0;
205 dst[3] = scale_y;
206 dst[4] = 0;
207 dst[5] = 0;
208 return GD_TRUE;
209 }
210
211 /**
212 * Function: gdAffineRotate
213 * Set up a rotation affine transform.
214 *
215 * Like the other angle in libGD, in which increasing y moves
216 * downward, this is a counterclockwise rotation.
217 *
218 * Parameters:
219 * dst - Where to store the resulting affine transform
220 * angle - Rotation angle in degrees
221 *
222 * Returns:
223 * GD_TRUE on success or GD_FALSE
224 */
225 BGD_DECLARE(int) gdAffineRotate (double dst[6], const double angle)
226 {
227 const double sin_t = sin (angle * M_PI / 180.0);
228 const double cos_t = cos (angle * M_PI / 180.0);
229
230 dst[0] = cos_t;
231 dst[1] = sin_t;
232 dst[2] = -sin_t;
233 dst[3] = cos_t;
234 dst[4] = 0;
235 dst[5] = 0;
236 return GD_TRUE;
237 }
238
239 /**
240 * Function: gdAffineShearHorizontal
241 * Set up a horizontal shearing matrix || becomes \\.
242 *
243 * Parameters:
244 * dst - Where to store the resulting affine transform
245 * angle - Shear angle in degrees
246 *
247 * Returns:
248 * GD_TRUE on success or GD_FALSE
249 */
250 BGD_DECLARE(int) gdAffineShearHorizontal(double dst[6], const double angle)
251 {
252 dst[0] = 1;
253 dst[1] = 0;
254 dst[2] = tan(angle * M_PI / 180.0);
255 dst[3] = 1;
256 dst[4] = 0;
257 dst[5] = 0;
258 return GD_TRUE;
259 }
260
261 /**
262 * Function: gdAffineShearVertical
263 * Set up a vertical shearing matrix, columns are untouched.
264 *
265 * Parameters:
266 * dst - Where to store the resulting affine transform
267 * angle - Shear angle in degrees
268 *
269 * Returns:
270 * GD_TRUE on success or GD_FALSE
271 */
272 BGD_DECLARE(int) gdAffineShearVertical(double dst[6], const double angle)
273 {
274 dst[0] = 1;
275 dst[1] = tan(angle * M_PI / 180.0);
276 dst[2] = 0;
277 dst[3] = 1;
278 dst[4] = 0;
279 dst[5] = 0;
280 return GD_TRUE;
281 }
282
283 /**
284 * Function: gdAffineTranslate
285 * Set up a translation matrix.
286 *
287 * Parameters:
288 * dst - Where to store the resulting affine transform
289 * offset_x - Horizontal translation amount
290 * offset_y - Vertical translation amount
291 *
292 * Returns:
293 * GD_TRUE on success or GD_FALSE
294 */
295 BGD_DECLARE(int) gdAffineTranslate (double dst[6], const double offset_x, const double offset_y)
296 {
297 dst[0] = 1;
298 dst[1] = 0;
299 dst[2] = 0;
300 dst[3] = 1;
301 dst[4] = offset_x;
302 dst[5] = offset_y;
303 return GD_TRUE;
304 }
305
306 /**
307 * gdAffineexpansion: Find the affine's expansion factor.
308 * @src: The affine transformation.
309 *
310 * Finds the expansion factor, i.e. the square root of the factor
311 * by which the affine transform affects area. In an affine transform
312 * composed of scaling, rotation, shearing, and translation, returns
313 * the amount of scaling.
314 *
315 * GD_TRUE on success or GD_FALSE
316 **/
317 BGD_DECLARE(double) gdAffineExpansion (const double src[6])
318 {
319 return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
320 }
321
322 /**
323 * Function: gdAffineRectilinear
324 * Determines whether the affine transformation is axis aligned. A
325 * tolerance has been implemented using GD_EPSILON.
326 *
327 * Parameters:
328 * m - The affine transformation
329 *
330 * Returns:
331 * GD_TRUE if the affine is rectilinear or GD_FALSE
332 */
333 BGD_DECLARE(int) gdAffineRectilinear (const double m[6])
334 {
335 return ((fabs (m[1]) < GD_EPSILON && fabs (m[2]) < GD_EPSILON) ||
336 (fabs (m[0]) < GD_EPSILON && fabs (m[3]) < GD_EPSILON));
337 }
338
339 /**
340 * Function: gdAffineEqual
341 * Determines whether two affine transformations are equal. A tolerance
342 * has been implemented using GD_EPSILON.
343 *
344 * Parameters:
345 * m1 - The first affine transformation
346 * m2 - The first affine transformation
347 *
348 * Returns:
349 * GD_TRUE on success or GD_FALSE
350 */
351 BGD_DECLARE(int) gdAffineEqual (const double m1[6], const double m2[6])
352 {
353 return (fabs (m1[0] - m2[0]) < GD_EPSILON &&
354 fabs (m1[1] - m2[1]) < GD_EPSILON &&
355 fabs (m1[2] - m2[2]) < GD_EPSILON &&
356 fabs (m1[3] - m2[3]) < GD_EPSILON &&
357 fabs (m1[4] - m2[4]) < GD_EPSILON &&
358 fabs (m1[5] - m2[5]) < GD_EPSILON);
359 }