## "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.

```    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 hlOpen(54,1);{
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 hlClose(1, 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  *
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 hlOpen(84,1);{
85     double r_det = (src[0] * src[3] - src[1] * src[2]);
86
87     if (!isfinite(r_det)) hlOpen(87,2);{
88         return GD_FALSE;
89     hlClose(3, 89);}
90     if (r_det == 0) hlOpen(90,2);{
91         return GD_FALSE;
92     hlClose(4, 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 hlClose(2, 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 hlOpen(122,1);{
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 hlClose(5, 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 hlOpen(150,1);{
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 hlClose(6, 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 hlOpen(179,1);{
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 hlClose(7, 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 hlOpen(201,1);{
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 hlClose(8, 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 hlOpen(226,1);{
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 hlClose(9, 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 hlOpen(251,1);{
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 hlClose(10, 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 hlOpen(273,1);{
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 hlClose(11, 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 hlOpen(296,1);{
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 hlClose(12, 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 hlOpen(318,1);{
319   return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
320 hlClose(13, 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 hlOpen(334,1);{
335   return ((fabs (m[1]) < GD_EPSILON && fabs (m[2]) < GD_EPSILON) ||
336       (fabs (m[0]) < GD_EPSILON && fabs (m[3]) < GD_EPSILON));
337 hlClose(14, 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 hlOpen(352,1);{
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 hlClose(15, 359);}
```