Tab expansion in all the source files
[adg.git] / cpml / cpml-pair.c
blob5dc8b06a6144d648c6b6f52bf49d49af9647ac5a
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 Library 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 * Library 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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 /**
22 * SECTION:cpmlpair
23 * @title: CpmlPair
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.
32 /**
33 * CpmlPair:
34 * @x: the x component of the pair
35 * @y: the y component of the pair
37 * A generic 2D structure.
40 /**
41 * CpmlVector:
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"
52 #include <stdlib.h>
55 static CpmlPair fallback_pair = { 0., 0. };
58 /**
59 * cpml_pair_copy:
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
67 cairo_bool_t
68 cpml_pair_copy(CpmlPair *pair, const CpmlPair *src)
70 pair->x = src->x;
71 pair->y = src->y;
72 return 1;
75 /**
76 * cpml_pair_distance:
77 * @from: the first #CpmlPair struct
78 * @to: the second #CpmlPair struct
79 * @distance: where to store the result
81 * Gets the distance between @from and @to, storing the result in @distance.
82 * If you need this value only for comparation purpose, you could use
83 * cpm_pair_squared_distance() instead that is a lot faster, since no square
84 * root operation is involved.
86 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
87 * will be used.
89 * Return value: 1 if @distance was properly set, 0 on errors
91 cairo_bool_t
92 cpml_pair_distance(const CpmlPair *from, const CpmlPair *to,
93 double *distance)
95 if (!cpml_pair_square_distance(from, to, distance))
96 return 0;
98 *distance = sqrt(*distance);
99 return 1;
103 * cpml_pair_square_distance:
104 * @from: the first #CpmlPair struct
105 * @to: the second #CpmlPair struct
106 * @distance: where to store the result
108 * Gets the square distance between @from and @to, storing the result in
109 * @distance. This value is useful for comparation purpose: if you need to
110 * get the real distance, use cpml_pair_distance().
112 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
113 * will be used.
115 * Return value: 1 if @distance was properly set, 0 on errors
117 cairo_bool_t
118 cpml_pair_square_distance(const CpmlPair *from, const CpmlPair *to,
119 double *distance)
121 double x, y;
123 if (from == NULL)
124 from = &fallback_pair;
125 if (to == NULL)
126 to = &fallback_pair;
128 x = to->x - from->x;
129 y = to->y - from->y;
130 *distance = x * x + y * y;
131 return 1;
135 * cpml_pair_angle:
136 * @from: the first #CpmlPair struct
137 * @to: the second #CpmlPair struct
138 * @angle: where to store the result
140 * Gets the angle between @from and @to, storing the result in @angle.
142 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
143 * will be used.
145 * Return value: 1 if @angle was properly set, 0 on errors
147 cairo_bool_t
148 cpml_pair_angle(const CpmlPair *from, const CpmlPair *to, double *angle)
150 static CpmlPair cached_pair = { 1., 0. };
151 static double cached_angle = 0.;
152 CpmlPair pair;
154 if (from == NULL)
155 from = &fallback_pair;
156 if (to == NULL)
157 to = &fallback_pair;
159 pair.x = to->x - from->x;
160 pair.y = to->y - from->y;
162 /* Check for cached result */
163 if (pair.x == cached_pair.x && pair.y == cached_pair.y) {
164 *angle = cached_angle;
165 } else if (pair.y == 0.) {
166 *angle = pair.x >= 0. ? CPML_DIR_RIGHT : CPML_DIR_LEFT;
167 } else if (pair.x == 0.) {
168 *angle = pair.y > 0. ? CPML_DIR_UP : CPML_DIR_DOWN;
169 } else if (pair.x == pair.y) {
170 *angle = pair.x > 0. ? M_PI / 4. : 5. * M_PI / 4.;
171 } else if (pair.x == -pair.y) {
172 *angle = pair.x > 0. ? 7. * M_PI / 4. : 3. * M_PI / 4.;
173 } else {
174 *angle = atan(pair.y / pair.x);
176 if (pair.x < 0.0)
177 *angle += M_PI;
178 else if (pair.y < 0.0)
179 *angle += 2.0 * M_PI;
181 /* Cache registration */
182 cached_angle = *angle;
183 cpml_pair_copy(&cached_pair, &pair);
186 return 1;
190 * cpml_vector_from_pair:
191 * @vector: an allocated #CpmlPair struct
192 * @pair: the source pair
194 * Unitizes @pair, that is given the line L passing throught the origin and
195 * @pair, gets the coordinate of the point on this line far 1.0 from
196 * the origin, and store the result in @vector.
198 * @pair and @vector can be the same struct.
200 * Return value: 1 if @vector was properly set, 0 on errors
202 cairo_bool_t
203 cpml_vector_from_pair(CpmlPair *vector, const CpmlPair *pair)
205 double length;
207 if (!cpml_pair_distance(pair, NULL, &length) || length == 0.)
208 return 0;
210 vector->x = pair->x / length;
211 vector->y = pair->y / length;
212 return 1;
216 * cpml_vector_from_angle:
217 * @vector: an allocated #CpmlPair struct
218 * @angle: angle of direction, in radians
220 * Calculates the coordinates of the point far 1.0 from the origin in the
221 * @angle direction. The result is stored in @vector.
223 * Return value: 1 if @vector was properly set, 0 on errors
225 cairo_bool_t
226 cpml_vector_from_angle(CpmlPair *vector, double angle)
228 static double cached_angle = 0.;
229 static CpmlPair cached_vector = { 1., 0. };
231 /* Check for cached result */
232 if (angle == cached_angle) {
233 vector->x = cached_vector.x;
234 vector->y = cached_vector.y;
235 } else if (angle == CPML_DIR_RIGHT) {
236 vector->x = +1.;
237 vector->y = 0.;
238 } else if (angle == CPML_DIR_UP) {
239 vector->x = 0.;
240 vector->y = -1.;
241 } else if (angle == CPML_DIR_LEFT) {
242 vector->x = -1.;
243 vector->y = 0.;
244 } else if (angle == CPML_DIR_DOWN) {
245 vector->x = 0.;
246 vector->y = +1.;
247 } else {
248 vector->x = cos(angle);
249 vector->y = sin(angle);
251 /* Cache registration */
252 cached_angle = angle;
253 cpml_pair_copy(&cached_vector, vector);
256 return 1;