1 /*   EXTRAITS DE LA LICENCE
2 	Copyright CEA, contributeurs : Damien
3 	CALISTE, laboratoire L_Sim, (2016)
4 
5 	Adresse mèl :
6 	BILLARD, non joignable par mèl ;
7 	CALISTE, damien P caliste AT cea P fr.
8 
9 	Ce logiciel est un programme informatique servant à visualiser des
10 	structures atomiques dans un rendu pseudo-3D.
11 
12 	Ce logiciel est régi par la licence CeCILL soumise au droit français et
13 	respectant les principes de diffusion des logiciels libres. Vous pouvez
14 	utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
16 	sur le site "http://www.cecill.info".
17 
18 	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
19 	pris connaissance de la licence CeCILL, et que vous en avez accepté les
20 	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22 
23 /*   LICENCE SUM UP
24 	Copyright CEA, contributors : Damien
25 	CALISTE, laboratoire L_Sim, (2016)
26 
27 	E-mail address:
28 	BILLARD, not reachable any more ;
29 	CALISTE, damien P caliste AT cea P fr.
30 
31 	This software is a computer program whose purpose is to visualize atomic
32 	configurations in 3D.
33 
34 	This software is governed by the CeCILL  license under French law and
35 	abiding by the rules of distribution of free software.  You can  use,
36 	modify and/ or redistribute the software under the terms of the CeCILL
37 	license as circulated by CEA, CNRS and INRIA at the following URL
38 	"http://www.cecill.info".
39 
40 	The fact that you are presently reading this means that you have had
41 	knowledge of the CeCILL license and that you accept its terms. You can
42 	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44 
45 #include "link.h"
46 
47 #include "iface_wire.h"
48 #include "iface_cylinder.h"
49 
50 #include <visu_basic.h>
51 #include <visu_configFile.h>
52 
53 /**
54  * SECTION:link
55  * @short_description: An object to store rendering properties of a
56  * #VisuPair for a given distance criterion.
57  *
58  * <para>#VisuPair describes pairs between two #VisuElement. Such a
59  * pair can have several #VisuPairLink, depending on a distance
60  * criterion. Each link then has several rendering parameters, such as
61  * its color, its rendering method (wire or cylinder), if it is drawn...</para>
62  */
63 
64 /* Parameters */
65 static ToolColor *defaultPairColor = NULL;
66 /* static void exportConfig(GString *data, VisuData *dataObj); */
67 
68 struct _VisuPairLinkPrivate
69 {
70   gboolean dispose_has_run;
71 
72   GWeakRef ele1;
73   GWeakRef ele2;
74 
75   float minMax[2];
76   ToolUnits units;
77 
78   gboolean drawn;
79   gboolean printLength;
80   ToolColor color;
81 
82   guint width;
83   ToolShade *shade;
84   guint16 stipple;
85 
86   gfloat radius;
87   VisuPairCylinderColorId colorType;
88 };
89 
90 static void visu_pair_link_dispose(GObject* obj);
91 static void visu_pair_link_get_property(GObject* obj, guint property_id,
92                                         GValue *value, GParamSpec *pspec);
93 static void visu_pair_link_set_property(GObject* obj, guint property_id,
94                                         const GValue *value, GParamSpec *pspec);
95 static void visu_pair_wire_interface_init(VisuPairWireInterface *iface);
96 static void visu_pair_cylinder_interface_init(VisuPairCylinderInterface *iface);
97 static gboolean   _setWidth(VisuPairWire *data, guint val);
98 static guint      _getWidth(VisuPairWire *data);
99 static gboolean   _setShade(VisuPairWire *data, ToolShade *shade);
100 static ToolShade* _getShade(VisuPairWire *data);
101 static gboolean   _setStipple(VisuPairWire *data, guint16 stipple);
102 static guint16    _getStipple(VisuPairWire *data);
103 static gboolean   _setRadius(VisuPairCylinder *data, gfloat val);
104 static gfloat     _getRadius(VisuPairCylinder *data);
105 static gboolean   _setColorType(VisuPairCylinder *data, VisuPairCylinderColorId val);
106 static VisuPairCylinderColorId _getColorType(VisuPairCylinder *data);
107 
108 static void onEntryUnit(VisuPairLink *link, VisuConfigFileEntry *entry, VisuConfigFile *obj);
109 /* enum { */
110 /*   LAST_SIGNAL */
111 /* }; */
112 /* static guint _signals[LAST_SIGNAL] = { 0 }; */
113 
114 enum
115   {
116     PROP_0,
117     MIN_PROP,
118     MAX_PROP,
119     UNITS_PROP,
120 
121     USE_PROP,
122     LENGTH_PROP,
123     COLOR_PROP,
124 
125     WIDTH_PROP,
126     SHADE_PROP,
127     STIPPLE_PROP,
128 
129     RADIUS_PROP,
130     TYPE_PROP,
131 
132     N_PROP
133   };
134 static GParamSpec *_properties[N_PROP];
135 
G_DEFINE_TYPE_WITH_CODE(VisuPairLink,visu_pair_link,VISU_TYPE_OBJECT,G_ADD_PRIVATE (VisuPairLink)G_IMPLEMENT_INTERFACE (VISU_TYPE_PAIR_WIRE,visu_pair_wire_interface_init)G_IMPLEMENT_INTERFACE (VISU_TYPE_PAIR_CYLINDER,visu_pair_cylinder_interface_init))136 G_DEFINE_TYPE_WITH_CODE(VisuPairLink, visu_pair_link, VISU_TYPE_OBJECT,
137                         G_ADD_PRIVATE(VisuPairLink)
138                         G_IMPLEMENT_INTERFACE(VISU_TYPE_PAIR_WIRE,
139                                               visu_pair_wire_interface_init)
140                         G_IMPLEMENT_INTERFACE(VISU_TYPE_PAIR_CYLINDER,
141                                               visu_pair_cylinder_interface_init))
142 
143 static void visu_pair_link_class_init(VisuPairLinkClass *klass)
144 {
145   float rgbOfPairs[4] = {1.0, 0.6, 0.2, 1.};
146   /* VisuConfigFileEntry *entry; */
147 
148   DBG_fprintf(stderr, "Visu Pair Link: creating the class of the object.\n");
149 
150   DBG_fprintf(stderr, "                - adding new signals ;\n");
151 
152   /* Connect the overloading methods. */
153   G_OBJECT_CLASS(klass)->dispose  = visu_pair_link_dispose;
154   G_OBJECT_CLASS(klass)->set_property = visu_pair_link_set_property;
155   G_OBJECT_CLASS(klass)->get_property = visu_pair_link_get_property;
156 
157   /**
158    * VisuPairLink::min:
159    *
160    * Store the link minimal distance.
161    *
162    * Since: 3.8
163    */
164   _properties[MIN_PROP] = g_param_spec_float("min", "Min",
165                                              "minimal distance",
166                                              0.f, G_MAXFLOAT, 0.f,
167                                              G_PARAM_READWRITE);
168   g_object_class_install_property(G_OBJECT_CLASS(klass), MIN_PROP,
169 				  _properties[MIN_PROP]);
170   /**
171    * VisuPairLink::max:
172    *
173    * Store the link maximal distance.
174    *
175    * Since: 3.8
176    */
177   _properties[MAX_PROP] = g_param_spec_float("max", "Max",
178                                              "maximal distance",
179                                              0.f, G_MAXFLOAT, 0.f,
180                                              G_PARAM_READWRITE);
181   g_object_class_install_property(G_OBJECT_CLASS(klass), MAX_PROP,
182 				  _properties[MAX_PROP]);
183   /**
184    * VisuPairLink::units:
185    *
186    * The units of the length dimensions.
187    *
188    * Since: 3.8
189    */
190   _properties[UNITS_PROP] = g_param_spec_uint("units", "Units",
191                                               "Units of dimensions",
192                                               TOOL_UNITS_UNDEFINED, TOOL_UNITS_N_VALUES - 1,
193                                               TOOL_UNITS_UNDEFINED, G_PARAM_READWRITE);
194   g_object_class_install_property(G_OBJECT_CLASS(klass), UNITS_PROP,
195 				  _properties[UNITS_PROP]);
196   /**
197    * VisuPairLink::drawn:
198    *
199    * If the link should be drawn or not.
200    *
201    * Since: 3.8
202    */
203   _properties[USE_PROP] = g_param_spec_boolean("drawn", "Drawn",
204                                                "link is displayed or not",
205                                                TRUE, G_PARAM_READWRITE);
206   g_object_class_install_property(G_OBJECT_CLASS(klass), USE_PROP,
207 				  _properties[USE_PROP]);
208   /**
209    * VisuPairLink::display-length:
210    *
211    * If the link should display its length or not.
212    *
213    * Since: 3.8
214    */
215   _properties[LENGTH_PROP] = g_param_spec_boolean("display-length", "Display length",
216                                                   "link displays its length or not",
217                                                   FALSE, G_PARAM_READWRITE);
218   g_object_class_install_property(G_OBJECT_CLASS(klass), LENGTH_PROP,
219 				  _properties[LENGTH_PROP]);
220   /**
221    * VisuPairLink::color:
222    *
223    * Store the color of the link.
224    *
225    * Since: 3.8
226    */
227   _properties[COLOR_PROP] = g_param_spec_boxed("color", "color", "rendering color",
228                                                TOOL_TYPE_COLOR, G_PARAM_READWRITE);
229   g_object_class_install_property(G_OBJECT_CLASS(klass), COLOR_PROP, _properties[COLOR_PROP]);
230 
231   g_object_class_override_property(G_OBJECT_CLASS(klass), WIDTH_PROP, "width");
232   g_object_class_override_property(G_OBJECT_CLASS(klass), STIPPLE_PROP, "stipple");
233   g_object_class_override_property(G_OBJECT_CLASS(klass), SHADE_PROP, "shade");
234 
235   g_object_class_override_property(G_OBJECT_CLASS(klass), RADIUS_PROP, "radius");
236   g_object_class_override_property(G_OBJECT_CLASS(klass), TYPE_PROP, "color-type");
237 
238   /* entry = visu_config_file_addEnumEntry(VISU_CONFIG_FILE_RESOURCE, */
239   /*                                       FLAG_PAIRS_UNIT, DESC_PAIRS_UNIT, */
240   /*                                       &defaultUnits, _toUnit, FALSE); */
241   /* visu_config_file_entry_setVersion(entry, 3.8f); */
242   /* visu_config_file_addExportFunction(VISU_CONFIG_FILE_RESOURCE, */
243   /*                                    exportConfig); */
244 
245   defaultPairColor = tool_color_addFloatRGBA(rgbOfPairs, NULL);
246 }
visu_pair_wire_interface_init(VisuPairWireInterface * iface)247 static void visu_pair_wire_interface_init(VisuPairWireInterface *iface)
248 {
249   iface->set_width = _setWidth;
250   iface->get_width = _getWidth;
251   iface->set_stipple = _setStipple;
252   iface->get_stipple = _getStipple;
253   iface->set_shade = _setShade;
254   iface->get_shade = _getShade;
255 }
visu_pair_cylinder_interface_init(VisuPairCylinderInterface * iface)256 static void visu_pair_cylinder_interface_init(VisuPairCylinderInterface *iface)
257 {
258   iface->set_radius = _setRadius;
259   iface->get_radius = _getRadius;
260   iface->set_colorType = _setColorType;
261   iface->get_colorType = _getColorType;
262 }
visu_pair_link_init(VisuPairLink * obj)263 static void visu_pair_link_init(VisuPairLink *obj)
264 {
265   DBG_fprintf(stderr, "Visu Pair Link: initializing a new object (%p).\n",
266 	      (gpointer)obj);
267 
268   obj->priv = visu_pair_link_get_instance_private(obj);
269   obj->priv->dispose_has_run = FALSE;
270 
271   /* Private data. */
272   g_weak_ref_init(&obj->priv->ele1, (gpointer)0);
273   g_weak_ref_init(&obj->priv->ele2, (gpointer)0);
274   obj->priv->units             = visu_basic_getPreferedUnit();
275   obj->priv->minMax[VISU_DISTANCE_MIN] = G_MAXFLOAT;
276   obj->priv->minMax[VISU_DISTANCE_MAX] = G_MAXFLOAT;
277   obj->priv->drawn             = TRUE;
278   obj->priv->printLength       = FALSE;
279   tool_color_copy(&obj->priv->color, defaultPairColor);
280 
281   obj->priv->width = G_MAXUINT;
282   obj->priv->stipple = G_MAXUINT16;
283   obj->priv->shade = (ToolShade*)0;
284 
285   obj->priv->radius = G_MAXFLOAT;
286   obj->priv->colorType = VISU_CYLINDER_N_COLOR;
287 
288   g_signal_connect_object(VISU_CONFIG_FILE_RESOURCE, "parsed::main_unit",
289                           G_CALLBACK(onEntryUnit), (gpointer)obj, G_CONNECT_SWAPPED);
290 }
visu_pair_link_dispose(GObject * obj)291 static void visu_pair_link_dispose(GObject* obj)
292 {
293   VisuPairLink *data;
294 
295   DBG_fprintf(stderr, "Visu Pair Link: dispose object %p.\n", (gpointer)obj);
296 
297   data = VISU_PAIR_LINK(obj);
298   if (data->priv->dispose_has_run)
299     return;
300   data->priv->dispose_has_run = TRUE;
301 
302   g_weak_ref_clear(&data->priv->ele1);
303   g_weak_ref_clear(&data->priv->ele2);
304 
305   /* Chain up to the parent class */
306   G_OBJECT_CLASS(visu_pair_link_parent_class)->dispose(obj);
307 }
visu_pair_link_get_property(GObject * obj,guint property_id,GValue * value,GParamSpec * pspec)308 static void visu_pair_link_get_property(GObject* obj, guint property_id,
309                                         GValue *value, GParamSpec *pspec)
310 {
311   VisuPairLink *self = VISU_PAIR_LINK(obj);
312 
313   DBG_fprintf(stderr, "Visu Pair Link: get property '%s' -> ",
314 	      g_param_spec_get_name(pspec));
315   switch (property_id)
316     {
317     case COLOR_PROP:
318       g_value_set_boxed(value, &self->priv->color);
319       DBG_fprintf(stderr, "%gx%gx%g.\n", self->priv->color.rgba[0], self->priv->color.rgba[1], self->priv->color.rgba[2]);
320       break;
321     case MIN_PROP:
322       g_value_set_float(value, self->priv->minMax[0]);
323       DBG_fprintf(stderr, "%g.\n", self->priv->minMax[0]);
324       break;
325     case MAX_PROP:
326       g_value_set_float(value, self->priv->minMax[1]);
327       DBG_fprintf(stderr, "%g.\n", self->priv->minMax[1]);
328       break;
329     case UNITS_PROP:
330       g_value_set_uint(value, self->priv->units);
331       DBG_fprintf(stderr, "%d.\n", self->priv->units);
332       break;
333     case USE_PROP:
334       g_value_set_boolean(value, self->priv->drawn);
335       DBG_fprintf(stderr, "%d.\n", self->priv->drawn);
336       break;
337     case LENGTH_PROP:
338       g_value_set_boolean(value, self->priv->printLength);
339       DBG_fprintf(stderr, "%d.\n", self->priv->printLength);
340       break;
341     case WIDTH_PROP:
342       g_value_set_uint(value, _getWidth(VISU_PAIR_WIRE(obj)));
343       DBG_fprintf(stderr, "%d.\n", g_value_get_uint(value));
344       break;
345     case STIPPLE_PROP:
346       g_value_set_uint(value, _getStipple(VISU_PAIR_WIRE(obj)));
347       DBG_fprintf(stderr, "%d.\n", g_value_get_uint(value));
348       break;
349     case SHADE_PROP:
350       g_value_set_boxed(value, self->priv->shade);
351       DBG_fprintf(stderr, "%p.\n", (gpointer)self->priv->shade);
352       break;
353     case RADIUS_PROP:
354       g_value_set_float(value, _getRadius(VISU_PAIR_CYLINDER(obj)));
355       DBG_fprintf(stderr, "%g.\n", self->priv->radius);
356       break;
357     case TYPE_PROP:
358       g_value_set_uint(value, _getColorType(VISU_PAIR_CYLINDER(obj)));
359       DBG_fprintf(stderr, "%d.\n", g_value_get_uint(value));
360       break;
361     default:
362       /* We don't have any other property... */
363       G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
364       break;
365     }
366 }
visu_pair_link_set_property(GObject * obj,guint property_id,const GValue * value,GParamSpec * pspec)367 static void visu_pair_link_set_property(GObject* obj, guint property_id,
368                                         const GValue *value, GParamSpec *pspec)
369 {
370   VisuPairLink *self = VISU_PAIR_LINK(obj);
371 
372   DBG_fprintf(stderr, "Visu Pair Link: set property '%s' -> ",
373 	      g_param_spec_get_name(pspec));
374   switch (property_id)
375     {
376     case COLOR_PROP:
377       visu_pair_link_setColor(self, g_value_get_boxed(value));
378       DBG_fprintf(stderr, "%gx%gx%g.\n", self->priv->color.rgba[0], self->priv->color.rgba[1], self->priv->color.rgba[2]);
379       break;
380     case MIN_PROP:
381       visu_pair_link_setDistance(self, g_value_get_float(value), VISU_DISTANCE_MIN);
382       DBG_fprintf(stderr, "%g.\n", self->priv->minMax[0]);
383       break;
384     case MAX_PROP:
385       visu_pair_link_setDistance(self, g_value_get_float(value), VISU_DISTANCE_MAX);
386       DBG_fprintf(stderr, "%g.\n", self->priv->minMax[1]);
387       break;
388     case UNITS_PROP:
389       DBG_fprintf(stderr, "%d.\n", g_value_get_uint(value));
390       visu_pair_link_setUnits(self, g_value_get_uint(value));
391       break;
392     case USE_PROP:
393       visu_pair_link_setDrawn(self, g_value_get_boolean(value));
394       DBG_fprintf(stderr, "%d.\n", self->priv->drawn);
395       break;
396     case LENGTH_PROP:
397       visu_pair_link_setPrintLength(self, g_value_get_boolean(value));
398       DBG_fprintf(stderr, "%d.\n", self->priv->printLength);
399       break;
400     case WIDTH_PROP:
401       DBG_fprintf(stderr, "%d.\n", g_value_get_uint(value));
402       visu_pair_wire_setWidth(VISU_PAIR_WIRE(obj), g_value_get_uint(value));
403       break;
404     case STIPPLE_PROP:
405       DBG_fprintf(stderr, "%d.\n", g_value_get_uint(value));
406       visu_pair_wire_setStipple(VISU_PAIR_WIRE(obj), (guint16)g_value_get_uint(value));
407       break;
408     case SHADE_PROP:
409       DBG_fprintf(stderr, "%p.\n", (gpointer)g_value_get_boxed(value));
410       visu_pair_wire_setShade(VISU_PAIR_WIRE(obj), (ToolShade*)g_value_dup_boxed(value));
411       break;
412     case RADIUS_PROP:
413       DBG_fprintf(stderr, "%g.\n", g_value_get_float(value));
414       visu_pair_cylinder_setRadius(VISU_PAIR_CYLINDER(obj), g_value_get_float(value));
415       break;
416     case TYPE_PROP:
417       DBG_fprintf(stderr, "%d.\n", g_value_get_uint(value));
418       visu_pair_cylinder_setColorType(VISU_PAIR_CYLINDER(obj), g_value_get_uint(value));
419       break;
420     default:
421       /* We don't have any other property... */
422       G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
423       break;
424     }
425 }
426 /**
427  * visu_pair_link_new:
428  * @ele1: a #VisuElement object ;
429  * @ele2: a #VisuElement object ;
430  * @minMax: (array fixed-size=2): the two min and max distances.
431  *
432  * A link between two elements is characterized by its boundary distances.
433  *
434  * Returns: (transfer none): the #VisuPairLink object associated to the given two
435  *          elements and distances. If none exists it is created. The
436  *          returned value should not be freed.
437  */
visu_pair_link_new(VisuElement * ele1,VisuElement * ele2,const float minMax[2])438 VisuPairLink* visu_pair_link_new(VisuElement *ele1, VisuElement *ele2, const float minMax[2])
439 {
440   VisuPairLink *data;
441 
442   data = VISU_PAIR_LINK(g_object_new(VISU_TYPE_PAIR_LINK, NULL));
443   data->priv->minMax[VISU_DISTANCE_MIN] = minMax[0];
444   data->priv->minMax[VISU_DISTANCE_MAX] = minMax[1];
445   g_weak_ref_set(&data->priv->ele1, ele1);
446   g_weak_ref_set(&data->priv->ele2, ele2);
447   DBG_fprintf(stderr, " | new %p %s-%s (%g %g).\n", (gpointer)data,
448               ele1->name, ele2->name,
449 	      data->priv->minMax[0], data->priv->minMax[1]);
450 
451   return data;
452 }
453 /**
454  * visu_pair_link_getFirstElement:
455  * @data: a #VisuPairLink object.
456  *
457  * Retrieve one of the #VisuElement @data is linking.
458  *
459  * Since: 3.8
460  *
461  * Returns: (transfer full): a #VisuElement the link is linking.
462  **/
visu_pair_link_getFirstElement(VisuPairLink * data)463 VisuElement* visu_pair_link_getFirstElement(VisuPairLink *data)
464 {
465   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), (VisuElement*)0);
466   return g_weak_ref_get(&data->priv->ele1);
467 }
468 /**
469  * visu_pair_link_getSecondElement:
470  * @data: a #VisuPairLink object.
471  *
472  * Retrieve one of the #VisuElement @data is linking.
473  *
474  * Since: 3.8
475  *
476  * Returns: (transfer full): a #VisuElement the link is linking.
477  **/
visu_pair_link_getSecondElement(VisuPairLink * data)478 VisuElement* visu_pair_link_getSecondElement(VisuPairLink *data)
479 {
480   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), (VisuElement*)0);
481   return g_weak_ref_get(&data->priv->ele2);
482 }
483 /**
484  * visu_pair_link_setDrawn:
485  * @data: a #VisuPairLink object ;
486  * @drawn: a boolean.
487  *
488  * A pair can or cannot be drawn, use this method to tune it.
489  *
490  * Returns: TRUE if parameter has been changed.
491  */
visu_pair_link_setDrawn(VisuPairLink * data,gboolean drawn)492 gboolean visu_pair_link_setDrawn(VisuPairLink *data, gboolean drawn)
493 {
494   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), FALSE);
495 
496   DBG_fprintf(stderr, "Visu Pairs: set drawn status %d (%d) for %p.\n",
497 	      (int)drawn, (int)data->priv->drawn, (gpointer)data);
498   if (data->priv->drawn == drawn)
499     return FALSE;
500 
501   data->priv->drawn = drawn;
502   g_object_notify_by_pspec(G_OBJECT(data), _properties[USE_PROP]);
503   return TRUE;
504 }
505 /**
506  * visu_pair_link_setPrintLength:
507  * @data: a #VisuPairLink object ;
508  * @status: TRUE to print length near pairs.
509  *
510  * Set the attribute that controls if the length of pairs are drawn near pairs.
511  *
512  * Returns: TRUE if parameter has been changed.
513  */
visu_pair_link_setPrintLength(VisuPairLink * data,gboolean status)514 gboolean visu_pair_link_setPrintLength(VisuPairLink *data, gboolean status)
515 {
516   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), FALSE);
517 
518   DBG_fprintf(stderr, "Visu Pairs: set print length status %d (%d) for %p.\n",
519 	      (int)status, (int)data->priv->printLength, (gpointer)data);
520   if (data->priv->printLength == status)
521     return FALSE;
522 
523   data->priv->printLength = status;
524   g_object_notify_by_pspec(G_OBJECT(data), _properties[LENGTH_PROP]);
525   return TRUE;
526 }
527 /**
528  * visu_pair_link_getDrawn:
529  * @data: a #VisuPairLink object ;
530  *
531  * A pair can or cannot be drawn, use this method to retrieve its state.
532  *
533  * Returns: TRUE if pairs can be drawn.
534  */
visu_pair_link_getDrawn(const VisuPairLink * data)535 gboolean visu_pair_link_getDrawn(const VisuPairLink *data)
536 {
537   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), FALSE);
538   return data->priv->drawn;
539 }
540 /**
541  * visu_pair_link_setColor:
542  * @data: a #VisuPairLink object ;
543  * @destColor: a #ToolColor object.
544  *
545  * Set the color of the given pair.
546  *
547  * Returns: TRUE if parameter has been changed.
548  */
visu_pair_link_setColor(VisuPairLink * data,const ToolColor * destColor)549 gboolean visu_pair_link_setColor(VisuPairLink *data, const ToolColor* destColor)
550 {
551   g_return_val_if_fail(VISU_IS_PAIR_LINK(data) && destColor, FALSE);
552 
553   DBG_fprintf(stderr, "Visu Pairs: set color [%g;%g;%g] for %p.\n",
554 	      destColor->rgba[0], destColor->rgba[1], destColor->rgba[2],
555 	      (gpointer)data);
556 
557   if (tool_color_equal(&data->priv->color, destColor))
558     return FALSE;
559 
560   /* Copy values of dest to current color. */
561   tool_color_copy(&data->priv->color, destColor);
562   g_object_notify_by_pspec(G_OBJECT(data), _properties[COLOR_PROP]);
563   return TRUE;
564 }
565 /**
566  * visu_pair_link_getColor:
567  * @data: a #VisuPairLink object.
568  *
569  * Look for the properties of the pair @data to find if a colour has
570  * been defined. If none, the default colour is returned instead.
571  *
572  * Returns: (transfer none): a colour (don't free it).
573  */
visu_pair_link_getColor(const VisuPairLink * data)574 ToolColor* visu_pair_link_getColor(const VisuPairLink *data)
575 {
576   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), defaultPairColor);
577 
578   return &data->priv->color;
579 }
580 /**
581  * visu_pair_link_setDistance:
582  * @val: a floating point value ;
583  * @data: a #VisuPairLink object ;
584  * @minOrMax: #VISU_DISTANCE_MAX or #VISU_DISTANCE_MIN.
585  *
586  * Set the minimum or the maximum length for the given pair.
587  *
588  * Returns: TRUE if parameter has been changed.
589  */
visu_pair_link_setDistance(VisuPairLink * data,float val,VisuPairLinkDistances minOrMax)590 gboolean visu_pair_link_setDistance(VisuPairLink *data, float val,
591                                     VisuPairLinkDistances minOrMax)
592 {
593   g_return_val_if_fail(VISU_IS_PAIR_LINK(data) &&
594                        (minOrMax == VISU_DISTANCE_MIN ||
595                         minOrMax == VISU_DISTANCE_MAX), FALSE);
596 
597   if (data->priv->minMax[minOrMax] == val)
598     return FALSE;
599 
600   data->priv->minMax[minOrMax] = val;
601   g_object_notify_by_pspec(G_OBJECT(data), _properties[(minOrMax) ? MAX_PROP : MIN_PROP]);
602   return TRUE;
603 }
604 /**
605  * visu_pair_link_setUnits:
606  * @data: a #VisuPairLink object.
607  * @units: a unit.
608  *
609  * Define the unit used to store the distances.
610  *
611  * Since: 3.8
612  *
613  * Returns: TRUE if value is actually changed.
614  **/
visu_pair_link_setUnits(VisuPairLink * data,ToolUnits units)615 gboolean visu_pair_link_setUnits(VisuPairLink *data, ToolUnits units)
616 {
617   ToolUnits unit_;
618   double fact;
619 
620   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), FALSE);
621 
622   if (data->priv->units == units)
623     return FALSE;
624 
625   unit_ = data->priv->units;
626   data->priv->units = units;
627   g_object_notify_by_pspec(G_OBJECT(data), _properties[UNITS_PROP]);
628 
629   if (unit_ == TOOL_UNITS_UNDEFINED || units == TOOL_UNITS_UNDEFINED)
630     return TRUE;
631 
632   fact = (double)tool_physic_getUnitValueInMeter(unit_) /
633     tool_physic_getUnitValueInMeter(units);
634 
635   data->priv->minMax[VISU_DISTANCE_MIN] *= fact;
636   g_object_notify_by_pspec(G_OBJECT(data), _properties[MIN_PROP]);
637   data->priv->minMax[VISU_DISTANCE_MAX] *= fact;
638   g_object_notify_by_pspec(G_OBJECT(data), _properties[MAX_PROP]);
639 
640   return TRUE;
641 }
642 /**
643  * visu_pair_link_getUnits:
644  * @data: a #VisuPairLink object.
645  *
646  * Get the units of distance definition of @data.
647  *
648  * Returns: TRUE if length are printed.
649  */
visu_pair_link_getUnits(const VisuPairLink * data)650 ToolUnits visu_pair_link_getUnits(const VisuPairLink *data)
651 {
652   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), FALSE);
653   return data->priv->units;
654 }
655 /**
656  * visu_pair_link_getPrintLength:
657  * @data: a #VisuPairLink object.
658  *
659  * Get the print length parameter of a pair. This parameter is used to tell if
660  * length should be drawn near pairs of this kind.
661  *
662  * Returns: TRUE if length are printed.
663  */
visu_pair_link_getPrintLength(const VisuPairLink * data)664 gboolean visu_pair_link_getPrintLength(const VisuPairLink *data)
665 {
666   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), FALSE);
667   return data->priv->printLength;
668 }
669 /**
670  * visu_pair_link_getDistance:
671  * @data: a #VisuPairLink object ;
672  * @minOrMax: #VISU_DISTANCE_MIN or #VISU_DISTANCE_MAX.
673  *
674  * A pair between @ele1 and @ele2 is drawn only if its length is between
675  * a minimum and a maximum value. This method can get these values.
676  *
677  * Returns: the minimum or the maximum value for the pair between @ele1 and @ele2.
678  */
visu_pair_link_getDistance(const VisuPairLink * data,VisuPairLinkDistances minOrMax)679 float visu_pair_link_getDistance(const VisuPairLink *data, VisuPairLinkDistances minOrMax)
680 {
681   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), 0.f);
682   g_return_val_if_fail(minOrMax == VISU_DISTANCE_MIN ||
683                        minOrMax == VISU_DISTANCE_MAX, 0.);
684 
685   return data->priv->minMax[minOrMax];
686 }
687 /**
688  * visu_pair_link_match:
689  * @data: a #VisuPairLink object.
690  * @minMax: (array fixed-size=2): two floats.
691  *
692  * Returns if @data is a link with distance criterions defined by @minMax.
693  *
694  * Since: 3.8
695  *
696  * Returns: %TRUE, if @data matches @minMax.
697  **/
visu_pair_link_match(const VisuPairLink * data,const float minMax[2])698 gboolean visu_pair_link_match(const VisuPairLink *data, const float minMax[2])
699 {
700   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), FALSE);
701   DBG_fprintf(stderr, " | test %p (%g %g).\n", (gpointer)data,
702               data->priv->minMax[0], data->priv->minMax[1]);
703   return (data->priv->minMax[0] == minMax[0] && data->priv->minMax[1] == minMax[1]);
704 }
705 /**
706  * visu_pair_link_isDrawn:
707  * @data: a #VisuPairLink object.
708  *
709  * A link is used or not depending on a distance criterion and a flag,
710  * see visu_pair_link_setDrawn() and visu_pair_link_setDistance().
711  *
712  * Since: 3.7
713  *
714  * Returns: TRUE if the @data is indeed drawn or not.
715  **/
visu_pair_link_isDrawn(const VisuPairLink * data)716 gboolean visu_pair_link_isDrawn(const VisuPairLink *data)
717 {
718   g_return_val_if_fail(VISU_IS_PAIR_LINK(data), FALSE);
719 
720   return (data->priv->drawn &&
721           data->priv->minMax[VISU_DISTANCE_MAX] >
722           data->priv->minMax[VISU_DISTANCE_MIN] &&
723           data->priv->minMax[VISU_DISTANCE_MAX] > 0.f);
724 }
_setWidth(VisuPairWire * data,guint val)725 static gboolean   _setWidth(VisuPairWire *data, guint val)
726 {
727   if (VISU_PAIR_LINK(data)->priv->width == val)
728     return FALSE;
729   VISU_PAIR_LINK(data)->priv->width = val;
730 
731   return TRUE;
732 }
_getWidth(VisuPairWire * data)733 static guint      _getWidth(VisuPairWire *data)
734 {
735   return VISU_PAIR_LINK(data)->priv->width == G_MAXUINT ? visu_pair_wire_getDefaultWidth() : VISU_PAIR_LINK(data)->priv->width;
736 }
_setShade(VisuPairWire * data,ToolShade * shade)737 static gboolean   _setShade(VisuPairWire *data, ToolShade *shade)
738 {
739   if (tool_shade_compare(VISU_PAIR_LINK(data)->priv->shade, shade))
740     return FALSE;
741   VISU_PAIR_LINK(data)->priv->shade = shade;
742 
743   return TRUE;
744 }
_getShade(VisuPairWire * data)745 static ToolShade* _getShade(VisuPairWire *data)
746 {
747   return VISU_PAIR_LINK(data)->priv->shade;
748 }
_setStipple(VisuPairWire * data,guint16 stipple)749 static gboolean   _setStipple(VisuPairWire *data, guint16 stipple)
750 {
751   if (VISU_PAIR_LINK(data)->priv->stipple == stipple)
752     return FALSE;
753   VISU_PAIR_LINK(data)->priv->stipple = stipple;
754 
755   return TRUE;
756 }
_getStipple(VisuPairWire * data)757 static guint16    _getStipple(VisuPairWire *data)
758 {
759   return VISU_PAIR_LINK(data)->priv->stipple == G_MAXUINT16 ? visu_pair_wire_getDefaultStipple() : VISU_PAIR_LINK(data)->priv->stipple;
760 }
_setRadius(VisuPairCylinder * data,gfloat val)761 static gboolean   _setRadius(VisuPairCylinder *data, gfloat val)
762 {
763   if (VISU_PAIR_LINK(data)->priv->radius == val)
764     return FALSE;
765   VISU_PAIR_LINK(data)->priv->radius = val;
766 
767   return TRUE;
768 }
_getRadius(VisuPairCylinder * data)769 static gfloat     _getRadius(VisuPairCylinder *data)
770 {
771   return VISU_PAIR_LINK(data)->priv->radius == G_MAXFLOAT ? visu_pair_cylinder_getDefaultRadius() : VISU_PAIR_LINK(data)->priv->radius;
772 }
_setColorType(VisuPairCylinder * data,VisuPairCylinderColorId val)773 static gboolean   _setColorType(VisuPairCylinder *data, VisuPairCylinderColorId val)
774 {
775   if (VISU_PAIR_LINK(data)->priv->colorType == val)
776     return FALSE;
777   VISU_PAIR_LINK(data)->priv->colorType = val;
778 
779   return TRUE;
780 }
_getColorType(VisuPairCylinder * data)781 static VisuPairCylinderColorId _getColorType(VisuPairCylinder *data)
782 {
783   return VISU_PAIR_LINK(data)->priv->colorType >= VISU_CYLINDER_N_COLOR ? visu_pair_cylinder_getDefaultColorType() : VISU_PAIR_LINK(data)->priv->colorType;
784 }
785 
onEntryUnit(VisuPairLink * link,VisuConfigFileEntry * entry _U_,VisuConfigFile * obj _U_)786 static void onEntryUnit(VisuPairLink *link, VisuConfigFileEntry *entry _U_, VisuConfigFile *obj _U_)
787 {
788   if (link->priv->units != TOOL_UNITS_UNDEFINED)
789     return;
790 
791   visu_pair_link_setUnits(link, visu_basic_getPreferedUnit());
792 }
793 /* static void exportConfig(GString *data, VisuData *dataObj _U_) */
794 /* { */
795 /*   const gchar **units; */
796 
797 /*   if (defaultUnits != TOOL_UNITS_UNDEFINED) */
798 /*     { */
799 /*       units = tool_physic_getUnitNames(); */
800 
801 /*       visu_config_file_exportComment(data, DESC_PAIRS_UNIT); */
802 /*       visu_config_file_exportEntry(data, FLAG_PAIRS_UNIT, NULL, */
803 /*                                    "%s", units[defaultUnits]); */
804 /*       visu_config_file_exportComment(data, ""); */
805 /*     } */
806 /* } */
_next1(VisuPairLinkIter * iter,gboolean restart)807 static gboolean _next1(VisuPairLinkIter *iter, gboolean restart)
808 {
809   if (!visu_element_getRendered(iter->iter1.element))
810     return FALSE;
811 
812   if (restart)
813     visu_node_array_iterRestartNode(VISU_NODE_ARRAY(iter->data), &iter->iter1);
814   else
815     visu_node_array_iterNextNode(VISU_NODE_ARRAY(iter->data), &iter->iter1);
816 
817   while (iter->iter1.node &&
818          !visu_node_getVisibility(iter->iter1.node))
819     visu_node_array_iterNextNode(VISU_NODE_ARRAY(iter->data), &iter->iter1);
820 
821   if (iter->iter1.node)
822     visu_data_getNodePosition(iter->data, iter->iter1.node, iter->xyz1);
823 
824   return (iter->iter1.node != NULL);
825 }
_next2(VisuPairLinkIter * iter,gboolean restart)826 static gboolean _next2(VisuPairLinkIter *iter, gboolean restart)
827 {
828   if (!visu_element_getRendered(iter->iter2.element))
829     return FALSE;
830 
831   if (restart)
832     visu_node_array_iterRestartNode(VISU_NODE_ARRAY(iter->data), &iter->iter2);
833   else
834     visu_node_array_iterNextNode(VISU_NODE_ARRAY(iter->data), &iter->iter2);
835 
836   while (iter->iter2.node)
837     {
838       if (iter->iter1.element == iter->iter2.element &&
839           iter->iter2.node >= iter->iter1.node)
840         return FALSE;
841 
842       if (visu_node_getVisibility(iter->iter2.node))
843         {
844           visu_data_getNodePosition(iter->data, iter->iter2.node, iter->xyz2);
845           iter->dxyz[0] = iter->xyz2[0] - iter->xyz1[0];
846           iter->dxyz[1] = iter->xyz2[1] - iter->xyz1[1];
847           iter->dxyz[2] = iter->xyz2[2] - iter->xyz1[2];
848           if (iter->box)
849             iter->periodic = visu_box_getInside(iter->box, iter->dxyz, 0.6f);
850           iter->d2 = iter->dxyz[0] * iter->dxyz[0] +
851             iter->dxyz[1] * iter->dxyz[1] +
852             iter->dxyz[2] * iter->dxyz[2];
853           if(iter->d2 >= iter->l2_buffered[0] && iter->d2 <= iter->l2_buffered[1])
854             {
855               if (iter->d2 < iter->l2[0])
856                 iter->coeff = (iter->d2 - iter->l2_buffered[0]) /
857                   (iter->l2[0] - iter->l2_buffered[0]);
858               else if (iter->d2 > iter->l2[1])
859                 iter->coeff = (iter->l2_buffered[1] - iter->d2) /
860                   (iter->l2_buffered[1] - iter->l2[1]);
861               else
862                 iter->coeff = 1.f;
863               return TRUE;
864             }
865         }
866       visu_node_array_iterNextNode(VISU_NODE_ARRAY(iter->data), &iter->iter2);
867     }
868   return FALSE;
869 }
870 
871 /**
872  * VisuPairLinkIter:
873  * @parent: the #VisuPairLink this iterator is inheriting his properties.
874  * @data: the #VisuData this iterator have to work on.
875  * @iter1: a #VisuNodeArrayIter.
876  * @iter2: a second #VisuNodeArrayIter.
877  * @buffer: the length of the buffer around links, in percents.
878  * @l2: the current link length, squared.
879  * @l2_buffered: like @l2, but including the buffer.
880  * @box: (allow-none): a given box to apply periodicity if needed.
881  * @periodic: a boolean specifying if periodicity is to be taken into
882  * account when computing the vector linking two nodes.
883  * @xyz1: the current coordinates of the starting node in the link.
884  * @xyz2: the current coordinates of the ending node in the link.
885  * @dxyz: the current vector (within periodicity) linking node1 to
886  * node2.
887  * @d2: the length of the link, squared.
888  * @coeff: a value used to characterised link length with respect to
889  * buffer (1. means that length is within link characteristics, while
890  * 0. means that link is outside characteristics plus buffer).
891  *
892  * An iterator used to generate pairs with the characteristics given
893  * by @parent, over the node in @data.
894  *
895  * Since: 3.8
896  */
897 
898 /**
899  * visu_pair_link_iter_new:
900  * @link: a #VisuPairLink object.
901  * @data: a #VisuData object.
902  * @iter: (out caller-allocates): a pointer to a #VisuPairLinkIter
903  * structure.
904  * @usePeriodicty: a boolean.
905  *
906  * Initialise a new #VisuPairLinkIter structure to iterate over links
907  * defined by @link in @data. If @usePeriodicty is %TRUE, all links
908  * between two nodes are kept if their smallest vector, using the
909  * periodicty, is within the @link distance criterion.
910  *
911  * Since: 3.8
912  *
913  * Returns: TRUE if there is a valid link to draw.
914  **/
visu_pair_link_iter_new(VisuPairLink * link,VisuData * data,VisuPairLinkIter * iter,gboolean usePeriodicty)915 gboolean visu_pair_link_iter_new(VisuPairLink *link, VisuData *data,
916                                  VisuPairLinkIter *iter, gboolean usePeriodicty)
917 {
918   float mM[2], length;
919 
920   g_return_val_if_fail(VISU_IS_PAIR_LINK(link) && data && iter, FALSE);
921 
922   if (!visu_pair_link_isDrawn(link))
923     return FALSE;
924 
925   iter->parent = link;
926   iter->data = data;
927 
928   visu_node_array_iter_new(VISU_NODE_ARRAY(data), &iter->iter1);
929   visu_node_array_iter_new(VISU_NODE_ARRAY(data), &iter->iter2);
930   iter->iter1.element = visu_pair_link_getFirstElement(link);
931   iter->iter2.element = visu_pair_link_getSecondElement(link);
932   g_object_unref(iter->iter2.element);
933   g_object_unref(iter->iter1.element);
934 
935   iter->buffer = 0.15f;
936   mM[0] = visu_pair_link_getDistance(link, VISU_DISTANCE_MIN);
937   mM[1] = visu_pair_link_getDistance(link, VISU_DISTANCE_MAX);
938   iter->l2[0] = mM[0] * mM[0];
939   iter->l2[1] = mM[1] * mM[1];
940   length = mM[1] - mM[0];
941   iter->l2_buffered[0] = (mM[0] - iter->buffer * length);
942   iter->l2_buffered[0] *= iter->l2_buffered[0];
943   iter->l2_buffered[1] = (mM[1] + iter->buffer * length);
944   iter->l2_buffered[1] *= iter->l2_buffered[1];
945 
946   iter->box = (usePeriodicty) ? visu_boxed_getBox(VISU_BOXED(data)) : (VisuBox*)0;
947   iter->periodic = FALSE;
948 
949   if (_next1(iter, TRUE))
950     {
951       if (_next2(iter, TRUE))
952         return TRUE;
953 
954       while (_next1(iter, FALSE))
955         {
956           if (_next2(iter, TRUE))
957             return TRUE;
958         };
959     }
960 
961   return FALSE;
962 }
963 /**
964  * visu_pair_link_iter_next:
965  * @iter: a #VisuPairLinkIter object.
966  *
967  * Iterate to the next #VisuNode - #VisuNode pair.
968  *
969  * Since: 3.8
970  *
971  * Returns: TRUE if iterator is still valid.
972  **/
visu_pair_link_iter_next(VisuPairLinkIter * iter)973 gboolean visu_pair_link_iter_next(VisuPairLinkIter *iter)
974 {
975   if (_next2(iter, FALSE))
976     return TRUE;
977 
978   while (_next1(iter, FALSE))
979     {
980       if (_next2(iter, TRUE))
981         return TRUE;
982     };
983 
984   return FALSE;
985 }
986