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>
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
)
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
)
47 if ( fabs(self
->data
[i
] - vector
->data
[i
]) > HKL_EPSILON
)
53 int hkl_vector_is_opposite(HklVector
const *self
, HklVector
const *vector
)
58 if ( fabs(self
->data
[i
] + vector
->data
[i
]) > HKL_EPSILON
)
63 void hkl_vector_add_vector(HklVector
*self
, HklVector
const *vector
)
67 self
->data
[i
] += vector
->data
[i
];
70 void hkl_vector_minus_vector(HklVector
*self
, HklVector
const *vector
)
74 self
->data
[i
] -= vector
->data
[i
];
77 void hkl_vector_div_double(HklVector
*self
, double const d
)
84 void hkl_vector_times_double(HklVector
*self
, double const d
)
91 void hkl_vector_times_vector(HklVector
*self
, HklVector
const *vector
)
95 self
->data
[i
] *= vector
->data
[i
];
98 void hkl_vector_times_smatrix(HklVector
*self
, HklMatrix
const *m
)
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
)
119 scalar
+= self
->data
[i
] *vector
->data
[i
];
123 void hkl_vector_vectorial_product(HklVector
*self
, HklVector
const *vector
)
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
)
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
157 if (cos_angle
<= -1 )
160 angle
= acos(cos_angle
);
164 double hkl_vector_oriented_angle(HklVector
const *self
,
165 HklVector
const *vector
,
166 HklVector
const *ref
)
172 angle
= hkl_vector_angle(self
, vector
);
174 hkl_vector_vectorial_product(&tmp
, vector
);
175 hkl_vector_normalize(&tmp
);
177 hkl_vector_normalize(&ref_u
);
178 if (hkl_vector_is_opposite(&tmp
, &ref_u
))
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
;
202 int hkl_vector_is_colinear(HklVector
const *self
, HklVector
const *vector
)
205 HklVector tmp
= *self
;
207 hkl_vector_vectorial_product(&tmp
, vector
);
208 if (hkl_vector_norm2(&tmp
) < HKL_EPSILON
)
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
);
248 hkl_vector_normalize(&axe_n
);
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
276 void hkl_vector_rotated_quaternion(HklVector
*self
, HklQuaternion
const *qr
)
281 // compute qr * qv * *qr
283 hkl_quaternion_from_vector(&tmp
, self
);
285 hkl_quaternion_times_quaternion(&q
, &tmp
);
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
299 int hkl_vector_is_null(HklVector
const *self
)
303 if ( fabs(self
->data
[i
]) > HKL_EPSILON
)
308 void hkl_vector_project_on_plan(HklVector
*self
,
309 HklVector
const *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
);