1 /* EXTRAITS DE LA LICENCE
2 Copyright CEA, contributeurs : Damien
3 CALISTE, laboratoire L_Sim, (2017)
4
5 Adresse mèl :
6 CALISTE, damien P caliste AT cea P fr.
7
8 Ce logiciel est un programme informatique servant à visualiser des
9 structures atomiques dans un rendu pseudo-3D.
10
11 Ce logiciel est régi par la licence CeCILL soumise au droit français et
12 respectant les principes de diffusion des logiciels libres. Vous pouvez
13 utiliser, modifier et/ou redistribuer ce programme sous les conditions
14 de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
15 sur le site "http://www.cecill.info".
16
17 Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
18 pris connaissance de la licence CeCILL, et que vous en avez accepté les
19 termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
20 */
21
22 /* LICENCE SUM UP
23 Copyright CEA, contributors : Damien
24 CALISTE, laboratoire L_Sim, (2017)
25
26 E-mail address:
27 CALISTE, damien P caliste AT cea P fr.
28
29 This software is a computer program whose purpose is to visualize atomic
30 configurations in 3D.
31
32 This software is governed by the CeCILL license under French law and
33 abiding by the rules of distribution of free software. You can use,
34 modify and/ or redistribute the software under the terms of the CeCILL
35 license as circulated by CEA, CNRS and INRIA at the following URL
36 "http://www.cecill.info".
37
38 The fact that you are presently reading this means that you have had
39 knowledge of the CeCILL license and that you accept its terms. You can
40 find a copy of this licence shipped with this software at Documentation/licence.en.txt.
41 */
42
43 #include "spinMethod.h"
44
45 #include <math.h>
46
47 #include <visu_configFile.h>
48 #include <coreTools/toolMatrix.h>
49 #include <coreTools/toolColor.h>
50
51 /**
52 * SECTION:spinMethod
53 * @short_description: a class defining how a set of spin should be rendered.
54 *
55 * <para>Defines global properties for the rendering of spin data,
56 * like should atomic rendering be used in addition? How to orientate
57 * the colourisation cone?</para>
58 */
59
60 #define FLAG_RESOURCES_SPIN "spin_resources"
61 #define DESC_RESOURCES_SPIN "Global or element resource for rendering spin module"
62
63 #define FLAG_SPIN_CONE_ANGLE "spin_global_color_cone"
64 #define FLAG_SPIN_WHEEL_ANGLE "spin_global_color_wheel"
65 #define FLAG_SPIN_HIDING_MODE "spin_global_hiding_mode"
66 #define FLAG_SPIN_AND_ATOMIC "spin_global_atomic"
67 #define FLAG_SPIN_MODULUS "spin_global_modulus"
68 static gfloat _coneOrientation[2] = {0.f, 0.f};
69 static gfloat _colorWheel = 0.f;
70 static VisuMethodSpinDrawingPolicy _spinPolicy = VISU_METHOD_SPIN_ALWAYS;
71 static gboolean _spinAndAtomicRendering = FALSE;
72 static VisuMethodSpinModulusPolicy _spinModulusUsage = VISU_METHOD_SPIN_CONSTANT;
73
74 static const char* policyNameSpin[VISU_METHOD_SPIN_N_MODES + 1] = {"always",
75 "never",
76 "atomic",
77 (const char*)0};
78
79 enum
80 {
81 PROP_0,
82 PROP_CONETHETA,
83 PROP_CONEPHI,
84 PROP_COLORWHEEL,
85 PROP_HIDINGMODE,
86 PROP_ATOMIC,
87 PROP_MODULUS,
88 N_PROP,
89 };
90 static GParamSpec *_properties[N_PROP];
91
92 static VisuMethodSpin* _default = NULL;
93
94 struct _VisuMethodSpinPrivate
95 {
96 gfloat coneOrientation[2];
97 gfloat colorWheel;
98 VisuMethodSpinDrawingPolicy spinPolicy;
99 gboolean spinAndAtomicRendering;
100 VisuMethodSpinModulusPolicy spinModulusUsage;
101 };
102
103 static void visu_method_spin_get_property(GObject* obj, guint property_id,
104 GValue *value, GParamSpec *pspec);
105 static void visu_method_spin_set_property(GObject* obj, guint property_id,
106 const GValue *value, GParamSpec *pspec);
107
108 /* Local methods. */
109 static void onEntrySpin(VisuMethodSpin *method, VisuConfigFileEntry *entry, VisuConfigFile *obj);
110 static void exportResourcesRenderingSpin(GString *method, VisuData *dataObj);
111
G_DEFINE_TYPE_WITH_CODE(VisuMethodSpin,visu_method_spin,VISU_TYPE_OBJECT,G_ADD_PRIVATE (VisuMethodSpin))112 G_DEFINE_TYPE_WITH_CODE(VisuMethodSpin, visu_method_spin, VISU_TYPE_OBJECT,
113 G_ADD_PRIVATE(VisuMethodSpin))
114
115 static void visu_method_spin_class_init(VisuMethodSpinClass *klass)
116 {
117 VisuConfigFileEntry *resourceEntry;
118
119 /* Connect the overloading methods. */
120 G_OBJECT_CLASS(klass)->get_property = visu_method_spin_get_property;
121 G_OBJECT_CLASS(klass)->set_property = visu_method_spin_set_property;
122
123 /**
124 * VisuMethodSpin::cone-theta:
125 *
126 * The theta angle to orientate the colourisation cone.
127 *
128 * Since: 3.8
129 */
130 _properties[PROP_CONETHETA] =
131 g_param_spec_float("cone-theta", _("Theta angle"),
132 _("The theta angle to orientate the colourisation cone."), 0, 180, 0,
133 G_PARAM_READWRITE);
134 /**
135 * VisuMethodSpin::cone-phi:
136 *
137 * The phi angle to orientate the colourisation cone.
138 *
139 * Since: 3.8
140 */
141 _properties[PROP_CONEPHI] =
142 g_param_spec_float("cone-phi", _("Phi angle"),
143 _("The phi angle to orientate the colourisation cone."), 0, 360, 0,
144 G_PARAM_READWRITE);
145 /**
146 * VisuMethodSpin::cone-omega:
147 *
148 * The omega angle to orientate the colourisation cone.
149 *
150 * Since: 3.8
151 */
152 _properties[PROP_COLORWHEEL] =
153 g_param_spec_float("cone-omega", _("Omega angle"),
154 _("The omega angle to orientate the colourisation cone."), 0, 360, 0,
155 G_PARAM_READWRITE);
156 /**
157 * VisuMethodSpin::hiding-mode:
158 *
159 * The hiding policy for spin with a null modulus.
160 *
161 * Since: 3.8
162 */
163 _properties[PROP_HIDINGMODE] =
164 g_param_spec_uint("hiding-mode", _("Hiding policy for null modulus"),
165 _("The hiding policy for spin with a null modulus."),
166 0, VISU_METHOD_SPIN_N_MODES, VISU_METHOD_SPIN_ALWAYS,
167 G_PARAM_READWRITE);
168 /**
169 * VisuMethodSpin::modulus-scaling:
170 *
171 * The scaling policy based on modulus value.
172 *
173 * Since: 3.8
174 */
175 _properties[PROP_MODULUS] =
176 g_param_spec_uint("modulus-scaling", _("Scaling of spin depending on modulus value"),
177 _("The scaling policy based on modulus value."),
178 0, VISU_METHOD_SPIN_N_MODULUS_MODES, VISU_METHOD_SPIN_CONSTANT,
179 G_PARAM_READWRITE);
180 /**
181 * VisuMethodSpin::use-atomic:
182 *
183 * If atomic rendering is used in addition to spin rendering.
184 *
185 * Since: 3.8
186 */
187 _properties[PROP_ATOMIC] =
188 g_param_spec_boolean("use-atomic", _("Use atomic rendering"),
189 _("If atomic rendering is used in addition to spin rendering."),
190 FALSE, G_PARAM_READWRITE);
191 g_object_class_install_properties(G_OBJECT_CLASS(klass), N_PROP, _properties);
192
193 /* Dealing with config files. */
194 resourceEntry = visu_config_file_addTokenizedEntry(VISU_CONFIG_FILE_RESOURCE,
195 FLAG_RESOURCES_SPIN,
196 DESC_RESOURCES_SPIN,
197 TRUE);
198 visu_config_file_entry_setVersion(resourceEntry, 3.1f);
199 g_signal_connect_swapped(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCES_SPIN,
200 G_CALLBACK(onEntrySpin), (gpointer)0);
201 visu_config_file_addExportFunction(VISU_CONFIG_FILE_RESOURCE,
202 exportResourcesRenderingSpin);
203 }
visu_method_spin_init(VisuMethodSpin * obj)204 static void visu_method_spin_init(VisuMethodSpin *obj)
205 {
206 obj->priv = visu_method_spin_get_instance_private(obj);
207
208 /* Private method. */
209 obj->priv->spinPolicy = _spinPolicy;
210 obj->priv->spinAndAtomicRendering = _spinAndAtomicRendering;
211 obj->priv->spinModulusUsage = _spinModulusUsage;
212 obj->priv->coneOrientation[0] = _coneOrientation[0];
213 obj->priv->coneOrientation[1] = _coneOrientation[1];
214 obj->priv->colorWheel = _colorWheel;
215
216 g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::" FLAG_RESOURCES_SPIN,
217 G_CALLBACK(onEntrySpin), obj, G_CONNECT_SWAPPED);
218 }
visu_method_spin_get_property(GObject * obj,guint property_id,GValue * value,GParamSpec * pspec)219 static void visu_method_spin_get_property(GObject* obj, guint property_id,
220 GValue *value, GParamSpec *pspec)
221 {
222 VisuMethodSpin *self = VISU_METHOD_SPIN(obj);
223
224 switch (property_id)
225 {
226 case PROP_CONETHETA:
227 g_value_set_float(value, self->priv->coneOrientation[0]);
228 break;
229 case PROP_CONEPHI:
230 g_value_set_float(value, self->priv->coneOrientation[1]);
231 break;
232 case PROP_COLORWHEEL:
233 g_value_set_float(value, self->priv->colorWheel);
234 break;
235 case PROP_HIDINGMODE:
236 g_value_set_uint(value, self->priv->spinPolicy);
237 break;
238 case PROP_ATOMIC:
239 g_value_set_boolean(value, self->priv->spinAndAtomicRendering);
240 break;
241 case PROP_MODULUS:
242 g_value_set_uint(value, self->priv->spinModulusUsage);
243 break;
244 default:
245 /* We don't have any other property... */
246 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
247 break;
248 }
249 }
visu_method_spin_set_property(GObject * obj,guint property_id,const GValue * value,GParamSpec * pspec)250 static void visu_method_spin_set_property(GObject* obj, guint property_id,
251 const GValue *value, GParamSpec *pspec)
252 {
253 VisuMethodSpin *self = VISU_METHOD_SPIN(obj);
254
255 switch (property_id)
256 {
257 case PROP_CONETHETA:
258 self->priv->coneOrientation[0] = g_value_get_float(value);
259 break;
260 case PROP_CONEPHI:
261 self->priv->coneOrientation[1] = g_value_get_float(value);
262 break;
263 case PROP_COLORWHEEL:
264 self->priv->colorWheel = g_value_get_float(value);
265 break;
266 case PROP_HIDINGMODE:
267 self->priv->spinPolicy = g_value_get_uint(value);
268 break;
269 case PROP_ATOMIC:
270 self->priv->spinAndAtomicRendering = g_value_get_boolean(value);
271 break;
272 case PROP_MODULUS:
273 self->priv->spinModulusUsage = g_value_get_uint(value);
274 break;
275 default:
276 /* We don't have any other property... */
277 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
278 break;
279 }
280 }
281
282 /**
283 * visu_method_spin_new:
284 *
285 * Creates a #VisuMethodSpin object.
286 *
287 * Since: 3.8
288 *
289 * Returns: a newly allocated #VisuMethodSpin object.
290 **/
visu_method_spin_new(void)291 VisuMethodSpin* visu_method_spin_new(void)
292 {
293 return g_object_new(VISU_TYPE_METHOD_SPIN, NULL);
294 }
295 /**
296 * visu_method_spin_getDefault:
297 *
298 * Access the default spin method object.
299 *
300 * Since: 3.8
301 *
302 * Returns: (transfer none): the default spin method object.
303 **/
visu_method_spin_getDefault(void)304 VisuMethodSpin* visu_method_spin_getDefault(void)
305 {
306 if (!_default)
307 _default = g_object_new(VISU_TYPE_METHOD_SPIN, NULL);
308 return _default;
309 }
310
_getOrientationColor(const VisuMethodSpin * method,gfloat rgb[3],const gfloat spinValues[3])311 static void _getOrientationColor(const VisuMethodSpin *method, gfloat rgb[3],
312 const gfloat spinValues[3])
313 {
314 #ifndef DEG2RAD
315 #define DEG2RAD(x) (0.01745329251994329509 * x) /* pi / 180 * x */
316 #endif
317 gfloat spherical[3];
318 float cosCone, sinCone;
319 float matrix_rot_theta[3][3];
320 float matrix_rot_phi[3][3];
321 float cartesian[3];
322 float cartesian_prime[3];
323 float cartesian_second[3];
324 float hsl[3];
325
326 g_return_if_fail(VISU_IS_METHOD_SPIN(method));
327
328 /* We draw a spin shape. */
329 spherical[0] = 1;
330 spherical[1] = spinValues[TOOL_MATRIX_SPHERICAL_THETA];
331 spherical[2] = spinValues[TOOL_MATRIX_SPHERICAL_PHI];
332
333 cosCone = cos(DEG2RAD(method->priv->coneOrientation[0]));
334 sinCone = sin(DEG2RAD(method->priv->coneOrientation[0]));
335 matrix_rot_theta[0][0] = cosCone;
336 matrix_rot_theta[0][1] = 0;
337 matrix_rot_theta[0][2] = -sinCone;
338 matrix_rot_theta[1][0] = 0;
339 matrix_rot_theta[1][1] = 1;
340 matrix_rot_theta[1][2] = 0;
341 matrix_rot_theta[2][0] = sinCone;
342 matrix_rot_theta[2][1] = 0;
343 matrix_rot_theta[2][2] = cosCone;
344
345 cosCone = cos(DEG2RAD(-method->priv->coneOrientation[1]));
346 sinCone = sin(DEG2RAD(-method->priv->coneOrientation[1]));
347 matrix_rot_phi[0][0] = cosCone;
348 matrix_rot_phi[0][1] = -sinCone;
349 matrix_rot_phi[0][2] = 0;
350 matrix_rot_phi[1][0] = sinCone;
351 matrix_rot_phi[1][1] = cosCone;
352 matrix_rot_phi[1][2] = 0;
353 matrix_rot_phi[2][0] = 0;
354 matrix_rot_phi[2][1] = 0;
355 matrix_rot_phi[2][2] = 1;
356
357 cartesian[0] = sin(DEG2RAD(spinValues[TOOL_MATRIX_SPHERICAL_THETA])) *
358 cos(DEG2RAD(spinValues[TOOL_MATRIX_SPHERICAL_PHI]));
359 cartesian[1] = sin(DEG2RAD(spinValues[TOOL_MATRIX_SPHERICAL_THETA])) *
360 sin(DEG2RAD(spinValues[TOOL_MATRIX_SPHERICAL_PHI]));
361 cartesian[2] = cos(DEG2RAD(spinValues[TOOL_MATRIX_SPHERICAL_THETA]));
362
363 tool_matrix_productVector(cartesian_prime, matrix_rot_phi, cartesian);
364 tool_matrix_productVector(cartesian_second, matrix_rot_theta, cartesian_prime);
365
366 tool_matrix_cartesianToSpherical(spherical, cartesian_second);
367
368 hsl[0] = tool_modulo_float(spherical[2] - method->priv->colorWheel, 360.f) / 360.f;
369 hsl[1] = 1.f;
370 hsl[2] = 1.f - spherical[1] / 180.f;
371
372 tool_color_convertHSLtoRGB(rgb, hsl);
373 }
374 /**
375 * visu_method_spin_getSpinVector:
376 * @method: a #VisuMethodSpin object.
377 * @dataSpin: a #VisuDataSpin object.
378 * @node: a #VisuNode from @dataSpin.
379 * @ratio: (out): the ratio to apply when drawing the spin.
380 * @rgb: (out): a location to store the colour.
381 * @withAtomic: (out): a location to store if atomic rendering is
382 * required.
383 *
384 * Retrieves the spin of @node in spherical coordinates. According to
385 * rendering policy from @method, @ratio, @rgb and @withAtomic will be
386 * set to their respective values. If no spin should be rendered for
387 * @node, %NULL is returned.
388 *
389 * Since: 3.8
390 *
391 * Returns: three floats representing the spin.
392 **/
visu_method_spin_getSpinVector(const VisuMethodSpin * method,const VisuDataSpin * dataSpin,const VisuNode * node,gfloat * ratio,gfloat rgb[3],gboolean * withAtomic)393 const gfloat* visu_method_spin_getSpinVector(const VisuMethodSpin *method,
394 const VisuDataSpin *dataSpin,
395 const VisuNode *node,
396 gfloat *ratio, gfloat rgb[3],
397 gboolean *withAtomic)
398 {
399 const gfloat *spinValues;
400 gfloat globalMax;
401 guint iele;
402
403 spinValues = visu_node_values_vector_getAtSpherical(visu_data_spin_get(dataSpin),
404 node);
405
406 if (withAtomic)
407 *withAtomic = (method->priv->spinPolicy == VISU_METHOD_SPIN_ATOMIC_NULL &&
408 spinValues[TOOL_MATRIX_SPHERICAL_MODULUS] == 0.f) ||
409 method->priv->spinAndAtomicRendering;
410
411 if (spinValues && (spinValues[TOOL_MATRIX_SPHERICAL_MODULUS] != 0. ||
412 method->priv->spinPolicy == VISU_METHOD_SPIN_ALWAYS))
413 {
414 if (ratio)
415 /* Get the scaling factor for this element. */
416 switch (method->priv->spinModulusUsage)
417 {
418 case VISU_METHOD_SPIN_PER_TYPE:
419 *ratio = spinValues[TOOL_MATRIX_SPHERICAL_MODULUS] /
420 visu_data_spin_getMaxModulus(dataSpin, node->posElement);
421 break;
422 case VISU_METHOD_SPIN_GLOBAL:
423 globalMax = -G_MAXFLOAT;
424 for (iele = 0; iele < visu_node_array_getNElements(VISU_NODE_ARRAY_CONST(dataSpin), FALSE); iele++)
425 globalMax = MAX(visu_data_spin_getMaxModulus(dataSpin, iele), globalMax);
426 *ratio = spinValues[TOOL_MATRIX_SPHERICAL_MODULUS] / globalMax;
427 break;
428 case VISU_METHOD_SPIN_CONSTANT:
429 *ratio = 1.f;
430 break;
431 default:
432 *ratio = spinValues[TOOL_MATRIX_SPHERICAL_MODULUS];
433 break;
434 }
435 _getOrientationColor(method, rgb, spinValues);
436 return spinValues;
437 }
438 else
439 return (const gfloat*)0;
440 }
441 /**
442 * visu_method_spin_getHidingPolicyFromName:
443 * @name: (type filename): a string.
444 * @policy: a location.
445 *
446 * In the config file, the hiding policy resource is stored with its name (untranslated).
447 * This method is used to retrieve the id from the name.
448 *
449 * Returns: FALSE if the name does not match any value.
450 */
visu_method_spin_getHidingPolicyFromName(const char * name,VisuMethodSpinDrawingPolicy * policy)451 gboolean visu_method_spin_getHidingPolicyFromName(const char *name,
452 VisuMethodSpinDrawingPolicy *policy)
453 {
454 g_return_val_if_fail(name && policy, FALSE);
455
456 for (*policy = 0; *policy < VISU_METHOD_SPIN_N_MODES; *policy += 1)
457 if (!g_strcmp0(name, policyNameSpin[*policy]))
458 return TRUE;
459 return FALSE;
460 }
461
onEntrySpin(VisuMethodSpin * self,VisuConfigFileEntry * entry,VisuConfigFile * object _U_)462 static void onEntrySpin(VisuMethodSpin *self, VisuConfigFileEntry *entry, VisuConfigFile *object _U_)
463 {
464 const gchar *label;
465
466 label = visu_config_file_entry_getLabel(entry);
467
468 if (!g_strcmp0(label, FLAG_SPIN_CONE_ANGLE))
469 {
470 float angles[2];
471 float rg[2] = {0.f, 360.f};
472
473 if (!visu_config_file_entry_popTokenAsFloat(entry, 2, angles, rg))
474 return;
475 if (self)
476 g_object_set(self, "cone-theta", angles[0], "cone-phi", angles[1], NULL);
477 else
478 {
479 _coneOrientation[0] = angles[0];
480 _coneOrientation[1] = angles[1];
481 }
482 }
483 else if (!g_strcmp0(label, FLAG_SPIN_WHEEL_ANGLE))
484 {
485 float angle;
486 float rg[2] = {0.f, 360.f};
487
488 if (!visu_config_file_entry_popTokenAsFloat(entry, 1, &angle, rg))
489 return;
490 if (self)
491 g_object_set(self, "cone-omega", angle, NULL);
492 else
493 _colorWheel = angle;
494 }
495 else if (!g_strcmp0(label, FLAG_SPIN_HIDING_MODE))
496 {
497 VisuMethodSpinDrawingPolicy modeId;
498
499 if (!visu_config_file_entry_popTokenAsEnum(entry, &modeId, visu_method_spin_getHidingPolicyFromName))
500 return;
501 if (self)
502 g_object_set(self, "hiding-mode", modeId, NULL);
503 else
504 _spinPolicy = modeId;
505 }
506 else if (!g_strcmp0(label, FLAG_SPIN_AND_ATOMIC))
507 {
508 gboolean use;
509
510 if (!visu_config_file_entry_popTokenAsBoolean(entry, 1, &use))
511 return;
512 if (self)
513 g_object_set(self, "use-atomic", use, NULL);
514 else
515 _spinAndAtomicRendering = use;
516 }
517 else if (!g_strcmp0(label, FLAG_SPIN_MODULUS))
518 {
519 int modeId;
520 int rg[2] = {0, VISU_METHOD_SPIN_N_MODULUS_MODES - 1};
521
522 if (!visu_config_file_entry_popTokenAsInt(entry, 1, &modeId, rg))
523 return;
524 if (self)
525 g_object_set(self, "modulus-scaling", modeId, NULL);
526 else
527 _spinModulusUsage = modeId;
528 }
529 else
530 {
531 g_warning(_("Unknown flag '%s', value ignored."), label);
532 }
533 }
534
exportResourcesRenderingSpin(GString * method,VisuData * dataObj _U_)535 static void exportResourcesRenderingSpin(GString *method, VisuData* dataObj _U_)
536 {
537 DBG_fprintf(stderr, "Method Spin: exporting resources...\n");
538
539 visu_config_file_exportComment(method, DESC_RESOURCES_SPIN);
540 visu_config_file_exportEntry(method, FLAG_RESOURCES_SPIN, FLAG_SPIN_CONE_ANGLE,
541 "%f %f", _coneOrientation[0], _coneOrientation[1]);
542
543 visu_config_file_exportEntry(method, FLAG_RESOURCES_SPIN, FLAG_SPIN_WHEEL_ANGLE,
544 "%f", _colorWheel);
545
546 visu_config_file_exportEntry(method, FLAG_RESOURCES_SPIN, FLAG_SPIN_HIDING_MODE,
547 "%s", policyNameSpin[_spinPolicy]);
548
549 visu_config_file_exportEntry(method, FLAG_RESOURCES_SPIN, FLAG_SPIN_AND_ATOMIC,
550 "%d", _spinAndAtomicRendering);
551
552 visu_config_file_exportEntry(method, FLAG_RESOURCES_SPIN, FLAG_SPIN_MODULUS,
553 "%d", _spinModulusUsage);
554 DBG_fprintf(stderr, "Method Spin: resources succesfully exported\n");
555 }
556