SVector3 gmshFace::normal(const SPoint2 ¶m) const { if(s->Typ != MSH_SURF_PLAN){ Vertex vu = InterpolateSurface(s, param[0], param[1], 1, 1); Vertex vv = InterpolateSurface(s, param[0], param[1], 1, 2); Vertex n = vu % vv; n.norme(); return SVector3(n.Pos.X, n.Pos.Y, n.Pos.Z); } else{ // We cannot use InterpolateSurface() for plane surfaces since it // relies on the mean plane, which does not respect the // orientation // FIXME: move this test at the end of the MeanPlane computation // routine--and store the correct normal, damn it! double n[3] = {meanPlane.a, meanPlane.b, meanPlane.c}; norme(n); GPoint pt = point(param.x(), param.y()); double v[3] = {pt.x(), pt.y(), pt.z()}; int NP = 10, tries = 0; while(1){ tries++; double angle = 0.; for(int i = 0; i < List_Nbr(s->Generatrices); i++) { Curve *c; List_Read(s->Generatrices, i, &c); int N = (c->Typ == MSH_SEGM_LINE) ? 1 : NP; for(int j = 0; j < N; j++) { double u1 = (double)j / (double)N; double u2 = (double)(j + 1) / (double)N; Vertex p1 = InterpolateCurve(c, u1, 0); Vertex p2 = InterpolateCurve(c, u2, 0); double v1[3] = {p1.Pos.X, p1.Pos.Y, p1.Pos.Z}; double v2[3] = {p2.Pos.X, p2.Pos.Y, p2.Pos.Z}; angle += angle_plan(v, v1, v2, n); } } if(fabs(angle) < 0.5){ // we're outside NP *= 2; Msg::Debug("Could not compute normal of surface %d - retrying with %d points", tag(), NP); if(tries > 10){ Msg::Warning("Could not orient normal of surface %d", tag()); return SVector3(n[0], n[1], n[2]); } } else if(angle > 0) return SVector3(n[0], n[1], n[2]); else return SVector3(-n[0], -n[1], -n[2]); } } }
Pair<SVector3, SVector3> gmshFace::firstDer(const SPoint2 ¶m) const { if(s->Typ == MSH_SURF_PLAN && !s->geometry){ double x, y, z, VX[3], VY[3]; getMeanPlaneData(VX, VY, x, y, z); return Pair<SVector3, SVector3>(SVector3(VX[0], VX[1], VX[2]), SVector3(VY[0], VY[1], VY[2])); } else{ Vertex vu = InterpolateSurface(s, param[0], param[1], 1, 1); Vertex vv = InterpolateSurface(s, param[0], param[1], 1, 2); return Pair<SVector3, SVector3>(SVector3(vu.Pos.X, vu.Pos.Y, vu.Pos.Z), SVector3(vv.Pos.X, vv.Pos.Y, vv.Pos.Z)); } }
void gmshFace::secondDer(const SPoint2 ¶m, SVector3 *dudu, SVector3 *dvdv, SVector3 *dudv) const { if(s->Typ == MSH_SURF_PLAN && !s->geometry){ *dudu = SVector3(0., 0., 0.); *dvdv = SVector3(0., 0., 0.); *dudv = SVector3(0., 0., 0.); } else{ Vertex vuu = InterpolateSurface(s, param[0], param[1], 2, 1); Vertex vvv = InterpolateSurface(s, param[0], param[1], 2, 2); Vertex vuv = InterpolateSurface(s, param[0], param[1], 2, 3); *dudu = SVector3(vuu.Pos.X,vuu.Pos.Y,vuu.Pos.Z); *dvdv = SVector3(vvv.Pos.X,vvv.Pos.Y,vvv.Pos.Z); *dudv = SVector3(vuv.Pos.X,vuv.Pos.Y,vuv.Pos.Z); } }
GPoint gmshFace::point(double par1, double par2) const { double pp[2] = {par1, par2}; if(s->Typ == MSH_SURF_PLAN && !s->geometry){ double x, y, z, VX[3], VY[3]; getMeanPlaneData(VX, VY, x, y, z); return GPoint(x + VX[0] * par1 + VY[0] * par2, y + VX[1] * par1 + VY[1] * par2, z + VX[2] * par1 + VY[2] * par2, this, pp); } else{ Vertex v = InterpolateSurface(s, par1, par2, 0, 0); return GPoint(v.Pos.X, v.Pos.Y, v.Pos.Z, this, pp); } }
Vertex InterpolateSurface(Surface *s, double u, double v, int derivee, int u_v) { if(derivee == 1) { double eps = 1.e-8; Vertex D[4]; if(u_v == 1) { if(u - eps < 0.0) { D[0] = InterpolateSurface(s, u, v, 0, 0); D[1] = InterpolateSurface(s, u + eps, v, 0, 0); } else { D[0] = InterpolateSurface(s, u - eps, v, 0, 0); D[1] = InterpolateSurface(s, u, v, 0, 0); } } else { if(v - eps < 0.0) { D[0] = InterpolateSurface(s, u, v, 0, 0); D[1] = InterpolateSurface(s, u, v + eps, 0, 0); } else { D[0] = InterpolateSurface(s, u, v - eps, 0, 0); D[1] = InterpolateSurface(s, u, v, 0, 0); } } return Vertex((D[1].Pos.X - D[0].Pos.X) / eps, (D[1].Pos.Y - D[0].Pos.Y) / eps, (D[1].Pos.Z - D[0].Pos.Z) / eps); } else if (derivee == 2) { double eps = 1.e-6; Vertex D[2]; if(u_v == 1) { // dudu if(u - eps < 0.0) { D[0] = InterpolateSurface(s, u, v, 1, 1); D[1] = InterpolateSurface(s, u + eps, v, 1, 1); } else { D[0] = InterpolateSurface(s, u - eps, v, 1, 1); D[1] = InterpolateSurface(s, u, v, 1, 1); } } else if(u_v == 2) { // dvdv if(v - eps < 0.0) { D[0] = InterpolateSurface(s, u, v, 1, 2); D[1] = InterpolateSurface(s, u, v + eps, 1, 2); } else { D[0] = InterpolateSurface(s, u, v - eps, 1, 2); D[1] = InterpolateSurface(s, u, v, 1, 2); } } else { // dudv if(v - eps < 0.0) { D[0] = InterpolateSurface(s, u, v, 1, 1); D[1] = InterpolateSurface(s, u, v + eps, 1, 1); } else { D[0] = InterpolateSurface(s, u, v - eps, 1, 1); D[1] = InterpolateSurface(s, u, v, 1, 1); } } return Vertex((D[1].Pos.X - D[0].Pos.X) / eps, (D[1].Pos.Y - D[0].Pos.Y) / eps, (D[1].Pos.Z - D[0].Pos.Z) / eps); } if(s->geometry){ SPoint3 p = s->geometry->point(u, v); return Vertex(p.x(), p.y(), p.z()); } // Warning: we use the exact extrusion formula so we can create // exact surfaces of revolution. This WILL fail if the surface is // transformed after the extrusion: in that case set the // exactExtrusion option to 0 to use the normal code path if(CTX::instance()->geom.exactExtrusion && s->Extrude && s->Extrude->geo.Mode == EXTRUDED_ENTITY && s->Typ != MSH_SURF_PLAN) return InterpolateExtrudedSurface(s, u, v); switch (s->Typ) { case MSH_SURF_REGL: case MSH_SURF_TRIC: return InterpolateRuledSurface(s, u, v); case MSH_SURF_PLAN: Msg::Error("Should never interpolate plane surface in InterpolateSurface()"); return Vertex(0., 0., 0.); case MSH_SURF_BND_LAYER: Msg::Error("Cannot interpolate boundary layer surface"); return Vertex(0., 0., 0.); case MSH_SURF_DISCRETE: Msg::Error("Cannot interpolate discrete surface"); return Vertex(0., 0., 0.); default: Msg::Error("Unknown surface type in interpolation"); return Vertex(0., 0., 0.); } }