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-2010 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>
21 * Jens Krüger <Jens.Krueger@frm2.tum.de>
23 #include <gsl/gsl_sf_trig.h>
24 #include <hkl/hkl-pseudoaxis-auto.h>
25 #include <hkl/hkl-pseudoaxis-common-eulerians.h>
27 static int kappa_to_eulerian(double komega
, double kappa
, double kphi
,
28 double *omega
, double *chi
, double *phi
,
29 double alpha
, int solution
)
31 double Kappa
= gsl_sf_angle_restrict_symm(kappa
);
32 double p
= atan(tan(Kappa
/2.) * cos(alpha
));
35 *omega
= komega
+ p
- M_PI_2
;
36 *chi
= 2 * asin(sin(Kappa
/2.) * sin(alpha
));
37 *phi
= kphi
+ p
+ M_PI_2
;
39 *omega
= komega
+ p
+ M_PI_2
;
40 *chi
= -2 * asin(sin(Kappa
/2.) * sin(alpha
));
41 *phi
= kphi
+ p
- M_PI_2
;
47 static int eulerian_to_kappa(double omega
, double chi
, double phi
,
48 double *komega
, double *kappa
, double *kphi
,
49 double alpha
, double solution
)
51 int status
= HKL_SUCCESS
;
53 if (fabs(chi
) <= alpha
* 2){
54 double p
= asin(tan(chi
/2.)/tan(alpha
));
57 *komega
= omega
- p
+ M_PI_2
;
58 *kappa
= 2 * asin(sin(chi
/2.)/sin(alpha
));
59 *kphi
= phi
- p
- M_PI_2
;
61 *komega
= omega
+ p
- M_PI_2
;
62 *kappa
= -2 * asin(sin(chi
/2.)/sin(alpha
));
63 *kphi
= phi
+ p
+ M_PI_2
;
71 static int hkl_pseudo_axis_engine_mode_get_eulerians_real(HklPseudoAxisEngineMode
*self
,
72 HklPseudoAxisEngine
*engine
,
73 HklGeometry
*geometry
,
74 HklDetector
*detector
,
78 double komega
, kappa
, kphi
;
81 hkl_geometry_update(geometry
);
83 solution
= (int)self
->parameters
[0].value
;
85 komega
= ((HklParameter
*)hkl_geometry_get_axis_by_name(geometry
, "komega"))->value
;
86 kappa
= ((HklParameter
*)hkl_geometry_get_axis_by_name(geometry
, "kappa"))->value
;
87 kphi
= ((HklParameter
*)hkl_geometry_get_axis_by_name(geometry
, "kphi"))->value
;
89 return kappa_to_eulerian(komega
, kappa
, kphi
,
90 &((HklParameter
*)engine
->pseudoAxes
[0])->value
,
91 &((HklParameter
*)engine
->pseudoAxes
[1])->value
,
92 &((HklParameter
*)engine
->pseudoAxes
[2])->value
,
93 50 * HKL_DEGTORAD
, solution
);
96 static int hkl_pseudo_axis_engine_mode_set_eulerians_real(HklPseudoAxisEngineMode
*self
,
97 HklPseudoAxisEngine
*engine
,
98 HklGeometry
*geometry
,
99 HklDetector
*detector
,
103 int status
= HKL_SUCCESS
;
108 solution
= (int)self
->parameters
[0].value
;
110 status
|= eulerian_to_kappa(((HklParameter
*)engine
->pseudoAxes
[0])->value
,
111 ((HklParameter
*)engine
->pseudoAxes
[1])->value
,
112 ((HklParameter
*)engine
->pseudoAxes
[2])->value
,
113 &angles
[0], &angles
[1], &angles
[2],
114 50 * HKL_DEGTORAD
, solution
);
116 if (status
== HKL_SUCCESS
)
117 hkl_pseudo_axis_engine_add_geometry(engine
, angles
);
122 HklPseudoAxisEngine
*hkl_pseudo_axis_engine_eulerians_new(void)
124 HklPseudoAxisEngine
*self
;
125 HklPseudoAxisEngineMode
*mode
;
126 HklParameter parameter
= {"solution", {0, 1}, 1., NULL
, NULL
, 0, 0};
128 self
= hkl_pseudo_axis_engine_new("eulerians", 3, "omega", "chi", "phi");
131 hkl_parameter_init((HklParameter
*)self
->pseudoAxes
[0],
135 &hkl_unit_angle_rad
, &hkl_unit_angle_deg
);
137 hkl_parameter_init((HklParameter
*)self
->pseudoAxes
[1],
141 &hkl_unit_angle_rad
, &hkl_unit_angle_deg
);
143 hkl_parameter_init((HklParameter
*)self
->pseudoAxes
[2],
147 &hkl_unit_angle_rad
, &hkl_unit_angle_deg
);
150 mode
= hkl_pseudo_axis_engine_mode_new(
153 hkl_pseudo_axis_engine_mode_get_eulerians_real
,
154 hkl_pseudo_axis_engine_mode_set_eulerians_real
,
156 (size_t)1, parameter
,
157 (size_t)3, "komega", "kappa", "kphi");
158 hkl_pseudo_axis_engine_add_mode(self
, mode
);
160 hkl_pseudo_axis_engine_select_mode(self
, 0);