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-2017 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>
23 #include <tap/basic.h>
24 #include <tap/float.h>
25 #include <tap/hkl-tap.h>
27 /* BEWARE THESE TESTS ARE DEALING WITH HKL INTERNALS WHICH EXPOSE A
28 * NON PUBLIC API WHICH ALLOW TO SHOOT YOURSELF IN YOUR FOOT */
30 #include "hkl/ccan/container_of/container_of.h"
31 #include "hkl-axis-private.h" /* temporary */
32 #include "hkl-geometry-private.h"
34 static void add_holder(void)
36 HklGeometry
*g
= NULL
;
37 HklHolder
*holder
= NULL
;
39 g
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
40 is_int(0, darray_size(g
->holders
), __func__
);
42 holder
= hkl_geometry_add_holder(g
);
43 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
44 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
45 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_angle_deg
);
46 is_int(1, darray_size(g
->holders
), __func__
);
48 holder
= hkl_geometry_add_holder(g
);
49 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
50 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
51 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_angle_deg
);
52 is_int(2, darray_size(g
->holders
), __func__
);
54 ok(holder
== darray_item(g
->holders
, 1), __func__
);
59 static void get_axis(void)
62 HklGeometry
*g
= NULL
;
63 HklHolder
*holder
= NULL
;
64 const HklParameter
*axis0
;
67 g
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
69 holder
= hkl_geometry_add_holder(g
);
70 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
71 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
72 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_length_mm
);
74 holder
= hkl_geometry_add_holder(g
);
75 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
76 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
77 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_length_mm
);
79 /* check the private API */
80 res
&= DIAG(0 == !hkl_geometry_get_axis_by_name(g
, "A"));
81 res
&= DIAG(0 == !hkl_geometry_get_axis_by_name(g
, "B"));
82 res
&= DIAG(0 == !hkl_geometry_get_axis_by_name(g
, "C"));
83 res
&= DIAG(0 == !hkl_geometry_get_axis_by_name(g
, "T"));
84 res
&= DIAG(1 == !hkl_geometry_get_axis_by_name(g
, "DONOTEXIST"));
86 /* check the public API */
88 res
&= DIAG(NULL
!= hkl_geometry_axis_get(g
, "A", NULL
));
89 res
&= DIAG(NULL
== hkl_geometry_axis_get(g
, "DONOTEXIST", NULL
));
91 res
&= DIAG(NULL
!= hkl_geometry_axis_get(g
, "A", &error
));
92 res
&= DIAG(error
== NULL
);
93 res
&= DIAG(NULL
!= hkl_geometry_axis_get(g
, "T", &error
));
94 res
&= DIAG(error
== NULL
);
95 res
&= DIAG(NULL
== hkl_geometry_axis_get(g
, "DONOTEXIST", &error
));
96 res
&= DIAG(error
!= NULL
);
97 g_clear_error(&error
);
100 axis0
= hkl_geometry_axis_get(g
, "A", NULL
);
101 res
&= DIAG(TRUE
== hkl_geometry_axis_set(g
, "A", axis0
, NULL
));
102 res
&= DIAG(FALSE
== hkl_geometry_axis_set(g
, "B", axis0
, NULL
));
103 res
&= DIAG(FALSE
== hkl_geometry_axis_set(g
, "T", axis0
, NULL
));
106 res
&= DIAG(hkl_geometry_axis_set(g
, "A", axis0
, &error
));
107 res
&= DIAG(error
== NULL
);
109 res
&= DIAG(FALSE
== hkl_geometry_axis_set(g
, "B", axis0
, &error
));
110 res
&= DIAG(error
!= NULL
);
111 g_clear_error(&error
);
113 res
&= DIAG(FALSE
== hkl_geometry_axis_set(g
, "T", axis0
, &error
));
114 res
&= DIAG(error
!= NULL
);
115 g_clear_error(&error
);
119 hkl_geometry_free(g
);
122 static void update(void)
125 HklGeometry
*g
= NULL
;
126 HklHolder
*holder
= NULL
;
128 HklQuaternion q_ref
= {{1./sqrt(2), 1./sqrt(2), 0.0, 0.0 }};
130 g
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
132 holder
= hkl_geometry_add_holder(g
);
133 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
134 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
135 hkl_holder_add_translation(holder
, "T1", 1., 0., 0., &hkl_unit_length_mm
);
137 holder
= hkl_geometry_add_holder(g
);
138 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
139 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
140 hkl_holder_add_translation(holder
, "T2", 1., 0., 0., &hkl_unit_length_mm
);
142 axis1
= container_of(hkl_geometry_get_axis_by_name(g
, "B"), HklAxis
, parameter
);
143 res
&= DIAG(hkl_parameter_value_set(&axis1
->parameter
, M_PI_2
, HKL_UNIT_DEFAULT
, NULL
));
144 /* now axis1 is dirty */
145 ok(TRUE
== axis1
->parameter
.changed
, __func__
);
147 hkl_geometry_update(g
);
148 holder
= darray_item(g
->holders
, 0);
149 is_quaternion(&q_ref
, &holder
->q
, __func__
);
150 /* now axis1 is clean */
151 res
&= DIAG(FALSE
== axis1
->parameter
.changed
);
155 hkl_geometry_free(g
);
158 static void set(void)
164 HklFactory
*fake_factory
;
166 g
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
167 holder
= hkl_geometry_add_holder(g
);
168 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
169 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
170 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
171 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_length_mm
);
173 g1
= hkl_geometry_new_copy(g
);
175 /* it is required to use a fake factory, with the public API
176 * geometry contain always a real factory */
177 fake_factory
= (HklFactory
*)0x1;
178 g2
= hkl_geometry_new(fake_factory
, &hkl_geometry_operations_defaults
);
179 holder
= hkl_geometry_add_holder(g
);
180 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
181 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
183 ok(hkl_geometry_set(g
, g1
), __func__
);
185 hkl_geometry_free(g2
);
186 hkl_geometry_free(g1
);
187 hkl_geometry_free(g
);
190 static void axis_values_get_set(void)
195 static double set_1
[] = {1, 1, 1, 1};
196 static double set_10
[] = {10, 10, 10, 10};
200 g
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
201 holder
= hkl_geometry_add_holder(g
);
202 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
203 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
204 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
205 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_length_mm
);
207 /* check set DEFAULT unit */
209 ok(TRUE
== hkl_geometry_axis_values_set(g
, set_1
, ARRAY_SIZE(set_1
), HKL_UNIT_DEFAULT
, NULL
), __func__
);
210 ok(TRUE
== hkl_geometry_axis_values_set(g
, set_1
, ARRAY_SIZE(set_1
), HKL_UNIT_DEFAULT
, &error
), __func__
);
211 ok(error
== NULL
, __func__
);
212 for(i
=0; i
<ARRAY_SIZE(set_1
); ++i
)
213 is_double(set_1
[i
], hkl_parameter_value_get(darray_item(g
->axes
, i
), HKL_UNIT_DEFAULT
), HKL_EPSILON
, __func__
);
215 /* check get DEFAULT unit */
216 hkl_geometry_axis_values_get(g
, values
, ARRAY_SIZE(values
), HKL_UNIT_DEFAULT
);
217 for(i
=0; i
<ARRAY_SIZE(set_1
); ++i
)
218 is_double(set_1
[i
], values
[i
], HKL_EPSILON
, __func__
);
220 /* check set USER unit */
221 ok(TRUE
== hkl_geometry_axis_values_set(g
, set_10
, ARRAY_SIZE(set_10
), HKL_UNIT_USER
, NULL
), __func__
);
222 ok(TRUE
== hkl_geometry_axis_values_set(g
, set_10
, ARRAY_SIZE(set_10
), HKL_UNIT_USER
, &error
), __func__
);
223 ok(error
== NULL
, __func__
);
225 /* check get USER unit */
226 hkl_geometry_axis_values_get(g
, values
, ARRAY_SIZE(values
), HKL_UNIT_USER
);
227 for(i
=0; i
<ARRAY_SIZE(set_10
); ++i
)
228 is_double(set_10
[i
], values
[i
], HKL_EPSILON
, __func__
);
230 hkl_geometry_free(g
);
233 static void distance(void)
236 HklGeometry
*g1
= NULL
;
237 HklGeometry
*g2
= NULL
;
238 HklHolder
*holder
= NULL
;
240 g1
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
241 holder
= hkl_geometry_add_holder(g1
);
242 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
243 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
244 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
245 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_length_mm
);
247 g2
= hkl_geometry_new_copy(g1
);
249 res
&= DIAG(hkl_geometry_set_values_v(g1
, HKL_UNIT_DEFAULT
, NULL
, 0., 0., 0., 0.));
250 res
&= DIAG(hkl_geometry_set_values_v(g2
, HKL_UNIT_DEFAULT
, NULL
, 1., 1., 1., 1.));
251 is_double(4., hkl_geometry_distance(g1
, g2
), HKL_EPSILON
, __func__
);
255 hkl_geometry_free(g1
);
256 hkl_geometry_free(g2
);
259 static void is_valid(void)
262 HklGeometry
*geom
= NULL
;
263 HklHolder
*holder
= NULL
;
265 geom
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
266 holder
= hkl_geometry_add_holder(geom
);
267 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
268 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
269 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
270 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_length_mm
);
272 res
&= DIAG(hkl_geometry_set_values_v(geom
, HKL_UNIT_DEFAULT
, NULL
, 0., 0., 0., 0.));
273 res
&= DIAG(TRUE
== hkl_geometry_is_valid(geom
));
275 res
&= DIAG(hkl_geometry_set_values_v(geom
, HKL_UNIT_DEFAULT
, NULL
, -181. * HKL_DEGTORAD
, 0., 0., 0.));
276 res
&= DIAG(TRUE
== hkl_geometry_is_valid(geom
));
278 res
&= DIAG(hkl_parameter_min_max_set(darray_item(geom
->axes
, 0),
279 -100 * HKL_DEGTORAD
, 100 * HKL_DEGTORAD
,
280 HKL_UNIT_DEFAULT
, NULL
));
281 res
&= DIAG(FALSE
== hkl_geometry_is_valid(geom
));
285 hkl_geometry_free(geom
);
288 static void wavelength(void)
290 HklGeometry
*geom
= NULL
;
293 geom
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
295 is_double(1.54, hkl_geometry_wavelength_get(geom
, HKL_UNIT_DEFAULT
), HKL_EPSILON
, __func__
);
297 ok(TRUE
== hkl_geometry_wavelength_set(geom
, 2, HKL_UNIT_DEFAULT
, NULL
), __func__
);
298 is_double(2, hkl_geometry_wavelength_get(geom
, HKL_UNIT_DEFAULT
), HKL_EPSILON
, __func__
);
301 ok(TRUE
== hkl_geometry_wavelength_set(geom
, 2, HKL_UNIT_DEFAULT
, &error
), __func__
);
302 ok(error
== NULL
, __func__
);
303 is_double(2, hkl_geometry_wavelength_get(geom
, HKL_UNIT_DEFAULT
), HKL_EPSILON
, __func__
);
305 hkl_geometry_free(geom
);
308 static void xxx_rotation_get(void)
312 HklFactory
**factories
;
313 HklDetector
*detector
= hkl_detector_factory_new(HKL_DETECTOR_TYPE_0D
);
314 HklSample
*sample
= hkl_sample_new("test");
316 factories
= hkl_factory_get_all(&n
);
317 for(i
=0; i
<n
&& TRUE
== res
; i
++){
318 HklGeometry
*geometry
= NULL
;
319 HklQuaternion q_ref
= {{1, 0, 0, 0}};
323 geometry
= hkl_factory_create_new_geometry(factories
[i
]);
324 qs
= hkl_geometry_sample_rotation_get(geometry
, sample
);
325 qd
= hkl_geometry_detector_rotation_get(geometry
, detector
);
327 res
&= DIAG(TRUE
== hkl_quaternion_cmp(&q_ref
, &qs
));
328 res
&= DIAG(TRUE
== hkl_quaternion_cmp(&q_ref
, &qd
));
330 hkl_geometry_free(geometry
);
334 hkl_detector_free(detector
);
335 hkl_sample_free(sample
);
338 static void list(void)
343 HklGeometryList
*list
;
344 const HklGeometryListItem
*item
;
346 static double values
[] = {0. * HKL_DEGTORAD
, 10 * HKL_DEGTORAD
, 30 * HKL_DEGTORAD
, 100 * HKL_DEGTORAD
};
348 g
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
349 holder
= hkl_geometry_add_holder(g
);
350 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
351 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
352 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
353 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_length_mm
);
355 list
= hkl_geometry_list_new();
357 res
&= DIAG(hkl_geometry_set_values_v(g
, HKL_UNIT_DEFAULT
, NULL
, values
[0], 0., 0., 0.));
358 hkl_geometry_list_add(list
, g
);
359 is_int(1, hkl_geometry_list_n_items_get(list
), __func__
);
361 /* can not add two times the same geometry */
362 hkl_geometry_list_add(list
, g
);
363 is_int(1, hkl_geometry_list_n_items_get(list
), __func__
);
365 res
&= DIAG(hkl_geometry_set_values_v(g
, HKL_UNIT_DEFAULT
, NULL
, values
[2], 0., 0., 0.));
366 hkl_geometry_list_add(list
, g
);
367 res
&= DIAG(hkl_geometry_set_values_v(g
, HKL_UNIT_DEFAULT
, NULL
, values
[1], 0., 0., 0.));
368 hkl_geometry_list_add(list
, g
);
369 is_int(3, hkl_geometry_list_n_items_get(list
), __func__
);
371 res
&= DIAG(hkl_geometry_set_values_v(g
, HKL_UNIT_DEFAULT
, NULL
, values
[0], 0., 0., 0.));
372 hkl_geometry_list_sort(list
, g
);
374 HKL_GEOMETRY_LIST_FOREACH(item
, list
){
375 is_double(values
[i
++],
376 hkl_parameter_value_get(darray_item(item
->geometry
->axes
, 0), HKL_UNIT_DEFAULT
),
377 HKL_EPSILON
, __func__
);
382 hkl_geometry_free(g
);
383 hkl_geometry_list_free(list
);
386 static void list_multiply_from_range(void)
390 HklGeometryList
*list
;
392 HklParameter
*axisA
, *axisB
, *axisC
, *axisT
;
394 g
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
395 holder
= hkl_geometry_add_holder(g
);
396 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
397 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
398 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
399 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_length_mm
);
401 axisA
= hkl_geometry_get_axis_by_name(g
, "A");
402 axisB
= hkl_geometry_get_axis_by_name(g
, "B");
403 axisC
= hkl_geometry_get_axis_by_name(g
, "C");
404 axisT
= hkl_geometry_get_axis_by_name(g
, "T");
406 res
&= DIAG(hkl_parameter_min_max_set(axisA
, -190, 190, HKL_UNIT_USER
, NULL
));
407 res
&= DIAG(hkl_parameter_min_max_set(axisB
, -190, 190, HKL_UNIT_USER
, NULL
));
408 res
&= DIAG(hkl_parameter_min_max_set(axisC
, -190, 190, HKL_UNIT_USER
, NULL
));
409 res
&= DIAG(hkl_parameter_min_max_set(axisT
, -190, 190., HKL_UNIT_USER
, NULL
));
411 list
= hkl_geometry_list_new();
413 res
&= DIAG(hkl_geometry_set_values_v(g
, HKL_UNIT_DEFAULT
, NULL
,
414 185. * HKL_DEGTORAD
, -185. * HKL_DEGTORAD
, 190. * HKL_DEGTORAD
, 100.));
415 hkl_geometry_list_add(list
, g
);
417 hkl_geometry_list_multiply_from_range(list
);
419 res
&= DIAG(8 == hkl_geometry_list_n_items_get(list
));
423 hkl_geometry_free(g
);
424 hkl_geometry_list_free(list
);
427 static void list_remove_invalid(void)
431 HklGeometryList
*list
;
433 HklParameter
*axisA
, *axisB
, *axisC
, *axisT
;
435 g
= hkl_geometry_new(NULL
, &hkl_geometry_operations_defaults
);
436 holder
= hkl_geometry_add_holder(g
);
437 hkl_holder_add_rotation(holder
, "A", 1., 0., 0., &hkl_unit_angle_deg
);
438 hkl_holder_add_rotation(holder
, "B", 1., 0., 0., &hkl_unit_angle_deg
);
439 hkl_holder_add_rotation(holder
, "C", 1., 0., 0., &hkl_unit_angle_deg
);
440 hkl_holder_add_translation(holder
, "T", 1., 0., 0., &hkl_unit_length_mm
);
442 axisA
= hkl_geometry_get_axis_by_name(g
, "A");
443 axisB
= hkl_geometry_get_axis_by_name(g
, "B");
444 axisC
= hkl_geometry_get_axis_by_name(g
, "C");
445 axisT
= hkl_geometry_get_axis_by_name(g
, "T");
447 res
&= DIAG(hkl_parameter_min_max_set(axisA
, -100, 180., HKL_UNIT_USER
, NULL
));
448 res
&= DIAG(hkl_parameter_min_max_set(axisB
, -100., 180., HKL_UNIT_USER
, NULL
));
449 res
&= DIAG(hkl_parameter_min_max_set(axisC
, -100., 180., HKL_UNIT_USER
, NULL
));
450 res
&= DIAG(hkl_parameter_min_max_set(axisT
, 0.0, 179., HKL_UNIT_USER
, NULL
));
452 list
= hkl_geometry_list_new();
454 res
&= DIAG(hkl_geometry_set_values_v(g
, HKL_UNIT_DEFAULT
, NULL
,
456 -185. * HKL_DEGTORAD
,
459 hkl_geometry_list_add(list
, g
);
461 res
&= DIAG(hkl_geometry_set_values_v(g
, HKL_UNIT_DEFAULT
, NULL
,
462 -190. * HKL_DEGTORAD
,
463 -190. * HKL_DEGTORAD
,
464 -190. * HKL_DEGTORAD
,
466 hkl_geometry_list_add(list
, g
);
468 res
&= DIAG(hkl_geometry_set_values_v(g
, HKL_UNIT_DEFAULT
, NULL
,
473 hkl_geometry_list_add(list
, g
);
475 is_int(3, hkl_geometry_list_n_items_get(list
), __func__
);
476 hkl_geometry_list_remove_invalid(list
);
477 is_int(1, hkl_geometry_list_n_items_get(list
), __func__
);
481 hkl_geometry_free(g
);
482 hkl_geometry_list_free(list
);
493 axis_values_get_set();
500 list_multiply_from_range();
501 list_remove_invalid();