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-2014 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 <alloca.h> // for alloca
23 #include <gsl/gsl_sf_trig.h> // for gsl_sf_angle_restrict_symm
24 #include <gsl/gsl_sys.h> // for gsl_isnan
25 #include <math.h> // for fabs, M_PI
26 #include <stdarg.h> // for va_arg, va_end, va_list, etc
27 #include <stddef.h> // for size_t
28 #include <stdio.h> // for fprintf, FILE, stderr
29 #include <stdlib.h> // for free, exit, realloc
30 #include <string.h> // for NULL, strcmp, memcpy
31 #include <sys/types.h> // for uint
32 #include "hkl-axis-private.h" // for HklAxis, etc
33 #include "hkl-geometry-private.h" // for _HklGeometry, etc
34 #include "hkl-interval-private.h" // for HklInterval
35 #include "hkl-macros-private.h" // for HKL_MALLOC
36 #include "hkl-parameter-private.h" // for _HklParameter, etc
37 #include "hkl-quaternion-private.h" // for _HklQuaternion, etc
38 #include "hkl-source-private.h" // for HklSource, hkl_source_init
39 #include "hkl-unit-private.h" // for HklUnit, hkl_unit_factor
40 #include "hkl-vector-private.h" // for HklVector, HklQuaternion, etc
41 #include "hkl.h" // for HklGeometry, etc
42 #include "hkl/ccan/container_of/container_of.h" // for container_of
43 #include "hkl/ccan/darray/darray.h" // for darray_foreach, darray_item, etc
46 * Try to add a axis to the axes list,
47 * if a identical axis is present in the list return it
48 * else create a new on and add it to the list.
49 * die if try to add an axis with the same name but a different axis_v
51 static size_t hkl_geometry_add_rotation(HklGeometry
*self
,
52 const char *name
, const HklVector
*axis_v
)
55 HklParameter
**parameter
;
57 /* check if an axis with the same name is on the axis list */
58 darray_foreach(parameter
, self
->axes
){
59 HklAxis
*axis
= container_of(*parameter
, HklAxis
, parameter
);
60 if(!strcmp((*parameter
)->name
, name
)){
61 if (hkl_vector_cmp(&axis
->axis_v
,
63 fprintf(stderr
, "can not add two axis with the same name \"%s\" but different axes <%f, %f, %f> != <%f, %f, %f> into an HklAxes.",
65 axis
->axis_v
.data
[0], axis
->axis_v
.data
[1], axis
->axis_v
.data
[2],
66 axis_v
->data
[0], axis_v
->data
[1], axis_v
->data
[2]);
75 /* no so create and add it to the list */
76 darray_append(self
->axes
, hkl_parameter_new_axis(name
, axis_v
));
78 return darray_size(self
->axes
) - 1;
85 static struct HklHolderConfig
*hkl_holder_config_new(void)
87 struct HklHolderConfig
*self
;
89 self
= HKL_MALLOC(struct HklHolderConfig
);
98 static struct HklHolderConfig
*hkl_holder_config_ref(struct HklHolderConfig
*self
)
108 static void hkl_holder_config_unref(struct HklHolderConfig
*self
)
124 static HklHolder
*hkl_holder_new(HklGeometry
*geometry
)
126 static HklQuaternion q0
= {{1, 0, 0, 0}};
127 HklHolder
*self
= HKL_MALLOC(HklHolder
);
129 self
->config
= hkl_holder_config_new();
130 self
->geometry
= geometry
;
136 static HklHolder
*hkl_holder_new_copy(HklHolder
*src
, HklGeometry
*geometry
)
138 HklHolder
*self
= HKL_MALLOC(HklHolder
);
140 self
->config
= hkl_holder_config_ref(src
->config
);
141 self
->geometry
= geometry
;
147 static void hkl_holder_free(HklHolder
*self
)
149 hkl_holder_config_unref(self
->config
);
153 static void hkl_holder_update(HklHolder
*self
)
155 static HklQuaternion q0
= {{1, 0, 0, 0}};
159 for(i
=0; i
<self
->config
->len
; ++i
)
160 hkl_quaternion_times_quaternion(&self
->q
,
161 &container_of(darray_item(self
->geometry
->axes
,
162 self
->config
->idx
[i
]),
163 HklAxis
, parameter
)->q
);
166 HklParameter
*hkl_holder_add_rotation_axis(HklHolder
*self
,
167 const char *name
, double x
, double y
, double z
)
169 HklParameter
*axis
= NULL
;
177 idx
= hkl_geometry_add_rotation(self
->geometry
, name
, &axis_v
);
179 /* check that the axis is not already in the holder */
180 for(i
=0; i
<self
->config
->len
; i
++)
181 if (idx
== self
->config
->idx
[i
])
184 axis
= darray_item(self
->geometry
->axes
, idx
);
185 self
->config
->idx
= realloc(self
->config
->idx
, sizeof(*self
->config
->idx
) * (self
->config
->len
+ 1));
186 self
->config
->idx
[self
->config
->len
++] = idx
;
196 * hkl_geometry_new: (skip)
202 HklGeometry
*hkl_geometry_new(const HklFactory
*factory
)
204 HklGeometry
*g
= NULL
;
206 g
= HKL_MALLOC(HklGeometry
);
208 g
->factory
= factory
;
209 hkl_source_init(&g
->source
, 1.54, 1, 0, 0);
210 darray_init(g
->axes
);
211 darray_init(g
->holders
);
217 * hkl_geometry_new_copy: (skip)
224 HklGeometry
*hkl_geometry_new_copy(const HklGeometry
*src
)
226 HklGeometry
*self
= NULL
;
233 self
= HKL_MALLOC(HklGeometry
);
235 self
->factory
= src
->factory
;
236 self
->source
= src
->source
;
239 darray_init(self
->axes
);
240 darray_foreach(axis
, src
->axes
){
241 darray_append(self
->axes
, hkl_parameter_new_copy(*axis
));
244 /* copy the holders */
245 darray_init(self
->holders
);
246 darray_foreach(holder
, src
->holders
){
247 darray_append(self
->holders
,
248 hkl_holder_new_copy(*holder
, self
));
255 * hkl_geometry_free: (skip)
260 void hkl_geometry_free(HklGeometry
*self
)
265 darray_foreach(axis
, self
->axes
){
266 hkl_parameter_free(*axis
);
268 darray_free(self
->axes
);
270 darray_foreach(holder
, self
->holders
){
271 hkl_holder_free(*holder
);
273 darray_free(self
->holders
);
279 * hkl_geometry_set: (skip)
280 * @self: the this ptr
281 * @src: the other #HklGeometry to set from
283 * Set an #HklGeometry from another one.
285 * Returns: TRUE on success, FALSE if an error occurred
287 int hkl_geometry_set(HklGeometry
*self
, const HklGeometry
*src
)
291 g_return_val_if_fail(self
->factory
== src
->factory
, FALSE
);
293 self
->source
= src
->source
;
295 /* copy the axes configuration and mark it as dirty */
296 for(i
=0; i
<darray_size(self
->axes
); ++i
)
297 hkl_parameter_init_copy(darray_item(self
->axes
, i
),
298 darray_item(src
->axes
, i
), NULL
);
300 for(i
=0; i
<darray_size(src
->holders
); ++i
)
301 darray_item(self
->holders
, i
)->q
= darray_item(src
->holders
, i
)->q
;
307 * hkl_geometry_axis_get: (skip)
308 * @self: the this ptr
309 * @name: the name of the axis your are requesting
310 * @error: return location for a GError, or NULL
312 * Return value: (allow-none): the parameter corresponding to the axis name.
314 const HklParameter
*hkl_geometry_axis_get(const HklGeometry
*self
,
320 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
322 darray_foreach(axis
, self
->axes
){
323 if (!strcmp((*axis
)->name
, name
))
329 HKL_GEOMETRY_ERROR_AXIS_GET
,
330 "this geometry does not contain this axis \"%s\"",
337 * hkl_geometry_axis_set: (skip)
338 * @self: the this ptr
339 * @name: the name of the axis to set
340 * @axis: The #HklParameter to set
341 * @error: return location for a GError, or NULL
343 * @todo: check if the error is well tested
345 * Returns: TRUE on success, FALSE if an error occurred
347 int hkl_geometry_axis_set(HklGeometry
*self
, const char *name
,
348 const HklParameter
*axis
,
351 HklParameter
**_axis
;
353 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
355 if(name
!= axis
->name
&& strcmp(name
, axis
->name
)){
358 HKL_GEOMETRY_ERROR_AXIS_SET
,
359 "The axis to set \"%s\" is different from the parameter name \"\"\n",
364 darray_foreach(_axis
, self
->axes
){
367 if (!strcmp(axis
->name
, (*_axis
)->name
)){
368 hkl_parameter_init_copy(*_axis
, axis
, NULL
);
372 hkl_geometry_update(self
);
378 * hkl_geometry_wavelength_get: (skip)
379 * @self: the this ptr
381 * Get the wavelength of the HklGeometry
383 * Returns: the wavelength
385 double hkl_geometry_wavelength_get(const HklGeometry
*self
)
387 return self
->source
.wave_length
;
392 * hkl_geometry_wavelength_set:
395 * @error: return location for a GError, or NULL
397 * Set the wavelength of the geometry
398 * @todo: check the validity of the wavelength
400 * Returns: TRUE on success, FALSE if an error occurred
402 int hkl_geometry_wavelength_set(HklGeometry
*self
, double wavelength
,
405 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
407 self
->source
.wave_length
= wavelength
;
413 * hkl_geometry_init_geometry: (skip)
414 * @self: the this ptr
415 * @src: the #HklGeometry to set from
417 * initilize an HklGeometry
419 * Returns: TRUE on success, FALSE if an error occurred
421 int hkl_geometry_init_geometry(HklGeometry
*self
, const HklGeometry
*src
)
423 return hkl_geometry_set(self
, src
);
427 * hkl_geometry_add_holder: (skip)
430 * add an Holder to the #HklGeometry
434 HklHolder
*hkl_geometry_add_holder(HklGeometry
*self
)
436 HklHolder
*holder
= hkl_holder_new(self
);
437 darray_append(self
->holders
, holder
);
443 * hkl_geometry_update: (skip)
446 * update the geometry internal once an Axis values changed
448 void hkl_geometry_update(HklGeometry
*self
)
454 darray_foreach(axis
, self
->axes
){
455 if ((*axis
)->changed
) {
464 darray_foreach(holder
, self
->holders
){
465 hkl_holder_update(*holder
);
468 darray_foreach(axis
, self
->axes
){
469 (*axis
)->changed
= FALSE
;
474 const char *hkl_geometry_name_get(const HklGeometry
*self
)
476 return hkl_factory_name(self
->factory
);
480 * hkl_geometry_get_axis_idx_by_name: (skip)
484 * get the index of the axes named @name in the geometry
486 * Returns: -1 if the axis was not found
488 int hkl_geometry_get_axis_idx_by_name(const HklGeometry
*self
, const char *name
)
496 darray_foreach(axis
, self
->axes
){
497 if (!strcmp((*axis
)->name
, name
))
506 * hkl_geometry_get_axis_by_name:
510 * get an #HklAxis using its name
512 * Returns: (transfer none):
514 HklParameter
*hkl_geometry_get_axis_by_name(HklGeometry
*self
, const char *name
)
518 darray_foreach(axis
, self
->axes
){
519 if (!strcmp((*axis
)->name
, name
))
526 * hkl_geometry_randomize: (skip)
529 * randomize the #HklGeometry
531 void hkl_geometry_randomize(HklGeometry
*self
)
535 darray_foreach(axis
, self
->axes
){
536 hkl_parameter_randomize(*axis
);
538 hkl_geometry_update(self
);
542 * hkl_geometry_set_values_v: (skip)
547 * set the axes values
551 int hkl_geometry_set_values_v(HklGeometry
*self
, size_t len
, ...)
556 if (!self
|| darray_size(self
->axes
) != len
)
560 darray_foreach(axis
, self
->axes
){
561 hkl_parameter_value_set(*axis
,
562 va_arg(ap
, double), NULL
);
566 hkl_geometry_update(self
);
571 int hkl_geometry_set_values_unit_v(HklGeometry
*self
, GError
**error
, ...)
576 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
579 darray_foreach(axis
, self
->axes
){
580 if(!hkl_parameter_value_unit_set(*axis
,
581 va_arg(ap
, double), error
)){
582 g_assert (error
== NULL
|| *error
!= NULL
);
584 hkl_geometry_update(self
);
588 g_assert (error
== NULL
|| *error
== NULL
);
592 hkl_geometry_update(self
);
598 * hkl_geometry_distance:
599 * @self: the this ptr
600 * @ref: the #HklGeometry to compare with
602 * compute the distance between two #HklGeometries
604 * Returns: the distance between the two geometries
606 double hkl_geometry_distance(const HklGeometry
*self
,
607 const HklGeometry
*ref
)
610 double value1
, value2
;
611 double distance
= 0.;
616 for(i
=0; i
<darray_size(self
->axes
); ++i
){
617 value1
= darray_item(self
->axes
, i
)->_value
;
618 value2
= darray_item(ref
->axes
, i
)->_value
;
619 distance
+= fabs(value2
- value1
);
626 * hkl_geometry_distance_orthodromic: (skip)
627 * @self: the this ptr
628 * @ref: the reference #HklGeometry to compare with.
630 * Returns: the orthodromique distance
632 double hkl_geometry_distance_orthodromic(const HklGeometry
*self
,
633 const HklGeometry
*ref
)
636 double value1
, value2
;
637 double distance
= 0.;
642 for(i
=0; i
<darray_size(self
->axes
); ++i
){
645 value1
= darray_item(self
->axes
, i
)->_value
;
646 value2
= darray_item(ref
->axes
, i
)->_value
;
647 d
= fabs(gsl_sf_angle_restrict_symm(value2
) - gsl_sf_angle_restrict_symm(value1
));
648 /* as M_PI and -M_PI are included in the GSL restriction */
658 * hkl_geometry_is_valid: (skip)
661 * check if all axes of the #HklGeometry are valid.
665 int hkl_geometry_is_valid(const HklGeometry
*self
)
669 darray_foreach(axis
, self
->axes
){
670 if(!hkl_parameter_is_valid(*axis
))
678 * hkl_geometry_closest_from_geometry_with_range: (skip)
682 * get the closest axes values in the HklInterval compatible with the
683 * current axes values
687 int hkl_geometry_closest_from_geometry_with_range(HklGeometry
*self
,
688 const HklGeometry
*ref
)
691 uint len
= darray_size(self
->axes
);
692 double *values
= alloca(len
* sizeof(*values
));
696 values
[i
] = hkl_parameter_value_get_closest(darray_item(self
->axes
, i
),
697 darray_item(ref
->axes
, i
));
698 if(gsl_isnan(values
[i
])){
705 hkl_parameter_value_set(darray_item(self
->axes
, i
),
707 hkl_geometry_update(self
);
713 * hkl_geometry_fprintf: (skip)
717 * print into a file the #HklGeometry
719 void hkl_geometry_fprintf(FILE *file
, const HklGeometry
*self
)
723 for(i
=0; i
<darray_size(self
->axes
); ++i
){
726 hkl_parameter_fprintf(file
, darray_item(self
->axes
, i
));
730 /*******************/
731 /* HklGeometryList */
732 /*******************/
735 * hkl_geometry_list_new: (skip)
741 HklGeometryList
*hkl_geometry_list_new(void)
743 HklGeometryList
*self
;
745 self
= HKL_MALLOC(HklGeometryList
);
747 list_head_init(&self
->items
);
749 self
->multiply
= NULL
;
755 * hkl_geometry_list_new_copy: (skip)
762 HklGeometryList
*hkl_geometry_list_new_copy(const HklGeometryList
*self
)
764 HklGeometryList
*dup
;
765 HklGeometryListItem
*item
;
770 dup
= HKL_MALLOC(HklGeometryList
);
772 list_head_init(&dup
->items
);
773 /* now copy the item arrays */
774 list_for_each(&self
->items
, item
, list
){
775 list_add_tail(&dup
->items
,
776 &hkl_geometry_list_item_new_copy(item
)->list
);
778 dup
->n_items
= self
->n_items
;
779 dup
->multiply
= self
->multiply
;
785 * hkl_geometry_list_free: (skip)
790 void hkl_geometry_list_free(HklGeometryList
*self
)
792 hkl_geometry_list_reset(self
);
797 * hkl_geometry_list_add: (skip)
798 * @self: The current #HklGeometryList
799 * @geometry: the #HklGeometry to add
801 * this method Add a geometry to the geometries
803 * This method try to be clever by allocating memory only if the
804 * current length of the geometries is not large enought. Then it just
805 * set the geometry axes and copy it to the right geometries. We do
806 * not gives the x len as it is equal to the self->axes_len.
808 void hkl_geometry_list_add(HklGeometryList
*self
, HklGeometry
*geometry
)
810 HklGeometryListItem
*item
;
812 /* now check if the geometry is already in the geometry list */
813 list_for_each(&self
->items
, item
, list
){
814 if (hkl_geometry_distance_orthodromic(geometry
,
815 item
->geometry
) < HKL_EPSILON
)
819 list_add_tail(&self
->items
,
820 &hkl_geometry_list_item_new(geometry
)->list
);
825 * hkl_geometry_list_n_items_get: (skip)
826 * @self: the this ptr
828 * get the number of items in the #HklGeometryList
830 * Returns: the number of items in the list
832 size_t hkl_geometry_list_n_items_get(const HklGeometryList
*self
)
834 return self
->n_items
;
838 * hkl_geometry_list_items_first_get: (skip)
839 * @self: the this ptr
841 * get the first solution of the #HklGeometryList
843 * Returns: the first solution of the list
845 const HklGeometryListItem
*hkl_geometry_list_items_first_get(const HklGeometryList
*self
)
847 return list_top(&self
->items
, HklGeometryListItem
, list
);
851 * hkl_geometry_list_items_next_get: (skip)
852 * @self: the this ptr
853 * @item: the current #HklGeometryListItem solution of the #HklGeometryList
855 * get the next solution of the #HklGeometryList from the current item location.
857 * Returns: the next solution of the list
859 const HklGeometryListItem
*hkl_geometry_list_items_next_get(const HklGeometryList
*self
,
860 const HklGeometryListItem
*item
)
862 return list_next(&self
->items
, item
, list
);
866 * hkl_geometry_list_reset: (skip)
867 * @self: the this ptr
869 * reset the HklGeometry, in fact it is a sort of clean method remove
870 * all the items of the list.
872 void hkl_geometry_list_reset(HklGeometryList
*self
)
874 HklGeometryListItem
*item
;
875 HklGeometryListItem
*next
;
877 list_for_each_safe(&self
->items
, item
, next
, list
)
878 hkl_geometry_list_item_free(item
);
880 list_head_init(&self
->items
);
885 * hkl_geometry_list_sort: (skip)
889 * sort the #HklGeometryList compare to the distance of the given
892 void hkl_geometry_list_sort(HklGeometryList
*self
, HklGeometry
*ref
)
894 double *distances
= alloca(self
->n_items
* sizeof(*distances
));
895 size_t *idx
= alloca(self
->n_items
* sizeof(*idx
));
896 HklGeometryListItem
**items
= alloca(self
->n_items
* sizeof(*items
));
897 HklGeometryListItem
*item
;
898 HklGeometryListItem
*next
;
903 /* compute the distances once for all */
904 list_for_each(&self
->items
, item
, list
){
905 distances
[i
] = hkl_geometry_distance(ref
, item
->geometry
);
911 /* insertion sorting */
912 for(i
=1; i
<self
->n_items
; ++i
){
914 /* find the smallest idx p lower than i with distance[idx[p]] >= distance[x] */
915 for(p
= 0; distances
[idx
[p
]] < distances
[x
] && fabs(distances
[idx
[p
]] - distances
[x
]) > HKL_EPSILON
; p
++);
917 /* move everythings in between p and i */
918 for(j
=i
-1; j
>=p
; j
--)
921 idx
[p
] = x
; /* insert the saved idx */
924 list_head_init(&self
->items
);
926 for(i
=0; i
<self
->n_items
; ++i
)
927 list_add_tail(&self
->items
, &items
[idx
[i
]]->list
);
931 * hkl_geometry_list_fprintf: (skip)
935 * print to a file the #HklGeometryList
937 void hkl_geometry_list_fprintf(FILE *f
, const HklGeometryList
*self
)
946 fprintf(f
, "multiply method: %p \n", self
->multiply
);
948 HklGeometryListItem
*item
;
952 darray_foreach(axis
, list_top(&self
->items
, HklGeometryListItem
, list
)->geometry
->axes
){
953 fprintf(f
, "%19s", (*axis
)->name
);
957 list_for_each(&self
->items
, item
, list
){
958 fprintf(f
, "\n%d :", i
++);
959 darray_foreach(axis
, item
->geometry
->axes
){
960 value
= hkl_parameter_value_unit_get(*axis
);
962 fprintf(f
, " % 18.15f %s", value
, (*axis
)->punit
->repr
);
964 fprintf(f
, " % 18.15f", value
);
968 darray_foreach(axis
, item
->geometry
->axes
){
969 value
= hkl_parameter_value_get(*axis
);
970 value
= gsl_sf_angle_restrict_symm(value
);
971 value
*= hkl_unit_factor((*axis
)->unit
,
974 fprintf(f
, " % 18.15f %s", value
, (*axis
)->punit
->repr
);
976 fprintf(f
, " % 18.15f", value
);
984 * hkl_geometry_list_multiply: (skip)
987 * apply the multiply lenthod to the #HklGeometry
989 void hkl_geometry_list_multiply(HklGeometryList
*self
)
992 uint len
= self
->n_items
;
993 HklGeometryListItem
*item
;
995 if(!self
|| !self
->multiply
)
999 * warning this method change the self->len so we need to save it
1000 * before using the recursive perm_r calls
1002 for(i
=0, item
=list_top(&self
->items
, HklGeometryListItem
, list
);
1004 ++i
, item
=list_next(&self
->items
, item
, list
))
1005 self
->multiply(self
, item
);
1008 static void perm_r(HklGeometryList
*self
, const HklGeometry
*ref
,
1009 const HklGeometry
*geometry
, const int perm
[],
1010 const unsigned int axis_idx
)
1012 if (axis_idx
== darray_size(geometry
->axes
)){
1013 if(hkl_geometry_distance(geometry
, ref
) > HKL_EPSILON
){
1014 list_add_tail(&self
->items
,
1015 &hkl_geometry_list_item_new(geometry
)->list
);
1020 HklParameter
*axis
= darray_item(geometry
->axes
, axis_idx
);
1021 const double max
= axis
->range
.max
;;
1022 const double value0
= axis
->_value
;
1027 /* fprintf(stdout, "\n%d %s, %f", axis_idx, hkl_axis_get_name(axis), value * HKL_RADTODEG); */
1028 perm_r(self
, ref
, geometry
, perm
, axis_idx
+ 1);
1030 if(value
<= (max
+ HKL_EPSILON
)){
1031 /* optimisation here: */
1032 /* instead of using set_value
1033 * we directly write the
1034 * HklParameter value, BEWARE
1035 * that it require that
1036 * HklParameter is a rotation
1037 * (for now it is always
1039 axis
->_value
= value
;
1041 }while(value
<= (max
+ HKL_EPSILON
));
1042 /* restore the initial value */
1043 axis
->_value
= value0
;
1045 perm_r(self
, ref
, geometry
, perm
, axis_idx
+ 1);
1049 void hkl_geometry_list_multiply_from_range(HklGeometryList
*self
)
1052 uint len
= self
->n_items
;
1054 const HklGeometryListItem
*item
;
1060 * warning this method change the self->len so we need to save it
1061 * before using the recursive perm_r calls
1064 for(i
=0, item
=list_top(&self
->items
, HklGeometryListItem
, list
);
1066 ++i
, item
=list_next(&self
->items
, item
, list
)){
1067 HklGeometry
*geometry
;
1068 HklParameter
**axis
;
1071 geometry
= hkl_geometry_new_copy(item
->geometry
);
1072 perm
= alloca(darray_size(geometry
->axes
) * sizeof(*perm
));
1074 /* find axes to permute and the first solution of thoses axes */
1075 darray_foreach(axis
, geometry
->axes
){
1076 perm
[j
] = hkl_parameter_is_valid(*axis
);
1077 /* fprintf(stdout, "%d %d\n", j, perm[j]); */
1079 hkl_parameter_value_set_smallest_in_range(*axis
);
1083 * fprintf(stdout, "FIRST SOLUTION\n");
1084 * hkl_geometry_fprintf(stdout, geometry);
1087 perm_r(self
, item
->geometry
, geometry
, perm
, 0);
1088 hkl_geometry_free(geometry
);
1093 * hkl_geometry_list_remove_invalid: (skip)
1096 * remove all invalid #HklGeometry from the #HklGeometryList
1098 void hkl_geometry_list_remove_invalid(HklGeometryList
*self
)
1100 HklGeometryListItem
*item
, *next
;
1102 list_for_each_safe(&self
->items
, item
, next
, list
)
1103 if(!hkl_geometry_is_valid(item
->geometry
)){
1104 list_del(&item
->list
);
1106 hkl_geometry_list_item_free(item
);
1110 /***********************/
1111 /* HklGeometryListItem */
1112 /***********************/
1115 * hkl_geometry_list_item_new: (skip)
1122 HklGeometryListItem
*hkl_geometry_list_item_new(const HklGeometry
*geometry
)
1124 HklGeometryListItem
*self
;
1129 self
= HKL_MALLOC(HklGeometryListItem
);
1131 self
->geometry
= hkl_geometry_new_copy(geometry
);
1137 * hkl_geometry_list_item_new_copy: (skip)
1144 HklGeometryListItem
*hkl_geometry_list_item_new_copy(const HklGeometryListItem
*self
)
1146 HklGeometryListItem
*dup
;
1151 dup
= HKL_MALLOC(HklGeometryListItem
);
1153 dup
->geometry
= hkl_geometry_new_copy(self
->geometry
);
1159 * hkl_geometry_list_item_free: (skip)
1164 void hkl_geometry_list_item_free(HklGeometryListItem
*self
)
1169 hkl_geometry_free(self
->geometry
);
1174 * hkl_geometry_list_item_geometry_get: (skip)
1175 * @self: the this ptr
1177 * Return value: The geometry contain inside the HklGeometryListItem
1179 const HklGeometry
*hkl_geometry_list_item_geometry_get(const HklGeometryListItem
*self
)
1181 return self
->geometry
;