bool gmshFace::containsPoint(const SPoint3 &pt) const { if(s->Typ == MSH_SURF_PLAN){ // OK to use the normal from the mean plane here: we compensate // for the (possibly wrong) orientation at the end double n[3] = {meanPlane.a, meanPlane.b, meanPlane.c}; norme(n); double angle = 0.; double v[3] = {pt.x(), pt.y(), pt.z()}; 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 : 10; 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); } } // we're inside if angle equals 2 * pi if(fabs(angle) > 2 * M_PI - 0.5 && fabs(angle) < 2 * M_PI + 0.5) return true; return false; } return false; }
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]); } } }
static Vertex InterpolateExtrudedSurface(Surface *s, double u, double v) { Curve *c = FindCurve(s->Extrude->geo.Source); // find position of c in the list of generatrices int num = -1; for(int i = 0; i < List_Nbr(s->Generatrices); i++){ if(c == *(Curve**)List_Pointer(s->Generatrices, i)){ num = i; break; } } Vertex T; if(num < 0){ Msg::Error("Unknown curve in extruded surface"); return T; } switch(num){ case 0: T = InterpolateCurve(c, c->ubeg + (c->uend - c->ubeg) * u, 0); s->Extrude->Extrude(v, T.Pos.X, T.Pos.Y, T.Pos.Z); return T; case 1: T = InterpolateCurve(c, c->ubeg + (c->uend - c->ubeg) * v, 0); s->Extrude->Extrude(1. - u, T.Pos.X, T.Pos.Y, T.Pos.Z); return T; case 2: T = InterpolateCurve(c, c->ubeg + (c->uend - c->ubeg) * (1. - u), 0); s->Extrude->Extrude(1. - v, T.Pos.X, T.Pos.Y, T.Pos.Z); return T; default: T = InterpolateCurve(c, c->ubeg + (c->uend - c->ubeg) * (1. - v), 0); s->Extrude->Extrude(u, T.Pos.X, T.Pos.Y, T.Pos.Z); return T; } }
SVector3 gmshEdge::secondDer(double par) const { Vertex a = InterpolateCurve(c, par, 2); return SVector3(a.Pos.X, a.Pos.Y, a.Pos.Z); }
GPoint gmshEdge::point(double par) const { Vertex a = InterpolateCurve(c, par, 0); return GPoint(a.Pos.X, a.Pos.Y, a.Pos.Z, this, par); }
static Vertex InterpolateRuledSurface(Surface *s, double u, double v) { Curve *C[4] = {0, 0, 0, 0}; for(int i = 0; i < std::min(List_Nbr(s->Generatrices), 4); i++) List_Read(s->Generatrices, i, &C[i]); Vertex *O = 0; bool isSphere = true; // Ugly hack: "fix" transfinite interpolation if we have a sphere // patch if(List_Nbr(s->InSphereCenter)) { // it's on a sphere: get the center List_Read(s->InSphereCenter, 0, &O); } else{ // try to be intelligent (hum) for(int i = 0; i < std::min(List_Nbr(s->Generatrices), 4); i++) { if(C[i]->Typ != MSH_SEGM_CIRC && C[i]->Typ != MSH_SEGM_CIRC_INV){ isSphere = false; } else if(isSphere){ if(!i){ List_Read(C[i]->Control_Points, 1, &O); } else{ Vertex *tmp; List_Read(C[i]->Control_Points, 1, &tmp); if(compareVertex(&O, &tmp)) isSphere = false; } } } if(isSphere){ double n[3] = {C[0]->Circle.invmat[0][2], C[0]->Circle.invmat[1][2], C[0]->Circle.invmat[2][2]}; bool isPlane = true; for(int i = 1; i < std::min(List_Nbr(s->Generatrices), 4); i++) isPlane &= (n[0] == C[i]->Circle.invmat[0][2] && n[1] == C[i]->Circle.invmat[1][2] && n[2] == C[i]->Circle.invmat[2][2]); if(isPlane) isSphere = false; } } Vertex *S[4], V[4],VB[3], T; if(s->Typ == MSH_SURF_REGL && List_Nbr(s->Generatrices) >= 4){ S[0] = C[0]->beg; S[1] = C[1]->beg; S[2] = C[2]->beg; S[3] = C[3]->beg; V[0] = InterpolateCurve(C[0], C[0]->ubeg + (C[0]->uend - C[0]->ubeg) * u, 0); V[1] = InterpolateCurve(C[1], C[1]->ubeg + (C[1]->uend - C[1]->ubeg) * v, 0); V[2] = InterpolateCurve(C[2], C[2]->ubeg + (C[2]->uend - C[2]->ubeg) * (1. - u), 0); V[3] = InterpolateCurve(C[3], C[3]->ubeg + (C[3]->uend - C[3]->ubeg) * (1. - v), 0); /* #if defined(HAVE_BFGS) printf("----- u %f v %f %g %g\n", u, v,C[1]->ubeg,C[1]->uend); printf("S[0] %f %f %f\n", S[0]->Pos.X, S[0]->Pos.Y,S[0]->Pos.Z); printf("S[1] %f %f %f\n", S[1]->Pos.X, S[1]->Pos.Y,S[1]->Pos.Z); printf("S[2] %f %f %f\n", S[2]->Pos.X, S[2]->Pos.Y,S[2]->Pos.Z); printf("S[3] %f %f %f\n", S[3]->Pos.X, S[3]->Pos.Y,S[3]->Pos.Z); printf("V[0] %f %f %f\n", V[0].Pos.X, V[0].Pos.Y,V[0].Pos.Z); printf("V[1] %f %f %f\n", V[1].Pos.X, V[1].Pos.Y,V[1].Pos.Z); printf("V[2] %f %f %f\n", V[2].Pos.X, V[2].Pos.Y,V[2].Pos.Z); printf("V[3] %f %f %f\n", V[3].Pos.X, V[3].Pos.Y,V[3].Pos.Z); #endif */ T = TransfiniteQua(V[0], V[1], V[2], V[3], *S[0], *S[1], *S[2], *S[3], u, v); if(isSphere) TransfiniteSph(*S[0], *O, &T); } else if(List_Nbr(s->Generatrices) >= 3){ S[0] = C[0]->beg; S[1] = C[1]->beg; S[2] = C[2]->beg; if(CTX::instance()->geom.oldRuledSurface){ V[0] = InterpolateCurve(C[0], C[0]->ubeg + (C[0]->uend - C[0]->ubeg) * u, 0); V[1] = InterpolateCurve(C[1], C[1]->ubeg + (C[1]->uend - C[1]->ubeg) * v, 0); V[2] = InterpolateCurve(C[2], C[2]->ubeg + (C[2]->uend - C[2]->ubeg) * (1. - u), 0); T = TransfiniteTri(V[0], V[1], V[2], *S[0], *S[1], *S[2], u, v); } else{ V[0] = InterpolateCurve(C[0], C[0]->ubeg + (C[0]->uend - C[0]->ubeg) * (u-v), 0); V[1] = InterpolateCurve(C[1], C[1]->ubeg + (C[1]->uend - C[1]->ubeg) * v, 0); V[2] = InterpolateCurve(C[2], C[2]->ubeg + (C[2]->uend - C[2]->ubeg) * (1. - u), 0); VB[0] = InterpolateCurve(C[0], C[0]->ubeg + (C[0]->uend - C[0]->ubeg) * u, 0); VB[1] = InterpolateCurve(C[1], C[1]->ubeg + (C[1]->uend - C[1]->ubeg) * (1-u+v), 0); VB[2] = InterpolateCurve(C[2], C[2]->ubeg + (C[2]->uend - C[2]->ubeg) * (1. - v), 0); T = TransfiniteTriB(V[0],VB[0], V[1],VB[1], V[2],VB[2], *S[0], *S[1], *S[2], u, v); } if(isSphere) { TransfiniteSph(*S[0], *O, &T); } } return T; }
Vertex InterpolateCurve(Curve *c, double u, int derivee) { if(c->Num < 0) { Curve *C0 = FindCurve(-c->Num); if(!C0){ Msg::Error("Unknown curve %d", -c->Num); return Vertex(0., 0., 0.); } return InterpolateCurve(C0, C0->ubeg + (C0->uend - C0->ubeg) * (1. - u), derivee); } Vertex V; if(derivee==1) { // switch (c->Typ) { // case MSH_SEGM_BSPLN: // case MSH_SEGM_BEZIER: // V = InterpolateUBS(c, u, 1); // V.u = u; // break; // default : double eps1 = (u == 0) ? 0 : 1.e-5; double eps2 = (u == 1) ? 0 : 1.e-5; Vertex D[2]; D[0] = InterpolateCurve(c, u - eps1, 0); D[1] = InterpolateCurve(c, u + eps2, 0); V.Pos.X = (D[1].Pos.X - D[0].Pos.X) / (eps1 + eps2); V.Pos.Y = (D[1].Pos.Y - D[0].Pos.Y) / (eps1 + eps2); V.Pos.Z = (D[1].Pos.Z - D[0].Pos.Z) / (eps1 + eps2); V.u = u; // break; // } return V; } if(derivee==2) { switch (c->Typ) { case MSH_SEGM_BSPLN: V = InterpolateUBS(c, u, 2); V.u = u; break; case MSH_SEGM_BEZIER: V = InterpolateBezier(c, u, 2); V.u = u; break; default : double eps1 = (u == 0) ? 0 : 1.e-5; double eps2 = (u == 1) ? 0 : 1.e-5; Vertex D[2]; D[0] = InterpolateCurve(c, u - eps1, 1); D[1] = InterpolateCurve(c, u + eps2, 1); V.Pos.X = (D[1].Pos.X - D[0].Pos.X) / (eps1 + eps2); V.Pos.Y = (D[1].Pos.Y - D[0].Pos.Y) / (eps1 + eps2); V.Pos.Z = (D[1].Pos.Z - D[0].Pos.Z) / (eps1 + eps2); V.u = u; break; } return V; } int N, i; Vertex *v[5]; double theta, t1, t2, t; Vertex temp1, temp2; switch (c->Typ) { case MSH_SEGM_LINE: #if defined(HAVE_BFGS) // printf("MSH_SEGM_LINE\n"); #endif N = List_Nbr(c->Control_Points); i = (int)((double)(N - 1) * u); while(i >= N - 1) i--; while(i < 0) i++; t1 = (double)(i) / (double)(N - 1); t2 = (double)(i + 1) / (double)(N - 1); t = (u - t1) / (t2 - t1); List_Read(c->Control_Points, i, &v[1]); List_Read(c->Control_Points, i + 1, &v[2]); if(!c->geometry){ V.Pos.X = v[1]->Pos.X + t * (v[2]->Pos.X - v[1]->Pos.X); V.Pos.Y = v[1]->Pos.Y + t * (v[2]->Pos.Y - v[1]->Pos.Y); V.Pos.Z = v[1]->Pos.Z + t * (v[2]->Pos.Z - v[1]->Pos.Z); V.w = (1. - t) * v[1]->w + t * v[2]->w; V.lc = (1. - t) * v[1]->lc + t * v[2]->lc; } else{ SPoint2 p = v[1]->pntOnGeometry + (v[2]->pntOnGeometry - v[1]->pntOnGeometry) * t; SPoint3 pp = c->geometry->point(p); V.Pos.X = pp.x(); V.Pos.Y = pp.y(); V.Pos.Z = pp.z(); } break; case MSH_SEGM_CIRC: case MSH_SEGM_CIRC_INV: case MSH_SEGM_ELLI: case MSH_SEGM_ELLI_INV: if(c->Typ == MSH_SEGM_CIRC_INV || c->Typ == MSH_SEGM_ELLI_INV) { V.u = 1. - u; u = V.u; } theta = c->Circle.t1 - (c->Circle.t1 - c->Circle.t2) * u; theta -= c->Circle.incl; // for ellipses V.Pos.X = c->Circle.f1 * cos(theta) * cos(c->Circle.incl) - c->Circle.f2 * sin(theta) * sin(c->Circle.incl); V.Pos.Y = c->Circle.f1 * cos(theta) * sin(c->Circle.incl) + c->Circle.f2 * sin(theta) * cos(c->Circle.incl); V.Pos.Z = 0.0; Projette(&V, c->Circle.invmat); List_Read(c->Control_Points, 1, &v[0]); V.Pos.X += v[0]->Pos.X; V.Pos.Y += v[0]->Pos.Y; V.Pos.Z += v[0]->Pos.Z; V.w = (1. - u) * c->beg->w + u * c->end->w; V.lc = (1. - u) * c->beg->lc + u * c->end->lc; break; case MSH_SEGM_BSPLN: V = InterpolateUBS(c, u, 0); break; case MSH_SEGM_BEZIER: V = InterpolateBezier(c, u, 0); break; case MSH_SEGM_NURBS: V = InterpolateNurbs(c, u, 0); break; case MSH_SEGM_SPLN: N = List_Nbr(c->Control_Points); i = (int)((double)(N - 1) * u); if(i < 0) i = 0; if(i >= N - 1) i = N - 2; t1 = (double)(i) / (double)(N - 1); t2 = (double)(i + 1) / (double)(N - 1); t = (u - t1) / (t2 - t1); List_Read(c->Control_Points, i, &v[1]); List_Read(c->Control_Points, i + 1, &v[2]); if(!i) { if(c->beg == c->end){ List_Read(c->Control_Points, N - 2, &v[0]); } else{ v[0] = &temp1; v[0]->Pos.X = 2. * v[1]->Pos.X - v[2]->Pos.X; v[0]->Pos.Y = 2. * v[1]->Pos.Y - v[2]->Pos.Y; v[0]->Pos.Z = 2. * v[1]->Pos.Z - v[2]->Pos.Z; v[0]->pntOnGeometry = v[1]->pntOnGeometry * 2. - v[2]->pntOnGeometry; } } else { List_Read(c->Control_Points, i - 1, &v[0]); } if(i == N - 2) { if(c->beg == c->end){ List_Read(c->Control_Points, 1, &v[3]); } else{ v[3] = &temp2; v[3]->Pos.X = 2. * v[2]->Pos.X - v[1]->Pos.X; v[3]->Pos.Y = 2. * v[2]->Pos.Y - v[1]->Pos.Y; v[3]->Pos.Z = 2. * v[2]->Pos.Z - v[1]->Pos.Z; v[3]->pntOnGeometry = v[2]->pntOnGeometry * 2. - v[1]->pntOnGeometry; } } else { List_Read(c->Control_Points, i + 2, &v[3]); } if(c->geometry){ SPoint2 pp = InterpolateCubicSpline(v, t, c->mat, t1, t2,c->geometry,0); SPoint3 pt = c->geometry->point(pp); V.Pos.X = pt.x(); V.Pos.Y = pt.y(); V.Pos.Z = pt.z(); } else V = InterpolateCubicSpline(v, t, c->mat, 0, t1, t2); break; case MSH_SEGM_BND_LAYER: Msg::Debug("Cannot interpolate boundary layer curve"); break; case MSH_SEGM_DISCRETE: Msg::Debug("Cannot interpolate discrete curve"); break; case MSH_SEGM_COMPOUND: Msg::Debug("Cannot interpolate compound curve"); break; default: Msg::Error("Unknown curve type in interpolation"); break; } V.u = u; return V; }