* add lifting detector mode with different sample axes.
[hkl.git] / src / hkl-vector.c
blob3e5aab16e5dd8c2c22afe2bedab6b8693b215b99
1 /* This file is part of the hkl library.
3 * The hkl library is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * The hkl library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with the hkl library. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright (C) 2003-2009 Synchrotron SOLEIL
17 * L'Orme des Merisiers Saint-Aubin
18 * BP 48 91192 GIF-sur-YVETTE CEDEX
20 * Authors: Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>
22 #include <stdlib.h>
23 #include <assert.h>
24 #include <string.h>
26 #include <hkl/hkl-vector.h>
27 #include <hkl/hkl-matrix.h>
28 #include <hkl/hkl-quaternion.h>
30 void hkl_vector_init(HklVector *v, double x, double y, double z)
32 v->data[0] = x;
33 v->data[1] = y;
34 v->data[2] = z;
37 void hkl_vector_fprintf(FILE *file, HklVector const *self)
39 fprintf(file, "|%f, %f, %f|", self->data[0], self->data[1], self->data[2]);
42 int hkl_vector_cmp(HklVector const *self, HklVector const *vector)
44 unsigned int i;
46 for (i=0; i<3; i++)
47 if ( fabs(self->data[i] - vector->data[i]) > HKL_EPSILON )
48 return HKL_TRUE;
49 return HKL_FALSE;
52 /**not yet used*/
53 int hkl_vector_is_opposite(HklVector const *self, HklVector const *vector)
55 unsigned int i;
57 for (i=0; i<3; i++)
58 if ( fabs(self->data[i] + vector->data[i]) > HKL_EPSILON )
59 return HKL_FALSE;
60 return HKL_TRUE;
63 void hkl_vector_add_vector(HklVector *self, HklVector const *vector)
65 unsigned int i;
66 for (i=0;i<3;i++)
67 self->data[i] += vector->data[i];
70 void hkl_vector_minus_vector(HklVector *self, HklVector const *vector)
72 unsigned int i;
73 for (i=0;i<3;i++)
74 self->data[i] -= vector->data[i];
77 void hkl_vector_div_double(HklVector *self, double const d)
79 unsigned int i;
80 for (i=0;i<3;i++)
81 self->data[i] /= d;
84 void hkl_vector_times_double(HklVector *self, double const d)
86 unsigned int i;
87 for (i=0;i<3;i++)
88 self->data[i] *= d;
91 void hkl_vector_times_vector(HklVector *self, HklVector const *vector)
93 unsigned int i;
94 for (i=0;i<3;i++)
95 self->data[i] *= vector->data[i];
98 void hkl_vector_times_smatrix(HklVector *self, HklMatrix const *m)
100 HklVector tmp;
101 tmp = *self;
103 self->data[0] = tmp.data[0] *m->data[0][0] + tmp.data[1] *m->data[1][0] + tmp.data[2] *m->data[2][0];
104 self->data[1] = tmp.data[0] *m->data[0][1] + tmp.data[1] *m->data[1][1] + tmp.data[2] *m->data[2][1];
105 self->data[2] = tmp.data[0] *m->data[0][2] + tmp.data[1] *m->data[1][2] + tmp.data[2] *m->data[2][2];
108 double hkl_vector_sum(HklVector const *self)
110 return self->data[0] + self->data[1] + self->data[2];
113 double hkl_vector_scalar_product(HklVector const *self, HklVector const *vector)
115 unsigned int i;
116 double scalar = 0;
118 for (i=0;i<3;i++)
119 scalar += self->data[i] *vector->data[i];
120 return scalar;
123 void hkl_vector_vectorial_product(HklVector *self, HklVector const *vector)
125 HklVector tmp;
127 tmp = *self;
128 self->data[0] = tmp.data[1] * vector->data[2] - tmp.data[2] * vector->data[1];
129 self->data[1] = tmp.data[2] * vector->data[0] - tmp.data[0] * vector->data[2];
130 self->data[2] = tmp.data[0] * vector->data[1] - tmp.data[1] * vector->data[0];
134 double hkl_vector_angle(HklVector const *self, HklVector const *vector)
136 double angle;
137 double cos_angle;
138 double norm;
139 double norm_self;
140 double norm_vector;
142 norm_self = hkl_vector_norm2(self);
143 norm_vector = hkl_vector_norm2(vector);
145 // check the validity of the parameters
146 assert(norm_self > HKL_EPSILON);
147 assert(norm_vector > HKL_EPSILON);
149 norm = norm_self *norm_vector;
151 cos_angle = hkl_vector_scalar_product(self, vector) / norm;
153 // problem with round
154 if (cos_angle >= 1 )
155 angle = 0;
156 else
157 if (cos_angle <= -1 )
158 angle = M_PI;
159 else
160 angle = acos(cos_angle);
161 return angle;
164 double hkl_vector_oriented_angle(HklVector const *self,
165 HklVector const *vector,
166 HklVector const *ref)
168 double angle;
169 HklVector tmp;
170 HklVector ref_u;
172 angle = hkl_vector_angle(self, vector);
173 tmp = *self;
174 hkl_vector_vectorial_product(&tmp, vector);
175 hkl_vector_normalize(&tmp);
176 ref_u = *ref;
177 hkl_vector_normalize(&ref_u);
178 if (hkl_vector_is_opposite(&tmp, &ref_u))
179 angle = -angle;
180 return angle;
184 *@brief normalize a hkl_vector
185 *@return true if the hkl_vector can be normalized, false otherwise
186 *@todo check the status
188 int hkl_vector_normalize(HklVector *self)
190 int status = HKL_FAIL;
192 double norm = hkl_vector_norm2(self);
193 if ( norm > HKL_EPSILON )
195 hkl_vector_div_double(self, norm);
196 status = HKL_SUCCESS;
199 return status;
202 int hkl_vector_is_colinear(HklVector const *self, HklVector const *vector)
204 int is_colinear = 0;
205 HklVector tmp = *self;
207 hkl_vector_vectorial_product(&tmp, vector);
208 if (hkl_vector_norm2(&tmp) < HKL_EPSILON)
209 is_colinear = 1;
211 return is_colinear;
215 void hkl_vector_randomize(HklVector *self)
217 self->data[0] = -1 + 2 *rand()/(RAND_MAX+1.0);
218 self->data[1] = -1 + 2 *rand()/(RAND_MAX+1.0);
219 self->data[2] = -1 + 2 *rand()/(RAND_MAX+1.0);
222 void hkl_vector_randomize_vector(HklVector *self, HklVector const *vector)
225 hkl_vector_randomize(self);
226 while (!hkl_vector_cmp(self, vector));
229 void hkl_vector_randomize_vector_vector(HklVector *self,
230 HklVector const *vector1,
231 HklVector const *vector2)
234 hkl_vector_randomize(self);
235 while (!hkl_vector_cmp(self, vector1) || !hkl_vector_cmp(self, vector2));
238 /**rotate a vector around another vector with an angle */
239 void hkl_vector_rotated_around_vector(HklVector *self,
240 HklVector const *axe, double angle)
242 double c = cos(angle);
243 double s = sin(angle);
244 HklVector axe_n;
245 HklVector tmp;
247 axe_n = *axe;
248 hkl_vector_normalize(&axe_n);
250 tmp = *self;
252 self->data[0] = (c + (1 - c) * axe_n.data[0] * axe_n.data[0]) * tmp.data[0];
253 self->data[0] += ((1 - c) * axe_n.data[0] * axe_n.data[1] - axe_n.data[2] * s) * tmp.data[1];
254 self->data[0] += ((1 - c) * axe_n.data[0] * axe_n.data[2] + axe_n.data[1] * s) * tmp.data[2];
256 self->data[1] = ((1 - c) * axe_n.data[0] * axe_n.data[1] + axe_n.data[2] * s) * tmp.data[0];
257 self->data[1] += (c + (1 - c) * axe_n.data[1] * axe_n.data[1]) * tmp.data[1];
258 self->data[1] += ((1 - c) * axe_n.data[1] * axe_n.data[2] - axe_n.data[0] * s) * tmp.data[2];
260 self->data[2] = ((1 - c) * axe_n.data[0] * axe_n.data[2] - axe_n.data[1] * s) * tmp.data[0];
261 self->data[2] += ((1 - c) * axe_n.data[1] * axe_n.data[2] + axe_n.data[0] * s) * tmp.data[1];
262 self->data[2] += (c + (1 - c) * axe_n.data[2] * axe_n.data[2]) * tmp.data[2];
265 double hkl_vector_norm2(HklVector const *self)
267 return sqrt(self->data[0] * self->data[0]
268 + self->data[1] * self->data[1]
269 + self->data[2] * self->data[2]);
273 * apply a quaternion rotation to a vector
274 * @todo test
276 void hkl_vector_rotated_quaternion(HklVector *self, HklQuaternion const *qr)
278 HklQuaternion q;
279 HklQuaternion tmp;
281 // compute qr * qv * *qr
282 q = *qr;
283 hkl_quaternion_from_vector(&tmp, self);
285 hkl_quaternion_times_quaternion(&q, &tmp);
286 tmp = *qr;
287 hkl_quaternion_conjugate(&tmp);
288 hkl_quaternion_times_quaternion(&q, &tmp);
290 // copy the vector part of the quaternion in the vector
291 memcpy(self->data, &q.data[1], sizeof(self->data));
295 * @brief check if the hkl_vector is null
296 * @return true if all |elements| are below HKL_EPSILON, false otherwise
297 * @todo test
299 int hkl_vector_is_null(HklVector const *self)
301 unsigned int i;
302 for (i=0; i<3; i++)
303 if ( fabs(self->data[i]) > HKL_EPSILON )
304 return HKL_FALSE;
305 return HKL_TRUE;
308 void hkl_vector_project_on_plan(HklVector *self,
309 HklVector const *plan)
311 HklVector tmp;
313 tmp = *plan;
314 hkl_vector_normalize(&tmp);
315 hkl_vector_times_double(&tmp, hkl_vector_scalar_product(self, &tmp));
316 hkl_vector_minus_vector(self, &tmp);