[CPML] Removed inexistent arg from docblock
[adg.git] / src / cpml / cpml-pair.c
bloba13839645b03f8fddba58a84ad24440c1f7fdfb6
1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 2008,2009,2010,2011 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.
21 /**
22 * SECTION:cpml-pair
23 * @Section_Id:CpmlPair
24 * @title: CpmlPair
25 * @short_description: Basic struct holding a couple of values
27 * The #CpmlPair is a generic 2D structure. It can be used to represent
28 * coordinates, sizes, offsets or whatever have two components.
30 * The name comes from MetaFont.
31 **/
33 /**
34 * CpmlPair:
35 * @x: the x component of the pair
36 * @y: the y component of the pair
38 * A generic 2D structure.
39 **/
41 /**
42 * CpmlVector:
43 * @x: the x component of the vector
44 * @y: the y component of the vector
46 * Another name for #CpmlPair. It is used to clarify when a function
47 * expects a generic pair (usually coordinates) or a vector.
49 * A vector represents a line starting from the origin (0,0) and ending
50 * to the given coordinates pair. Vectors are useful to define direction
51 * and length at once. Keep in mind the cairo default coordinates system
52 * is not problably what you expect: the x axis increases at right
53 * (as usual) but the y axis increases at down (the reverse of a usual
54 * cartesian plan). An angle of 0 is at V=(1; 0) (middle right).
55 **/
58 #include "cpml-internal.h"
59 #include <string.h>
60 #include <math.h>
63 static CpmlPair fallback_pair = { 0, 0 };
66 /**
67 * cpml_pair_from_cairo:
68 * @pair: the destination #CpmlPair
69 * @path_data: the original path data point
71 * Sets @pair from a #cairo_path_data_t struct. @path_data should contains
72 * a point data: it is up to the caller to be sure @path_data is valid.
73 **/
74 void
75 cpml_pair_from_cairo(CpmlPair *pair, const cairo_path_data_t *path_data)
77 pair->x = path_data->point.x;
78 pair->y = path_data->point.y;
81 /**
82 * cpml_pair_copy:
83 * @pair: the destination #CpmlPair
84 * @src: the source #CpmlPair
86 * Copies @src in @pair.
87 **/
88 void
89 cpml_pair_copy(CpmlPair *pair, const CpmlPair *src)
91 memcpy(pair, src, sizeof(CpmlPair));
94 /**
95 * cpml_pair_equal:
96 * @pair: the first pair to compare
97 * @src: the second pair to compare
99 * Compares @pair to @src and returns 1 if the pairs are equals.
100 * Two %NULL pairs are considered equal.
102 * Returns: 1 if @pair is equal to @src, 0 otherwise
104 cairo_bool_t
105 cpml_pair_equal(const CpmlPair *pair, const CpmlPair *src)
107 if (pair == NULL && src == NULL)
108 return 1;
110 if (pair == NULL || src == NULL)
111 return 0;
113 return pair->x == src->x && pair->y == src->y ? 1 : 0;
117 * cpml_pair_transform:
118 * @pair: the destination #CpmlPair struct
119 * @matrix: the transformation matrix
121 * Shortcut to apply a specific transformation matrix to @pair.
123 void
124 cpml_pair_transform(CpmlPair *pair, const cairo_matrix_t *matrix)
126 cairo_matrix_transform_point(matrix, &pair->x, &pair->y);
130 * cpml_pair_squared_distance:
131 * @from: the first #CpmlPair struct
132 * @to: the second #CpmlPair struct
134 * Gets the squared distance between @from and @to. This value is useful
135 * for comparation purpose: if you need to get the real distance, use
136 * cpml_pair_distance().
138 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
139 * will be used.
141 * Returns: the squared distance
143 double
144 cpml_pair_squared_distance(const CpmlPair *from, const CpmlPair *to)
146 double x, y;
148 if (from == NULL)
149 from = &fallback_pair;
150 if (to == NULL)
151 to = &fallback_pair;
153 x = to->x - from->x;
154 y = to->y - from->y;
156 return x * x + y * y;
160 * cpml_pair_distance:
161 * @from: the first #CpmlPair struct
162 * @to: the second #CpmlPair struct
164 * Gets the distance between @from and @to. If you need this value only
165 * for comparation purpose, you could use cpm_pair_squared_distance()
166 * instead.
168 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
169 * will be used.
171 * The algorithm used is adapted from:
172 * "Replacing Square Roots by Pythagorean Sums"
173 * by Clave Moler and Donald Morrison (1983)
174 * IBM Journal of Research and Development 27 (6): 577–581
175 * http://www.research.ibm.com/journal/rd/276/ibmrd2706P.pdf
177 * Returns: the distance
179 double
180 cpml_pair_distance(const CpmlPair *from, const CpmlPair *to)
182 double x, y;
183 double p, q, r, s;
185 if (from == NULL)
186 from = &fallback_pair;
187 if (to == NULL)
188 to = &fallback_pair;
190 x = to->x - from->x;
191 y = to->y - from->y;
193 if (x < 0)
194 x = -x;
195 if (y < 0)
196 y = -y;
198 if (x > y) {
199 p = x;
200 q = y;
201 } else {
202 p = y;
203 q = x;
206 if (p > 0) {
207 for (;;) {
208 r = q/p;
209 r *= r;
210 if (r == 0)
211 break;
213 s = r / (4+r);
214 p += 2*s*p;
215 q *= s;
219 return p;
223 * cpml_pair_to_cairo:
224 * @pair: the destination #CpmlPair
225 * @path_data: the original path data point
227 * Sets a #cairo_path_data_t struct to @pair. This is exactly the reverse
228 * operation of cpml_pair_from_cairo().
230 void
231 cpml_pair_to_cairo(const CpmlPair *pair, cairo_path_data_t *path_data)
233 path_data->point.x = pair->x;
234 path_data->point.y = pair->y;
239 * cpml_vector_from_angle:
240 * @vector: the destination #CpmlVector
241 * @angle: angle of direction, in radians
243 * Calculates the coordinates of the point far %1 from the origin
244 * in the @angle direction. The result is stored in @vector.
246 void
247 cpml_vector_from_angle(CpmlVector *vector, double angle)
249 /* Check for common conditions */
250 if (angle == -M_PI_2) {
251 vector->x = 0;
252 vector->y = -1;
253 } else if (angle == M_PI_2) {
254 vector->x = 0;
255 vector->y = +1;
256 } else if (angle == M_PI || angle == -M_PI) {
257 vector->x = -1;
258 vector->y = 0;
259 } else if (angle == 0) {
260 vector->x = +1;
261 vector->y = 0;
262 } else {
263 vector->x = cos(angle);
264 vector->y = sin(angle);
269 * cpml_vector_set_length:
270 * @vector: a #CpmlVector
271 * @length: the new length
273 * Imposes the specified @length to @vector. If the old length is %0
274 * (and so the direction is not known), nothing happens. If @length
275 * is %0, @vector is set to (0, 0).
277 * The @length parameter can be negative, in which case the vector
278 * is inverted.
280 void
281 cpml_vector_set_length(CpmlVector *vector, double length)
283 double divisor;
285 if (length == 0) {
286 vector->x = 0;
287 vector->y = 0;
288 return;
291 divisor = cpml_pair_distance(NULL, vector);
293 /* Check for valid length (anything other than 0) */
294 if (divisor != 0) {
295 divisor /= length;
296 vector->x /= divisor;
297 vector->y /= divisor;
302 * cpml_vector_angle:
303 * @vector: the source #CpmlVector
305 * Gets the angle of @vector, in radians. If @vector is (0, 0),
306 * 0 is returned.
308 * Returns: the angle in radians, a value between -M_PI and M_PI
310 double
311 cpml_vector_angle(const CpmlVector *vector)
313 /* Check for common conditions */
314 if (vector->y == 0)
315 return vector->x >= 0 ? 0 : M_PI;
316 if (vector->x == 0)
317 return vector->y > 0 ? M_PI_2 : -M_PI_2;
318 if (vector->x == vector->y)
319 return vector->x > 0 ? M_PI_4 : -M_PI_4 * 3;
320 if (vector->x == -vector->y)
321 return vector->x > 0 ? -M_PI_4 : M_PI_4 * 3;
323 return atan2(vector->y, vector->x);
327 * cpml_vector_normal:
328 * @vector: the subject #CpmlVector
330 * Stores in @vector a vector normal to the original @vector.
331 * The length is retained.
333 * The algorithm is really quick because no trigonometry is involved.
335 void
336 cpml_vector_normal(CpmlVector *vector)
338 double tmp = vector->x;
340 vector->x = -vector->y;
341 vector->y = tmp;
345 * cpml_vector_transform:
346 * @vector: the destination #CpmlPair struct
347 * @matrix: the transformation matrix
349 * Shortcut to apply a specific transformation matrix to @vector.
350 * It works in a similar way of cpml_pair_transform() but uses
351 * cairo_matrix_transform_distance() instead of
352 * cairo_matrix_transform_point().
354 void
355 cpml_vector_transform(CpmlPair *vector, const cairo_matrix_t *matrix)
357 cairo_matrix_transform_distance(matrix, &vector->x, &vector->y);