1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 2008, Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
24 * @short_description: A structure holding a couple of values
26 * The CpmlPair is a generic 2D structure. It can be used to represent points,
27 * sizes, offsets or whatever have two components.
29 * The name comes from MetaFont.
34 * @x: the x component of the pair
35 * @y: the y component of the pair
37 * A generic 2D structure.
42 * @x: the x component of the vector
43 * @y: the y component of the vector
45 * A subclass of a #CpmlPair. A vector represents the coordinates of a point
46 * distant 1 from the origin (0, 0). The vectors are useful to define a
47 * direction and are better suited than angles for simplifying interpolations.
50 #include "cpml-pair.h"
55 static CpmlPair fallback_pair
= { 0., 0. };
60 * @pair: the destination #CpmlPair struct
61 * @src: the source #CpmlPair struct
63 * Assign @src to @pair.
65 * Return value: 1 if @pair was set, 0 on errors
68 cpml_pair_copy(CpmlPair
*pair
, const CpmlPair
*src
)
76 * cpml_pair_transform:
77 * @pair: the destination #CpmlPair struct
78 * @matrix: the transformation matrix
80 * Shortcut to apply a specific transformation matrix to @pair.
82 * Return value: 1 if @pair was transformed, 0 on errors
85 cpml_pair_transform(CpmlPair
*pair
, const cairo_matrix_t
*matrix
)
87 cairo_matrix_transform_point(matrix
, &pair
->x
, &pair
->y
);
93 * @from: the first #CpmlPair struct
94 * @to: the second #CpmlPair struct
95 * @distance: where to store the result
97 * Gets the distance between @from and @to, storing the result in @distance.
98 * If you need this value only for comparation purpose, you could use
99 * cpm_pair_squared_distance() instead that is a lot faster, since no square
100 * root operation is involved.
102 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
105 * Return value: 1 if @distance was properly set, 0 on errors
108 cpml_pair_distance(double *distance
, const CpmlPair
*from
, const CpmlPair
*to
)
110 if (!cpml_pair_square_distance(distance
, from
, to
))
113 *distance
= sqrt(*distance
);
118 * cpml_pair_square_distance:
119 * @from: the first #CpmlPair struct
120 * @to: the second #CpmlPair struct
121 * @distance: where to store the result
123 * Gets the square distance between @from and @to, storing the result in
124 * @distance. This value is useful for comparation purpose: if you need to
125 * get the real distance, use cpml_pair_distance().
127 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
130 * Return value: 1 if @distance was properly set, 0 on errors
133 cpml_pair_square_distance(double *distance
,
134 const CpmlPair
*from
, const CpmlPair
*to
)
139 from
= &fallback_pair
;
145 *distance
= x
* x
+ y
* y
;
151 * @from: the first #CpmlPair struct
152 * @to: the second #CpmlPair struct
153 * @angle: where to store the result
155 * Gets the angle between @from and @to, storing the result in @angle.
157 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
160 * Return value: 1 if @angle was properly set, 0 on errors
163 cpml_pair_angle(double *angle
, const CpmlPair
*from
, const CpmlPair
*to
)
165 static CpmlPair cached_pair
= { 1., 0. };
166 static double cached_angle
= 0.;
170 from
= &fallback_pair
;
174 pair
.x
= to
->x
- from
->x
;
175 pair
.y
= to
->y
- from
->y
;
177 /* Check for cached result */
178 if (pair
.x
== cached_pair
.x
&& pair
.y
== cached_pair
.y
) {
179 *angle
= cached_angle
;
180 } else if (pair
.y
== 0.) {
181 *angle
= pair
.x
>= 0. ? CPML_DIR_RIGHT
: CPML_DIR_LEFT
;
182 } else if (pair
.x
== 0.) {
183 *angle
= pair
.y
> 0. ? CPML_DIR_UP
: CPML_DIR_DOWN
;
184 } else if (pair
.x
== pair
.y
) {
185 *angle
= pair
.x
> 0. ? M_PI
/ 4. : 5. * M_PI
/ 4.;
186 } else if (pair
.x
== -pair
.y
) {
187 *angle
= pair
.x
> 0. ? 7. * M_PI
/ 4. : 3. * M_PI
/ 4.;
189 *angle
= atan(pair
.y
/ pair
.x
);
193 else if (pair
.y
< 0.0)
194 *angle
+= 2.0 * M_PI
;
196 /* Cache registration */
197 cached_angle
= *angle
;
198 cpml_pair_copy(&cached_pair
, &pair
);
205 * cpml_vector_from_pair:
206 * @vector: an allocated #CpmlPair struct
207 * @pair: the source pair
209 * Unitizes @pair, that is given the line L passing throught the origin and
210 * @pair, gets the coordinate of the point on this line far 1.0 from
211 * the origin, and store the result in @vector.
213 * @pair and @vector can be the same struct.
215 * Return value: 1 if @vector was properly set, 0 on errors
218 cpml_vector_from_pair(CpmlPair
*vector
, const CpmlPair
*pair
)
222 if (!cpml_pair_distance(&length
, pair
, NULL
) || length
== 0.)
225 vector
->x
= pair
->x
/ length
;
226 vector
->y
= pair
->y
/ length
;
231 * cpml_vector_from_angle:
232 * @vector: an allocated #CpmlPair struct
233 * @angle: angle of direction, in radians
235 * Calculates the coordinates of the point far 1.0 from the origin in the
236 * @angle direction. The result is stored in @vector.
238 * Return value: 1 if @vector was properly set, 0 on errors
241 cpml_vector_from_angle(CpmlPair
*vector
, double angle
)
243 static double cached_angle
= 0.;
244 static CpmlPair cached_vector
= { 1., 0. };
246 /* Check for cached result */
247 if (angle
== cached_angle
) {
248 vector
->x
= cached_vector
.x
;
249 vector
->y
= cached_vector
.y
;
250 } else if (angle
== CPML_DIR_RIGHT
) {
253 } else if (angle
== CPML_DIR_UP
) {
256 } else if (angle
== CPML_DIR_LEFT
) {
259 } else if (angle
== CPML_DIR_DOWN
) {
263 vector
->x
= cos(angle
);
264 vector
->y
= sin(angle
);
266 /* Cache registration */
267 cached_angle
= angle
;
268 cpml_pair_copy(&cached_vector
, vector
);