double qmQuadrangleAngles (MQuadrangle *e) { double a = 100; double worst_quality = std::numeric_limits<double>::max(); double mat[3][3]; double mat2[3][3]; double den = atan(a*(M_PI/4)) + atan(a*(2*M_PI/4 - (M_PI/4))); // This matrix is used to "rotate" the triangle to get each vertex // as the "origin" of the mapping in turn //double rot[3][3]; //rot[0][0]=-1; rot[0][1]=1; rot[0][2]=0; //rot[1][0]=-1; rot[1][1]=0; rot[1][2]=0; //rot[2][0]= 0; rot[2][1]=0; rot[2][2]=1; //double tmp[3][3]; const double u[9] = {-1,-1, 1, 1, 0,0,1,-1,0}; const double v[9] = {-1, 1, 1,-1, -1,1,0,0,0}; for (int i = 0; i < 9; i++) { e->getJacobian(u[i], v[i], 0, mat); e->getPrimaryJacobian(u[i],v[i],0,mat2); //for (int j = 0; j < i; j++) { // matmat(rot,mat,tmp); // memcpy(mat, tmp, sizeof(mat)); //} //get angle double v1[3] = {mat[0][0], mat[0][1], mat[0][2] }; double v2[3] = {mat[1][0], mat[1][1], mat[1][2] }; double v3[3] = {mat2[0][0], mat2[0][1], mat2[0][2] }; double v4[3] = {mat2[1][0], mat2[1][1], mat2[1][2] }; norme(v1); norme(v2); norme(v3); norme(v4); double v12[3], v34[3]; prodve(v1,v2,v12); prodve(v3,v4,v34); norme(v12); norme(v34); double orientation; prosca(v12,v34,&orientation); // If the if the triangle is "flipped" it's no good // if (orientation < 0) // return -std::numeric_limits<double>::max(); double c; prosca(v1,v2,&c); double x = fabs(acos(c))-M_PI/2; //double angle = fabs(acos(c))*180/M_PI; double quality = (atan(a*(x+M_PI/4)) + atan(a*(2*M_PI/4 - (x+M_PI/4))))/den; worst_quality = std::min(worst_quality, quality); } return worst_quality; }
double qmTriangle(const double &xa, const double &ya, const double &za, const double &xb, const double &yb, const double &zb, const double &xc, const double &yc, const double &zc, const qualityMeasure4Triangle &cr) { double quality; switch(cr){ case QMTRI_RHO: { // quality = rho / R = 2 * inscribed radius / circumradius double a [3] = {xc - xb, yc - yb, zc - zb}; double b [3] = {xa - xc, ya - yc, za - zc}; double c [3] = {xb - xa, yb - ya, zb - za}; norme(a); norme(b); norme(c); double pva [3]; prodve(b, c, pva); const double sina = norm3(pva); double pvb [3]; prodve(c, a, pvb); const double sinb = norm3(pvb); double pvc [3]; prodve(a, b, pvc); const double sinc = norm3(pvc); if (sina == 0.0 && sinb == 0.0 && sinc == 0.0) quality = 0.0; else quality = 2 * (2 * sina * sinb * sinc / (sina + sinb + sinc)); } break; // condition number case QMTRI_COND: { /* double a [3] = {xc - xa, yc - ya, zc - za}; double b [3] = {xb - xa, yb - ya, zb - za}; double c [3] ; prodve(a, b, c); norme(c); double A[3][3] = {{a[0] , b[0] , c[0]} , {a[1] , b[1] , c[1]} , {a[2] , b[2] , c[2]}}; */ quality = -1; } break; default: Msg::Error("Unknown quality measure"); return 0.; } return quality; }
int IsoSimplex(double *X, double *Y, double *Z, double *Val, double V, double *Xp, double *Yp, double *Zp, double n[3]) { if(Val[0] == Val[1] && Val[0] == Val[2] && Val[0] == Val[3]) return 0; int nb = 0; if((Val[0] >= V && Val[1] <= V) || (Val[1] >= V && Val[0] <= V)) { InterpolateIso(X, Y, Z, Val, V, 0, 1, &Xp[nb], &Yp[nb], &Zp[nb]); nb++; } if((Val[0] >= V && Val[2] <= V) || (Val[2] >= V && Val[0] <= V)) { InterpolateIso(X, Y, Z, Val, V, 0, 2, &Xp[nb], &Yp[nb], &Zp[nb]); nb++; } if((Val[0] >= V && Val[3] <= V) || (Val[3] >= V && Val[0] <= V)) { InterpolateIso(X, Y, Z, Val, V, 0, 3, &Xp[nb], &Yp[nb], &Zp[nb]); nb++; } if((Val[1] >= V && Val[2] <= V) || (Val[2] >= V && Val[1] <= V)) { InterpolateIso(X, Y, Z, Val, V, 1, 2, &Xp[nb], &Yp[nb], &Zp[nb]); nb++; } if((Val[1] >= V && Val[3] <= V) || (Val[3] >= V && Val[1] <= V)) { InterpolateIso(X, Y, Z, Val, V, 1, 3, &Xp[nb], &Yp[nb], &Zp[nb]); nb++; } if((Val[2] >= V && Val[3] <= V) || (Val[3] >= V && Val[2] <= V)) { InterpolateIso(X, Y, Z, Val, V, 2, 3, &Xp[nb], &Yp[nb], &Zp[nb]); nb++; } // Remove identical nodes (this can happen if an edge belongs to the // zero levelset). We should be doing this even for nb < 4, but it // would slow us down even more (and we don't really care if some // nodes in a postprocessing element are identical) if(nb > 4) { double xi[6], yi[6], zi[6]; affect(xi, yi, zi, 0, Xp, Yp, Zp, 0); int ni = 1; for(int j = 1; j < nb; j++) { for(int i = 0; i < ni; i++) { if(fabs(Xp[j] - xi[i]) < 1.e-12 && fabs(Yp[j] - yi[i]) < 1.e-12 && fabs(Zp[j] - zi[i]) < 1.e-12) { break; } if(i == ni - 1) { affect(xi, yi, zi, i + 1, Xp, Yp, Zp, j); ni++; } } } for(int i = 0; i < ni; i++) affect(Xp, Yp, Zp, i, xi, yi, zi, i); nb = ni; } if(nb < 3 || nb > 4) return 0; // 3 possible quads at this point: (0,2,5,3), (0,1,5,4) or // (1,2,4,3), so simply invert the 2 last vertices for having the // quad ordered if(nb == 4) { double x = Xp[3], y = Yp[3], z = Zp[3]; Xp[3] = Xp[2]; Yp[3] = Yp[2]; Zp[3] = Zp[2]; Xp[2] = x; Yp[2] = y; Zp[2] = z; } // to get a nice isosurface, we should have n . grad v > 0, where n // is the normal to the polygon and v is the unknown field we want // to draw double v1[3] = {Xp[2] - Xp[0], Yp[2] - Yp[0], Zp[2] - Zp[0]}; double v2[3] = {Xp[1] - Xp[0], Yp[1] - Yp[0], Zp[1] - Zp[0]}; prodve(v1, v2, n); norme(n); double g[3]; gradSimplex(X, Y, Z, Val, g); double gdotn; prosca(g, n, &gdotn); if(gdotn > 0.) { double Xpi[6], Ypi[6], Zpi[6]; for(int i = 0; i < nb; i++) { Xpi[i] = Xp[i]; Ypi[i] = Yp[i]; Zpi[i] = Zp[i]; } for(int i = 0; i < nb; i++) { Xp[i] = Xpi[nb - i - 1]; Yp[i] = Ypi[nb - i - 1]; Zp[i] = Zpi[nb - i - 1]; } } else { n[0] = -n[0]; n[1] = -n[1]; n[2] = -n[2]; } return nb; }
int CutTriangle(double *X, double *Y, double *Z, double *Val, double V1, double V2, double *Xp2, double *Yp2, double *Zp2, double *Vp2) { // fill io so that it contains an indexing of the nodes such that // Val[io[i]] > Val[io[j]] if i > j int io[3] = {0, 1, 2}; for(int i = 0; i < 2; i++) { for(int j = i + 1; j < 3; j++) { if(Val[io[i]] > Val[io[j]]) { int iot = io[i]; io[i] = io[j]; io[j] = iot; } } } if(Val[io[0]] > V2 || Val[io[2]] < V1) return 0; if(V1 <= Val[io[0]] && Val[io[2]] <= V2) { for(int i = 0; i < 3; i++) { Vp2[i] = Val[i]; Xp2[i] = X[i]; Yp2[i] = Y[i]; Zp2[i] = Z[i]; } return 3; } int Np = 0, Fl = 0; double Xp[10], Yp[10], Zp[10], Vp[10]; if(V1 <= Val[io[0]]) { Vp[Np] = Val[io[0]]; Xp[Np] = X[io[0]]; Yp[Np] = Y[io[0]]; Zp[Np] = Z[io[0]]; Np++; Fl = 1; } else if(Val[io[0]] < V1 && V1 <= Val[io[1]]) { Vp[Np] = V1; InterpolateIso(X, Y, Z, Val, V1, io[0], io[2], &Xp[Np], &Yp[Np], &Zp[Np]); Np++; Vp[Np] = V1; InterpolateIso(X, Y, Z, Val, V1, io[0], io[1], &Xp[Np], &Yp[Np], &Zp[Np]); Np++; Fl = 1; } else { Vp[Np] = V1; InterpolateIso(X, Y, Z, Val, V1, io[0], io[2], &Xp[Np], &Yp[Np], &Zp[Np]); Np++; Vp[Np] = V1; InterpolateIso(X, Y, Z, Val, V1, io[1], io[2], &Xp[Np], &Yp[Np], &Zp[Np]); Np++; Fl = 0; } if(V2 == Val[io[0]]) { return 0; } else if((Val[io[0]] < V2) && (V2 < Val[io[1]])) { Vp[Np] = V2; InterpolateIso(X, Y, Z, Val, V2, io[0], io[1], &Xp[Np], &Yp[Np], &Zp[Np]); Np++; Vp[Np] = V2; InterpolateIso(X, Y, Z, Val, V2, io[0], io[2], &Xp[Np], &Yp[Np], &Zp[Np]); Np++; } else if(V2 < Val[io[2]]) { if(Fl) { Vp[Np] = Val[io[1]]; Xp[Np] = X[io[1]]; Yp[Np] = Y[io[1]]; Zp[Np] = Z[io[1]]; Np++; } Vp[Np] = V2; InterpolateIso(X, Y, Z, Val, V2, io[1], io[2], &Xp[Np], &Yp[Np], &Zp[Np]); Np++; Vp[Np] = V2; InterpolateIso(X, Y, Z, Val, V2, io[0], io[2], &Xp[Np], &Yp[Np], &Zp[Np]); Np++; } else { if(Fl) { Vp[Np] = Val[io[1]]; Xp[Np] = X[io[1]]; Yp[Np] = Y[io[1]]; Zp[Np] = Z[io[1]]; Np++; } Vp[Np] = Val[io[2]]; Xp[Np] = X[io[2]]; Yp[Np] = Y[io[2]]; Zp[Np] = Z[io[2]]; Np++; } Vp2[0] = Vp[0]; Xp2[0] = Xp[0]; Yp2[0] = Yp[0]; Zp2[0] = Zp[0]; int Np2 = 1; for(int i = 1; i < Np; i++) { if((Xp[i] != Xp2[Np2 - 1]) || (Yp[i] != Yp2[Np2 - 1]) || (Zp[i] != Zp2[Np2 - 1])){ Vp2[Np2] = Vp[i]; Xp2[Np2] = Xp[i]; Yp2[Np2] = Yp[i]; Zp2[Np2] = Zp[i]; Np2++; } } if(Xp2[0] == Xp2[Np2 - 1] && Yp2[0] == Yp2[Np2 - 1] && Zp2[0] == Zp2[Np2 - 1]) { Np2--; } // check and fix orientation double in1[3] = {X[1] - X[0], Y[1] - Y[0], Z[1] - Z[0]}; double in2[3] = {X[2] - X[0], Y[2] - Y[0], Z[2] - Z[0]}; double inn[3]; prodve(in1, in2, inn); double out1[3] = {Xp2[1] - Xp2[0], Yp2[1] - Yp2[0], Zp2[1] - Zp2[0]}; double out2[3] = {Xp2[2] - Xp2[0], Yp2[2] - Yp2[0], Zp2[2] - Zp2[0]}; double outn[3]; prodve(out1, out2, outn); double res; prosca(inn, outn, &res); if(res < 0){ for(int i = 0; i < Np2; i++){ Vp[i] = Vp2[Np2 - i - 1]; Xp[i] = Xp2[Np2 - i - 1]; Yp[i] = Yp2[Np2 - i - 1]; Zp[i] = Zp2[Np2 - i - 1]; } for(int i = 0; i < Np2; i++){ Vp2[i] = Vp[i]; Xp2[i] = Xp[i]; Yp2[i] = Yp[i]; Zp2[i] = Zp[i]; } } return Np2; }
static void eigen(std::vector<double> &inList, int inNb, std::vector<double> &outList, int *outNb, int nbTime, int nbNod, int nbComp, int lam) { if(!inNb || (nbComp != 3 && nbComp != 9) || lam < 1 || lam > 3) return; // loop on elements int nb = inList.size() / inNb; for(std::size_t i = 0; i < inList.size(); i += nb) { // copy node coordinates for(int j = 0; j < 3 * nbNod; j++) outList.push_back(inList[i + j]); // loop on time steps for(int j = 0; j < nbTime; j++) { double *x = &inList[i]; double *y = &inList[i + nbNod]; double *z = &inList[i + 2 * nbNod]; double GradVel[3][3]; if(nbComp == 9) { // val is the velocity gradient tensor: we assume that it is // constant per element double *v = &inList[i + 3 * nbNod + nbNod * nbComp * j + nbComp * 0]; GradVel[0][0] = v[0]; GradVel[0][1] = v[1]; GradVel[0][2] = v[2]; GradVel[1][0] = v[3]; GradVel[1][1] = v[4]; GradVel[1][2] = v[5]; GradVel[2][0] = v[6]; GradVel[2][1] = v[7]; GradVel[2][2] = v[8]; } else if(nbComp == 3) { // FIXME: the following could be greatly simplified and // generalized by using the classes in shapeFunctions.h // val contains the velocities: compute the gradient tensor // from them const int MAX_NOD = 4; double val[3][MAX_NOD]; for(int k = 0; k < nbNod; k++) { double *v = &inList[i + 3 * nbNod + nbNod * nbComp * j + nbComp * k]; for(int l = 0; l < 3; l++) { val[l][k] = v[l]; } } // compute gradient of shape functions double GradPhi_x[MAX_NOD][3]; double GradPhi_ksi[MAX_NOD][3]; double dx_dksi[3][3]; double dksi_dx[3][3]; double det; if(nbNod == 3) { // triangles double a[3], b[3], cross[3]; a[0] = x[1] - x[0]; a[1] = y[1] - y[0]; a[2] = z[1] - z[0]; b[0] = x[2] - x[0]; b[1] = y[2] - y[0]; b[2] = z[2] - z[0]; prodve(a, b, cross); dx_dksi[0][0] = x[1] - x[0]; dx_dksi[0][1] = x[2] - x[0]; dx_dksi[0][2] = cross[0]; dx_dksi[1][0] = y[1] - y[0]; dx_dksi[1][1] = y[2] - y[0]; dx_dksi[1][2] = cross[1]; dx_dksi[2][0] = z[1] - z[0]; dx_dksi[2][1] = z[2] - z[0]; dx_dksi[2][2] = cross[2]; inv3x3tran(dx_dksi, dksi_dx, &det); GradPhi_ksi[0][0] = -1; GradPhi_ksi[0][1] = -1; GradPhi_ksi[0][2] = 0; GradPhi_ksi[1][0] = 1; GradPhi_ksi[1][1] = 0; GradPhi_ksi[1][2] = 0; GradPhi_ksi[2][0] = 0; GradPhi_ksi[2][1] = 1; GradPhi_ksi[2][2] = 0; } else if(nbNod == 4) { // tetrahedra dx_dksi[0][0] = x[1] - x[0]; dx_dksi[0][1] = x[2] - x[0]; dx_dksi[0][2] = x[3] - x[0]; dx_dksi[1][0] = y[1] - y[0]; dx_dksi[1][1] = y[2] - y[0]; dx_dksi[1][2] = y[3] - y[0]; dx_dksi[2][0] = z[1] - z[0]; dx_dksi[2][1] = z[2] - z[0]; dx_dksi[2][2] = z[3] - z[0]; inv3x3tran(dx_dksi, dksi_dx, &det); GradPhi_ksi[0][0] = -1; GradPhi_ksi[0][1] = -1; GradPhi_ksi[0][2] = -1; GradPhi_ksi[1][0] = 1; GradPhi_ksi[1][1] = 0; GradPhi_ksi[1][2] = 0; GradPhi_ksi[2][0] = 0; GradPhi_ksi[2][1] = 1; GradPhi_ksi[2][2] = 0; GradPhi_ksi[3][0] = 0; GradPhi_ksi[3][1] = 0; GradPhi_ksi[3][2] = 1; } else { Msg::Error("Lambda2 not ready for this type of element"); return; } for(int k = 0; k < nbNod; k++) { for(int l = 0; l < 3; l++) { GradPhi_x[k][l] = 0.0; for(int m = 0; m < 3; m++) { GradPhi_x[k][l] += GradPhi_ksi[k][m] * dksi_dx[l][m]; } } } // compute gradient of velocities for(int k = 0; k < 3; k++) { for(int l = 0; l < 3; l++) { GradVel[k][l] = 0.0; for(int m = 0; m < nbNod; m++) { GradVel[k][l] += val[k][m] * GradPhi_x[m][l]; } } } } else for(int k = 0; k < 3; k++) for(int l = 0; l < 3; l++) GradVel[k][l] = 0.0; // compute the sym and antisymetric parts double sym[3][3]; double asym[3][3]; for(int m = 0; m < 3; m++) { for(int n = 0; n < 3; n++) { sym[m][n] = 0.5 * (GradVel[m][n] + GradVel[n][m]); asym[m][n] = 0.5 * (GradVel[m][n] - GradVel[n][m]); } } double a[3][3]; for(int m = 0; m < 3; m++) { for(int n = 0; n < 3; n++) { a[m][n] = 0.0; for(int l = 0; l < 3; l++) a[m][n] += sym[m][l] * sym[l][n] + asym[m][l] * asym[l][n]; } } // compute the eigenvalues double lambda[3]; eigenvalue(a, lambda); for(int k = 0; k < nbNod; k++) outList.push_back(lambda[lam - 1]); } (*outNb)++; } }
double qmTriangleAngles (MTriangle *e) { double a = 500; double worst_quality = std::numeric_limits<double>::max(); double mat[3][3]; double mat2[3][3]; double den = atan(a*(M_PI/9)) + atan(a*(M_PI/9)); // This matrix is used to "rotate" the triangle to get each vertex // as the "origin" of the mapping in turn double rot[3][3]; rot[0][0]=-1; rot[0][1]=1; rot[0][2]=0; rot[1][0]=-1; rot[1][1]=0; rot[1][2]=0; rot[2][0]= 0; rot[2][1]=0; rot[2][2]=1; double tmp[3][3]; //double minAngle = 120.0; for (int i = 0; i < e->getNumPrimaryVertices(); i++) { const double u = i == 1 ? 1 : 0; const double v = i == 2 ? 1 : 0; const double w = 0; e->getJacobian(u, v, w, mat); e->getPrimaryJacobian(u,v,w,mat2); for (int j = 0; j < i; j++) { matmat(rot,mat,tmp); memcpy(mat, tmp, sizeof(mat)); } //get angle double v1[3] = {mat[0][0], mat[0][1], mat[0][2] }; double v2[3] = {mat[1][0], mat[1][1], mat[1][2] }; double v3[3] = {mat2[0][0], mat2[0][1], mat2[0][2] }; double v4[3] = {mat2[1][0], mat2[1][1], mat2[1][2] }; norme(v1); norme(v2); norme(v3); norme(v4); double v12[3], v34[3]; prodve(v1,v2,v12); prodve(v3,v4,v34); norme(v12); norme(v34); double orientation; prosca(v12,v34,&orientation); // If the triangle is "flipped" it's no good if (orientation < 0) return -std::numeric_limits<double>::max(); double c; prosca(v1,v2,&c); double x = acos(c)-M_PI/3; //double angle = (x+M_PI/3)/M_PI*180; double quality = (atan(a*(x+M_PI/9)) + atan(a*(M_PI/9-x)))/den; worst_quality = std::min(worst_quality, quality); //minAngle = std::min(angle, minAngle); //printf("Angle %g ", angle); // printf("Quality %g\n",quality); } //printf("MinAngle %g \n", minAngle); //return minAngle; return worst_quality; }
void GMSH_LevelsetPlugin::_cutAndAddElements(PViewData *vdata, PViewData *wdata, int ent, int ele, int vstep, int wstep, double x[8], double y[8], double z[8], double levels[8], double scalarValues[8], PViewDataList* out) { int stepmin = vstep, stepmax = vstep + 1, otherstep = wstep; if(stepmin < 0){ stepmin = vdata->getFirstNonEmptyTimeStep(); stepmax = vdata->getNumTimeSteps(); } if(wstep < 0) otherstep = wdata->getFirstNonEmptyTimeStep(); int numNodes = vdata->getNumNodes(stepmin, ent, ele); int numEdges = vdata->getNumEdges(stepmin, ent, ele); int numComp = wdata->getNumComponents(otherstep, ent, ele); int type = vdata->getType(stepmin, ent, ele); // decompose the element into simplices for(int simplex = 0; simplex < numSimplexDec(type); simplex++){ int n[4], ep[12], nsn, nse; getSimplexDec(numNodes, numEdges, type, simplex, n[0], n[1], n[2], n[3], nsn, nse); // loop over time steps for(int step = stepmin; step < stepmax; step++){ // check which edges cut the iso and interpolate the value if(wstep < 0) otherstep = step; if(!wdata->hasTimeStep(otherstep)) continue; int np = 0; double xp[12], yp[12], zp[12], valp[12][9]; for(int i = 0; i < nse; i++){ int n0 = exn[nse][i][0], n1 = exn[nse][i][1]; if(levels[n[n0]] * levels[n[n1]] <= 0.) { double c = InterpolateIso(x, y, z, levels, 0., n[n0], n[n1], &xp[np], &yp[np], &zp[np]); for(int comp = 0; comp < numComp; comp++){ double v0, v1; wdata->getValue(otherstep, ent, ele, n[n0], comp, v0); wdata->getValue(otherstep, ent, ele, n[n1], comp, v1); valp[np][comp] = v0 + c * (v1 - v0); } ep[np++] = i + 1; } } // remove identical nodes (this can happen if an edge actually // belongs to the zero levelset, i.e., if levels[] * levels[] == 0) if(np > 1) removeIdenticalNodes(&np, numComp, xp, yp, zp, valp, ep); // if there are no cuts and we extract the volume, save the full // element if it is on the correct side of the levelset if(np <= 1 && _extractVolume){ bool add = true; for(int nod = 0; nod < nsn; nod++){ if((_extractVolume < 0. && levels[n[nod]] > 0.) || (_extractVolume > 0. && levels[n[nod]] < 0.)){ add = false; break; } } if(add){ for(int nod = 0; nod < nsn; nod++){ xp[nod] = x[n[nod]]; yp[nod] = y[n[nod]]; zp[nod] = z[n[nod]]; for(int comp = 0; comp < numComp; comp++) wdata->getValue(otherstep, ent, ele, n[nod], comp, valp[nod][comp]); } _addElement(nsn, nse, numComp, xp, yp, zp, valp, out, step == stepmin); } continue; } // discard invalid cases if(numEdges > 4 && np < 3) // 3D input should only lead to 2D output continue; else if(numEdges > 1 && np < 2) // 2D input should only lead to 1D output continue; else if(np < 1 || np > 4) // can't deal with this continue; // avoid "butterflies" if(np == 4) reorderQuad(numComp, xp, yp, zp, valp, ep); // orient the triangles and the quads to get the normals right if(!_extractVolume && (np == 3 || np == 4)) { // compute invertion test only once for spatially-fixed views if(step == stepmin || !_valueIndependent) { double v1[3] = {xp[2] - xp[0], yp[2] - yp[0], zp[2] - zp[0]}; double v2[3] = {xp[1] - xp[0], yp[1] - yp[0], zp[1] - zp[0]}; double gr[3], normal[3]; prodve(v1, v2, normal); switch (_orientation) { case MAP: gradSimplex(x, y, z, scalarValues, gr); prosca(gr, normal, &_invert); break; case PLANE: prosca(normal, _ref, &_invert); break; case SPHERE: gr[0] = xp[0] - _ref[0]; gr[1] = yp[0] - _ref[1]; gr[2] = zp[0] - _ref[2]; prosca(gr, normal, &_invert); case NONE: default: break; } } if(_invert > 0.) { double xpi[12], ypi[12], zpi[12], valpi[12][9]; int epi[12]; for(int k = 0; k < np; k++) affect(xpi, ypi, zpi, valpi, epi, k, xp, yp, zp, valp, ep, k, numComp); for(int k = 0; k < np; k++) affect(xp, yp, zp, valp, ep, k, xpi, ypi, zpi, valpi, epi, np - k - 1, numComp); } } // if we extract volumes, add the nodes on the chosen side // (FIXME: when cutting 2D views, the elts can have the wrong // orientation) if(_extractVolume){ int nbCut = np; for(int nod = 0; nod < nsn; nod++){ if((_extractVolume < 0. && levels[n[nod]] < 0.) || (_extractVolume > 0. && levels[n[nod]] > 0.)){ xp[np] = x[n[nod]]; yp[np] = y[n[nod]]; zp[np] = z[n[nod]]; for(int comp = 0; comp < numComp; comp++) wdata->getValue(otherstep, ent, ele, n[nod], comp, valp[np][comp]); ep[np] = -(nod + 1); // store node num! np++; } } removeIdenticalNodes(&np, numComp, xp, yp, zp, valp, ep); if(np == 4 && numEdges <= 4) reorderQuad(numComp, xp, yp, zp, valp, ep); if(np == 6) reorderPrism(numComp, xp, yp, zp, valp, ep, nbCut); if(np > 8) // can't deal with this continue; } // finally, add the new element _addElement(np, numEdges, numComp, xp, yp, zp, valp, out, step == stepmin); } if(vstep < 0){ for(int i = stepmin; i < stepmax; i++) { out->Time.push_back(vdata->getTime(i)); } } } }