/* 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_pickMesure.h" #include #include #include "visu_tools.h" #include "visu_data.h" #include "visu_object.h" #include "visu_extension.h" #include "openGLFunctions/text.h" #include "openGLFunctions/objectList.h" #include "renderingBackend/visu_windowInterface.h" #include #include #include #include #include OpenGLExtension *extensionMarks; int openGlListMarksId; #define PICK_MESURE_MARK_BIG_SQUARE_SIZE 8 #define PICK_MESURE_MARK_SMALL_SQUARE_SIZE 4 guchar pickMesureMark_bigSquare[PICK_MESURE_MARK_BIG_SQUARE_SIZE * PICK_MESURE_MARK_BIG_SQUARE_SIZE * 4]; guchar pickMesureMark_smallSquare[PICK_MESURE_MARK_SMALL_SQUARE_SIZE * PICK_MESURE_MARK_SMALL_SQUARE_SIZE * 4]; typedef enum { PICK_MESURE_MARK_BIG_SQUARE, PICK_MESURE_MARK_SMALL_SQUARE, PICK_MESURE_END_MARK_DOT, PICK_MESURE_MARK_DISTANCE, PICK_MESURE_END_MARK_LINK } PickMesureMarkType; struct MarkInfo_struct { /* Mark type. */ PickMesureMarkType type; /* Pointer to one VisuNode. */ VisuNode *node1; /* Id used to address the VisuNode when the pointer node1 has changed, for example when a new VisuData is loaded with the same geometry and we want to apply this mark. */ int idNode1; /* Idem for a second node. */ VisuNode *node2; int idNode2; /* Text not used. */ gchar *text; }; /** * PickMesure_struct: * @xRef1: x coordinates of reference 1 (if set) in window coordinates ; * @yRef1: y coordinates of reference 1 (if set) in window coordinates ; * @ref1: a #VisuNode corresponding to reference 1 (if set) ; * @xRef2: x coordinates of reference 2 (if set) in window coordinates ; * @yRef2: y coordinates of reference 2 (if set) in window coordinates ; * @ref2: a #VisuNode corresponding to reference 2 (if set) ; * @selected: a #VisuNode corresponding to the normal selected node (if set) ; * @info: a string containing the formated pick informations ; * @error: a string containing an error message (if any) ; * @newValuesAvailable: a flag to set if the pick action has canged anything ; * @formatFlag: if set, the errors and info GString are used and strings * output for the pick action are created. * * This structure reflects the state of a current pick session used for * distance and angles measurements. */ struct PickMesure_struct { VisuData *data; int xRef1, yRef1; VisuNode *ref1; int idRef1; int xRef2, yRef2; VisuNode *ref2; int idRef2; VisuNode *selected; int idSelected; gboolean formatFlag; GString *info; GString *errors; gboolean newValuesAvailable; GList *storedMarks; gboolean storeDistance; gulong onPositionChangeSignalId; gulong onNodeRenderedChangeSignalId; gulong onElementRenderedChangeSignalId; }; /* Local methods. */ static PickMesure* initPickMesure(VisuData *data, gboolean formatFlag, gboolean storeDistance); static void pickMesureFree(gpointer data); static void pickMesureRebuild_list(VisuData *dataObj); /* Local drawing methods. */ void updateMarkList(VisuData *data, GList *list); /* Dots drawing methods. */ void drawMarkDot(VisuData *data, VisuNode *node, PickMesureMarkType type); void putMarkDot(VisuData *data, VisuNode *node, PickMesureMarkType type); void addMarkDotToList(PickMesure *mesureData, VisuNode *node, PickMesureMarkType type); void removeMarkDotFromList(PickMesure *mesureData, VisuNode *node); /* Distances drawing method. */ void drawMarkDistance(VisuData *data, VisuNode *nodeRef, VisuNode *node, PickMesureMarkType type); void putMarkDistance(VisuData *data, VisuNode *nodeRef, VisuNode *node, PickMesureMarkType type); void addMarkDistanceToList(PickMesure *mesureData, VisuNode *nodeRef, VisuNode *node, PickMesureMarkType type); /* gboolean pickMesureRemove_allDistanceMarks(PickMesure *mesureData, VisuData *data); */ /* Local callbacks. */ void createPickMesureOnNewData(GObject *visu, VisuData *dataObj, gpointer data); void updateListOnNodeChange(VisuData *dataObj, gpointer data); void updateListOnElementChange(VisuData *dataObj, VisuElement *ele, gpointer data); void initPick_module() { char *description = _("Draw some marks on element in video inverse."); int i; /* Get an id for the OpenGL list used to draw marks. */ openGlListMarksId = openGLObjectList_new(1); /* Create the marks. */ for (i = 0; i < PICK_MESURE_MARK_BIG_SQUARE_SIZE * PICK_MESURE_MARK_BIG_SQUARE_SIZE * 4 ; i++) pickMesureMark_bigSquare[i] = 0xff; for (i = 0; i < PICK_MESURE_MARK_SMALL_SQUARE_SIZE * PICK_MESURE_MARK_SMALL_SQUARE_SIZE * 4; i++) pickMesureMark_smallSquare[i] = 0xff; /* We listen to the dataReadyForRendering signal to create a pickMesure object and attach it to an object when created. */ g_signal_connect(G_OBJECT(visu), "dataNew", G_CALLBACK(createPickMesureOnNewData), (gpointer)0); /* Initialize an extension to draw the marks. */ extensionMarks = OpenGLExtension_new("Marks", description, openGlListMarksId, pickMesureRebuild_list); OpenGLExtensionRegister(extensionMarks); OpenGLExtensionSet_priority(extensionMarks, OPENGL_EXTENSION_PRIORITY_LAST); OpenGLExtensionSet_saveOpenGLState(extensionMarks, TRUE); extensionMarks->used = 1; } static PickMesure* initPickMesure(VisuData *data, gboolean formatFlag, gboolean storeDistance) { PickMesure *mesureData; g_return_val_if_fail(data, (PickMesure*)0); mesureData = g_malloc(sizeof(PickMesure)); mesureData->data = data; /* g_object_ref(data); */ mesureData->ref1 = (VisuNode*)0; mesureData->ref2 = (VisuNode*)0; mesureData->selected = (VisuNode*)0; mesureData->info = (GString*)0; mesureData->errors = (GString*)0; mesureData->newValuesAvailable = FALSE; mesureData->formatFlag = formatFlag; mesureData->storedMarks = (GList*)0; mesureData->storeDistance = storeDistance; if (storeDistance) openGLText_initFontList(); /* Connect a signal on file change to remove everything. */ mesureData->onPositionChangeSignalId = g_signal_connect(G_OBJECT(data), "NodePositionChanged", G_CALLBACK(updateListOnNodeChange), (gpointer)mesureData); mesureData->onNodeRenderedChangeSignalId = g_signal_connect(G_OBJECT(data), "NodeRenderedChanged", G_CALLBACK(updateListOnNodeChange), (gpointer)mesureData); mesureData->onElementRenderedChangeSignalId = g_signal_connect(G_OBJECT(data), "ElementRenderedChanged", G_CALLBACK(updateListOnElementChange), (gpointer)mesureData); DBG_fprintf(stderr, "Visu PickMesure : create a new object (formating : %d), %p.\n", (int)formatFlag, (gpointer)mesureData); return mesureData; } void createPickMesureOnNewData(GObject *visu, VisuData *dataObj, gpointer data) { PickMesure *mesureData; if (!dataObj) return; /* By default, we need no extended output but we draw measurements on screen. */ mesureData = initPickMesure(dataObj, FALSE, TRUE); visuDataSet_propertyWithDestroyFunc(dataObj, "pickMesure_data", (gpointer)mesureData, pickMesureFree); /* Empty the OpenGL list. */ updateMarkList(dataObj, mesureData->storedMarks); } void pickMesureFree(gpointer data) { GList *list; PickMesure *mesureData; mesureData = (PickMesure*)data; DBG_fprintf(stderr, "Visu PickMesure : Freeing pick mesure data from %p (VisuData %p).\n", (gpointer)mesureData, (gpointer)mesureData->data); /* Detach signals. */ /* g_signal_handler_disconnect(G_OBJECT(mesureData->data), */ /* mesureData->onPositionChangeSignalId); */ /* g_signal_handler_disconnect(G_OBJECT(mesureData->data), */ /* mesureData->onNodeRenderedChangeSignalId); */ /* g_signal_handler_disconnect(G_OBJECT(mesureData->data), */ /* mesureData->onElementRenderedChangeSignalId); */ /* redraw = pickMesureRemove_allMarks(mesureData); */ if (mesureData->info) g_string_free(mesureData->info, TRUE); if (mesureData->errors) g_string_free(mesureData->errors, TRUE); list = mesureData->storedMarks; while (list) { g_free(list->data); list = g_list_next(list); } g_list_free(mesureData->storedMarks); g_free(mesureData); } gboolean pickMesureRemove_allMarks(PickMesure *mesureData) { gboolean redraw; g_return_val_if_fail(mesureData, FALSE); if (mesureData->ref1) removeMarkDotFromList(mesureData, mesureData->ref1); if (mesureData->ref2) removeMarkDotFromList(mesureData, mesureData->ref2); mesureData->ref1 = (VisuNode*)0; mesureData->ref2 = (VisuNode*)0; mesureData->selected = (VisuNode*)0; redraw = pickMesureRemove_allDistanceMarks(mesureData); return redraw; } void putMarkDot(VisuData *data, VisuNode *node, PickMesureMarkType type) { VisuElement *ele; /* If the node is masked, then we don't draw the dot. */ if (!node->rendered) return; /* If one of the element is masked, then we don't draw the distance. */ ele = data->fromIntToVisuElement[node->posElement]; if (!ele->rendered) return; glDrawBuffer(GL_FRONT); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glDisable(GL_FOG); glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR); drawMarkDot(data, node, type); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPopAttrib(); glDrawBuffer(GL_BACK); } void drawMarkDot(VisuData *data, VisuNode *node, PickMesureMarkType type) { float xyz[3]; OpenGLView *view; VisuElement *ele; /* If the node is masked, then we don't draw the dot. */ if (!node->rendered) return; /* If one of the element is masked, then we don't draw the distance. */ ele = data->fromIntToVisuElement[node->posElement]; if (!ele->rendered) return; visuDataGet_nodePosition(data, node, xyz); view = visuDataGet_openGLView(data); glRasterPos3f(xyz[0] - view->box->dxxs2, xyz[1] - view->box->dyys2, xyz[2] - view->box->dzzs2); switch (type) { case PICK_MESURE_MARK_BIG_SQUARE: glDrawPixels(PICK_MESURE_MARK_BIG_SQUARE_SIZE, PICK_MESURE_MARK_BIG_SQUARE_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, pickMesureMark_bigSquare); break; case PICK_MESURE_MARK_SMALL_SQUARE: glDrawPixels(PICK_MESURE_MARK_SMALL_SQUARE_SIZE, PICK_MESURE_MARK_SMALL_SQUARE_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, pickMesureMark_smallSquare); break; default: break; } } void putMarkDistance(VisuData *data, VisuNode *nodeRef, VisuNode *node, PickMesureMarkType type) { VisuElement *ele; /* If one of the node is masked, then we don't draw the distance. */ if (!nodeRef->rendered || !node->rendered) return; /* If one of the element is masked, then we don't draw the distance. */ ele = data->fromIntToVisuElement[nodeRef->posElement]; if (!ele->rendered) return; ele = data->fromIntToVisuElement[node->posElement]; if (!ele->rendered) return; DBG_fprintf(stderr, "Visu pickMesure : draw directly a distance on front buffer.\n"); glDrawBuffer(GL_FRONT); glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glDisable(GL_FOG); glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR); drawMarkDistance(data, nodeRef, node, type); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPopAttrib(); glDrawBuffer(GL_BACK); } void drawMarkDistance(VisuData *data, VisuNode *nodeRef, VisuNode *node, PickMesureMarkType type) { float xyzRef[3], xyz[3], dist; int i; char distStr[8]; OpenGLView *view; VisuElement *ele; /* If one of the node is masked, then we don't draw the distance. */ if (!nodeRef->rendered || !node->rendered) return; /* If one of the element is masked, then we don't draw the distance. */ ele = data->fromIntToVisuElement[nodeRef->posElement]; if (!ele->rendered) return; ele = data->fromIntToVisuElement[node->posElement]; if (!ele->rendered) return; visuDataGet_nodePosition(data, nodeRef, xyzRef); visuDataGet_nodePosition(data, node, xyz); view = visuDataGet_openGLView(data); dist = 0.; for (i = 0; i < 3; i++) dist += (xyzRef[i] - xyz[i]) * (xyzRef[i] - xyz[i]); sprintf(distStr, "%7.3f", sqrt(dist)); distStr[7] = '\0'; DBG_fprintf(stderr, "Visu pickMesure : draw a link with distance %s.\n", distStr); glPushMatrix(); glTranslated(-view->box->dxxs2, -view->box->dyys2, -view->box->dzzs2); glLineWidth(1); glColor4f(1., 1., 1., 0.); glBegin(GL_LINES); glVertex3fv(xyzRef); glVertex3fv(xyz); glEnd(); glPointSize(8.); glBegin(GL_POINTS); glVertex3fv(xyzRef); glVertex3fv(xyz); glEnd(); glRasterPos3f((xyzRef[0] + xyz[0])/2., (xyzRef[1] + xyz[1])/2, (xyzRef[2] + xyz[2])/2.); openGLText_drawChars(distStr); /* fprintf(stderr, "----> '%s'\n", distStr); */ glPopMatrix(); /* drawMarkDot(data, node, PICK_MESURE_MARK_SMALL_SQUARE); */ } /* This method recreate the opengl list associated to marks with all the marks given as argument. */ void updateMarkList(VisuData *data, GList *list) { struct MarkInfo_struct *mark; DBG_fprintf(stderr, "Visu pickMesure : update the list %p" " of mark distances.\n", (gpointer)list); glDeleteLists(openGlListMarksId, 1); if (!list) return; glNewList(openGlListMarksId, GL_COMPILE); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_FOG); /* glDisable(GL_DITHER); */ glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR); while(list) { mark = (struct MarkInfo_struct*)list->data; DBG_fprintf(stderr, " | draw mark of type %d.\n", mark->type); if (mark->type < PICK_MESURE_END_MARK_DOT) drawMarkDot(data, mark->node1, mark->type); else if (mark->type > PICK_MESURE_END_MARK_DOT && mark->type < PICK_MESURE_END_MARK_LINK) drawMarkDistance(data, mark->node1, mark->node2, mark->type); list = g_list_next(list); } glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEndList(); } /* Method that add a dot mark to the list of drawn marks. The given new mark is drawn and the opengl list is updated for future use. */ void addMarkDotToList(PickMesure *mesureData, VisuNode *node, PickMesureMarkType type) { struct MarkInfo_struct *mark; g_return_if_fail(type < PICK_MESURE_END_MARK_DOT && node && mesureData); mark = g_malloc(sizeof(struct MarkInfo_struct)); mark->type = type; mark->node1 = node; mark->idNode1 = node->number; mark->node2 = (VisuNode*)0; mesureData->storedMarks = g_list_append(mesureData->storedMarks, (gpointer)mark); putMarkDot(mesureData->data, node, type); glFlush(); updateMarkList(mesureData->data, mesureData->storedMarks); } /* Method that remove a dot mark to the list of drawn marks. The removed mark is selected by its VisuNode. */ void removeMarkDotFromList(PickMesure *mesureData, VisuNode *node) { GList *list; struct MarkInfo_struct *mark; g_return_if_fail(node && mesureData); mark = (struct MarkInfo_struct*)0; list = mesureData->storedMarks; while (list) { if (((struct MarkInfo_struct*)list->data)->node1 == node && ((struct MarkInfo_struct*)list->data)->node2 == (VisuNode*)0) { mark = (struct MarkInfo_struct*)list->data; list = (GList*)0; } else list = g_list_next(list); } g_return_if_fail(mark); mesureData->storedMarks = g_list_remove(mesureData->storedMarks, mark); putMarkDot(mesureData->data, node, mark->type); glFlush(); g_free(mark); updateMarkList(mesureData->data, mesureData->storedMarks); } /* Method that add a distance mark to the list of drawn marks. The given new mark is drawn and the opengl list is updated for future use. */ void addMarkDistanceToList(PickMesure *mesureData, VisuNode *nodeRef, VisuNode *node, PickMesureMarkType type) { struct MarkInfo_struct *mark; g_return_if_fail(type > PICK_MESURE_END_MARK_DOT && type < PICK_MESURE_END_MARK_LINK && nodeRef && node && mesureData); if (!mesureData->storeDistance) return; mark = g_malloc(sizeof(struct MarkInfo_struct)); mark->type = type; mark->node1 = nodeRef; mark->idNode1 = nodeRef->number; mark->node2 = node; mark->idNode2 = node->number; mesureData->storedMarks = g_list_append(mesureData->storedMarks, (gpointer)mark); putMarkDistance(mesureData->data, nodeRef, node, type); glFlush(); updateMarkList(mesureData->data, mesureData->storedMarks); } /* Method that removes all distance marks from the list of drawn marks. */ gboolean pickMesureRemove_allDistanceMarks(PickMesure *mesureData) { GList *list, *rmList; struct MarkInfo_struct *mark; g_return_val_if_fail(mesureData, FALSE); mark = (struct MarkInfo_struct*)0; list = mesureData->storedMarks; rmList = (GList*)0; while (list) { if (((struct MarkInfo_struct*)list->data)->type > PICK_MESURE_END_MARK_DOT && ((struct MarkInfo_struct*)list->data)->type < PICK_MESURE_END_MARK_LINK) rmList = g_list_append(rmList, list->data); list = g_list_next(list); } if (!rmList) return FALSE; list = rmList; while (list) { mark = (struct MarkInfo_struct*)list->data; mesureData->storedMarks = g_list_remove(mesureData->storedMarks, mark); g_free(mark); list = g_list_next(list); } g_list_free(rmList); updateMarkList(mesureData->data, mesureData->storedMarks); return TRUE; } void marksAndMesures(const VisuPick *info, gpointer data) { double dx, dy, dz, dr, dx1, dy1, dz1, dr1, dx2, dy2, dz2, dr2; double ang; float posRef1[3], posRef2[3], posSelect[3]; PickMesure *mesureData; g_return_if_fail(info && data); mesureData = data; g_return_if_fail(mesureData->data == info->data); mesureData->newValuesAvailable = TRUE; if (mesureData->formatFlag) { if (!mesureData->info) mesureData->info = g_string_new(""); else mesureData->info = g_string_erase(mesureData->info, 0, -1); if (!mesureData->errors) mesureData->errors = g_string_new(""); else mesureData->errors = g_string_erase(mesureData->errors, 0, -1); } mesureData->selected = (VisuNode*)0; if (info->button == 1) { if (info->node) { mesureData->selected = info->node; mesureData->idSelected = info->node->number; if (mesureData->ref1) addMarkDistanceToList(mesureData, mesureData->ref1, info->node, PICK_MESURE_MARK_DISTANCE); } else { if (mesureData->formatFlag) mesureData->errors = g_string_append(mesureData->errors, _("You picked nothing.\n")); mesureData->selected = (VisuNode*)0; } } else if (info->button == 2) { if (!(info->shiftMod)) { if (info->node) { if (mesureData->ref2 == info->node) { if (mesureData->formatFlag) mesureData->errors = g_string_append(mesureData->errors, _("1st reference node should be distinct\n" "from 2nd one.\n")); } else { if (mesureData->ref1) removeMarkDotFromList(mesureData, mesureData->ref1); mesureData->xRef1 = info->x; mesureData->yRef1 = info->y; mesureData->ref1 = info->node; mesureData->idRef1 = info->node->number; addMarkDotToList(mesureData, mesureData->ref1, PICK_MESURE_MARK_BIG_SQUARE); } } else { if (mesureData->formatFlag) mesureData->errors = g_string_append(mesureData->errors, _("Unset reference 1.\n")); if (mesureData->ref1) removeMarkDotFromList(mesureData, mesureData->ref1); mesureData->ref1 = (VisuNode*)0; if (mesureData->ref2) removeMarkDotFromList(mesureData, mesureData->ref2); mesureData->ref2 = (VisuNode*)0; } } else { if (mesureData->ref2) removeMarkDotFromList(mesureData, mesureData->ref2); mesureData->ref2 = (VisuNode*)0; if (info->node) { if (!mesureData->ref1) { if (mesureData->formatFlag) mesureData->errors = g_string_append(mesureData->errors, _("Unable to set reference 2\n" "without existing reference 1, use\n" "middle button alone to set reference 1.\n")); } else if (mesureData->ref1 == info->node) { if (mesureData->formatFlag) mesureData->errors = g_string_append(mesureData->errors, _("2nd reference node should be distinct\n" "from 1st one.\n")); } else { mesureData->xRef2 = info->x; mesureData->yRef2 = info->y; mesureData->ref2 = info->node; mesureData->idRef2 = info->node->number; addMarkDotToList(mesureData, mesureData->ref2, PICK_MESURE_MARK_SMALL_SQUARE); } } else { if (mesureData->formatFlag) mesureData->errors = g_string_append(mesureData->errors, _("Unset reference 2.\n")); } } } else { DBG_fprintf(stderr, "Mesure pick : unknown clic %d %d .\n", info->button, info->shiftMod); mesureData->newValuesAvailable = FALSE; return; } if (!mesureData->formatFlag) return; /* Create a string with informations. */ if (mesureData->ref1) { g_string_append_printf(mesureData->info, _("Reference node #%d\n" " x = %7.3f\n" " y = %7.3f\n" " z = %7.3f\n"), mesureData->ref1->number, mesureData->ref1->x, mesureData->ref1->y, mesureData->ref1->z); } if (mesureData->ref2) { visuDataGet_nodePosition(mesureData->data, mesureData->ref1, posRef1); visuDataGet_nodePosition(mesureData->data, mesureData->ref2, posRef2); dx = posRef2[0] - posRef1[0]; dy = posRef2[1] - posRef1[1]; dz = posRef2[2] - posRef1[2]; g_string_append_printf(mesureData->info, _("2nd Reference node #%d\n" " x = %7.3f dx = %7.3f\n" " y = %7.3f dy = %7.3f\n" " z = %7.3f dz = %7.3f\n"), mesureData->ref2->number, mesureData->ref2->x, dx, mesureData->ref2->y, dy, mesureData->ref2->z, dz); dr = sqrt(dx*dx + dy*dy + dz*dz); if (mesureData->selected) g_string_append_printf(mesureData->info, _(" i.e. dr = %7.3f\n"), dr); else g_string_append_printf(mesureData->info, _(" i.e. dr = %7.3f"), dr); } if (mesureData->selected) { if (!mesureData->ref2) { if (mesureData->ref1) { visuDataGet_nodePosition(mesureData->data, mesureData->selected, posSelect); visuDataGet_nodePosition(mesureData->data, mesureData->ref1, posRef1); dx = posSelect[0] - posRef1[0]; dy = posSelect[1] - posRef1[1]; dz = posSelect[2] - posRef1[2]; g_string_append_printf(mesureData->info, _("Newly picked node #%d\n" " x = %7.3f dx = %7.3f\n" " y = %7.3f dy = %7.3f\n" " z = %7.3f dz = %7.3f\n"), mesureData->selected->number, mesureData->selected->x, dx, mesureData->selected->y, dy, mesureData->selected->z, dz); dr = sqrt(dx*dx + dy*dy + dz*dz); g_string_append_printf(mesureData->info, _(" i.e. dr = %7.3f"), dr); } else g_string_append_printf(mesureData->info, _("Newly picked node #%d\n" " x = %7.3f\n" " y = %7.3f\n" " z = %7.3f\n"), mesureData->selected->number, mesureData->selected->x, mesureData->selected->y, mesureData->selected->z ); } else { visuDataGet_nodePosition(mesureData->data, mesureData->selected, posSelect); visuDataGet_nodePosition(mesureData->data, mesureData->ref1, posRef1); visuDataGet_nodePosition(mesureData->data, mesureData->ref2, posRef2); dx1 = posSelect[0] - posRef1[0]; dy1 = posSelect[1] - posRef1[1]; dz1 = posSelect[2] - posRef1[2]; dx2 = posRef2[0] - posRef1[0]; dy2 = posRef2[1] - posRef1[1]; dz2 = posRef2[2] - posRef1[2]; g_string_append_printf(mesureData->info, _("Newly picked node #%d\n" " x = %7.3f dx1 = %7.3f dx2 = %7.3f\n" " y = %7.3f dy1 = %7.3f dx2 = %7.3f\n" " z = %7.3f dz1 = %7.3f dx2 = %7.3f\n"), mesureData->selected->number, mesureData->selected->x, dx1, dx2, mesureData->selected->y, dy1, dy2, mesureData->selected->z, dz1, dz2); dr1 = sqrt(dx1*dx1 + dy1*dy1 + dz1*dz1); dr2 = sqrt(dx2*dx2 + dy2*dy2 + dz2*dz2); ang = acos((dx2*dx1+dy2*dy1+dz2*dz1)/(dr2*dr1))/PI180; g_string_append_printf(mesureData->info, _(" i.e. dr = %7.3f dr2 = %7.3f \n" " (Ref-Ref2, Ref-New) = %5.2f degrees"), dr1, dr2, ang); } } DBG_fprintf(stderr, "Pick mesure info : %s\n", mesureData->info->str); DBG_fprintf(stderr, "Pick mesure error : %s\n", mesureData->errors->str); } gchar* getPickMesureInfos(PickMesure *mesureData) { g_return_val_if_fail(mesureData, (gchar*)0); if (!mesureData->info || !mesureData->formatFlag) return (gchar*)0; return mesureData->info->str; } gchar* getPickMesureErrors(PickMesure *mesureData) { g_return_val_if_fail(mesureData, (gchar*)0); if (!mesureData->errors || !mesureData->formatFlag) return (gchar*)0; return mesureData->errors->str; } gboolean pickMesureGet_newsAvailable(PickMesure *mesureData) { g_return_val_if_fail(mesureData, FALSE); return mesureData->newValuesAvailable; } struct MarkInfo_struct* pickMesureCopyMark(struct MarkInfo_struct* mark) { struct MarkInfo_struct *newMark; g_return_val_if_fail(mark, (struct MarkInfo_struct*)0); newMark = g_malloc(sizeof(struct MarkInfo_struct)); newMark->type = mark->type; newMark->node1 = mark->node1; newMark->idNode1 = mark->idNode1; newMark->node2 = mark->node2; newMark->idNode2 = mark->idNode2; newMark->text = (gchar*)0; return newMark; } void pickMesureUpdate(VisuData *newData, VisuData *oldData) { GList *list; PickMesure *newPick, *oldPick; struct MarkInfo_struct* mark, *newMark; gboolean remove; if (!newData || !oldData) return; DBG_fprintf(stderr, "Visu PickMesure : updating list of marks.\n"); newPick = (PickMesure*)visuDataGet_property(newData, "pickMesure_data"); oldPick = (PickMesure*)visuDataGet_property(oldData, "pickMesure_data"); g_return_if_fail(newPick && oldPick); /* Try to match previous marks on new VisuData. */ list = oldPick->storedMarks; while (list) { mark = (struct MarkInfo_struct*)list->data; DBG_fprintf(stderr, " | old mark %p of type %d.\n", (gpointer)mark, mark->type); remove = FALSE; /* We remove all dot marks. */ /* If the distance mark can't match on new data, we remove also. */ if (mark->type < PICK_MESURE_END_MARK_DOT) { mark->node1 = visuDataGet_nodeFromNumber(newData, mark->idNode1); remove = remove || !mark->node1; } else if (mark->type > PICK_MESURE_END_MARK_DOT && mark->type < PICK_MESURE_END_MARK_LINK) { mark->node1 = visuDataGet_nodeFromNumber(newData, mark->idNode1); mark->node2 = visuDataGet_nodeFromNumber(newData, mark->idNode2); remove = remove || !(mark->node1 && mark->node2); } if (!remove && newPick != oldPick) { /* We keep it, and add it in the list of newPick. */ newMark = pickMesureCopyMark(mark); newPick->storedMarks = g_list_prepend(newPick->storedMarks, newMark); DBG_fprintf(stderr, " | adding new mark %p of type %d.\n", (gpointer)newMark, newMark->type); } if (remove && newPick == oldPick) { /* We remove it, from newPick. */ DBG_fprintf(stderr, " | delete old mark %p of type %d.\n", (gpointer)mark, mark->type); newPick->storedMarks = g_list_delete_link(newPick->storedMarks, list); } list = g_list_next(list); } DBG_fprintf(stderr, " | New mark list is pointing to %p.\n", (gpointer)newPick->storedMarks); if (oldPick->ref1) { DBG_fprintf(stderr, "Visu PickMesure : trying to match ref1 node (id: %d).\n", oldPick->idRef1); newPick->ref1 = visuDataGet_nodeFromNumber(newData, oldPick->idRef1); newPick->idRef1 = oldPick->idRef1; } if (oldPick->ref2) { DBG_fprintf(stderr, "Visu PickMesure : trying to match ref2 node (id: %d).\n", oldPick->idRef2); newPick->ref2 = visuDataGet_nodeFromNumber(newData, oldPick->idRef2); newPick->idRef2 = oldPick->idRef2; } if (oldPick->selected) { DBG_fprintf(stderr, "Visu PickMesure : trying to match selected node (id: %d).\n", oldPick->idSelected); newPick->selected = visuDataGet_nodeFromNumber(newData, oldPick->idSelected); newPick->idSelected = oldPick->idSelected; } newPick->storeDistance = oldPick->storeDistance; newPick->formatFlag = oldPick->formatFlag; updateMarkList(newPick->data, newPick->storedMarks); } VisuNode* pickMesureGet_selectedNode(PickMesure *mesureData) { g_return_val_if_fail(mesureData, (VisuNode*)0); return mesureData->selected; } VisuNode* pickMesureGet_firstReference(PickMesure *mesureData) { g_return_val_if_fail(mesureData, (VisuNode*)0); return mesureData->ref1; } void updateListOnNodeChange(VisuData *dataObj, gpointer data) { g_return_if_fail(data); DBG_fprintf(stderr, "Visu PickMesure : caught a node rendering" " changing signal (%p).\n", data); updateMarkList(dataObj, ((PickMesure*)data)->storedMarks); } void updateListOnElementChange(VisuData *dataObj, VisuElement *ele, gpointer data) { g_return_if_fail(data); DBG_fprintf(stderr, "Visu PickMesure : caught an element rendering" " changing signal (%p).\n", data); updateMarkList(dataObj, ((PickMesure*)data)->storedMarks); } void pickMesureSet_storeDistance(PickMesure *mesureData, gboolean storeDistance) { g_return_if_fail(mesureData); DBG_fprintf(stderr, "Visu PickMesure : set store distance to %d.\n", (int)storeDistance); mesureData->storeDistance = storeDistance; if (storeDistance) openGLText_initFontList(); } void pickMesureSet_formatedOutput(PickMesure *mesureData, gboolean formatedOutput) { g_return_if_fail(mesureData); DBG_fprintf(stderr, "Visu PickMesure : set formated output to %d.\n", (int)formatedOutput); mesureData->formatFlag = formatedOutput; } static void pickMesureRebuild_list(VisuData *dataObj) { PickMesure *pickMesure; pickMesure = visuDataGet_property(dataObj, "pickMesure_data"); if (!pickMesure) return; DBG_fprintf(stderr, "Visu PickMesure : rebuilding object list for PickMesure %p.\n", (gpointer)pickMesure); updateMarkList(dataObj, pickMesure->storedMarks); }