Skip to content
Snippets Groups Projects
Forked from gmsh / gmsh
18762 commits behind the upstream repository.
  • Christophe Geuzaine's avatar
    09149e34
    · 09149e34
    Christophe Geuzaine authored
    This patch fixes an old design flaw in the post-processing module,
    namely that we used a list of Post_View objects instead of a list of
    pointers to Post_View objects in CTX.post.list.
    
    This had many annoying consequences, in particular the fact that we
    needed to be extra careful every time the list was reallocated (as
    pointers to the list elements would become invalid).
    
    I tried very hard to change the code everywhere it should be changed,
    but I might have missed something. Please let me know if you see
    anything suspicious (like a crash when you duplicate/remove/combine/...
    post-processing views).
    09149e34
    History
    Christophe Geuzaine authored
    This patch fixes an old design flaw in the post-processing module,
    namely that we used a list of Post_View objects instead of a list of
    pointers to Post_View objects in CTX.post.list.
    
    This had many annoying consequences, in particular the fact that we
    needed to be extra careful every time the list was reallocated (as
    pointers to the list elements would become invalid).
    
    I tried very hard to change the code everywhere it should be changed,
    but I might have missed something. Please let me know if you see
    anything suspicious (like a crash when you duplicate/remove/combine/...
    post-processing views).
Skin.cpp 8.18 KiB
// $Id: Skin.cpp,v 1.29 2004-11-25 02:10:40 geuzaine Exp $
//
// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
// 
// Please report all bugs and problems to <gmsh@geuz.org>.

#include "Plugin.h"
#include "Skin.h"
#include "List.h"
#include "Tree.h"
#include "Views.h"
#include "Context.h"
#include "Malloc.h"

extern Context_T CTX;

List_T *GMSH_SkinPlugin::_list = NULL;
Tree_T *GMSH_SkinPlugin::_skin = NULL;
int *GMSH_SkinPlugin::_nbList = NULL;
int GMSH_SkinPlugin::_nbNod = 0;
int GMSH_SkinPlugin::_nbComp = 0;
int GMSH_SkinPlugin::_nbTimeStep = 0;

StringXNumber SkinOptions_Number[] = {
  {GMSH_FULLRC, "iView", NULL, -1.}
};

extern "C"
{
  GMSH_Plugin *GMSH_RegisterSkinPlugin()
  {
    return new GMSH_SkinPlugin();
  }
}

GMSH_SkinPlugin::GMSH_SkinPlugin()
{
  ;
}

void GMSH_SkinPlugin::getName(char *name) const
{
  strcpy(name, "Skin");
}

void GMSH_SkinPlugin::getInfos(char *author, char *copyright, char *help_text) const
{
  strcpy(author, "C. Geuzaine (geuz@geuz.org)");
  strcpy(copyright, "DGR (www.multiphysics.com)");
  strcpy(help_text,
         "Plugin(Skin) extracts the skin (the boundary) of\n"
	 "the view `iView'. If `iView' < 0, the plugin is run\n"
	 "on the current view.\n"
	 "\n"
	 "Plugin(Skin) creates one new view.\n");
}

int GMSH_SkinPlugin::getNbOptions() const
{
  return sizeof(SkinOptions_Number) / sizeof(StringXNumber);
}

StringXNumber *GMSH_SkinPlugin::getOption(int iopt)
{
  return &SkinOptions_Number[iopt];
}

void GMSH_SkinPlugin::catchErrorMessage(char *errorMessage) const
{
  strcpy(errorMessage, "Skin failed...");
}

int GMSH_SkinPlugin::fcmpElm(const void *a, const void *b)
{
  Elm *e1 = (Elm *)a, *e2 = (Elm *)b;
  double s1, s2, TOL = CTX.lc * 1.e-12;
  int i;

  s1 = s2 = 0.0;
  for(i = 0; i < _nbNod; i++) {
    s1 += e1->coord[i];
    s2 += e2->coord[i];
  }
  if(s1 - s2 > TOL)
    return 1;
  else if(s1 - s2 < -TOL)
    return -1;
  s1 = s2 = 0.0;
  for(i = 0; i < _nbNod; i++) {
    s1 += e1->coord[_nbNod + i];
    s2 += e2->coord[_nbNod + i];
  }
  if(s1 - s2 > TOL)
    return 1;
  else if(s1 - s2 < -TOL)
    return -1;
  s1 = s2 = 0.0;
  for(i = 0; i < _nbNod; i++) {
    s1 += e1->coord[2 * _nbNod + i];
    s2 += e2->coord[2 * _nbNod + i];
  }
  if(s1 - s2 > TOL)
    return 1;
  else if(s1 - s2 < -TOL)
    return -1;

  return 0;
}

void GMSH_SkinPlugin::addInView(void *a, void *b)
{
  Elm *e = (Elm *)a;

  for(int i = 0; i < 3 * _nbNod; i++)
    List_Add(_list, &e->coord[i]);
  for(int ts = 0; ts < _nbTimeStep; ts++)
    for(int k = 0; k < _nbNod * _nbComp; k++)
      List_Add(_list, &e->val[_nbNod * _nbComp * ts + k]);
  Free(e->val);
  (*_nbList)++;
}

void GMSH_SkinPlugin::skinList(List_T *inList, int inNbList, 
			       int inNbNod, int inNbFac, int fxn[6][4])
{
  if(!inNbList)
    return;

  int nb = List_Nbr(inList) / inNbList;
  for(int i = 0; i < List_Nbr(inList); i += nb) {
    double *coord = (double *)List_Pointer_Fast(inList, i);
    double *val = (double *)List_Pointer_Fast(inList, i + 3 * inNbNod);
    for(int j = 0; j < inNbFac; j++) {
      Elm e, *pe;
      for(int k = 0; k < _nbNod; k++) {
	e.coord[k] = coord[fxn[j][k]]; // x
	e.coord[_nbNod + k] = coord[inNbNod + fxn[j][k]]; // y
	e.coord[2 * _nbNod + k] = coord[2 * inNbNod + fxn[j][k]]; // z
      }
      if(!(pe = (Elm *)Tree_PQuery(_skin, &e))) {
	e.val = (double *)Malloc(_nbNod * _nbComp * _nbTimeStep * sizeof(double));
	for(int k = 0; k < _nbNod; k++)
	  for(int ts = 0; ts < _nbTimeStep; ts++)
	    for(int n = 0; n < _nbComp; n++)
	      e.val[_nbNod * _nbComp * ts + _nbComp * k + n] =
		val[inNbNod * _nbComp * ts + _nbComp * fxn[j][k] + n];
        Tree_Add(_skin, &e);
      }
      else {
        Free(pe->val);
        Tree_Suppress(_skin, pe);
      }
    }
  }
}

Post_View *GMSH_SkinPlugin::execute(Post_View * v)
{
  int iView = (int)SkinOptions_Number[0].def;

  if(iView < 0)
    iView = v ? v->Index : 0;

  if(!List_Pointer_Test(CTX.post.list, iView)) {
    Msg(GERROR, "View[%d] does not exist", iView);
    return v;
  }

  Post_View *v1 = *(Post_View **)List_Pointer(CTX.post.list, iView);
  Post_View *v2 = BeginView(1);

  _nbTimeStep = v1->NbTimeStep;

  int skinTri[6][4] = {{0,1,-1,-1}, {1,2,-1,-1}, {2,0,-1,-1}};
  int skinQua[6][4] = {{0,1,-1,-1}, {1,2,-1,-1}, {2,3,-1,-1}, {3,0,-1,-1}};
  int skinTet[6][4] = {{0,1,3,-1}, {0,2,1,-1}, {0,3,2,-1}, {1,2,3,-1}};
  int skinHex[6][4] = {{0,1,5,4}, {0,3,2,1}, {0,4,7,3},
		       {1,2,6,5}, {2,3,7,6}, {4,5,6,7}};
  int skinPri1[6][4] = {{0,1,4,3}, {0,3,5,2}, {1,2,5,4}};
  int skinPri2[6][4] = {{0,2,1,-1}, {3,4,5,-1}};
  int skinPyr1[6][4] = {{0,3,2,1}};
  int skinPyr2[6][4] = {{0,1,4,-1}, {0,4,3,-1}, {1,2,4,-1}, {2,3,4,-1}};

  // Generate lines
  _nbNod = 2;
  // scalar
  _skin = Tree_Create(sizeof(Elm), fcmpElm);
  _list = v2->SL; _nbList = &v2->NbSL; _nbComp = 1;
  skinList(v1->ST, v1->NbST, 3, 3, skinTri);
  skinList(v1->SQ, v1->NbSQ, 4, 4, skinQua);
  Tree_Action(_skin, addInView);
  Tree_Delete(_skin);
  // vector
  _skin = Tree_Create(sizeof(Elm), fcmpElm);
  _list = v2->VL; _nbList = &v2->NbVL; _nbComp = 3;
  skinList(v1->VT, v1->NbVT, 3, 3, skinTri);
  skinList(v1->VQ, v1->NbVQ, 4, 4, skinQua);
  Tree_Action(_skin, addInView);
  Tree_Delete(_skin);
  // tensor
  _skin = Tree_Create(sizeof(Elm), fcmpElm);
  _list = v2->TL; _nbList = &v2->NbTL; _nbComp = 9;
  skinList(v1->TT, v1->NbTT, 3, 3, skinTri);
  skinList(v1->TQ, v1->NbTQ, 4, 4, skinQua);
  Tree_Action(_skin, addInView);
  Tree_Delete(_skin);

  // Generate triangles
  _nbNod = 3;
  // scalar
  _skin = Tree_Create(sizeof(Elm), fcmpElm);
  _list = v2->ST; _nbList = &v2->NbST; _nbComp = 1;
  skinList(v1->SS, v1->NbSS, 4, 4, skinTet);
  skinList(v1->SI, v1->NbSI, 6, 2, skinPri2);
  skinList(v1->SY, v1->NbSY, 5, 4, skinPyr2);
  Tree_Action(_skin, addInView);
  Tree_Delete(_skin);
  // vector
  _skin = Tree_Create(sizeof(Elm), fcmpElm);
  _list = v2->VT; _nbList = &v2->NbVT; _nbComp = 3;
  skinList(v1->VS, v1->NbVS, 4, 4, skinTet);
  skinList(v1->VI, v1->NbVI, 6, 2, skinPri2);
  skinList(v1->VY, v1->NbVY, 5, 4, skinPyr2);
  Tree_Action(_skin, addInView);
  Tree_Delete(_skin);
  // tensor
  _skin = Tree_Create(sizeof(Elm), fcmpElm);
  _list = v2->TT; _nbList = &v2->NbTT; _nbComp = 9;
  skinList(v1->TS, v1->NbTS, 4, 4, skinTet);
  skinList(v1->TI, v1->NbTI, 6, 2, skinPri2);
  skinList(v1->TY, v1->NbTY, 5, 4, skinPyr2);
  Tree_Action(_skin, addInView);
  Tree_Delete(_skin);

  // Generate quads
  _nbNod = 4;
  // scalar
  _skin = Tree_Create(sizeof(Elm), fcmpElm);
  _list = v2->SQ; _nbList = &v2->NbSQ; _nbComp = 1;
  skinList(v1->SH, v1->NbSH, 8, 6, skinHex);
  skinList(v1->SI, v1->NbSI, 6, 3, skinPri1);
  skinList(v1->SY, v1->NbSY, 5, 1, skinPyr1);
  Tree_Action(_skin, addInView);
  Tree_Delete(_skin);
  // vector
  _skin = Tree_Create(sizeof(Elm), fcmpElm);
  _list = v2->VQ; _nbList = &v2->NbVQ; _nbComp = 3;
  skinList(v1->VH, v1->NbVH, 8, 6, skinHex);
  skinList(v1->VI, v1->NbVI, 6, 3, skinPri1);
  skinList(v1->VY, v1->NbVY, 5, 1, skinPyr1);
  Tree_Action(_skin, addInView);
  Tree_Delete(_skin);
  // tensor
  _skin = Tree_Create(sizeof(Elm), fcmpElm);
  _list = v2->TQ; _nbList = &v2->NbTQ; _nbComp = 9;
  skinList(v1->TH, v1->NbTH, 8, 6, skinHex);
  skinList(v1->TI, v1->NbTI, 6, 3, skinPri1);
  skinList(v1->TY, v1->NbTY, 5, 1, skinPyr1);
  Tree_Action(_skin, addInView);
  Tree_Delete(_skin);

  // copy time data
  for(int i = 0; i < List_Nbr(v1->Time); i++)
    List_Add(v2->Time, List_Pointer(v1->Time, i));
  // finalize
  char name[1024], filename[1024];
  sprintf(name, "%s_Skin", v1->Name);
  sprintf(filename, "%s_Skin.pos", v1->Name);
  EndView(v2, 1, filename, name);
  return v2;
}