// $Id: PostElement.cpp,v 1.26 2004-04-20 19:15:14 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>. // // Contributor(s): // Laurent Stainier // Jean-Luc Flejou // OK, I understand why the Cut2D stuff does not work correctly with a // TWO_FACE light: the normal has too be coherent with the vertex // ordering of the polygon. Doing i=nb-1; i>=0; i-- works when the // classic order does not. So we really have to check the ordering of // the output of cut2d... #include "Gmsh.h" #include "GmshUI.h" #include "Geo.h" #include "Mesh.h" #include "Draw.h" #include "Iso.h" #include "Context.h" #include "Numeric.h" #define POINT 0 #define LINE 1 #define TRIANGLE 2 #define QUADRANGLE 3 #define TETRAHEDRON 4 #define HEXAHEDRON 5 #define PRISM 6 #define PYRAMID 7 extern Context_T CTX; void Draw_ElementBoundary(int type, Post_View * View, double *X, double *Y, double *Z, double Raise[3][8]) { int k; double xx[8], yy[8], zz[8]; glColor4ubv((GLubyte *) & CTX.color.fg); switch (type) { case POINT: Draw_Point(View->PointType, View->PointSize, X, Y, Z, Raise, View->Light); break; case LINE: Draw_Line(0, View->LineWidth, X, Y, Z, Raise, View->Light); break; case TRIANGLE: glBegin(GL_LINE_LOOP); for(k = 0; k < 3; k++) glVertex3d(X[k] + Raise[0][k], Y[k] + Raise[1][k], Z[k] + Raise[2][k]); glEnd(); break; case TETRAHEDRON: for(k = 0; k < 4; k++) { xx[k] = X[k] + Raise[0][k]; yy[k] = Y[k] + Raise[1][k]; zz[k] = Z[k] + Raise[2][k]; } glBegin(GL_LINES); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[3], yy[3], zz[3]); glEnd(); break; case QUADRANGLE: glBegin(GL_LINE_LOOP); for(k = 0; k < 4; k++) glVertex3d(X[k] + Raise[0][k], Y[k] + Raise[1][k], Z[k] + Raise[2][k]); glEnd(); break; case HEXAHEDRON: for(k = 0; k < 8; k++) { xx[k] = X[k] + Raise[0][k]; yy[k] = Y[k] + Raise[1][k]; zz[k] = Z[k] + Raise[2][k]; } glBegin(GL_LINES); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[4], yy[4], zz[4]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[5], yy[5], zz[5]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[6], yy[6], zz[6]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[7], yy[7], zz[7]); glVertex3d(xx[4], yy[4], zz[4]); glVertex3d(xx[5], yy[5], zz[5]); glVertex3d(xx[4], yy[4], zz[4]); glVertex3d(xx[7], yy[7], zz[7]); glVertex3d(xx[5], yy[5], zz[5]); glVertex3d(xx[6], yy[6], zz[6]); glVertex3d(xx[6], yy[6], zz[6]); glVertex3d(xx[7], yy[7], zz[7]); glEnd(); break; case PRISM: for(k = 0; k < 6; k++) { xx[k] = X[k] + Raise[0][k]; yy[k] = Y[k] + Raise[1][k]; zz[k] = Z[k] + Raise[2][k]; } glBegin(GL_LINES); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[4], yy[4], zz[4]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[5], yy[5], zz[5]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[4], yy[4], zz[4]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[5], yy[5], zz[5]); glVertex3d(xx[4], yy[4], zz[4]); glVertex3d(xx[5], yy[5], zz[5]); glEnd(); break; case PYRAMID: for(k = 0; k < 5; k++) { xx[k] = X[k] + Raise[0][k]; yy[k] = Y[k] + Raise[1][k]; zz[k] = Z[k] + Raise[2][k]; } glBegin(GL_LINES); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[0], yy[0], zz[0]); glVertex3d(xx[4], yy[4], zz[4]); glVertex3d(xx[1], yy[1], zz[1]); glVertex3d(xx[4], yy[4], zz[4]); glVertex3d(xx[3], yy[3], zz[3]); glVertex3d(xx[4], yy[4], zz[4]); glVertex3d(xx[2], yy[2], zz[2]); glVertex3d(xx[4], yy[4], zz[4]); glEnd(); break; } } void SaturateValues(int saturate, double min, double max, double *v1, double *v2, int nbnod) { int i; if(saturate) { for(i = 0; i < nbnod; i++) { if(v1[i] > max) v2[i] = max; else if(v1[i] < min) v2[i] = min; else v2[i] = v1[i]; } } else { for(i = 0; i < nbnod; i++) { v2[i] = v1[i]; } } } #define REORDER2(e,f) \ Xp[0] = X[e]; Yp[0] = Y[e]; Zp[0] = Z[e]; Val[0] = vv[e]; \ Xp[1] = X[f]; Yp[1] = Y[f]; Zp[1] = Z[f]; Val[1] = vv[f] #define REORDER3(e,f,g) \ Xp[0] = X[e]; Yp[0] = Y[e]; Zp[0] = Z[e]; Val[0] = vv[e]; \ Xp[1] = X[f]; Yp[1] = Y[f]; Zp[1] = Z[f]; Val[1] = vv[f]; \ Xp[2] = X[g]; Yp[2] = Y[g]; Zp[2] = Z[g]; Val[2] = vv[g] #define REORDER4(e,f,g,h) \ Xp[0] = X[e]; Yp[0] = Y[e]; Zp[0] = Z[e]; Val[0] = vv[e]; \ Xp[1] = X[f]; Yp[1] = Y[f]; Zp[1] = Z[f]; Val[1] = vv[f]; \ Xp[2] = X[g]; Yp[2] = Y[g]; Zp[2] = Z[g]; Val[2] = vv[g]; \ Xp[3] = X[h]; Yp[3] = Y[h]; Zp[3] = Z[h]; Val[3] = vv[h] #define REORDER6(e,f,g,h,i,j) \ Xp[0] = X[e]; Yp[0] = Y[e]; Zp[0] = Z[e]; Val[0] = vv[e]; \ Xp[1] = X[f]; Yp[1] = Y[f]; Zp[1] = Z[f]; Val[1] = vv[f]; \ Xp[2] = X[g]; Yp[2] = Y[g]; Zp[2] = Z[g]; Val[2] = vv[g]; \ Xp[3] = X[h]; Yp[3] = Y[h]; Zp[3] = Z[h]; Val[3] = vv[h]; \ Xp[4] = X[i]; Yp[4] = Y[i]; Zp[4] = Z[i]; Val[4] = vv[i]; \ Xp[5] = X[j]; Yp[5] = Y[j]; Zp[5] = Z[j]; Val[5] = vv[j] // Scalar Elements void Draw_ScalarPoint(Post_View * View, int preproNormals, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { double d; char Num[100]; if(View->Boundary > 0) return; d = V[View->TimeStep]; if(View->SaturateValues) { if(d > ValMax) d = ValMax; else if(d < ValMin) d = ValMin; } RaiseFill(0, d, ValMin, Raise); if(View->ShowElement) Draw_ElementBoundary(POINT, View, X, Y, Z, Raise); if(d >= ValMin && d <= ValMax) { PaletteContinuous(View, ValMin, ValMax, d); if(View->IntervalsType == DRAW_POST_NUMERIC) { glRasterPos3d(X[0] + Raise[0][0], Y[0] + Raise[1][0], Z[0] + Raise[2][0]); sprintf(Num, View->Format, d); Draw_String(Num); } else Draw_Point(View->PointType, View->PointSize, X, Y, Z, Raise, View->Light); } } void Draw_ScalarLine(Post_View * View, int preproNormals, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { int i, k, nb = 0; double d; double Xp[5], Yp[5], Zp[5], Val[5], value[5], thev; char Num[100]; double *vv = &V[2 * View->TimeStep]; if(View->Boundary > 0) { View->Boundary--; int ts = View->TimeStep; View->TimeStep = 0; Draw_ScalarPoint(View, 0, ValMin, ValMax, Raise, &X[0], &Y[0], &Z[0], &vv[0]); //0 Draw_ScalarPoint(View, 0, ValMin, ValMax, Raise, &X[1], &Y[1], &Z[1], &vv[1]); //1 View->TimeStep = ts; View->Boundary++; return; } SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 2); for(k = 0; k < 2; k++) RaiseFill(k, Val[k], ValMin, Raise); if(View->ShowElement) Draw_ElementBoundary(LINE, View, X, Y, Z, Raise); if(View->IntervalsType == DRAW_POST_NUMERIC) { d = (Val[0] + Val[1]) / 2.; if(d >= ValMin && d <= ValMax) { PaletteContinuous(View, ValMin, ValMax, d); sprintf(Num, View->Format, d); glRasterPos3d((X[0] + Raise[0][0] + X[1] + Raise[0][1]) / 2., (Y[0] + Raise[1][0] + Y[1] + Raise[1][1]) / 2., (Z[0] + Raise[2][0] + Z[1] + Raise[2][1]) / 2.); Draw_String(Num); } } else { if(View->IntervalsType == DRAW_POST_CONTINUOUS) { if(Val[0] >= ValMin && Val[0] <= ValMax && Val[1] >= ValMin && Val[1] <= ValMax) { if(View->LineType) { // not perfect... PaletteContinuous(View, ValMin, ValMax, Val[0]); Draw_Line(View->LineType, View->LineWidth, X, Y, Z, Raise, View->Light); } else { glBegin(GL_LINES); PaletteContinuous(View, ValMin, ValMax, Val[0]); glVertex3d(X[0] + Raise[0][0], Y[0] + Raise[1][0], Z[0] + Raise[2][0]); PaletteContinuous(View, ValMin, ValMax, Val[1]); glVertex3d(X[1] + Raise[0][1], Y[1] + Raise[1][1], Z[1] + Raise[2][1]); glEnd(); } } else { //todo } } else { for(k = 0; k < View->NbIso; k++) { PaletteDiscrete(View, View->NbIso, k); if(View->IntervalsType == DRAW_POST_DISCRETE) { CutLine1D(X, Y, Z, &Val[0], View->GVFI(ValMin, ValMax, View->NbIso + 1, k), View->GVFI(ValMin, ValMax, View->NbIso + 1, k + 1), Xp, Yp, Zp, &nb, value); if(nb == 2) { for(i = 0; i < 2; i++) RaiseFill(i, value[i], ValMin, Raise); Draw_Line(View->LineType, View->LineWidth, Xp, Yp, Zp, Raise, View->Light); } } else { thev = View->GVFI(ValMin, ValMax, View->NbIso, k); CutLine0D(X, Y, Z, &Val[0], thev, Xp, Yp, Zp, &nb); if(nb) { RaiseFill(0, thev, ValMin, Raise); Draw_Point(View->PointType, View->PointSize, Xp, Yp, Zp, Raise, View->Light); } } } } } } void Draw_ScalarTriangle(Post_View * View, int preproNormals, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { int i, k, nb = 0; double d; double x1x0, y1y0, z1z0, x2x0, y2y0, z2z0, nn[3], norms[9]; double Xp[5], Yp[5], Zp[5], Val[3], value[5], thev; char Num[100]; double *vv = &V[3 * View->TimeStep]; if(!preproNormals && View->Boundary > 0) { View->Boundary--; int ts = View->TimeStep; View->TimeStep = 0; Draw_ScalarLine(View, 0, ValMin, ValMax, Raise, &X[0], &Y[0], &Z[0], &vv[0]); //01 Draw_ScalarLine(View, 0, ValMin, ValMax, Raise, &X[1], &Y[1], &Z[1], &vv[1]); //12 REORDER2(0, 2); Draw_ScalarLine(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //02 View->TimeStep = ts; View->Boundary++; return; } SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 3); for(k = 0; k < 3; k++) RaiseFill(k, Val[k], ValMin, Raise); if(View->Light) { x1x0 = (X[1] + Raise[0][1]) - (X[0] + Raise[0][0]); y1y0 = (Y[1] + Raise[1][1]) - (Y[0] + Raise[1][0]); z1z0 = (Z[1] + Raise[2][1]) - (Z[0] + Raise[2][0]); x2x0 = (X[2] + Raise[0][2]) - (X[0] + Raise[0][0]); y2y0 = (Y[2] + Raise[1][2]) - (Y[0] + Raise[1][0]); z2z0 = (Z[2] + Raise[2][2]) - (Z[0] + Raise[2][0]); nn[0] = y1y0 * z2z0 - z1z0 * y2y0; nn[1] = z1z0 * x2x0 - x1x0 * z2z0; nn[2] = x1x0 * y2y0 - y1y0 * x2x0; if(View->SmoothNormals) { if(preproNormals) { for(i = 0; i < 3; i++) { View->add_normal(X[i] + Raise[0][i], Y[i] + Raise[1][i], Z[i] + Raise[2][i], nn[0], nn[1], nn[2]); } return; } else { for(i = 0; i < 3; i++) { norms[3 * i] = nn[0]; norms[3 * i + 1] = nn[1]; norms[3 * i + 2] = nn[2]; if(!View-> get_normal(X[i] + Raise[0][i], Y[i] + Raise[1][i], Z[i] + Raise[2][i], norms[3 * i], norms[3 * i + 1], norms[3 * i + 2])) { //don't print this (unless we fix draw_vector_triangle with displacement) //Msg(WARNING, "Oups, did not find smoothed normal"); } } } } else { for(i = 0; i < 3; i++) { norms[3 * i] = nn[0]; norms[3 * i + 1] = nn[1]; norms[3 * i + 2] = nn[2]; } } //norme(norms); not necessary since GL_NORMALIZE is enabled //norme(&norms[3]); //norme(&norms[6]); glNormal3dv(norms); } if(preproNormals) return; if(View->ShowElement) Draw_ElementBoundary(TRIANGLE, View, X, Y, Z, Raise); if(View->IntervalsType == DRAW_POST_NUMERIC) { d = (Val[0] + Val[1] + Val[2]) / 3.; if(d >= ValMin && d <= ValMax) { PaletteContinuous(View, ValMin, ValMax, d); sprintf(Num, View->Format, d); glRasterPos3d((X[0] + Raise[0][0] + X[1] + Raise[0][1] + X[2] + Raise[0][2]) / 3., (Y[0] + Raise[1][0] + Y[1] + Raise[1][1] + Y[2] + Raise[1][2]) / 3., (Z[0] + Raise[2][0] + Z[1] + Raise[2][1] + Z[2] + Raise[2][2]) / 3.); Draw_String(Num); } } else { if(View->Light) glEnable(GL_LIGHTING); glEnable(GL_POLYGON_OFFSET_FILL); if(View->IntervalsType == DRAW_POST_CONTINUOUS) { if(Val[0] >= ValMin && Val[0] <= ValMax && Val[1] >= ValMin && Val[1] <= ValMax && Val[2] >= ValMin && Val[2] <= ValMax) { glBegin(GL_TRIANGLES); PaletteContinuous(View, ValMin, ValMax, Val[0]); glNormal3dv(&norms[0]); glVertex3d(X[0] + Raise[0][0], Y[0] + Raise[1][0], Z[0] + Raise[2][0]); PaletteContinuous(View, ValMin, ValMax, Val[1]); glNormal3dv(&norms[3]); glVertex3d(X[1] + Raise[0][1], Y[1] + Raise[1][1], Z[1] + Raise[2][1]); PaletteContinuous(View, ValMin, ValMax, Val[2]); glNormal3dv(&norms[6]); glVertex3d(X[2] + Raise[0][2], Y[2] + Raise[1][2], Z[2] + Raise[2][2]); glEnd(); } else { CutTriangle2D(X, Y, Z, Val, ValMin, ValMax, Xp, Yp, Zp, &nb, value); if(nb >= 3) { glBegin(GL_POLYGON); for(i = 0; i < nb; i++) { PaletteContinuous(View, ValMin, ValMax, value[i]); RaiseFill(i, value[i], ValMin, Raise); glVertex3d(Xp[i] + Raise[0][i], Yp[i] + Raise[1][i], Zp[i] + Raise[2][i]); } glEnd(); } } } else { for(k = 0; k < View->NbIso; k++) { PaletteDiscrete(View, View->NbIso, k); if(View->IntervalsType == DRAW_POST_DISCRETE) { CutTriangle2D(X, Y, Z, Val, View->GVFI(ValMin, ValMax, View->NbIso + 1, k), View->GVFI(ValMin, ValMax, View->NbIso + 1, k + 1), Xp, Yp, Zp, &nb, value); if(nb >= 3) { for(i = 0; i < nb; i++) RaiseFill(i, value[i], ValMin, Raise); glBegin(GL_POLYGON); for(i = 0; i < nb; i++) glVertex3d(Xp[i] + Raise[0][i], Yp[i] + Raise[1][i], Zp[i] + Raise[2][i]); glEnd(); } } else { thev = View->GVFI(ValMin, ValMax, View->NbIso, k); CutTriangle1D(X, Y, Z, Val, thev, Xp, Yp, Zp, &nb); if(nb == 2) { for(i = 0; i < 2; i++) RaiseFill(i, thev, ValMin, Raise); Draw_Line(View->LineType, View->LineWidth, Xp, Yp, Zp, Raise, View->Light); } } } } glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_LIGHTING); } } void Draw_ScalarTetrahedron(Post_View * View, int preproNormals, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { int k; double d, Xp[4], Yp[4], Zp[4]; char Num[100]; double Val[4]; double *vv = &V[4 * View->TimeStep]; if(!preproNormals && View->Boundary > 0) { View->Boundary--; int ts = View->TimeStep; View->TimeStep = 0; Draw_ScalarTriangle(View, 0, ValMin, ValMax, Raise, &X[0], &Y[0], &Z[0], &vv[0]); //012 Draw_ScalarTriangle(View, 0, ValMin, ValMax, Raise, &X[1], &Y[1], &Z[1], &vv[1]); //123 REORDER3(0, 1, 3); Draw_ScalarTriangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //013 Xp[1] = X[2]; Yp[1] = Y[2]; Zp[1] = Z[2]; Val[1] = vv[2]; Draw_ScalarTriangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //023 View->TimeStep = ts; View->Boundary++; return; } SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 4); for(k = 0; k < 4; k++) RaiseFill(k, Val[k], ValMin, Raise); if(!preproNormals && View->ShowElement) Draw_ElementBoundary(TETRAHEDRON, View, X, Y, Z, Raise); if(!preproNormals && View->IntervalsType == DRAW_POST_NUMERIC) { d = 0.25 * (Val[0] + Val[1] + Val[2] + Val[3]); if(d >= ValMin && d <= ValMax) { PaletteContinuous(View, ValMin, ValMax, d); sprintf(Num, View->Format, d); glRasterPos3d(0.25 * (X[0] + Raise[0][0] + X[1] + Raise[0][1] + X[2] + Raise[0][2] + X[3] + Raise[0][3]), 0.25 * (Y[0] + Raise[1][0] + Y[1] + Raise[1][1] + Y[2] + Raise[1][2] + Y[3] + Raise[1][3]), 0.25 * (Z[0] + Raise[2][0] + Z[1] + Raise[2][1] + Z[2] + Raise[2][2] + Z[3] + Raise[2][3])); Draw_String(Num); } } else { for(k = 0; k < View->NbIso; k++) { if(!preproNormals) PaletteDiscrete(View, View->NbIso, k); IsoSimplex(View, preproNormals, X, Y, Z, Val, View->GVFI(ValMin, ValMax, View->NbIso, k), Raise); } } } void Draw_ScalarQuadrangle(Post_View * View, int preproNormals, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { int k, ts, show = 0; double Val[4], Xp[4], Yp[4], Zp[4]; double *vv = &V[4 * View->TimeStep]; ts = View->TimeStep; View->TimeStep = 0; if(!preproNormals && View->Boundary > 0) { View->Boundary--; Draw_ScalarLine(View, 0, ValMin, ValMax, Raise, &X[0], &Y[0], &Z[0], &vv[0]); //01 Draw_ScalarLine(View, 0, ValMin, ValMax, Raise, &X[1], &Y[1], &Z[1], &vv[1]); //12 Draw_ScalarLine(View, 0, ValMin, ValMax, Raise, &X[2], &Y[2], &Z[2], &vv[2]); //23 REORDER2(0, 3); Draw_ScalarLine(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //03 View->TimeStep = ts; View->Boundary++; return; } show = View->ShowElement; View->ShowElement = 0; if(!preproNormals && show) { SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 4); for(k = 0; k < 4; k++) RaiseFill(k, Val[k], ValMin, Raise); Draw_ElementBoundary(QUADRANGLE, View, X, Y, Z, Raise); } Draw_ScalarTriangle(View, preproNormals, ValMin, ValMax, Raise, X, Y, Z, vv); //012 REORDER3(0, 2, 3); Draw_ScalarTriangle(View, preproNormals, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //023 View->TimeStep = ts; View->ShowElement = show; } void Draw_ScalarHexahedron(Post_View * View, int preproNormals, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { int k, ts, show = 0; double Val[8], Xp[8], Yp[8], Zp[8]; double *vv = &V[8 * View->TimeStep]; ts = View->TimeStep; View->TimeStep = 0; if(!preproNormals && View->Boundary > 0) { View->Boundary--; REORDER4(0, 1, 5, 4); Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //0154 REORDER4(0, 3, 2, 1); Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //0321 REORDER4(0, 4, 7, 3); Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //0473 REORDER4(1, 2, 6, 5); Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //1265 REORDER4(2, 3, 7, 6); Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //2376 Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, &X[4], &Y[4], &Z[4], &vv[4]); //4567 View->TimeStep = ts; View->Boundary++; return; } show = View->ShowElement; View->ShowElement = 0; if(!preproNormals && show) { SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 8); for(k = 0; k < 8; k++) RaiseFill(k, Val[k], ValMin, Raise); Draw_ElementBoundary(HEXAHEDRON, View, X, Y, Z, Raise); } REORDER6(0, 1, 3, 4, 5, 7); Draw_ScalarPrism(View, preproNormals, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); REORDER6(1, 2, 3, 5, 6, 7); Draw_ScalarPrism(View, preproNormals, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); View->TimeStep = ts; View->ShowElement = show; } void Draw_ScalarPrism(Post_View * View, int preproNormals, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { int k, ts, show = 0; double Val[6], Xp[6], Yp[6], Zp[6]; double *vv = &V[6 * View->TimeStep]; ts = View->TimeStep; View->TimeStep = 0; if(!preproNormals && View->Boundary > 0) { View->Boundary--; REORDER4(0, 1, 4, 3); Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); REORDER3(0, 2, 1); Draw_ScalarTriangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); REORDER4(0, 3, 5, 2); Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); REORDER4(1, 2, 5, 4); Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); Draw_ScalarTriangle(View, 0, ValMin, ValMax, Raise, &X[3], &Y[3], &Z[3], &V[3]); View->TimeStep = ts; View->Boundary++; return; } show = View->ShowElement; View->ShowElement = 0; if(!preproNormals && show) { SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 6); for(k = 0; k < 6; k++) RaiseFill(k, Val[k], ValMin, Raise); Draw_ElementBoundary(PRISM, View, X, Y, Z, Raise); } Draw_ScalarTetrahedron(View, preproNormals, ValMin, ValMax, Raise, X, Y, Z, vv); //0123 REORDER4(3, 4, 5, 2); Draw_ScalarTetrahedron(View, preproNormals, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //3452 REORDER4(1, 2, 4, 3); Draw_ScalarTetrahedron(View, preproNormals, ValMin, ValMax, Raise, Xp, Yp, Zp, Val); //1243 View->TimeStep = ts; View->ShowElement = show; } void Draw_ScalarPyramid(Post_View * View, int preproNormals, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { static int error = 0; if(!error) { error = 1; Msg(WARNING, "Pyramid drawing not implemented yet..."); } } // Vector Elements void Draw_VectorElement(int type, Post_View * View, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { int j, k, nbnod = 0; double fact, xx[8], yy[8], zz[8], xc = 0., yc = 0., zc = 0.; double Val[8][3], d[8]; double dx = 0., dy = 0., dz = 0., dd; char Num[100]; switch (type) { case POINT: nbnod = 1; break; case LINE: nbnod = 2; break; case TRIANGLE: nbnod = 3; break; case QUADRANGLE: nbnod = 4; break; case TETRAHEDRON: nbnod = 4; break; case HEXAHEDRON: nbnod = 8; break; case PRISM: nbnod = 6; break; case PYRAMID: nbnod = 5; break; } for(k = 0; k < nbnod; k++) { Val[k][0] = V[3 * nbnod * View->TimeStep + 3 * k]; Val[k][1] = V[3 * nbnod * View->TimeStep + 3 * k + 1]; Val[k][2] = V[3 * nbnod * View->TimeStep + 3 * k + 2]; d[k] = sqrt(Val[k][0] * Val[k][0] + Val[k][1] * Val[k][1] + Val[k][2] * Val[k][2]); RaiseFill(k, d[k], ValMin, Raise); } if(View->VectorType == DRAW_POST_DISPLACEMENT) { fact = View->DisplacementFactor; for(k = 0; k < nbnod; k++) { xx[k] = X[k] + fact * Val[k][0] + Raise[0][k]; yy[k] = Y[k] + fact * Val[k][1] + Raise[1][k]; zz[k] = Z[k] + fact * Val[k][2] + Raise[2][k]; } int ts = View->TimeStep; View->TimeStep = 0; switch (type) { case POINT: Draw_ScalarPoint(View, 0, ValMin, ValMax, Raise, xx, yy, zz, d); if(ts) { //draw trajectory if(View->LineType) { double dx2, dy2, dz2, XX[2], YY[2], ZZ[2]; // warning, warning... Raise[0][1] = Raise[0][0]; Raise[1][1] = Raise[1][0]; Raise[2][1] = Raise[2][0]; for(j = 0; j < ts; j++) { dx = V[3 * (ts - j)]; dy = V[3 * (ts - j) + 1]; dz = V[3 * (ts - j) + 2]; dx2 = V[3 * (ts - j - 1)]; dy2 = V[3 * (ts - j - 1) + 1]; dz2 = V[3 * (ts - j - 1) + 2]; dd = sqrt(dx * dx + dy * dy + dz * dz); // not perfect... PaletteContinuous(View, ValMin, ValMax, dd); XX[0] = X[0] + fact * dx; XX[1] = X[0] + fact * dx2; YY[0] = Y[0] + fact * dy; YY[1] = Y[0] + fact * dy2; ZZ[0] = Z[0] + fact * dz; ZZ[1] = Z[0] + fact * dz2; Draw_Line(View->LineType, View->LineWidth, XX, YY, ZZ, Raise, View->Light); } } else { glBegin(GL_LINE_STRIP); for(j = 0; j < ts + 1; j++) { dx = V[3 * (ts - j)]; dy = V[3 * (ts - j) + 1]; dz = V[3 * (ts - j) + 2]; dd = sqrt(dx * dx + dy * dy + dz * dz); PaletteContinuous(View, ValMin, ValMax, dd); glVertex3d(X[0] + fact * dx + Raise[0][0], Y[0] + fact * dy + Raise[1][0], Z[0] + fact * dz + Raise[2][0]); } glEnd(); } } break; case LINE: Draw_ScalarLine(View, 0, ValMin, ValMax, Raise, xx, yy, zz, d); break; case TRIANGLE: Draw_ScalarTriangle(View, 0, ValMin, ValMax, Raise, xx, yy, zz, d); break; case TETRAHEDRON: Draw_ScalarTetrahedron(View, 0, ValMin, ValMax, Raise, xx, yy, zz, d); break; case QUADRANGLE: Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, xx, yy, zz, d); break; case HEXAHEDRON: Draw_ScalarHexahedron(View, 0, ValMin, ValMax, Raise, xx, yy, zz, d); break; case PRISM: Draw_ScalarPrism(View, 0, ValMin, ValMax, Raise, xx, yy, zz, d); break; case PYRAMID: Draw_ScalarPyramid(View, 0, ValMin, ValMax, Raise, xx, yy, zz, d); break; } View->TimeStep = ts; return; } if(View->ShowElement) Draw_ElementBoundary(type, View, X, Y, Z, Raise); if(View->ArrowLocation == DRAW_POST_LOCATE_COG || View->IntervalsType == DRAW_POST_NUMERIC) { for(k = 0; k < nbnod; k++) { dx += Val[k][0]; xc += X[k] + Raise[0][k]; dy += Val[k][1]; yc += Y[k] + Raise[1][k]; dz += Val[k][2]; zc += Z[k] + Raise[2][k]; } dx /= (double)nbnod; xc /= (double)nbnod; dy /= (double)nbnod; yc /= (double)nbnod; dz /= (double)nbnod; zc /= (double)nbnod; dd = sqrt(dx * dx + dy * dy + dz * dz); // allow for some roundoff error due to the computation at the barycenter if(dd != 0.0 && dd >= ValMin * (1. - 1.e-15) && dd <= ValMax * (1. + 1.e-15)) { if(View->IntervalsType == DRAW_POST_CONTINUOUS) PaletteContinuous(View, ValMin, ValMax, dd); else PaletteDiscrete(View, View->NbIso, View->GIFV(ValMin, ValMax, View->NbIso, dd)); if(View->IntervalsType == DRAW_POST_NUMERIC) { glRasterPos3d(xc, yc, zc); sprintf(Num, View->Format, dd); Draw_String(Num); } else { fact = CTX.pixel_equiv_x / CTX.s[0] * View->ArrowSize / ValMax; if(View->ScaleType == DRAW_POST_LOGARITHMIC && ValMin > 0) { dx /= dd; dy /= dd; dz /= dd; dd = log10(dd / ValMin); dx *= dd; dy *= dd; dz *= dd; } RaiseFill(0, dd, ValMin, Raise); Draw_Vector(View->VectorType, View->IntervalsType != DRAW_POST_ISO, View->ArrowRelHeadRadius, View->ArrowRelStemLength, View->ArrowRelStemRadius, xc, yc, zc, fact * dx, fact * dy, fact * dz, Raise, View->Light); } } } else { for(k = 0; k < nbnod; k++) { if(d[k] != 0.0 && d[k] >= ValMin && d[k] <= ValMax) { if(View->IntervalsType == DRAW_POST_CONTINUOUS) PaletteContinuous(View, ValMin, ValMax, d[k]); else PaletteDiscrete(View, View->NbIso, View->GIFV(ValMin, ValMax, View->NbIso, d[k])); fact = CTX.pixel_equiv_x / CTX.s[0] * View->ArrowSize / ValMax; if(View->ScaleType == DRAW_POST_LOGARITHMIC && ValMin > 0) { Val[k][0] /= d[k]; Val[k][1] /= d[k]; Val[k][2] /= d[k]; d[k] = log10(d[k] / ValMin); Val[k][0] *= d[k]; Val[k][1] *= d[k]; Val[k][2] *= d[k]; } RaiseFill(0, d[k], ValMin, Raise); Draw_Vector(View->VectorType, View->IntervalsType != DRAW_POST_ISO, View->ArrowRelHeadRadius, View->ArrowRelStemLength, View->ArrowRelStemRadius, X[k], Y[k], Z[k], fact * Val[k][0], fact * Val[k][1], fact * Val[k][2], Raise, View->Light); } } } } #define ARGS Post_View *View, \ double ValMin, double ValMax, double Raise[3][8], \ double *X, double *Y, double *Z, double *V void Draw_VectorPoint(ARGS) { Draw_VectorElement(POINT, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_VectorLine(ARGS) { Draw_VectorElement(LINE, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_VectorTriangle(ARGS) { Draw_VectorElement(TRIANGLE, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_VectorTetrahedron(ARGS) { Draw_VectorElement(TETRAHEDRON, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_VectorQuadrangle(ARGS) { Draw_VectorElement(QUADRANGLE, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_VectorHexahedron(ARGS) { Draw_VectorElement(HEXAHEDRON, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_VectorPrism(ARGS) { Draw_VectorElement(PRISM, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_VectorPyramid(ARGS) { Draw_VectorElement(PYRAMID, View, ValMin, ValMax, Raise, X, Y, Z, V); } #undef ARGS // Tensor Elements void Draw_TensorElement(int type, Post_View * View, double ValMin, double ValMax, double Raise[3][8], double *X, double *Y, double *Z, double *V) { int nbnod = 0; switch (type) { case POINT: nbnod = 1; break; case LINE: nbnod = 2; break; case TRIANGLE: nbnod = 3; break; case QUADRANGLE: nbnod = 4; break; case TETRAHEDRON: nbnod = 4; break; case HEXAHEDRON: nbnod = 8; break; case PRISM: nbnod = 6; break; case PYRAMID: nbnod = 5; break; } /// By lack of any current better solution, tensors are displayed as /// their Von Mises invariant (J2 invariant); this will simply call /// the scalar function... // View->TensorType == DRAW_POST_VONMISES int ts = View->TimeStep; View->TimeStep = 0; double V_VonMises[8]; for(int i = 0; i < nbnod; i++){ V_VonMises[i] = ComputeVonMises(V + 9*(i + nbnod * ts)); } switch (type) { case POINT: Draw_ScalarPoint(View, 0, ValMin, ValMax, Raise, X, Y, Z, V_VonMises); break; case LINE: Draw_ScalarLine(View, 0, ValMin, ValMax, Raise, X, Y, Z, V_VonMises); break; case TRIANGLE: Draw_ScalarTriangle(View, 0, ValMin, ValMax, Raise, X, Y, Z, V_VonMises); break; case QUADRANGLE: Draw_ScalarQuadrangle(View, 0, ValMin, ValMax, Raise, X, Y, Z, V_VonMises); break; case TETRAHEDRON: Draw_ScalarTetrahedron(View, 0, ValMin, ValMax, Raise, X, Y, Z, V_VonMises); break; case HEXAHEDRON: Draw_ScalarHexahedron(View, 0, ValMin, ValMax, Raise, X, Y, Z, V_VonMises); break; case PRISM: Draw_ScalarPrism(View, 0, ValMin, ValMax, Raise, X, Y, Z, V_VonMises); break; case PYRAMID: Draw_ScalarPyramid(View, 0, ValMin, ValMax, Raise, X, Y, Z, V_VonMises); break; } View->TimeStep = ts; } #define ARGS Post_View *View, \ double ValMin, double ValMax, double Raise[3][8], \ double *X, double *Y, double *Z, double *V void Draw_TensorPoint(ARGS) { Draw_TensorElement(POINT, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_TensorLine(ARGS) { Draw_TensorElement(LINE, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_TensorTriangle(ARGS) { Draw_TensorElement(TRIANGLE, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_TensorTetrahedron(ARGS) { Draw_TensorElement(TETRAHEDRON, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_TensorQuadrangle(ARGS) { Draw_TensorElement(QUADRANGLE, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_TensorHexahedron(ARGS) { Draw_TensorElement(HEXAHEDRON, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_TensorPrism(ARGS) { Draw_TensorElement(PRISM, View, ValMin, ValMax, Raise, X, Y, Z, V); } void Draw_TensorPyramid(ARGS) { Draw_TensorElement(PYRAMID, View, ValMin, ValMax, Raise, X, Y, Z, V); } #undef ARGS