/* EXTRAITS DE LA LICENCE Copyright CEA, contributeurs : Luc BILLARD et Damien CALISTE, laboratoire L_Sim, (2001-2005) Adresse mèl : BILLARD, non joignable par mèl ; CALISTE, damien P caliste AT cea P fr. Ce logiciel est un programme informatique servant à visualiser des structures atomiques dans un rendu pseudo-3D. Ce logiciel est régi par la licence CeCILL soumise au droit français et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". Le fait que vous puissiez accéder à cet en-tête signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accepté les termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel). */ /* LICENCE SUM UP Copyright CEA, contributors : Luc BILLARD et Damien CALISTE, laboratoire L_Sim, (2001-2005) E-mail address: BILLARD, not reachable any more ; CALISTE, damien P caliste AT cea P fr. This software is a computer program whose purpose is to visualize atomic configurations in 3D. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. You can find a copy of this licence shipped with this software at Documentation/licence.en.txt. */ #include "visu_data.h" #include #include #include #include #include #include #include "visu_object.h" #include "visu_tools.h" #include "visu_nodes.h" #include "visu_extension.h" #include "visu_rendering.h" #include "openGLFunctions/objectList.h" struct nodesProperties_struct { /* This table has the same size and structure than the nodes table of a #VisuData object. */ gpointer **data; /* These store the allocated size of the data table. */ int sizeElement; int *sizeNode; /* This method is called for each stored token if not NULL when the table is freed. */ GDestroyNotify freeTokenFunc; }; struct dataProperties_struct { /* A debug pointer on the key. */ gchar* name; /* This is a pointer to the data stored. */ gpointer data; /* This method is called if not NULL when the table is freed. */ GDestroyNotify freeTokenFunc; }; struct FileDescription_struct { /* Identity. */ int kind; /* The name of a file. */ gchar *name; /* The format of the file. This format can be null, if the file has not been parsed yet and the format is unknown. If the file file is not parsed but the format is set, then it is just an indication and may not be the right format. */ FileFormat *format; }; /* * @NODE_RENDERED_CHANGED_SIGNAL: emitted when some #VisuNodes are hidden or revealed * (after all changes have been done) ; * @NODE_RENDERED_CHANGED_SIGNAL: emitted when some #VisuNodes are moved ; * @NODE_ASK_FOR_SHOW_HIDE_SIGNAL: emitted when a method wants to change the * rendered attribute of a node. It asks for all * modules that deals with this attribute to update * it ; * @OPENGL_FACETTES_CHANGED_SIGNAL: emitted whenever this rendered object must be computed again ; * @OPENGL_OBSERVE_MOVEMENT_SIGNAL: emitted when an observe movement begins or finishes ; * @OPENGL_THETA_PHI_OMEGA_CHANGED_SIGNAL: emitted when the camera is moved ; * @OPENGL_XS_YS_CHANGED_SIGNAL: emitted when translation has been applied to rendering ; * @OPENGL_GROSS_CHANGED_SIGNAL: emitted when the camera zooms ; * @OPENGL_PERSP_CHANGED_SIGNAL: emitted when the perspective is changed ; * @OPENGL_NEAR_FAR_CHANGED_SIGNAL: emitted when the view is changed ; * @OPENGL_WIDTH_HEIGHT_CHANGED_SIGNAL: emitted when the size of the window is changed ; * @VISU_DATA_FREED_SIGNAL : all object with a weak reference on this object should, * release it since this object is being freed. */ enum { ELEMENT_RENDERED_CHANGED_SIGNAL, NODE_RENDERED_CHANGED_SIGNAL, NODE_POSITION_CHANGED_SIGNAL, NODE_ASK_FOR_SHOW_HIDE_SIGNAL, OPENGL_OBSERVE_MOVEMENT_SIGNAL, OPENGL_THETA_PHI_OMEGA_CHANGED_SIGNAL, OPENGL_XS_YS_CHANGED_SIGNAL, OPENGL_GROSS_CHANGED_SIGNAL, OPENGL_PERSP_CHANGED_SIGNAL, OPENGL_NEAR_FAR_CHANGED_SIGNAL, OPENGL_WIDTH_HEIGHT_CHANGED_SIGNAL, OPENGL_FACETTES_CHANGED_SIGNAL, VISU_DATA_FREED_SIGNAL, LAST_SIGNAL }; struct _VisuDataClass { GObjectClass parent; int identifierAllNodes; }; static GObjectClass *parent_class = NULL; struct VisuData_private_struct { gboolean dispose_has_run; /********************/ /* Files attributes */ /********************/ /* Files that correspond to that VisuData. They are identified by a kind which is an integer. The list is pointers to FileDescription_struct. */ GList *files; /* Commentary associated to the rendered data. */ gchar* commentary; /********************/ /* Box attributes */ /********************/ /* This is the geometry of the box. Array position 1 to 6 correspond to xx, xy, yy, zx, zy and zz. */ float boxGeometry[6]; /* This is the unitary vector corresponding to boxGeometry. */ float boxNorm[6]; /* This is the matrix that transform cartesian coordinates to coordinates in the box geometry. Use visuDataConvert_XYZtoBoxCoordinates() to access this matrix. */ float transformXYZtoBoxCoordinates[3][3]; /* This is the matrix that transform box coordinates to cartesian coordinates. Use visuDataConvert_boxCoordinatestoXYZ() to access this matrix. */ float transformBoxCoordinatestoXYZ[3][3]; /* TRUE if the box is periodic. It is FALSE by default. */ gboolean isBoxPeriodic; /* Translation applied to all nodes when rendered. */ float translation[3]; /********************/ /* Misc. attributes */ /********************/ /* This is a table to store data, reachable with string keys. It should be accessed via visuDataSet_nodeProperty and visuDataGet_nodeProperty. */ GHashTable *nodesProperties; /* This hashtable is usefull to store some data associated with the VisuData. It should be accessed with the visuDataSet_property() and the visuDataGet_property methods. */ GHashTable *properties; /* This list contains pointers on source id, to be removed when the object is finalized. */ GList *timeoutList; /* This pointer is used to gain access to the window the #VisuData may be attached to. */ GenericRenderingWindow attachingWindow; /* This object is used to describe the geometry of the OpenGL context. */ OpenGLView *attachedView; /* Callbacks of signals that this object listen to. */ gulong dataLoadedSignalId; }; static void visu_data_class_init(VisuDataClass *klass); static void visu_data_init (VisuData *obj); static void visu_data_dispose (GObject* obj); static void visu_data_finalize (GObject* obj); /* Local callbacks. */ static void freeNodepropertiesStruct(gpointer data); static void freeDatapropertiesStruct(gpointer data); static void onDataLoadedSignal(GObject *obj, VisuData *visuData, gpointer data); static void onAskForShowHideSignal(VisuData *visuData, gboolean *redraw, gpointer data); static void visuData_rebuildList(VisuData *dataObj); static guint visu_data_signals[LAST_SIGNAL] = { 0 }; static GList* allObjects; GType visu_data_get_type(void) { static GType visu_data_type = 0; if (!visu_data_type) { static const GTypeInfo visu_data_info = { sizeof (VisuDataClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc)visu_data_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (VisuData), 0, (GInstanceInitFunc)visu_data_init, NULL }; visu_data_type = g_type_register_static(G_TYPE_OBJECT, "VisuDataType", &visu_data_info, 0); DBG_fprintf(stderr, "Visu data : creating the type VisuData %d.\n", (int)visu_data_type); } return visu_data_type; } static void visu_data_class_init(VisuDataClass *klass) { GType paramPointer[1] = {G_TYPE_POINTER}; GType paramBool[1] = {G_TYPE_BOOLEAN}; char *name = _("All elements"); char *description = _("Draw all the nodes."); OpenGLExtension *extensionData; DBG_fprintf(stderr, "Visu data : creating the class of the object.\n"); parent_class = g_type_class_peek_parent(klass); DBG_fprintf(stderr, " - adding new signals ;\n"); visu_data_signals[ELEMENT_RENDERED_CHANGED_SIGNAL] = g_signal_newv("ElementRenderedChanged", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, paramPointer); visu_data_signals[NODE_RENDERED_CHANGED_SIGNAL] = g_signal_newv("NodeRenderedChanged", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); visu_data_signals[NODE_POSITION_CHANGED_SIGNAL] = g_signal_newv ("NodePositionChanged", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); visu_data_signals[NODE_ASK_FOR_SHOW_HIDE_SIGNAL] = g_signal_newv ("NodeAskForShowHide", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, paramPointer); visu_data_signals[OPENGL_OBSERVE_MOVEMENT_SIGNAL] = g_signal_newv ("OpenGLObserveMovement", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, paramBool); visu_data_signals[OPENGL_THETA_PHI_OMEGA_CHANGED_SIGNAL] = g_signal_newv ("OpenGLThetaPhiOmega", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, paramPointer); visu_data_signals[OPENGL_XS_YS_CHANGED_SIGNAL] = g_signal_newv ("OpenGLXsYs", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, paramPointer); visu_data_signals[OPENGL_GROSS_CHANGED_SIGNAL] = g_signal_newv ("OpenGLGross", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, paramPointer); visu_data_signals[OPENGL_PERSP_CHANGED_SIGNAL] = g_signal_newv ("OpenGLPersp", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, paramPointer); visu_data_signals[OPENGL_NEAR_FAR_CHANGED_SIGNAL] = g_signal_newv ("OpenGLNearFar", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, paramPointer); visu_data_signals[OPENGL_WIDTH_HEIGHT_CHANGED_SIGNAL] = g_signal_newv ("OpenGLWidthHeight", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, paramPointer); visu_data_signals[OPENGL_FACETTES_CHANGED_SIGNAL] = g_signal_newv ("OpenGLFacetteChanged", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); visu_data_signals[VISU_DATA_FREED_SIGNAL] = g_signal_newv ("objectFreed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL , NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); /* Connect freeing methods. */ G_OBJECT_CLASS(klass)->dispose = visu_data_dispose; G_OBJECT_CLASS(klass)->finalize = visu_data_finalize; /* Initialise internal variables. */ /* Get an OpenGL identifier to store all the materials. */ klass->identifierAllNodes = openGLObjectList_new(NMAX_TP + 1); extensionData = OpenGLExtension_new(name, description, klass->identifierAllNodes, visuData_rebuildList); OpenGLExtensionSet_priority(extensionData, OPENGL_EXTENSION_PRIORITY_FIRST); OpenGLExtensionSet_sensitiveToRenderingMode(extensionData, TRUE); extensionData->used = 1; OpenGLExtensionRegister(extensionData); allObjects = (GList*)0; } static void visu_data_init(VisuData *obj) { int i; DBG_fprintf(stderr, "Visu data : initializing a new object (%p).\n", (gpointer)obj); /* Connect a method to make all nodes rendered attribute to TRUE when the NodeAskForShowHide signal is emited. */ g_signal_connect(G_OBJECT(obj), "NodeAskForShowHide", G_CALLBACK(onAskForShowHideSignal), (gpointer)0); obj->privateDt = g_malloc(sizeof(VisuData_private)); obj->privateDt->dispose_has_run = FALSE; /* Public data. */ obj->ntype= 0; obj->fromVisuElementToInt = (GHashTable*)0; obj->fromNumberToVisuNode = (VisuNode**)0; obj->fromIntToVisuElement = (VisuElement**)0; obj->numberOfStoredNodes = (int*)0; obj->numberOfNodes = (int*)0; obj->nbOfAllStoredNodes = 0; obj->nodes = (VisuNode**)0; obj->setColor = (setColorFunc)0; /* Private data. */ obj->privateDt->files = (GList*)0; obj->privateDt->commentary = (gchar*)0; for (i = 0; i < 3; i++) obj->privateDt->translation[i] = 0.; for (i = 0; i < 6; i++) obj->privateDt->boxGeometry[i] = 0.; obj->privateDt->isBoxPeriodic = FALSE; obj->privateDt->timeoutList = (GList*)0; obj->privateDt->attachingWindow = (GenericRenderingWindow)0; obj->privateDt->attachedView = (OpenGLView*)0; obj->privateDt->dataLoadedSignalId = g_signal_connect_swapped(G_OBJECT(visu), "dataLoaded", G_CALLBACK(onDataLoadedSignal), (gpointer)obj); /* Initial allocations. */ obj->privateDt->nodesProperties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeNodepropertiesStruct); if (!obj->privateDt->nodesProperties) exit(1); obj->privateDt->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeDatapropertiesStruct); if (!obj->privateDt->properties) exit(1); obj->fromVisuElementToInt = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, freeInt); if (!obj->fromVisuElementToInt) exit(1); /* Add object from allObjects list. */ allObjects = g_list_append(allObjects, (gpointer)obj); DBG_fprintf(stderr, "Visu Data: emit the 'DataNew' signal.\n"); g_signal_emit(visu, VISU_GET_CLASS(visu)->dataNew_signal_id, 0 /* details */, G_OBJECT(obj), NULL); DBG_fprintf(stderr, "Visu Data: emission OK of the 'DataNew' signal.\n"); } /* This method can be called several times. It should unref all of its reference to GObjects. */ static void visu_data_dispose(GObject* obj) { DBG_fprintf(stderr, "Visu data : dispose object %p.\n", (gpointer)obj); if (VISU_DATA(obj)->privateDt->dispose_has_run) return; g_signal_handler_disconnect(visu, VISU_DATA(obj)->privateDt->dataLoadedSignalId); VISU_DATA(obj)->privateDt->dispose_has_run = TRUE; DBG_fprintf(stderr, "Visu Data : emit a 'objectFreed' signal.\n"); g_signal_emit(obj, visu_data_signals[VISU_DATA_FREED_SIGNAL], 0, NULL); /* Chain up to the parent class */ G_OBJECT_CLASS(parent_class)->dispose(obj); } /* This method is called once only. */ static void visu_data_finalize(GObject* obj) { int i; VisuData *data; GList *lst; g_return_if_fail(obj); DBG_fprintf(stderr, "Visu data : finalize object %p.\n", (gpointer)obj); /* Remove object from allObjects list. */ allObjects = g_list_remove(allObjects, (gpointer)obj); data = VISU_DATA(obj); /* Free public elements. */ if (data->fromVisuElementToInt) g_hash_table_destroy(data->fromVisuElementToInt); if (data->fromIntToVisuElement) free(data->fromIntToVisuElement); if (data->fromNumberToVisuNode) free(data->fromNumberToVisuNode); if (data->nodes) { for(i = 0; i < data->ntype; i++) free(data->nodes[i]); free(data->nodes); } if (data->numberOfNodes) free(data->numberOfNodes); if (data->numberOfStoredNodes) free(data->numberOfStoredNodes); /* Free privateDts elements. */ if (data->privateDt) { if (data->privateDt->files) { lst = data->privateDt->files; while (lst) { g_free(((struct FileDescription_struct*)lst->data)->name); g_free(lst->data); lst = g_list_next(lst); } g_list_free(data->privateDt->files); } if (data->privateDt->commentary) g_free(data->privateDt->commentary); if (data->privateDt->nodesProperties) g_hash_table_destroy(data->privateDt->nodesProperties); if (data->privateDt->properties) g_hash_table_destroy(data->privateDt->properties); if (data->privateDt->timeoutList) { lst = data->privateDt->timeoutList; while (lst) { g_source_remove(*(guint*)lst->data); g_free(lst->data); lst = g_list_next(lst); } g_list_free(data->privateDt->timeoutList); } g_free(data->privateDt); if (data->privateDt->attachedView) OpenGLViewFree(data->privateDt->attachedView); } /* The free is called by g_type_free_instance... */ /* free(data); */ /* Chain up to the parent class */ G_OBJECT_CLASS(parent_class)->finalize(obj); DBG_fprintf(stderr, "Visu data : freeing ... OK.\n"); } VisuData* visuDataNew() { VisuData *data; data = VISU_DATA(g_object_new(VISU_DATA_TYPE, NULL)); if (!data) return (VisuData*)0; data->privateDt->attachedView = OpenGLViewNew(); return data; } VisuData* visuDataNew_withOpenGLView(OpenGLView *view) { VisuData *data; g_return_val_if_fail(view, (VisuData*)0); data = VISU_DATA(g_object_new(VISU_DATA_TYPE, NULL)); if (!data) return (VisuData*)0; data->privateDt->attachedView = OpenGLViewCopy(view); return data; } /* This is the maximum size (in drawing mode) of all the VisuElements that have at least one VisuNode registered. */ /* float maxDrawingSizeOfVisuElements; */ static void onAskForShowHideSignal(VisuData *visuData, gboolean *redraw, gpointer data) { int i, j; DBG_fprintf(stderr, "Visu Data : caught the 'NodeAskForShowHide' signal," " setting all node rendered attribute to TRUE.\n"); for (i = 0; i < visuData->ntype; i++) for(j = 0; j < visuData->numberOfStoredNodes[i]; j++) *redraw = visuNodeSet_visibility(&visuData->nodes[i][j], TRUE) || *redraw; DBG_fprintf(stderr, " - returned redraw value : %d.\n", *redraw); } static void onDataLoadedSignal(GObject *obj, VisuData *visuData, gpointer data) { double p1_x, p2_x, p3_x, p4_x, p5_x, p6_x, p7_x, p8_x; double p1_y, p2_y, p3_y, p4_y, p5_y, p6_y, p7_y, p8_y; double p1_z, p2_z, p3_z, p4_z, p5_z, p6_z, p7_z, p8_z; double sc, su; OpenGLBox *box; if (VISU_DATA(obj) != visuData) return; DBG_fprintf(stderr, "Visu Data (%p) : caught the 'dataLoaded' signal," " customising the view.\n", (gpointer)obj); box = visuData->privateDt->attachedView->box; box->dxxs2 = 0.5 * (visuData->privateDt->boxGeometry[VISU_DATA_BOX_DXX] + visuData->privateDt->boxGeometry[VISU_DATA_BOX_DYX] + visuData->privateDt->boxGeometry[VISU_DATA_BOX_DZX]); box->dyys2 = 0.5 * (visuData->privateDt->boxGeometry[VISU_DATA_BOX_DYY] + visuData->privateDt->boxGeometry[VISU_DATA_BOX_DZY]); box->dzzs2 = 0.5 * (visuData->privateDt->boxGeometry[VISU_DATA_BOX_DZZ]); p1_x = p1_y = p1_z = 0.0; p2_x = visuData->privateDt->boxGeometry[VISU_DATA_BOX_DXX]; p2_y = p2_z = 0.0; p4_x = visuData->privateDt->boxGeometry[VISU_DATA_BOX_DYX]; p4_y = visuData->privateDt->boxGeometry[VISU_DATA_BOX_DYY]; p4_z = 0.0; p5_x = visuData->privateDt->boxGeometry[VISU_DATA_BOX_DZX]; p5_y = visuData->privateDt->boxGeometry[VISU_DATA_BOX_DZY]; p5_z = visuData->privateDt->boxGeometry[VISU_DATA_BOX_DZZ]; p3_x = p2_x + p4_x; p3_y = p2_y + p4_y; p3_z = p2_z + p4_z; p6_x = p5_x + p2_x; p6_y = p5_y + p2_y; p6_z = p5_z + p2_z; p7_x = p5_x + p3_x; p7_y = p5_y + p3_y; p7_z = p5_z + p3_z; p8_x = p5_x + p4_x; p8_y = p5_y + p4_y; p8_z = p5_z + p4_z; box->p1[0] = p1_x; box->p1[1] = p1_y; box->p1[2] = p1_z; box->p2[0] = p2_x; box->p2[1] = p2_y; box->p2[2] = p2_z; box->p3[0] = p3_x; box->p3[1] = p3_y; box->p3[2] = p3_z; box->p4[0] = p4_x; box->p4[1] = p4_y; box->p4[2] = p4_z; box->p5[0] = p5_x; box->p5[1] = p5_y; box->p5[2] = p5_z; box->p6[0] = p6_x; box->p6[1] = p6_y; box->p6[2] = p6_z; box->p7[0] = p7_x; box->p7[1] = p7_y; box->p7[2] = p7_z; box->p8[0] = p8_x; box->p8[1] = p8_y; box->p8[2] = p8_z; /* calculate bare = 1/2 radius of centered sample */ su = (p7_x-p1_x)*(p7_x-p1_x)+ (p7_y-p1_y)*(p7_y-p1_y)+ (p7_z-p1_z)*(p7_z-p1_z); sc = (p8_x-p2_x)*(p8_x-p2_x)+ (p8_y-p2_y)*(p8_y-p2_y)+ (p8_z-p2_z)*(p8_z-p2_z); if (sc > su) su = sc; sc = (p5_x-p3_x)*(p5_x-p3_x)+ (p5_y-p3_y)*(p5_y-p3_y)+ (p5_z-p3_z)*(p5_z-p3_z); if (sc > su) su = sc; sc = (p6_x-p4_x)*(p6_x-p4_x)+ (p6_y-p4_y)*(p6_y-p4_y)+ (p6_z-p4_z)*(p6_z-p4_z); if (sc > su) su = sc; box->extens = 1.1 * 0.5f * (float)sqrt(su); /* Not used anymore. */ /* g_signal_emit (visu, VISU_GET_CLASS (visu)->OpenGLExtens_signal_id, */ /* 0 , NULL); */ /* effectue les projections et force le recalcul des éléments dépendants des facettes. */ openGLViewCompute_matrixAndView(visuData->privateDt->attachedView); DBG_fprintf(stderr, "Visu Data : emitting 'OpenGLFacetteChanged' signal.\n"); g_signal_emit(visuData, visu_data_signals[OPENGL_FACETTES_CHANGED_SIGNAL], 0, NULL); visuData_createAllElements(visuData); DBG_fprintf(stderr, "Visu Data : emission done.\n"); } /***************/ /* OpenGL Part */ /***************/ void visuData_createNodes(VisuData *data, VisuElement *ele) { RenderingMethod *currentRenderingMethod; int *nEle; int j; int mat; g_return_if_fail(data && ele); nEle = (int*)g_hash_table_lookup(data->fromVisuElementToInt, (gpointer)ele); if (!nEle) { fprintf(stderr, "WARNING! 'visuData_createNodes' has been" " called but the given VisuElement %p-'%s' is not used.\n", (gpointer)ele, ele->name); return; } currentRenderingMethod = getRenderingMethodInUse(); if (!currentRenderingMethod) { fprintf(stderr, "WARNING! 'visuData_createNodes' has been called but no" " rendering method has been selected.\n"); return; } if (!currentRenderingMethod->createNode) { fprintf(stderr, "WARNING! 'visuData_createNodes' has been called but" " the current rendering method has no createNode method.\n"); return; } if (!ele->materialIsUpToDate) visuElement_createMaterial(ele); glNewList(VISU_DATA_GET_CLASS(data)->identifierAllNodes + *nEle + 1, GL_COMPILE); if (ele->rendered) { DBG_fprintf(stderr, "Visu Data : creating glObjectList of nodes for '%s' - %d.\n", ele->name, ele->openGLIdentifier); /* Set the material by default if available. */ mat = visuElementGet_identifierMaterial(ele); if (!mat) g_warning("Can't find the material identifier for the" " element '%s'.\n", ele->name); else glCallList(mat); for(j = 0; j < data->numberOfStoredNodes[*nEle]; j++) { if (data->nodes[*nEle][j].rendered) { glLoadName((GLuint)data->nodes[*nEle][j].number); currentRenderingMethod->createNode(data, &data->nodes[*nEle][j], ele); } } } else DBG_fprintf(stderr, "Visu Data : skipping glObjectList of nodes for '%s' - %d.\n", ele->name, ele->openGLIdentifier); glEndList(); } void visuData_createNode(VisuData *data, VisuNode *node) { RenderingMethod *currentRenderingMethod; int mat; VisuElement *ele; currentRenderingMethod = getRenderingMethodInUse(); if (!currentRenderingMethod) { fprintf(stderr, "WARNING! 'visuData_createNode' has been called but no" " rendering method has been selected.\n"); return; } if (!currentRenderingMethod->createNode) { fprintf(stderr, "WARNING! 'visuData_createNode' has been called but" " the current rendering method has no createNode method.\n"); return; } ele = data->fromIntToVisuElement[node->posElement]; /* Set the material by default if available. */ mat = visuElementGet_identifierMaterial(ele); if (!mat) g_warning("Can't find the material identifier for the" " element '%s'.\n", ele->name); else glCallList(mat); glLoadName((GLuint)node->number); currentRenderingMethod->createNode(data, node, ele); } void visuData_createAllNodes(VisuData *data) { int i; #if DEBUG == 1 GTimer *timer; gulong fractionTimer; #endif if (!data) { DBG_fprintf(stderr, "Visu Data : A file has just been loaded, but the" " currentVisuData variable is empty!\n"); return; } DBG_fprintf(stderr, "Visu Data : 'visuData_createAllNodes' called.\n"); #if DEBUG == 1 timer = g_timer_new(); g_timer_start(timer); #endif DBG_fprintf(stderr, "Visu Data : loop on elements.\n"); for (i = 0; i < data->ntype; i++) visuData_createNodes(data, data->fromIntToVisuElement[i]); DBG_fprintf(stderr, "Visu Data : OK.\n"); glNewList(VISU_DATA_GET_CLASS(data)->identifierAllNodes, GL_COMPILE); glLineWidth(1); for (i = 0; i < data->ntype; i++) { DBG_fprintf(stderr, "Visu Data : add list %d.\n", VISU_DATA_GET_CLASS(data)->identifierAllNodes + i + 1); /* if (currentVisuData->fromIntToVisuElement[i]->rendered) */ glCallList(VISU_DATA_GET_CLASS(data)->identifierAllNodes + i + 1); } glEndList(); #if DEBUG == 1 g_timer_stop(timer); fprintf(stderr, "Visu Data : lists built in %gµs.\n", g_timer_elapsed(timer, &fractionTimer)/1e-6); g_timer_destroy(timer); #endif } void visuData_createAllElements(VisuData *data) { int i, id; RenderingMethod *method; if (!data) { fprintf(stderr, "WARNING! 'visuData_createAllElements' has" " been called with a null 'data' argument.\n"); return; } DBG_fprintf(stderr, "Visu Data : creating OpenGl elements for" " all VisuElement used in given VisuData %p.\n", (gpointer)data); method = getRenderingMethodInUse(); if (!method) { fprintf(stderr, "WARNING! 'visuData_createAllElements' has" " been called but there is no selected rendering method.\n"); return; } for (i = 0; i < data->ntype; i++) { id = method->createElement(data, data->fromIntToVisuElement[i]); data->fromIntToVisuElement[i]->openGLIdentifier = id; } } int visuDataGet_objectList(VisuData *data) { return VISU_DATA_GET_CLASS(data)->identifierAllNodes; } static void visuData_rebuildList(VisuData *dataObj) { int i; DBG_fprintf(stderr, "Visu Data : rebuilding object list for visuData %p.\n", (gpointer)dataObj); g_return_if_fail(dataObj); for (i = 0; i < dataObj->ntype; i++) visuElement_createMaterial(dataObj->fromIntToVisuElement[i]); visuData_createAllElements(dataObj); visuData_createAllNodes(dataObj); } int visuDataSet_population(VisuData *data, int nbOfTypes, int* nbOfNodesPerVisuElement, VisuElement **visuElementUsed) { int i; int *pos; int nb; DBG_fprintf(stderr, "Visu Data : populating VisuData %p", (gpointer)data); data->fromIntToVisuElement = malloc(sizeof(VisuElement*) * nbOfTypes); if (!data->fromIntToVisuElement) { DBG_fprintf(stderr, " ... Error!\nVisu Data : allocate fromIntToVisuElement failed.\n"); return 0; } data->ntype = nbOfTypes; if (data->ntype <= 0) { DBG_fprintf(stderr, " ... Error!\nVisu Data : ntype <= 0 failed.\n"); return 0; } data->nodes = malloc(sizeof(VisuNode*) * data->ntype); if (!data->nodes) { DBG_fprintf(stderr, " ... Error!\nVisu Data : allocate nodes failed.\n"); return 0; } data->numberOfNodes = malloc(sizeof(int) * data->ntype); if (!data->numberOfNodes) { DBG_fprintf(stderr, " ... Error!\nVisu Data : allocate numberOfNodes failed.\n"); return 0; } data->numberOfStoredNodes = malloc(sizeof(int) * data->ntype); if (!data->numberOfStoredNodes) { DBG_fprintf(stderr, " ... Error!\nVisu Data : allocate numberOfStoredNodes failed.\n"); return 0; } nb = 0; for(i = 0; i < data->ntype; i++) { if (nbOfNodesPerVisuElement[i] <= 0) { DBG_fprintf(stderr, " ... Error!\nVisu Data : nb nodes for '%s' <= 0.\n", data->fromIntToVisuElement[i]->name); return 0; } data->nodes[i] = malloc(sizeof(VisuNode) * nbOfNodesPerVisuElement[i]); if (!data->nodes[i]) { DBG_fprintf(stderr, " ... Error!\nVisu Data : allocate nodes[%d] failed.\n", i); return 0; } nb += nbOfNodesPerVisuElement[i]; data->numberOfNodes[i] = nbOfNodesPerVisuElement[i]; data->numberOfStoredNodes[i] = 0; pos = malloc(sizeof(int)); if (!pos) { DBG_fprintf(stderr, " ... Error!\nVisu Data : allocate pos (%d) failed.\n", i); return 0; } *pos = i; g_hash_table_insert(data->fromVisuElementToInt, (gpointer)visuElementUsed[i], (gpointer)pos); data->fromIntToVisuElement[i] = visuElementUsed[i]; } data->nbOfAllStoredNodes = 0; data->fromNumberToVisuNode = malloc(sizeof(VisuNode*) * nb); if (!data->fromNumberToVisuNode) { DBG_fprintf(stderr, " ... Error!\nVisu Data : allocate fromNumberToVisuNode failed.\n"); return 0; } DBG_fprintf(stderr, " ... OK\n"); return 1; } void visuDataFree_population(VisuData *data) { int i; if (!data) return; DBG_fprintf(stderr, "Visu Data : freeing the population of VisuData %p ...\n", (gpointer)data); if (data->fromVisuElementToInt) g_hash_table_destroy(data->fromVisuElementToInt); data->fromVisuElementToInt = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, freeInt); if (data->fromIntToVisuElement) free(data->fromIntToVisuElement); data->fromIntToVisuElement = (VisuElement**)0; if (data->fromNumberToVisuNode) free(data->fromNumberToVisuNode); data->fromNumberToVisuNode = (VisuNode**)0; if (data->nodes) { for(i = 0; i < data->ntype; i++) free(data->nodes[i]); free(data->nodes); } data->nodes = (VisuNode**)0; if (data->numberOfNodes) free(data->numberOfNodes); data->numberOfNodes = (int*)0; if (data->numberOfStoredNodes) free(data->numberOfStoredNodes); data->numberOfStoredNodes = (int*)0; if (data->privateDt->nodesProperties) g_hash_table_destroy(data->privateDt->nodesProperties); data->privateDt->nodesProperties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeNodepropertiesStruct); DBG_fprintf(stderr, "Visu Data : freeing ... OK.\n"); } void visuDataAdd_file(VisuData *data, gchar* file, int kind, FileFormat *format) { struct FileDescription_struct *dt; g_return_if_fail(data && file); dt = g_malloc(sizeof(struct FileDescription_struct)); dt->kind = kind; dt->name = g_strdup(file); dt->format = format; data->privateDt->files = g_list_prepend(data->privateDt->files, (gpointer)dt); DBG_fprintf(stderr, "Visu Data : adding '%s' filename (key: %d) to the VisuData %p.\n", file, kind, (gpointer)data); } void visuDataRemove_allFiles(VisuData *data) { GList *lst; g_return_if_fail(data); lst = data->privateDt->files; while (lst) { g_free(((struct FileDescription_struct*)lst->data)->name); g_free(lst->data); lst = g_list_next(lst); } g_list_free(data->privateDt->files); data->privateDt->files = (GList*)0; if (data->privateDt->commentary) { g_free(data->privateDt->commentary); data->privateDt->commentary = (gchar*)0; } } gchar* visuDataGet_file(VisuData *data, int kind, FileFormat **format) { GList *lst; g_return_val_if_fail(data, (gchar*)0); DBG_fprintf(stderr, "Visu Data : retrieve filename with key %d from the VisuData %p.\n", kind, (gpointer)data); if (format) *format = (FileFormat*)0; lst = data->privateDt->files; while (lst) { if (((struct FileDescription_struct*)lst->data)->kind == kind) { if (format) *format = ((struct FileDescription_struct*)lst->data)->format; return ((struct FileDescription_struct*)lst->data)->name; } lst = g_list_next(lst); } return (gchar*)0; } void visuDataSet_fileCommentary(VisuData *data, gchar* commentary) { g_return_if_fail(data); data->privateDt->commentary = g_strdup(commentary); } gchar* visuDataGet_fileCommentary(VisuData *data) { g_return_val_if_fail(data, (gchar*)0); return data->privateDt->commentary; } gboolean visuData_compareElements(VisuData *data1, VisuData *data2) { int i; g_return_val_if_fail(data1 && data2, FALSE); DBG_fprintf(stderr, "Visu Data : comparing composition of '%p' and '%p'.\n", (gpointer)data1, (gpointer)data2); if (data1->ntype != data2->ntype) return FALSE; for (i = 0; i< data1->ntype; i++) if (!g_hash_table_lookup(data2->fromVisuElementToInt, (gpointer)data1->fromIntToVisuElement[i])) return FALSE; for (i = 0; i< data2->ntype; i++) if (!g_hash_table_lookup(data1->fromVisuElementToInt, (gpointer)data2->fromIntToVisuElement[i])) return FALSE; return TRUE; } void visuDataSet_changeElementFlag(VisuData *data, gboolean changeElement) { gboolean *val; g_return_if_fail(data); /* Test if already exists */ val = (gboolean*)visuDataGet_property(data, "changeElementListFlag"); if (!val) { val = g_malloc(sizeof(gboolean)); visuDataSet_property(data, "changeElementListFlag", val); } *val = changeElement; } gboolean visuDataGet_changeElementFlag(VisuData *data) { gboolean *val; g_return_val_if_fail(data, FALSE); val = (gboolean*)visuDataGet_property(data, "changeElementListFlag"); if (val) return *val; else return FALSE; } void visuDataSet_ColorFunc(VisuData *data, setColorFunc func) { g_return_if_fail(data); DBG_fprintf(stderr, "Visu Data : set the color method to %d.\n", GPOINTER_TO_INT(func)); data->setColor = func; } /** * visuDataAdd_VisuElement: * @data: the #VisuData where to add the new #VisuNode ; * @ele: the #VisuElement kind of the new #VisuNode ; * @x: its x coordinate ; * @y: its y coordinate ; * @z: its z coordinate ; * @number: its position in the input file (or anything else that can uniqualy * identify this new #VisuNode). * * This method adds a new #VisuNode to the specified #VisuData. Rotation is set to 0. * * Returns: 0 if everything is allright. */ int visuDataAdd_VisuElement(VisuData *data, VisuElement *ele, double x, double y, double z, int number) { int *pos; if (!data) return 1; pos = (int*)g_hash_table_lookup(data->fromVisuElementToInt, (gpointer)ele); if (!pos) { g_warning("Can't add a node of element '%s' in VisuData %p since" " no such element has been allocated.\n", ele->name, (gpointer)data); return 1; } if (*pos > data->ntype || *pos < 0) { g_warning("The hashtable from VisuElement to position" " of the VisuData %d is malformed since the VisuElement '%s' has a" " position %d.\n", GPOINTER_TO_INT(data), ele->name, *pos); return 1; } data->nbOfAllStoredNodes += 1; visuNodeSet_newValues(data->nodes[*pos] + data->numberOfStoredNodes[*pos], x, y, z, data->nbOfAllStoredNodes, 1, *pos, data->numberOfStoredNodes[*pos]); data->fromNumberToVisuNode[data->nbOfAllStoredNodes - 1] = data->nodes[*pos] + data->numberOfStoredNodes[*pos]; data->numberOfStoredNodes[*pos] += 1; return 0; } /** * visuDataAdd_int: * @data: the #VisuData where to add the new #VisuNode ; * @position: a integer corresponding to the position of * a #VisuElement in the array **nodes in the structure; * @x: its x coordinate ; * @y: its y coordinate ; * @z: its z coordinate ; * @number: its position in the input file (or anything else that can uniqualy * identify this new #VisuNode). * * This method adds a new #VisuNode to the specified #VisuData. Position must be * chosen between 0 and (ntype - 1) and corresponds to the position of the array * of #VisuNodes of a #VisuElement. * * Returns: 0 if everything is allright. */ int visuDataAdd_int(VisuData *data, int position, double x, double y, double z, int number) { if (!data) return 1; if (position > data->ntype || position < 0) return 1; data->nbOfAllStoredNodes += 1; visuNodeSet_newValues(data->nodes[position] + data->numberOfStoredNodes[position], x, y, z, data->nbOfAllStoredNodes, 1, position, data->numberOfStoredNodes[position]); data->fromNumberToVisuNode[data->nbOfAllStoredNodes - 1] = data->nodes[position] + data->numberOfStoredNodes[position]; data->numberOfStoredNodes[position] += 1; return 0; } void visuDataSet_nodeProperty(VisuData* data, VisuNode* node, char* key, gpointer value) { struct nodesProperties_struct *storedData; g_return_if_fail(data && node && key); storedData = (struct nodesProperties_struct*)g_hash_table_lookup(data->privateDt->nodesProperties, (gpointer)key); if (!storedData) { g_warning("The data %p has no nodesProperties" " identified by the key '%s'\n", (gpointer)data, key); return; } /* DBG_fprintf(stderr, "Visu Data : set a new value to the node" */ /* " property called '%s' : %p.\n", key, value); */ if (storedData->freeTokenFunc) storedData->freeTokenFunc(storedData->data[node->posElement][node->posNode]); storedData->data[node->posElement][node->posNode] = value; } gpointer visuDataGet_nodeProperty(VisuData* data, VisuNode* node, char* key) { struct nodesProperties_struct *storedData; g_return_val_if_fail(data && node && key, (gpointer)0); storedData = (struct nodesProperties_struct*)g_hash_table_lookup(data->privateDt->nodesProperties, (gpointer)key); if (!storedData) return (gpointer*)0; else return storedData->data[node->posElement][node->posNode]; } void visuDataRemove_nodeProperty(VisuData* data, char* key) { g_return_if_fail(data && key); g_hash_table_remove(data->privateDt->nodesProperties, key); DBG_fprintf(stderr, "Visu Data : removing the nodes property called '%s'.\n", key); } void visuDataAdd_nodeProperty(VisuData* data, char* key, GDestroyNotify freeFunc) { struct nodesProperties_struct *storedData; int i, j; g_return_if_fail(data && key); storedData = g_hash_table_lookup(data->privateDt->nodesProperties, key); if (storedData) { g_warning("The key '%s' is already associated.\n", key); return; } DBG_fprintf(stderr, "Visu Data : adding a new nodes property, called '%s'.\n", key); storedData = malloc(sizeof(struct nodesProperties_struct)); if (!storedData) { allocationProblems(); exit(1); } storedData->freeTokenFunc = freeFunc; storedData->data = malloc(sizeof(gpointer*) * data->ntype); if (!storedData->data) { allocationProblems(); exit(1); } storedData->sizeElement = data->ntype; storedData->sizeNode = malloc(sizeof(int) * data->ntype); if (!storedData->sizeNode) { allocationProblems(); exit(1); } for (i = 0; i < data->ntype; i++) { storedData->data[i] = malloc(sizeof(gpointer) * data->numberOfNodes[i]); if (!storedData->data[i]) { allocationProblems(); exit(1); } storedData->sizeNode[i] = data->numberOfNodes[i]; for (j = 0; j < data->numberOfNodes[i]; j++) storedData->data[i][j] = (gpointer)0; } g_hash_table_insert(data->privateDt->nodesProperties, (gpointer)key, (gpointer)storedData); } static void freeDatapropertiesStruct(gpointer data) { struct dataProperties_struct *dataSt; dataSt = (struct dataProperties_struct *)data; DBG_fprintf(stderr, "Visu Data : free the data property '%s' (%p).\n", dataSt->name, (gpointer)dataSt->data); if (dataSt->freeTokenFunc) dataSt->freeTokenFunc(dataSt->data); else g_free(dataSt->data); g_free(dataSt); } void visuDataSet_property(VisuData* data, char* key, gpointer value) { visuDataSet_propertyWithDestroyFunc(data, key, value, (GDestroyNotify)0); } void visuDataSet_propertyWithDestroyFunc(VisuData* data, char* key, gpointer value, GDestroyNotify freeFunc) { struct dataProperties_struct *dataSt; if (!data || !key) { fprintf(stderr, "WARNING! 'visuDataSet_property' has been called with" " a null data parameter or a null key parameter.\n"); return; } DBG_fprintf(stderr, "Visu Data : set a new value (with free method) to the " "property called '%s' : %p.\n", key, value); dataSt = g_malloc(sizeof(struct dataProperties_struct)); dataSt->name = key; dataSt->data = value; dataSt->freeTokenFunc = (GDestroyNotify)freeFunc; g_hash_table_insert(data->privateDt->properties, (gpointer)key, (gpointer)dataSt); } gpointer visuDataGet_property(VisuData* data, char* key) { struct dataProperties_struct *dataSt; if (!data || !key) { fprintf(stderr, "WARNING! 'visuDataGet_property' has been called with" " a null data parameter or a null key parameter.\n"); return (gpointer)0; } dataSt = (struct dataProperties_struct *)g_hash_table_lookup(data->privateDt->properties, (gpointer)key); DBG_fprintf(stderr, "Visu Data : get the value (%p) associated to the " " property called '%s'.\n", (gpointer)(dataSt)?dataSt->data:0, key); if (!dataSt) return (gpointer)0; else return dataSt->data; } void visuDataRemove_property(VisuData* data, char* key) { if (!data || !key) { fprintf(stderr, "WARNING! 'visuDataRemove_property' has been called with" " a null data parameter or a null key parameter.\n"); return; } g_hash_table_remove(data->privateDt->properties, (gpointer)key); } float* visuDataGet_XYZtranslation(VisuData* data) { float *trans; int i; if (!data) { fprintf(stderr, "WARNING! 'visuDataGet_translation' has been called with no 'data'" " attribute.\n"); return (float*)0; } trans = malloc(sizeof(float) * 3); if (!trans) { allocationProblems(); exit(1); } for (i = 0; i < 3; i++) trans[i] = data->privateDt->translation[i]; return trans; } int visuDataSet_XYZtranslation(VisuData* data, float xyz[3]) { int i, res; if (!data || !xyz) { fprintf(stderr, "WARNING! 'visuDataAdd_translation' has been called with no 'data'" " attribute.\n"); return 0; } res = 0; for (i = 0; i < 3; i++) { if (data->privateDt->translation[i] != xyz[i]) { data->privateDt->translation[i] = xyz[i]; res = 1; } } DBG_fprintf(stderr, "Visu Data : set translation to : %f %f %f\n", data->privateDt->translation[0], data->privateDt->translation[1], data->privateDt->translation[2]); return res; } void visuDataGet_boxMatrix(VisuData *data, float matrix[3][3]) { int i, j; g_return_if_fail(IS_VISU_DATA_TYPE(data) && matrix); for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) matrix[i][j] = data->privateDt->transformBoxCoordinatestoXYZ[i][j]; } void visuDataConvert_XYZtoBoxCoordinates(VisuData *data, float boxCoord[3], float xyz[3]) { int i, j; g_return_if_fail(data && boxCoord && xyz); for (i = 0; i < 3; i++) { boxCoord[i] = 0.; for (j = 0; j < 3; j++) boxCoord[i] += data->privateDt->transformXYZtoBoxCoordinates[i][j] * xyz[j]; } } void visuDataConvert_boxCoordinatestoXYZ(VisuData *data, float xyz[3], float boxCoord[3]) { int i, j; if (!data || !boxCoord || !xyz) { fprintf(stderr, "WARNING! 'visuDataConvert_boxCoordinatestoXYZ' has been called" " with no 'data' or no 'boxCoord' or no 'xyz' argument.\n"); return; } for (i = 0; i < 3; i++) { xyz[i] = 0.; for (j = 0; j < 3; j++) xyz[i] += data->privateDt->transformBoxCoordinatestoXYZ[i][j] * boxCoord[j]; } } void visuDataSet_boxGeometry(VisuData *data, float geometry[6], gboolean periodic) { int i; float normY, normZ; if (!data || !geometry) { fprintf(stderr, "WARNING! 'visuDataSet_boxGeometry' has been called with no 'data'" " or no 'geometry' attribute.\n"); return; } data->privateDt->isBoxPeriodic = periodic; for (i = 0; i < 6; i++) data->privateDt->boxGeometry[i] = geometry[i]; normY = sqrt(geometry[VISU_DATA_BOX_DYX] * geometry[VISU_DATA_BOX_DYX] + geometry[VISU_DATA_BOX_DYY] * geometry[VISU_DATA_BOX_DYY]); normZ = sqrt(geometry[VISU_DATA_BOX_DZX] * geometry[VISU_DATA_BOX_DZX] + geometry[VISU_DATA_BOX_DZY] * geometry[VISU_DATA_BOX_DZY] + geometry[VISU_DATA_BOX_DZZ] * geometry[VISU_DATA_BOX_DZZ]); data->privateDt->boxNorm[0] = 1.; for (i = 1; i < 3; i++) data->privateDt->boxNorm[i] = geometry[i] / normY; for (i = 3; i < 6; i++) data->privateDt->boxNorm[i] = geometry[i] / normZ; DBG_fprintf(stderr, "Visu Data : the bounding box is set to :\n %f %f %f\n %f %f %f\n", geometry[0], geometry[1], geometry[2], geometry[3], geometry[4], geometry[5]); /* Create the transformation matrix. */ data->privateDt->transformXYZtoBoxCoordinates[0][0] = 1 / data->privateDt->boxGeometry[VISU_DATA_BOX_DXX]; data->privateDt->transformXYZtoBoxCoordinates[0][1] = - data->privateDt->boxGeometry[VISU_DATA_BOX_DYX] / data->privateDt->boxGeometry[VISU_DATA_BOX_DXX] / data->privateDt->boxGeometry[VISU_DATA_BOX_DYY]; data->privateDt->transformXYZtoBoxCoordinates[0][2] = - (data->privateDt->boxGeometry[VISU_DATA_BOX_DZX] / data->privateDt->boxGeometry[VISU_DATA_BOX_DXX] - data->privateDt->boxGeometry[VISU_DATA_BOX_DYX] * data->privateDt->boxGeometry[VISU_DATA_BOX_DZY] / data->privateDt->boxGeometry[VISU_DATA_BOX_DXX] / data->privateDt->boxGeometry[VISU_DATA_BOX_DYY] ) / data->privateDt->boxGeometry[VISU_DATA_BOX_DZZ]; data->privateDt->transformXYZtoBoxCoordinates[1][0] = 0.; data->privateDt->transformXYZtoBoxCoordinates[1][1] = 1 / data->privateDt->boxGeometry[VISU_DATA_BOX_DYY]; data->privateDt->transformXYZtoBoxCoordinates[1][2] = - data->privateDt->boxGeometry[VISU_DATA_BOX_DZY] / data->privateDt->boxGeometry[VISU_DATA_BOX_DYY] / data->privateDt->boxGeometry[VISU_DATA_BOX_DZZ]; data->privateDt->transformXYZtoBoxCoordinates[2][0] = 0.; data->privateDt->transformXYZtoBoxCoordinates[2][1] = 0.; data->privateDt->transformXYZtoBoxCoordinates[2][2] = 1 / data->privateDt->boxGeometry[VISU_DATA_BOX_DZZ]; data->privateDt->transformBoxCoordinatestoXYZ[0][0] = data->privateDt->boxGeometry[VISU_DATA_BOX_DXX]; data->privateDt->transformBoxCoordinatestoXYZ[0][1] = data->privateDt->boxGeometry[VISU_DATA_BOX_DYX]; data->privateDt->transformBoxCoordinatestoXYZ[0][2] = data->privateDt->boxGeometry[VISU_DATA_BOX_DZX]; data->privateDt->transformBoxCoordinatestoXYZ[1][0] = 0.; data->privateDt->transformBoxCoordinatestoXYZ[1][1] = data->privateDt->boxGeometry[VISU_DATA_BOX_DYY]; data->privateDt->transformBoxCoordinatestoXYZ[1][2] = data->privateDt->boxGeometry[VISU_DATA_BOX_DZY]; data->privateDt->transformBoxCoordinatestoXYZ[2][0] = 0.; data->privateDt->transformBoxCoordinatestoXYZ[2][1] = 0.; data->privateDt->transformBoxCoordinatestoXYZ[2][2] = data->privateDt->boxGeometry[VISU_DATA_BOX_DZZ]; } float visuDataGet_boxGeometry(VisuData *data, int vector) { if (!data) { fprintf(stderr, "WARNING! 'visuDataGet_boxGeometry' has been called with no 'data'" " attribute.\n"); return -1.; } if (vector < 0 || vector >= 6) { fprintf(stderr, "WARNING! 'visuDataGet_boxGeometry' has been called" " with a wrong 'vector' attribute (%d).\n", vector); return -1.; } return data->privateDt->boxGeometry[vector]; } gboolean visuDataGet_periodic(VisuData *data) { if (!data) { fprintf(stderr, "WARNING! 'visuDataGet_boxGeometry' has been called with no 'data'" " attribute.\n"); return FALSE; } return data->privateDt->isBoxPeriodic; } int visuData_constrainedElementInTheBox(VisuData *data, VisuElement *element) { int *indexEle, i, j, k; gboolean moved, changed; float cartCoord[3], boxCoord[3]; if (!data || !element) { fprintf(stderr, "WARNING! 'visuData_constrainedElementInTheBox' has been" " called with no 'data' or no 'element' attribute.\n"); return 0; } indexEle = (int*)g_hash_table_lookup(data->fromVisuElementToInt, (gpointer)element); if (!indexEle) { fprintf(stderr, "WARNING! 'visuData_constrainedElementInTheBox' has been" " called with an 'element' attribute that is not in 'data' attribute.\n"); return 0; } i = *indexEle; if (!data->fromIntToVisuElement[i]->rendered) return 0; DBG_fprintf(stderr, "Visu Data : Checking for nodes of element '%s' to be in the box.\n", element->name); changed = FALSE; for(j = 0; j < data->numberOfStoredNodes[i]; j++) { cartCoord[0] = data->nodes[i][j].x + data->privateDt->translation[0] + data->nodes[i][j].translation[0]; cartCoord[1] = data->nodes[i][j].y + data->privateDt->translation[1] + data->nodes[i][j].translation[1]; cartCoord[2] = data->nodes[i][j].z + data->privateDt->translation[2] + data->nodes[i][j].translation[2]; visuDataConvert_XYZtoBoxCoordinates(data, boxCoord, cartCoord); moved = FALSE; for (k = 0; k < 3; k++) { while (boxCoord[k] < 0.) { moved = TRUE; boxCoord[k] += 1.; } while (boxCoord[k] > 1.) { moved = TRUE; boxCoord[k] -= 1.; } } if (moved) { changed = TRUE; visuDataConvert_boxCoordinatestoXYZ(data, cartCoord, boxCoord); data->nodes[i][j].translation[0] = cartCoord[0] - data->nodes[i][j].x - data->privateDt->translation[0]; data->nodes[i][j].translation[1] = cartCoord[1] - data->nodes[i][j].y - data->privateDt->translation[1]; data->nodes[i][j].translation[2] = cartCoord[2] - data->nodes[i][j].z - data->privateDt->translation[2]; } } return changed; } int visuData_constrainedInTheBox(VisuData *data) { int i; gboolean changed; if (!data) { fprintf(stderr, "WARNING! 'visuData_constrainedInTheBox' has been called with no 'data'" " attribute.\n"); return 0; } changed = FALSE; for (i = 0; i < data->ntype; i++) changed = visuData_constrainedElementInTheBox(data, data->fromIntToVisuElement[i]) || changed; if (changed) return 1; else return 0; } int visuData_constrainedFree(VisuData *data) { int i, j, k; if (!data) { fprintf(stderr, "WARNING! 'visuData_constrainedInTheBox' has been called with no 'data'" " attribute.\n"); return 0; } for (i = 0; i < data->ntype; i++) for(j = 0; j < data->numberOfStoredNodes[i]; j++) for (k = 0; k < 3; k++) data->nodes[i][j].translation[k] = 0.; return 1; } void visuDataGet_nodePosition(VisuData *data, VisuNode *node, float coord[3]) { if (!data || !node || !coord) { fprintf(stderr, "WARNING! 'visuDataGet_nodePosition' has been called" " with no 'data' or no 'node' or no 'coord' argument.\n"); return; } coord[0] = node->x + node->translation[0] + data->privateDt->translation[0]; coord[1] = node->y + node->translation[1] + data->privateDt->translation[1]; coord[2] = node->z + node->translation[2] + data->privateDt->translation[2]; } VisuNode* visuDataGet_nodeFromId(VisuData *data, int eleId, int posId) { g_return_val_if_fail(data && eleId >= 0 && posId >= 0, (VisuNode*)0); if (eleId < data->ntype && posId < data->numberOfStoredNodes[eleId]) return &data->nodes[eleId][posId]; else return (VisuNode*)0; } VisuNode* visuDataGet_nodeFromNumber(VisuData *data, int number) { g_return_val_if_fail(data && number > 0, (VisuNode*)0); if (number <= data->nbOfAllStoredNodes) return data->fromNumberToVisuNode[number - 1]; else return (VisuNode*)0; } /** * visuDataTrace: * @data: the #VisuData to trace. * * This method gives informations about the argument. */ void visuDataTrace(VisuData *data) { VisuElement *ele; int i; if (!data) return; fprintf(stderr, "Visu Data : data %d.\n", GPOINTER_TO_INT(data)); fprintf(stderr, " | nb VisuElements : %d\n", data->ntype); for (i = 0; i < data->ntype; i++) { ele = data->fromIntToVisuElement[i]; fprintf(stderr, " | VisuElements '%s' (%d), %d allocated VisuNodes and %d stored.\n", data->fromIntToVisuElement[i]->name, GPOINTER_TO_INT(data->fromIntToVisuElement[i]), data->numberOfNodes[i], data->numberOfStoredNodes[i]); } } void freeNodepropertiesStruct(gpointer data) { struct nodesProperties_struct *storedData; int i, j; DBG_fprintf(stderr, "Visu Data : freeing the allocated area of" " a nodes property.\n"); storedData = (struct nodesProperties_struct *)data; if (storedData->freeTokenFunc) for (i = 0; i < storedData->sizeElement; i++) for (j = 0; j < storedData->sizeNode[i]; j++) if (storedData->data[i][j]) storedData->freeTokenFunc(storedData->data[i][j]); for (i = 0; i < storedData->sizeElement; i++) free(storedData->data[i]); free(storedData->data); free(storedData->sizeNode); } void visuDataEmit_askForShowHideNodes(VisuData *data, gboolean *redraw) { g_return_if_fail(data && redraw); *redraw = FALSE; DBG_fprintf(stderr, "Visu data : %p emit the 'NodeAskForShowHide' signal.\n", (gpointer)data); g_signal_emit(data, visu_data_signals[NODE_ASK_FOR_SHOW_HIDE_SIGNAL], 0 , (gpointer)redraw, NULL); } void visuDataEmit_nodePositionChanged(VisuData *data) { g_return_if_fail(data); DBG_fprintf(stderr, "Visu data : %p emit the 'NodePositionChanged' signal.\n", (gpointer)data); g_signal_emit(data, visu_data_signals[NODE_POSITION_CHANGED_SIGNAL], 0 , NULL); } void visuDataEmit_elementRenderedChange(VisuData *data, VisuElement *element) { g_return_if_fail(data && element); DBG_fprintf(stderr, "Visu data : %p emit the 'ElementRenderedChanged'" " signal for element '%s'.\n", (gpointer)data, element->name); g_signal_emit(data, visu_data_signals[ELEMENT_RENDERED_CHANGED_SIGNAL], 0 , (gpointer)element, NULL); } void visuDataEmit_nodeRenderedChange(VisuData *data) { g_return_if_fail(data); DBG_fprintf(stderr, "Visu data : %p emit the 'NodeRenderedChanged' signal.\n", (gpointer)data); g_signal_emit(data, visu_data_signals[NODE_RENDERED_CHANGED_SIGNAL], 0 , NULL); } void visuDataEmit_observeMovement(VisuData *data, gboolean start) { g_return_if_fail(IS_VISU_DATA_TYPE(data)); DBG_fprintf(stderr, "Visu data : %p emit the 'OpenGLObserveMovement' signal.\n", (gpointer)data); g_signal_emit(data, visu_data_signals[OPENGL_OBSERVE_MOVEMENT_SIGNAL], 0 , start, NULL); } guint visuDataAdd_timeout(VisuData *data, guint time, GSourceFunc func, gpointer user_data) { guint *id; g_return_val_if_fail(IS_VISU_DATA_TYPE(data) && func, (guint)0); id = g_malloc(sizeof(guint)); *id = g_timeout_add(time, func, user_data); data->privateDt->timeoutList = g_list_append(data->privateDt->timeoutList, (gpointer)id); DBG_fprintf(stderr, "Visu data : create a new timeout callback : %d.\n", *id); return *id; } gboolean visuDataRemove_timeout(VisuData *data, guint timeoutId) { GList *lst; gboolean found; g_return_val_if_fail(IS_VISU_DATA_TYPE(data), FALSE); DBG_fprintf(stderr, "Visu data : trying to remove a timeout callback (%d) ... ", timeoutId); found = FALSE; lst = data->privateDt->timeoutList; while(lst) { if (*(guint*)lst->data == timeoutId) { found = g_source_remove(timeoutId); data->privateDt->timeoutList = g_list_delete_link(data->privateDt->timeoutList, lst); DBG_fprintf(stderr, "OK (%d).\n", found); return found; } lst = g_list_next(lst); } DBG_fprintf(stderr, "not found.\n"); return found; } GenericRenderingWindow visuDataGet_renderingWindow(VisuData *data) { g_return_val_if_fail(IS_VISU_DATA_TYPE(data), (GenericRenderingWindow)0); return data->privateDt->attachingWindow; } void visuDataSet_renderingWindow(VisuData *data, GenericRenderingWindow window) { g_return_if_fail(IS_VISU_DATA_TYPE(data)); data->privateDt->attachingWindow = window; } OpenGLView* visuDataGet_openGLView(VisuData *data) { g_return_val_if_fail(IS_VISU_DATA_TYPE(data), (OpenGLView*)0); return data->privateDt->attachedView; } int visuDataSet_angleOfView(VisuData *data, float valueTheta, float valuePhi, float valueOmega, int mask) { int res; g_return_val_if_fail(IS_VISU_DATA_TYPE(data), 0); res = openGLViewSet_thetaPhiOmega(data->privateDt->attachedView, valueTheta, valuePhi, valueOmega, mask); if (res) g_signal_emit(data, visu_data_signals[OPENGL_THETA_PHI_OMEGA_CHANGED_SIGNAL], 0, data->privateDt->attachedView, NULL); return res; } int visuDataSet_positionOfView(VisuData *data, float valueX, float valueY, int mask) { int res; g_return_val_if_fail(IS_VISU_DATA_TYPE(data), 0); res = openGLViewSet_XsYs(data->privateDt->attachedView, valueX, valueY, mask); if (res) { g_signal_emit(data, visu_data_signals[OPENGL_NEAR_FAR_CHANGED_SIGNAL], 0, data->privateDt->attachedView, NULL); g_signal_emit(data, visu_data_signals[OPENGL_XS_YS_CHANGED_SIGNAL], 0, data->privateDt->attachedView, NULL); } return res; } int visuDataSet_zoomOfView(VisuData *data, float value) { int res; g_return_val_if_fail(IS_VISU_DATA_TYPE(data), 0); res = openGLViewSet_gross(data->privateDt->attachedView, value); if (res) { g_signal_emit(data, visu_data_signals[OPENGL_NEAR_FAR_CHANGED_SIGNAL], 0, data->privateDt->attachedView, NULL); g_signal_emit(data, visu_data_signals[OPENGL_GROSS_CHANGED_SIGNAL], 0 , data->privateDt->attachedView, NULL); g_signal_emit(data, visu_data_signals[OPENGL_FACETTES_CHANGED_SIGNAL], 0 , NULL); visuData_createAllElements(data); } return res; } int visuDataSet_perspectiveOfView(VisuData *data, float value) { int res; g_return_val_if_fail(IS_VISU_DATA_TYPE(data), 0); res = openGLViewSet_persp(data->privateDt->attachedView, value); if (res) { g_signal_emit(data, visu_data_signals[OPENGL_NEAR_FAR_CHANGED_SIGNAL], 0, data->privateDt->attachedView, NULL); g_signal_emit(data, visu_data_signals[OPENGL_PERSP_CHANGED_SIGNAL], 0 , data->privateDt->attachedView, NULL); g_signal_emit(data, visu_data_signals[OPENGL_FACETTES_CHANGED_SIGNAL], 0 , NULL); visuData_createAllElements(data); } return res; } int visuDataSet_sizeOfView(VisuData *data, guint width, guint height) { int res; g_return_val_if_fail(IS_VISU_DATA_TYPE(data), 0); res = OpenGLViewSet_windowSize(data->privateDt->attachedView, width, height); if (res) { g_signal_emit(data, visu_data_signals[OPENGL_NEAR_FAR_CHANGED_SIGNAL], 0, data->privateDt->attachedView, NULL); g_signal_emit(data, visu_data_signals[OPENGL_WIDTH_HEIGHT_CHANGED_SIGNAL], 0 , data->privateDt->attachedView, NULL); g_signal_emit(data, visu_data_signals[OPENGL_FACETTES_CHANGED_SIGNAL], 0 , NULL); visuData_createAllElements(data); } return res; } void visuDataEmit_facettesChanged(VisuData *data) { g_return_if_fail(IS_VISU_DATA_TYPE(data)); g_signal_emit(data, visu_data_signals[OPENGL_FACETTES_CHANGED_SIGNAL], 0 , NULL); } GList* visuDataGet_allObjects() { DBG_fprintf(stderr, "Visu Data : get the allObjects list.\n"); return allObjects; } /**********************/ /* Obsolete functions */ /**********************/ /* Return the maxium size occupied by a VisuElement that has at least one VisuNode. */ /* float getMaxExtens() */ /* { */ /* return maxDrawingSizeOfVisuElements; */ /* } */ /* Store a new value in maxDrawingSizeOfVisuElements that controls the maximum size occupied by a VisuElement. This function emits a signal () that is tarpped by opengl.c. Value must be positive or nul. */ /* void setMaxExtends(float value) */ /* { */ /* if (value < 0.) */ /* return; */ /* maxDrawingSizeOfVisuElements = value; */ /* g_signal_emit (visu, VISU_GET_CLASS (visu)->VisuElementSizeChanged, */ /* 0 , NULL); */ /* } */