Forked from
gmsh / gmsh
19857 commits behind the upstream repository.
-
Christophe Geuzaine authored
Fix whitespace in copyright headers
Christophe Geuzaine authoredFix whitespace in copyright headers
Views.cpp 38.89 KiB
// $Id: Views.cpp,v 1.93 2003-03-21 00:52:35 geuzaine Exp $
//
// Copyright (C) 1997-2003 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 <set>
#include "Gmsh.h"
#include "Numeric.h"
#include "Views.h"
#include "Context.h"
#include "Options.h"
#include "ColorTable.h"
extern Context_T CTX;
#define VAL_INF 1.e200
// Static reference view
Post_View *Post_ViewReference = NULL;
// FIXME: the whole View interface should be rewritten in C++...
int fcmpPostViewNum(const void *v1, const void *v2)
{
return (((Post_View *) v1)->Num - ((Post_View *) v2)->Num);
}
int fcmpPostViewDuplicateOf(const void *v1, const void *v2)
{
return (((Post_View *) v1)->DuplicateOf - ((Post_View *) v2)->DuplicateOf);
}
Post_View *BeginView(int allocate)
{
Post_View vv, *v;
static int UniqueNum = 0;
int i;
if(!CTX.post.list)
CTX.post.list = List_Create(100, 1, sizeof(Post_View));
if(!CTX.post.force_num) {
vv.Num = ++UniqueNum; // each view _must_ have a unique number
List_Add(CTX.post.list, &vv);
}
else {
vv.Num = CTX.post.force_num;
List_Replace(CTX.post.list, &vv, fcmpPostViewNum);
}
i = List_ISearch(CTX.post.list, &vv, fcmpPostViewNum);
v = (Post_View *) List_Pointer(CTX.post.list, i);
v->Index = i;
v->Dirty = 1;
v->DisplayListNum = -1;
v->NbTimeStep = 0;
v->NbSP = v->NbVP = v->NbTP = 0;
v->NbSL = v->NbVL = v->NbTL = 0;
v->NbST = v->NbVT = v->NbTT = 0;
v->NbSQ = v->NbVQ = v->NbTQ = 0;
v->NbSS = v->NbVS = v->NbTS = 0;
v->NbSH = v->NbVH = v->NbTH = 0;
v->NbSI = v->NbVI = v->NbTI = 0;
v->NbSY = v->NbVY = v->NbTY = 0;
v->NbT2 = v->NbT3 = 0;
if(allocate) {
v->DataSize = sizeof(double);
v->Time = List_Create(100, 1000, sizeof(double));
v->SP = List_Create(100, 1000, sizeof(double));
v->VP = List_Create(100, 1000, sizeof(double));
v->TP = List_Create(100, 1000, sizeof(double));
v->SL = List_Create(100, 1000, sizeof(double));
v->VL = List_Create(100, 1000, sizeof(double));
v->TL = List_Create(100, 1000, sizeof(double));
v->ST = List_Create(100, 1000, sizeof(double));
v->VT = List_Create(100, 1000, sizeof(double));
v->TT = List_Create(100, 1000, sizeof(double));
v->SQ = List_Create(100, 1000, sizeof(double));
v->VQ = List_Create(100, 1000, sizeof(double));
v->TQ = List_Create(100, 1000, sizeof(double));
v->SS = List_Create(100, 1000, sizeof(double));
v->VS = List_Create(100, 1000, sizeof(double));
v->TS = List_Create(100, 1000, sizeof(double));
v->SH = List_Create(100, 1000, sizeof(double));
v->VH = List_Create(100, 1000, sizeof(double));
v->TH = List_Create(100, 1000, sizeof(double));
v->SI = List_Create(100, 1000, sizeof(double));
v->VI = List_Create(100, 1000, sizeof(double));
v->TI = List_Create(100, 1000, sizeof(double));
v->SY = List_Create(100, 1000, sizeof(double));
v->VY = List_Create(100, 1000, sizeof(double));
v->TY = List_Create(100, 1000, sizeof(double));
v->T2D = List_Create(10, 100, sizeof(double));
v->T2C = List_Create(100, 1000, sizeof(char));
v->T3D = List_Create(10, 100, sizeof(double));
v->T3C = List_Create(100, 1000, sizeof(char));
}
else {
v->Time = NULL;
v->SP = v->VP = v->TP = NULL;
v->SL = v->VL = v->TL = NULL;
v->ST = v->VT = v->TT = NULL;
v->SQ = v->VQ = v->TQ = NULL;
v->SS = v->VS = v->TS = NULL;
v->SH = v->VH = v->TH = NULL;
v->SI = v->VI = v->TI = NULL;
v->SY = v->VY = v->TY = NULL;
v->T2D = v->T2C = NULL;
v->T3D = v->T3C = NULL;
}
// Copy all options from the reference view initialized in InitOptions()
CopyViewOptions(Post_ViewReference, v);
v->Changed = 1;
v->Links = 0;
v->DuplicateOf = 0;
v->ScalarOnly = 1;
v->TextOnly = 1;
v->normals = NULL;
v->Min = VAL_INF;
v->Max = -VAL_INF;
for(i = 0; i < 3; i++) {
v->BBox[2 * i] = VAL_INF;
v->BBox[2 * i + 1] = -VAL_INF;
}
return v;
}
void Stat_Element(Post_View * v, int type, int nbnod, int N,
double *X, double *Y, double *Z, double *V)
{
int i;
double l0;
switch (type) {
case 0: // scalar
if(v->Min == VAL_INF || v->Max == -VAL_INF) {
v->Min = V[0];
v->Max = V[0];
v->NbTimeStep = N / nbnod;
}
else if(N / nbnod < v->NbTimeStep)
v->NbTimeStep = N / nbnod;
for(i = 0; i < N; i++) {
if(V[i] < v->Min)
v->Min = V[i];
if(V[i] > v->Max)
v->Max = V[i];
}
break;
case 1: // vector
if(v->Min == VAL_INF || v->Max == -VAL_INF) {
l0 = sqrt(DSQR(V[0]) + DSQR(V[1]) + DSQR(V[2]));
v->Min = l0;
v->Max = l0;
v->NbTimeStep = N / (3 * nbnod);
}
else if(N / (3 * nbnod) < v->NbTimeStep)
v->NbTimeStep = N / (3 * nbnod);
for(i = 0; i < N; i += 3) {
l0 = sqrt(DSQR(V[i]) + DSQR(V[i + 1]) + DSQR(V[i + 2]));
if(l0 < v->Min)
v->Min = l0;
if(l0 > v->Max)
v->Max = l0;
}
v->ScalarOnly = 0;
break;
case 2: // tensor - TODO!
if(v->Min == VAL_INF || v->Max == -VAL_INF) {
l0 = sqrt(DSQR(V[0]) + DSQR(V[4]) + DSQR(V[8]));
v->Min = l0;
v->Max = l0;
v->NbTimeStep = N / (9 * nbnod);
}
else if(N / (9 * nbnod) < v->NbTimeStep)
v->NbTimeStep = N / (9 * nbnod);
for(i = 0; i < N; i += 9) {
l0 = sqrt(DSQR(V[i]) + DSQR(V[i + 4]) + DSQR(V[i + 8]));
if(l0 < v->Min)
v->Min = l0;
if(l0 > v->Max)
v->Max = l0;
}
v->ScalarOnly = 0;
break;
}
for(i = 0; i < nbnod; i++) {
if(X[i] < v->BBox[0])
v->BBox[0] = X[i];
if(X[i] > v->BBox[1])
v->BBox[1] = X[i];
if(Y[i] < v->BBox[2])
v->BBox[2] = Y[i];
if(Y[i] > v->BBox[3])
v->BBox[3] = Y[i];
if(Z[i] < v->BBox[4])
v->BBox[4] = Z[i];
if(Z[i] > v->BBox[5])
v->BBox[5] = Z[i];
}
v->TextOnly = 0;
}
void Stat_List(Post_View * v, List_T * listelm, int type, int nbelm,
int nbnod)
{
int i, nb;
if(nbelm) {
nb = List_Nbr(listelm) / nbelm;
for(i = 0; i < List_Nbr(listelm); i += nb)
Stat_Element(v, type, nbnod, nb - 3 * nbnod,
(double *)List_Pointer_Fast(listelm, i),
(double *)List_Pointer_Fast(listelm, i + 1 * nbnod),
(double *)List_Pointer_Fast(listelm, i + 2 * nbnod),
(double *)List_Pointer_Fast(listelm, i + 3 * nbnod));
}
}
void EndView(Post_View * v, int add_in_gui, char *file_name, char *name)
{
int i;
double d;
// Points
Stat_List(v, v->SP, 0, v->NbSP, 1);
Stat_List(v, v->VP, 1, v->NbVP, 1);
Stat_List(v, v->TP, 2, v->NbTP, 1);
// Lines
Stat_List(v, v->SL, 0, v->NbSL, 2);
Stat_List(v, v->VL, 1, v->NbVL, 2);
Stat_List(v, v->TL, 2, v->NbTL, 2);
// Triangles
Stat_List(v, v->ST, 0, v->NbST, 3);
Stat_List(v, v->VT, 1, v->NbVT, 3);
Stat_List(v, v->TT, 2, v->NbTT, 3);
// Quadrangles
Stat_List(v, v->SQ, 0, v->NbSQ, 4);
Stat_List(v, v->VQ, 1, v->NbVQ, 4);
Stat_List(v, v->TQ, 2, v->NbTQ, 4);
// Tetrahedra
Stat_List(v, v->SS, 0, v->NbSS, 4);
Stat_List(v, v->VS, 1, v->NbVS, 4);
Stat_List(v, v->TS, 2, v->NbTS, 4);
// Hexahedra
Stat_List(v, v->SH, 0, v->NbSH, 8);
Stat_List(v, v->VH, 1, v->NbVH, 8);
Stat_List(v, v->TH, 2, v->NbTH, 8);
// Prisms
Stat_List(v, v->SI, 0, v->NbSI, 6);
Stat_List(v, v->VI, 1, v->NbVI, 6);
Stat_List(v, v->TI, 2, v->NbTI, 6);
// Pyramids
Stat_List(v, v->SY, 0, v->NbSY, 5);
Stat_List(v, v->VY, 1, v->NbVY, 5);
Stat_List(v, v->TY, 2, v->NbTY, 5);
// Dummy time values if using old parsed format
if(v->Time && !List_Nbr(v->Time)) {
for(i = 0; i < v->NbTimeStep; i++) {
d = (double)i;
List_Add(v->Time, &d);
}
}
opt_view_name(v->Index, GMSH_SET | GMSH_GUI, name);
opt_view_filename(v->Index, GMSH_SET | GMSH_GUI, file_name);
opt_view_nb_timestep(v->Index, GMSH_GUI, 0);
opt_view_timestep(v->Index, GMSH_SET | GMSH_GUI, v->TimeStep);
if(v->Min > v->Max) {
opt_view_min(v->Index, GMSH_SET | GMSH_GUI, 0.);
opt_view_max(v->Index, GMSH_SET | GMSH_GUI, 0.);
}
else {
opt_view_min(v->Index, GMSH_GUI, 0);
opt_view_max(v->Index, GMSH_GUI, 0);
}
opt_view_custom_min(v->Index, GMSH_SET | GMSH_GUI, v->Min);
opt_view_custom_max(v->Index, GMSH_SET | GMSH_GUI, v->Max);
if(CTX.post.smooth)
v->smooth();
#if defined(HAVE_FLTK)
extern int AddViewInUI(int, char *, int);
if(!CTX.post.force_num && add_in_gui)
AddViewInUI(List_Nbr(CTX.post.list), v->Name, v->Num);
#endif
v->Dirty = 0; //the view is complete, we may draw it
}
void DuplicateView(int num, int withoptions)
{
if(!CTX.post.list || num < 0 || num >= List_Nbr(CTX.post.list))
return;
DuplicateView((Post_View *) List_Pointer(CTX.post.list, num), withoptions);
}
void DuplicateView(Post_View * v1, int withoptions)
{
Post_View v, *v2, *v3;
v2 = BeginView(0);
EndView(v2, 0, v1->FileName, v1->Name);
if(!v1->DuplicateOf) {
v2->DuplicateOf = v1->Num;
v1->Links++;
}
else {
v.Num = v1->DuplicateOf;
if(!(v3 = (Post_View *) List_PQuery(CTX.post.list, &v, fcmpPostViewNum))) {
v2->DuplicateOf = v1->Num;
v1->Links++;
}
else {
v2->DuplicateOf = v3->Num;
v3->Links++;
}
}
// When we duplicate a view, we just point to a reference view: we
// DON'T allocate a new data set!
// *INDENT-OFF*
v2->Time = v1->Time;
v2->NbSP = v1->NbSP; v2->SP = v1->SP;
v2->NbVP = v1->NbVP; v2->VP = v1->VP;
v2->NbTP = v1->NbTP; v2->TP = v1->TP;
v2->NbSL = v1->NbSL; v2->SL = v1->SL;
v2->NbVL = v1->NbVL; v2->VL = v1->VL;
v2->NbTL = v1->NbTL; v2->TL = v1->TL;
v2->NbST = v1->NbST; v2->ST = v1->ST;
v2->NbVT = v1->NbVT; v2->VT = v1->VT;
v2->NbTT = v1->NbTT; v2->TT = v1->TT;
v2->NbSQ = v1->NbSQ; v2->SQ = v1->SQ;
v2->NbVQ = v1->NbVQ; v2->VQ = v1->VQ;
v2->NbTQ = v1->NbTQ; v2->TQ = v1->TQ;
v2->NbSS = v1->NbSS; v2->SS = v1->SS;
v2->NbVS = v1->NbVS; v2->VS = v1->VS;
v2->NbTS = v1->NbTS; v2->TS = v1->TS;
v2->NbSH = v1->NbSH; v2->SH = v1->SH;
v2->NbVH = v1->NbVH; v2->VH = v1->VH;
v2->NbTH = v1->NbTH; v2->TH = v1->TH;
v2->NbSI = v1->NbSI; v2->SI = v1->SI;
v2->NbVI = v1->NbVI; v2->VI = v1->VI;
v2->NbTI = v1->NbTI; v2->TI = v1->TI;
v2->NbSY = v1->NbSY; v2->SY = v1->SY;
v2->NbVY = v1->NbVY; v2->VY = v1->VY;
v2->NbTY = v1->NbTY; v2->TY = v1->TY;
v2->NbT2 = v1->NbT2; v2->T2D = v1->T2D; v2->T2C = v1->T2C;
v2->NbT3 = v1->NbT3; v2->T3D = v1->T3D; v2->T3C = v1->T3C;
v2->DataSize = v1->DataSize;
v2->ScalarOnly = v1->ScalarOnly;
v2->TextOnly = v1->TextOnly;
v2->Min = v1->Min;
v2->Max = v1->Max;
v2->NbTimeStep = v1->NbTimeStep;
for(int i=0 ; i<6 ; i++)
v2->BBox[i] = v1->BBox[i];
// *INDENT-ON*
if(withoptions)
CopyViewOptions(v1, v2);
#if defined(HAVE_FLTK)
extern int AddViewInUI(int, char *, int);
AddViewInUI(List_Nbr(CTX.post.list), v2->Name, v2->Num);
#endif
}
bool FreeView(int num)
{
Post_View *v;
Msg(DEBUG, "Trying to free view %d", num);
if(num < 0 || num >= List_Nbr(CTX.post.list)) {
return false;
}
v = (Post_View *) List_Pointer(CTX.post.list, num);
FreeView(v);
List_PSuppress(CTX.post.list, num);
Msg(INFO, "View %d deleted (%d views left)", num, List_Nbr(CTX.post.list));
return true;
}
void FreeView(Post_View * v)
{
Post_View vv, *v2;
int i, numdup, free = 1;
if(v->DuplicateOf) {
vv.Num = v->DuplicateOf;
Msg(DEBUG, "This view is a duplicata");
if(!(v2 = (Post_View *) List_PQuery(CTX.post.list, &vv, fcmpPostViewNum))) {
Msg(DEBUG, " -the original view is gone");
numdup = 0;
for(i = 0; i < List_Nbr(CTX.post.list); i++)
numdup +=
(((Post_View *) List_Pointer(CTX.post.list, i))->DuplicateOf ==
v->DuplicateOf);
if(numdup == 1) {
Msg(DEBUG, " -there are no other duplicata, so I can free");
free = 1;
}
else {
Msg(DEBUG, " -there are still duplicata, so I cannot free");
free = 0;
}
}
else {
v2->Links--;
free = 0;
Msg(DEBUG, " -the original still exists, so I cannot free");
}
}
if(free && !v->Links) {
Msg(DEBUG, "FREEING VIEW");
List_Delete(v->Time);
// *INDENT-OFF*
List_Delete(v->SP); List_Delete(v->VP); List_Delete(v->TP);
List_Delete(v->SL); List_Delete(v->VL); List_Delete(v->TL);
List_Delete(v->ST); List_Delete(v->VT); List_Delete(v->TT);
List_Delete(v->SQ); List_Delete(v->VQ); List_Delete(v->TQ);
List_Delete(v->SS); List_Delete(v->VS); List_Delete(v->TS);
List_Delete(v->SH); List_Delete(v->VH); List_Delete(v->TH);
List_Delete(v->SI); List_Delete(v->VI); List_Delete(v->TI);
List_Delete(v->SY); List_Delete(v->VY); List_Delete(v->TY);
List_Delete(v->T2D); List_Delete(v->T2C);
List_Delete(v->T3D); List_Delete(v->T3C);
// *INDENT-ON*
//set to NULL in case we don't free v (e.g. when doing a 'reload')
//+ the reload does not work (e.g. the file is gone). This way,
//the next Free stuff will still work gracefully.
v->Time = NULL;
v->SP = v->VP = v->TP = NULL;
v->SL = v->VL = v->TL = NULL;
v->ST = v->VT = v->TT = NULL;
v->SQ = v->VQ = v->TQ = NULL;
v->SS = v->VS = v->TS = NULL;
v->SH = v->VH = v->TH = NULL;
v->SI = v->VI = v->TI = NULL;
v->SY = v->VY = v->TY = NULL;
v->T2D = v->T2C = NULL;
v->T3D = v->T3C = NULL;
v->reset_normals();
}
}
void CopyViewOptions(Post_View * src, Post_View * dest)
{
dest->Type = src->Type;
dest->Position[0] = src->Position[0];
dest->Position[1] = src->Position[1];
dest->AutoPosition = src->AutoPosition;
dest->Size[0] = src->Size[0];
dest->Size[1] = src->Size[1];
strcpy(dest->Format, src->Format);
strcpy(dest->AbscissaFormat, src->AbscissaFormat);
strcpy(dest->AbscissaName, src->AbscissaName);
dest->CustomMin = src->CustomMin;
dest->CustomMax = src->CustomMax;
dest->Offset[0] = src->Offset[0];
dest->Offset[1] = src->Offset[1];
dest->Offset[2] = src->Offset[2];
dest->Raise[0] = src->Raise[0];
dest->Raise[1] = src->Raise[1];
dest->Raise[2] = src->Raise[2];
dest->ArrowScale = src->ArrowScale;
dest->Explode = src->Explode;
dest->Visible = src->Visible;
dest->IntervalsType = src->IntervalsType;
dest->SaturateValues = src->SaturateValues;
dest->Boundary = src->Boundary;
dest->NbAbscissa = src->NbAbscissa;
dest->NbIso = src->NbIso;
dest->Light = src->Light;
dest->SmoothNormals = src->SmoothNormals;
dest->AngleSmoothNormals = src->AngleSmoothNormals;
dest->ShowElement = src->ShowElement;
dest->ShowTime = src->ShowTime;
dest->ShowScale = src->ShowScale;
dest->DrawPoints = src->DrawPoints;
dest->DrawLines = src->DrawLines;
dest->DrawTriangles = src->DrawTriangles;
dest->DrawQuadrangles = src->DrawQuadrangles;
dest->DrawTetrahedra = src->DrawTetrahedra;
dest->DrawHexahedra = src->DrawHexahedra;
dest->DrawPrisms = src->DrawPrisms;
dest->DrawPyramids = src->DrawPyramids;
dest->DrawScalars = src->DrawScalars;
dest->DrawVectors = src->DrawVectors;
dest->DrawTensors = src->DrawTensors;
dest->DrawStrings = src->DrawStrings;
dest->TransparentScale = src->TransparentScale;
dest->ScaleType = src->ScaleType;
dest->RangeType = src->RangeType;
dest->ArrowType = src->ArrowType;
dest->ArrowLocation = src->ArrowLocation;
dest->TensorType = src->TensorType;
dest->TimeStep = src->TimeStep;
dest->PointSize = src->PointSize;
dest->LineWidth = src->LineWidth;
dest->PointType = src->PointType;
dest->LineType = src->LineType;
dest->Grid = src->Grid;
ColorTable_Copy(&src->CT);
ColorTable_Paste(&dest->CT);
}
GmshColorTable *Get_ColorTable(int num)
{
Post_View *v;
if(!CTX.post.list)
v = Post_ViewReference;
else
v = (Post_View *) List_Pointer_Test(CTX.post.list, num);
if(v)
return &v->CT;
else
return NULL;
}
void Print_ColorTable(int num, char *prefix, FILE * file)
{
char tmp[1024];
Post_View *v;
if(!CTX.post.list)
v = Post_ViewReference;
else
v = (Post_View *) List_Pointer_Test(CTX.post.list, num);
if(!v)
return;
sprintf(tmp, "%s = {", prefix);
if(file)
fprintf(file, "%s\n", tmp);
else
Msg(DIRECT, tmp);
ColorTable_Print(&v->CT, file);
sprintf(tmp, "};");
if(file)
fprintf(file, "%s\n", tmp);
else
Msg(DIRECT, tmp);
}
Post_View *Create2DGraph(char *xname, char *yname,
int nbdata, double *x, double *y)
{
int i;
double d = 0.;
char filename[1024];
Post_View *v;
v = BeginView(1);
for(i = 0; i < nbdata; i++) {
List_Add(v->SP, &x[i]);
List_Add(v->SP, &d);
List_Add(v->SP, &d);
List_Add(v->SP, &y[i]);
v->NbSP++;
}
sprintf(filename, "%s.pos", yname);
EndView(v, 1, filename, yname);
v->Type = DRAW_POST_2D_SPACE;
strcpy(v->AbscissaName, xname);
return v;
}
// INput/output
void ReadView(FILE * file, char *filename)
{
char str[256], name[256];
int i, nb, format, size, testone, swap, t2l, t3l;
double version;
Post_View *v;
while(1) {
do {
fgets(str, 256, file);
if(feof(file))
break;
} while(str[0] != '$');
if(feof(file))
break;
/* F o r m a t */
if(!strncmp(&str[1], "PostFormat", 10)) {
fscanf(file, "%lf %d %d\n", &version, &format, &size);
if(version < 1.0) {
Msg(GERROR,
"The version of this post-processing file is too old (%g < 1.0)",
version);
return;
}
if(size == sizeof(double))
Msg(DEBUG, "Data is in double precision format (size==%d)", size);
else if(size == sizeof(float))
Msg(DEBUG, "Data is in single precision format (size==%d)", size);
else {
Msg(GERROR,
"Unknown type of data (size = %d) in post-processing file", size);
return;
}
if(format == 0)
format = LIST_FORMAT_ASCII;
else if(format == 1)
format = LIST_FORMAT_BINARY;
else {
Msg(GERROR, "Unknown format for view");
return;
}
}
/* V i e w */
if(!strncmp(&str[1], "View", 4)) {
v = BeginView(0);
if(version <= 1.0) {
fscanf(file, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
name, &v->NbTimeStep,
&v->NbSP, &v->NbVP, &v->NbTP,
&v->NbSL, &v->NbVL, &v->NbTL,
&v->NbST, &v->NbVT, &v->NbTT, &v->NbSS, &v->NbVS, &v->NbTS);
v->NbT2 = t2l = v->NbT3 = t3l = 0;
Msg(INFO, "Detected version <= 1.0");
}
else if(version == 1.1) {
fscanf(file,
"%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
name, &v->NbTimeStep, &v->NbSP, &v->NbVP, &v->NbTP, &v->NbSL,
&v->NbVL, &v->NbTL, &v->NbST, &v->NbVT, &v->NbTT, &v->NbSS,
&v->NbVS, &v->NbTS, &v->NbT2, &t2l, &v->NbT3, &t3l);
Msg(INFO, "Detected version 1.1");
}
else if(version == 1.2) {
fscanf(file, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d "
"%d %d %d %d %d %d %d %d %d %d %d %d %d\n",
name, &v->NbTimeStep,
&v->NbSP, &v->NbVP, &v->NbTP,
&v->NbSL, &v->NbVL, &v->NbTL,
&v->NbST, &v->NbVT, &v->NbTT,
&v->NbSQ, &v->NbVQ, &v->NbTQ,
&v->NbSS, &v->NbVS, &v->NbTS,
&v->NbSH, &v->NbVH, &v->NbTH,
&v->NbSI, &v->NbVI, &v->NbTI,
&v->NbSY, &v->NbVY, &v->NbTY, &v->NbT2, &t2l, &v->NbT3, &t3l);
Msg(INFO, "Detected version 1.2");
}
else {
Msg(GERROR, "Unknown post-processing file format (version %g)",
version);
return;
}
for(i = 0; i < (int)strlen(name); i++)
if(name[i] == '^')
name[i] = ' ';
swap = 0;
if(format == LIST_FORMAT_BINARY) {
fread(&testone, sizeof(int), 1, file);
if(testone != 1) {
Msg(INFO, "Swapping bytes from binary file");
swap = 1;
}
}
v->DataSize = size;
// Time values
v->Time = List_CreateFromFile(v->NbTimeStep, size, file, format, swap);
#define LL List_CreateFromFile(nb, size, file, format, swap)
// Points
nb = v->NbSP ? v->NbSP * (v->NbTimeStep + 3) : 0;
v->SP = LL;
nb = v->NbVP ? v->NbVP * (v->NbTimeStep * 3 + 3) : 0;
v->VP = LL;
nb = v->NbTP ? v->NbTP * (v->NbTimeStep * 9 + 3) : 0;
v->TP = LL;
// Lines
nb = v->NbSL ? v->NbSL * (v->NbTimeStep * 2 + 6) : 0;
v->SL = LL;
nb = v->NbVL ? v->NbVL * (v->NbTimeStep * 2 * 3 + 6) : 0;
v->VL = LL;
nb = v->NbTL ? v->NbTL * (v->NbTimeStep * 2 * 9 + 6) : 0;
v->TL = LL;
// Triangles
nb = v->NbST ? v->NbST * (v->NbTimeStep * 3 + 9) : 0;
v->ST = LL;
nb = v->NbVT ? v->NbVT * (v->NbTimeStep * 3 * 3 + 9) : 0;
v->VT = LL;
nb = v->NbTT ? v->NbTT * (v->NbTimeStep * 3 * 9 + 9) : 0;
v->TT = LL;
// Quadrangles
nb = v->NbSQ ? v->NbSQ * (v->NbTimeStep * 4 + 12) : 0;
v->SQ = LL;
nb = v->NbVQ ? v->NbVQ * (v->NbTimeStep * 4 * 3 + 12) : 0;
v->VQ = LL;
nb = v->NbTQ ? v->NbTQ * (v->NbTimeStep * 4 * 9 + 12) : 0;
v->TQ = LL;
// Tetrahedra
nb = v->NbSS ? v->NbSS * (v->NbTimeStep * 4 + 12) : 0;
v->SS = LL;
nb = v->NbVS ? v->NbVS * (v->NbTimeStep * 4 * 3 + 12) : 0;
v->VS = LL;
nb = v->NbTS ? v->NbTS * (v->NbTimeStep * 4 * 9 + 12) : 0;
v->TS = LL;
// Hexahedra
nb = v->NbSH ? v->NbSH * (v->NbTimeStep * 8 + 24) : 0;
v->SH = LL;
nb = v->NbVH ? v->NbVH * (v->NbTimeStep * 8 * 3 + 24) : 0;
v->VH = LL;
nb = v->NbTH ? v->NbTH * (v->NbTimeStep * 8 * 9 + 24) : 0;
v->TH = LL;
// Prisms
nb = v->NbSI ? v->NbSI * (v->NbTimeStep * 6 + 18) : 0;
v->SI = LL;
nb = v->NbVI ? v->NbVI * (v->NbTimeStep * 6 * 3 + 18) : 0;
v->VI = LL;
nb = v->NbTI ? v->NbTI * (v->NbTimeStep * 6 * 9 + 18) : 0;
v->TI = LL;
// Pyramids
nb = v->NbSY ? v->NbSY * (v->NbTimeStep * 5 + 15) : 0;
v->SY = LL;
nb = v->NbVY ? v->NbVY * (v->NbTimeStep * 5 * 3 + 15) : 0;
v->VY = LL;
nb = v->NbTY ? v->NbTY * (v->NbTimeStep * 5 * 9 + 15) : 0;
v->TY = LL;
#undef LL
// Strings
nb = v->NbT2 ? v->NbT2 * 4 : 0;
v->T2D = List_CreateFromFile(nb, size, file, format, swap);
v->T2C = List_CreateFromFile(t2l, sizeof(char), file, format, swap);
nb = v->NbT3 ? v->NbT3 * 5 : 0;
v->T3D = List_CreateFromFile(nb, size, file, format, swap);
v->T3C = List_CreateFromFile(t3l, sizeof(char), file, format, swap);
Msg(DEBUG,
"Read View '%s' (%d TimeSteps): %d %d %d %d %d %d %d %d %d %d %d "
"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", name, v->NbTimeStep,
v->NbSP, v->NbVP, v->NbTP, v->NbSL, v->NbVL, v->NbTL, v->NbST,
v->NbVT, v->NbTT, v->NbSQ, v->NbVQ, v->NbTQ, v->NbSS, v->NbVS,
v->NbTS, v->NbSH, v->NbVH, v->NbTH, v->NbSI, v->NbVI, v->NbTI,
v->NbSY, v->NbVY, v->NbTY, v->NbT2, v->NbT3);
Msg(DEBUG,
"List_Nbrs: " "SP%d VP%d TP%d " "SL%d VL%d TL%d " "ST%d VT%d TT%d "
"SQ%d VQ%d TQ%d " "SS%d VS%d TS%d " "SH%d VH%d TH%d "
"SI%d VI%d TI%d " "SY%d VY%d TY%d " "T2D%d T2C%d T3D%d T3C%d",
List_Nbr(v->SP), List_Nbr(v->VP), List_Nbr(v->TP), List_Nbr(v->SL),
List_Nbr(v->VL), List_Nbr(v->TL), List_Nbr(v->ST), List_Nbr(v->VT),
List_Nbr(v->TT), List_Nbr(v->SQ), List_Nbr(v->VQ), List_Nbr(v->TQ),
List_Nbr(v->SS), List_Nbr(v->VS), List_Nbr(v->TS), List_Nbr(v->SH),
List_Nbr(v->VH), List_Nbr(v->TH), List_Nbr(v->SI), List_Nbr(v->VI),
List_Nbr(v->TI), List_Nbr(v->SY), List_Nbr(v->VY), List_Nbr(v->TY),
List_Nbr(v->T2D), List_Nbr(v->T2C), List_Nbr(v->T3D),
List_Nbr(v->T3C));
EndView(v, 1, filename, name);
}
do {
fgets(str, 256, file);
if(feof(file))
Msg(GERROR, "Prematured end of file");
} while(str[0] != '$');
} /* while 1 ... */
}
// FIXME: add an integer per simplex (region num)
// FIXME: add a format similar to the msh format (node list + simplex list)
// FIXME: add a structured format
void WriteView(int Flag_BIN, Post_View * v, char *filename)
{
FILE *file;
char name[256];
int i, f, One = 1;
if(filename) {
file = fopen(filename, "w");
if(!file) {
Msg(GERROR, "Unable to open file '%s'", filename);
return;
}
}
else
file = stdout;
fprintf(file, "$PostFormat /* Gmsh 1.2, %s */\n",
Flag_BIN ? "binary" : "ascii");
fprintf(file, "1.2 %d %d\n", Flag_BIN, (int)sizeof(double));
fprintf(file, "$EndPostFormat\n");
for(i = 0; i < (int)strlen(v->Name); i++) {
if(v->Name[i] == ' ')
name[i] = '^';
else
name[i] = v->Name[i];
}
name[i] = '\0';
fprintf(file, "$View /* %s */\n", v->Name);
fprintf(file, "%s ", name);
fprintf(file, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d "
"%d %d %d %d %d %d %d %d %d %d %d %d\n",
List_Nbr(v->Time),
v->NbSP, v->NbVP, v->NbTP, v->NbSL, v->NbVL, v->NbTL,
v->NbST, v->NbVT, v->NbTT, v->NbSQ, v->NbVQ, v->NbTQ,
v->NbSS, v->NbVS, v->NbTS, v->NbSH, v->NbVH, v->NbTH,
v->NbSI, v->NbVI, v->NbTI, v->NbSY, v->NbVY, v->NbTY,
v->NbT2, List_Nbr(v->T2C), v->NbT3, List_Nbr(v->T3C));
if(Flag_BIN) {
f = LIST_FORMAT_BINARY;
fwrite(&One, sizeof(int), 1, file);
}
else
f = LIST_FORMAT_ASCII;
List_WriteToFile(v->Time, file, f);
List_WriteToFile(v->SP, file, f);
List_WriteToFile(v->VP, file, f);
List_WriteToFile(v->TP, file, f);
List_WriteToFile(v->SL, file, f);
List_WriteToFile(v->VL, file, f);
List_WriteToFile(v->TL, file, f);
List_WriteToFile(v->ST, file, f);
List_WriteToFile(v->VT, file, f);
List_WriteToFile(v->TT, file, f);
List_WriteToFile(v->SQ, file, f);
List_WriteToFile(v->VQ, file, f);
List_WriteToFile(v->TQ, file, f);
List_WriteToFile(v->SS, file, f);
List_WriteToFile(v->VS, file, f);
List_WriteToFile(v->TS, file, f);
List_WriteToFile(v->SH, file, f);
List_WriteToFile(v->VH, file, f);
List_WriteToFile(v->TH, file, f);
List_WriteToFile(v->SI, file, f);
List_WriteToFile(v->VI, file, f);
List_WriteToFile(v->TI, file, f);
List_WriteToFile(v->SY, file, f);
List_WriteToFile(v->VY, file, f);
List_WriteToFile(v->TY, file, f);
List_WriteToFile(v->T2D, file, f);
List_WriteToFile(v->T2C, file, f);
List_WriteToFile(v->T3D, file, f);
List_WriteToFile(v->T3C, file, f);
fprintf(file, "\n");
fprintf(file, "$EndView\n");
if(filename) {
Msg(INFO, "View output complete '%s'", filename);
Msg(STATUS2, "Wrote '%s'", filename);
fclose(file);
}
}
// Smoothing
using namespace std;
struct xyzv
{
private:
public:
double x, y, z, *vals;
int nbvals;
int nboccurences;
static double eps;
void update(int nbVals, double *);
xyzv(double x, double y, double z);
~xyzv();
xyzv & operator =(const xyzv &);
xyzv(const xyzv &);
};
double xyzv::eps = 0.0;
xyzv::xyzv(double xx, double yy, double zz)
:x(xx), y(yy), z(zz), vals(0), nbvals(0), nboccurences(0)
{
}
xyzv::~xyzv()
{
if(vals)
delete[]vals;
}
xyzv::xyzv(const xyzv & other)
{
x = other.x;
y = other.y;
z = other.z;
nbvals = other.nbvals;
nboccurences = other.nboccurences;
if(other.vals && other.nbvals) {
vals = new double[other.nbvals];
for(int i = 0; i < nbvals; i++)
vals[i] = other.vals[i];
}
}
xyzv & xyzv::operator =(const xyzv & other)
{
if(this != &other) {
x = other.x;
y = other.y;
z = other.z;
nbvals = other.nbvals;
nboccurences = other.nboccurences;
if(other.vals && other.nbvals) {
vals = new double[other.nbvals];
for(int i = 0; i < nbvals; i++)
vals[i] = other.vals[i];
}
}
return *this;
}
void xyzv::update(int n, double *v)
{
int i;
if(!vals) {
vals = new double[n];
for(i = 0; i < n; i++)
vals[i] = 0.0;
nbvals = n;
nboccurences = 0;
}
else if(nbvals != n) {
throw n;
}
double x1 = (double)(nboccurences) / (double)(nboccurences + 1);
double x2 = 1. / (double)(nboccurences + 1);
for(i = 0; i < nbvals; i++)
vals[i] = (x1 * vals[i] + x2 * v[i]);
nboccurences++;
//printf("val(%d,%f,%f,%f) = %f\n",nboccurences,x,y,z,vals[0]);
}
struct lessthanxyzv
{
bool operator () (const xyzv & p2, const xyzv & p1)const
{
if(p1.x - p2.x > xyzv::eps)
return true;
if(p1.x - p2.x < -xyzv::eps)
return false;
if(p1.y - p2.y > xyzv::eps)
return true;
if(p1.y - p2.y < -xyzv::eps)
return false;
if(p1.z - p2.z > xyzv::eps)
return true;
return false;
}
};
typedef set < xyzv, lessthanxyzv > mycont;
typedef mycont::const_iterator iter;
class smooth_container
{
public: mycont c;
};
void generate_connectivities(List_T * SS, int NbTimeStep, int nbvert, int nb,
mycont & connectivities)
{
double *x, *y, *z, *v;
int i, j, k;
// double vals[NbTimeStep]; // sgi compiler does not allow this
double *vals = new double[NbTimeStep];
for(i = 0; i < List_Nbr(SS); i += nb) {
x = (double *)List_Pointer_Fast(SS, i);
y = (double *)List_Pointer_Fast(SS, i + nbvert);
z = (double *)List_Pointer_Fast(SS, i + 2 * nbvert);
v = (double *)List_Pointer_Fast(SS, i + 3 * nbvert);
for(j = 0; j < nbvert; j++) {
for(k = 0; k < NbTimeStep; k++)
vals[k] = v[j + k * nbvert];
xyzv xyz(x[j], y[j], z[j]);
iter it = connectivities.find(xyz);
if(it == connectivities.end()) {
xyz.update(NbTimeStep, vals);
connectivities.insert(xyz);
}
else {
// a little weird ... because we know that this will not
// destroy the set ordering
xyzv *xx = (xyzv *) & (*it);
xx->update(NbTimeStep, vals);
}
}
}
delete[]vals;
}
void smooth_list(List_T * SS, double *min, double *max,
int NbTimeStep, int nbvert, int nb, mycont & connectivities)
{
double *x, *y, *z, *v;
int i, j, k;
*min = VAL_INF;
*max = -VAL_INF;
for(i = 0; i < List_Nbr(SS); i += nb) {
x = (double *)List_Pointer_Fast(SS, i);
y = (double *)List_Pointer_Fast(SS, i + nbvert);
z = (double *)List_Pointer_Fast(SS, i + 2 * nbvert);
v = (double *)List_Pointer_Fast(SS, i + 3 * nbvert);
for(j = 0; j < nbvert; j++) {
xyzv xyz(x[j], y[j], z[j]);
iter it = connectivities.find(xyz);
if(it != connectivities.end()) {
for(k = 0; k < NbTimeStep; k++) {
v[j + k * nbvert] = (*it).vals[k];
if(v[j + k * nbvert] < *min)
*min = v[j + k * nbvert];
if(v[j + k * nbvert] > *max)
*max = v[j + k * nbvert];
}
}
}
}
}
void Post_View::smooth()
{
xyzv::eps = CTX.lc * 1.e-8;
if(NbSL || NbST || NbSQ || NbSS || NbSH || NbSI || NbSY) {
mycont con;
int nbl = 0, nbt = 0, nbq = 0, nbs = 0, nbh = 0, nbi = 0, nby = 0;
Msg(INFO, "Smoothing scalar primitives in view...");
if(NbSL) {
nbt = List_Nbr(SL) / NbSL;
generate_connectivities(SL, NbTimeStep, 2, nbl, con);
}
if(NbST) {
nbt = List_Nbr(ST) / NbST;
generate_connectivities(ST, NbTimeStep, 3, nbt, con);
}
if(NbSQ) {
nbq = List_Nbr(SQ) / NbSQ;
generate_connectivities(SQ, NbTimeStep, 4, nbq, con);
}
if(NbSS) {
nbs = List_Nbr(SS) / NbSS;
generate_connectivities(SS, NbTimeStep, 4, nbs, con);
}
if(NbSH) {
nbh = List_Nbr(SH) / NbSH;
generate_connectivities(SH, NbTimeStep, 8, nbh, con);
}
if(NbSI) {
nbi = List_Nbr(SI) / NbSI;
generate_connectivities(SI, NbTimeStep, 6, nbi, con);
}
if(NbSY) {
nby = List_Nbr(SY) / NbSY;
generate_connectivities(SY, NbTimeStep, 5, nby, con);
}
if(nbl)
smooth_list(SL, &Min, &Max, NbTimeStep, 2, nbl, con);
if(nbt)
smooth_list(ST, &Min, &Max, NbTimeStep, 3, nbt, con);
if(nbq)
smooth_list(SQ, &Min, &Max, NbTimeStep, 4, nbq, con);
if(nbs)
smooth_list(SS, &Min, &Max, NbTimeStep, 4, nbs, con);
if(nbh)
smooth_list(SH, &Min, &Max, NbTimeStep, 8, nbh, con);
if(nbi)
smooth_list(SI, &Min, &Max, NbTimeStep, 6, nbi, con);
if(nby)
smooth_list(SY, &Min, &Max, NbTimeStep, 5, nby, con);
Msg(INFO, "...done");
}
}
// Normal smoothing
void Post_View::reset_normals()
{
if(normals)
delete normals;
normals = 0;
}
void Post_View::add_normal(double x, double y, double z,
double nx, double ny, double nz)
{
if(!normals)
normals = new smooth_container;
double n[3] = { nx, ny, nz };
xyzv xyz(x, y, z);
iter it = normals->c.find(xyz);
if(it == normals->c.end()) {
xyz.update(3, n);
normals->c.insert(xyz);
}
else {
xyzv *xx = (xyzv *) & (*it);
xx->update(3, n);
}
}
double get_angle(double *aa, double *bb)
{
double angplan, cosc, sinc, a[3], b[3], c[3];
if(!aa || !bb)
return 0.;
a[0] = aa[0];
a[1] = aa[1];
a[2] = aa[2];
b[0] = bb[0];
b[1] = bb[1];
b[2] = bb[2];
norme(a);
norme(b);
prodve(a, b, c);
prosca(a, b, &cosc);
sinc = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
angplan = myatan2(sinc, cosc);
return angplan * 180. / Pi;
}
bool Post_View::get_normal(double x, double y, double z,
double &nx, double &ny, double &nz)
{
if(!normals)
return false;
double n[3] = { nx, ny, nz };
xyzv xyz(x, y, z);
iter it = normals->c.find(xyz);
if(it == normals->c.end())
return false;
double angle = get_angle((*it).vals, n);
if(fabs(angle) < AngleSmoothNormals) {
nx = (*it).vals[0];
ny = (*it).vals[1];
nz = (*it).vals[2];
}
return true;
}
// Transformation
static void transform(double mat[3][3], double v[3],
double *x, double *y, double *z)
{
*x = mat[0][0] * v[0] + mat[0][1] * v[1] + mat[0][2] * v[2];
*y = mat[1][0] * v[0] + mat[1][1] * v[1] + mat[1][2] * v[2];
*z = mat[2][0] * v[0] + mat[2][1] * v[1] + mat[2][2] * v[2];
}
static void transform_list(List_T * V, int NbTimeStep, int nbvert,
int nb, double mat[3][3])
{
double *x, *y, *z, v[3];
int i, j;
for(i = 0; i < List_Nbr(V); i += nb) {
x = (double *)List_Pointer_Fast(V, i);
y = (double *)List_Pointer_Fast(V, i + nbvert);
z = (double *)List_Pointer_Fast(V, i + 2 * nbvert);
for(j = 0; j < nbvert; j++) {
v[0] = x[j];
v[1] = y[j];
v[2] = z[j];
transform(mat, v, &x[j], &y[j], &z[j]);
}
}
}
void Post_View::transform(double mat[3][3])
{
int nb;
if(NbSP) {
nb = List_Nbr(SP) / NbSP;
transform_list(SP, NbTimeStep, 1, nb, mat);
}
if(NbSL) {
nb = List_Nbr(SL) / NbSL;
transform_list(SL, NbTimeStep, 2, nb, mat);
}
if(NbST) {
nb = List_Nbr(ST) / NbST;
transform_list(ST, NbTimeStep, 3, nb, mat);
}
if(NbSQ) {
nb = List_Nbr(SQ) / NbSQ;
transform_list(SQ, NbTimeStep, 4, nb, mat);
}
if(NbSS) {
nb = List_Nbr(SS) / NbSS;
transform_list(SS, NbTimeStep, 4, nb, mat);
}
if(NbSH) {
nb = List_Nbr(SH) / NbSH;
transform_list(SH, NbTimeStep, 8, nb, mat);
}
if(NbSI) {
nb = List_Nbr(SI) / NbSI;
transform_list(SI, NbTimeStep, 6, nb, mat);
}
if(NbSY) {
nb = List_Nbr(SY) / NbSY;
transform_list(SY, NbTimeStep, 5, nb, mat);
}
if(NbVP) {
nb = List_Nbr(VP) / NbVP;
transform_list(VP, NbTimeStep, 1, nb, mat);
}
if(NbVL) {
nb = List_Nbr(VL) / NbVL;
transform_list(VL, NbTimeStep, 2, nb, mat);
}
if(NbVT) {
nb = List_Nbr(VT) / NbVT;
transform_list(VT, NbTimeStep, 3, nb, mat);
}
if(NbVQ) {
nb = List_Nbr(VQ) / NbVQ;
transform_list(VQ, NbTimeStep, 4, nb, mat);
}
if(NbVS) {
nb = List_Nbr(VS) / NbVS;
transform_list(VS, NbTimeStep, 4, nb, mat);
}
if(NbVH) {
nb = List_Nbr(VH) / NbVH;
transform_list(VH, NbTimeStep, 8, nb, mat);
}
if(NbVI) {
nb = List_Nbr(VI) / NbVI;
transform_list(VI, NbTimeStep, 6, nb, mat);
}
if(NbVY) {
nb = List_Nbr(VY) / NbVY;
transform_list(VY, NbTimeStep, 5, nb, mat);
}
}
// merge lists
static void merge(List_T * a, List_T * b)
{
if(!a || !b)
return;
for(int i = 0; i < List_Nbr(a); i++) {
List_Add(b, List_Pointer(a, i));
}
}
void MergeViews(int all)
{
// sanity check
int first = 1, nbt;
for(int i = 0; i < List_Nbr(CTX.post.list) - 1; i++) {
Post_View *v = (Post_View *) List_Pointer(CTX.post.list, i);
if(all || v->Visible) {
if(first){
nbt = v->NbTimeStep;
first = 0;
}
else{
if(v->NbTimeStep != nbt){
Msg(GERROR, "Cannot merge views having different number of time steps");
return;
}
}
}
}
Post_View *vm = BeginView(1);
for(int i = 0; i < List_Nbr(CTX.post.list) - 1; i++) {
Post_View *v = (Post_View *) List_Pointer(CTX.post.list, i);
if(all || v->Visible) {
Msg(DEBUG, "Merging view %d", i);
// *INDENT-OFF*
merge(v->SP,vm->SP); vm->NbSP += v->NbSP;
merge(v->VP,vm->VP); vm->NbVP += v->NbVP;
merge(v->TP,vm->TP); vm->NbTP += v->NbTP;
merge(v->SL,vm->SL); vm->NbSL += v->NbSL;
merge(v->VL,vm->VL); vm->NbVL += v->NbVL;
merge(v->TL,vm->TL); vm->NbTL += v->NbTL;
merge(v->ST,vm->ST); vm->NbST += v->NbST;
merge(v->VT,vm->VT); vm->NbVT += v->NbVT;
merge(v->TT,vm->TT); vm->NbTT += v->NbTT;
merge(v->SQ,vm->SQ); vm->NbSQ += v->NbSQ;
merge(v->VQ,vm->VQ); vm->NbVQ += v->NbVQ;
merge(v->TQ,vm->TQ); vm->NbTQ += v->NbTQ;
merge(v->SS,vm->SS); vm->NbSS += v->NbSS;
merge(v->VS,vm->VS); vm->NbVS += v->NbVS;
merge(v->TS,vm->TS); vm->NbTS += v->NbTS;
merge(v->SH,vm->SH); vm->NbSH += v->NbSH;
merge(v->VH,vm->VH); vm->NbVH += v->NbVH;
merge(v->TH,vm->TH); vm->NbTH += v->NbTH;
merge(v->SI,vm->SI); vm->NbSI += v->NbSI;
merge(v->VI,vm->VI); vm->NbVI += v->NbVI;
merge(v->TI,vm->TI); vm->NbTI += v->NbTI;
merge(v->SY,vm->SY); vm->NbSY += v->NbSY;
merge(v->VY,vm->VY); vm->NbVY += v->NbVY;
merge(v->TY,vm->TY); vm->NbTY += v->NbTY;
// *INDENT-ON*
/* this more complicated: have to change the indices
merge(v->T2D,vm->T2D);
merge(v->T2C,vm->T2C); v->NbT2 += vm->NbT2;
merge(v->T3D,vm->T3D);
merge(v->T3C,vm->T3C); v->NbT2 += vm->NbT2;
*/
}
}
EndView(vm, 1, "merged.pos", "merged");
}
// generic access functions
int Post_View::get_val(int list, int node, int timestep, double *value)
{
return 0;
}
void Post_View::add_val(int list, int node, int timestep, double value)
{
;
}