Logo Search packages:      
Sourcecode: v-sim version File versions  Download package

visu_pickMesure.c

/*   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 <GL/gl.h>
#include <GL/glu.h> 

#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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <glib.h>

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.
 */
00118 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);
}

Generated by  Doxygen 1.6.0   Back to index