diff --git a/Mesh/Utils.cpp b/Mesh/Utils.cpp index a3de1e82b6c32bd195e24c318400166b8dc68655..951cb44df04889849ba5eb4aba76ee28a75bc73b 100644 --- a/Mesh/Utils.cpp +++ b/Mesh/Utils.cpp @@ -1,4 +1,4 @@ -// $Id: Utils.cpp,v 1.24 2004-04-13 18:49:58 geuzaine Exp $ +// $Id: Utils.cpp,v 1.25 2004-04-18 03:23:02 geuzaine Exp $ // // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle // @@ -244,7 +244,8 @@ end: #define Precision 1.e-10 -#define MaxIter 50 +#define MaxIter 25 +#define NumInitGuess 9 void find_bestuv(Surface * s, double X, double Y, double *U, double *V, double *Z, int N) @@ -361,7 +362,8 @@ void XYZtoUV(Surface * s, double X, double Y, double Z, double *U, double *V, Vertex D_u, D_v, P; double mat[3][3], jac[3][3]; double umin, umax, vmin, vmax; - + double init[NumInitGuess] = {0.487, 0.6, 0.4, 0.7, 0.3, 0.8, 0.2, 0.9, 0.1}; + if(s->Typ == MSH_SURF_NURBS) { umin = s->ku[0]; umax = s->ku[s->OrderU + s->Nu]; @@ -373,48 +375,58 @@ void XYZtoUV(Surface * s, double X, double Y, double Z, double *U, double *V, umax = vmax = 1.0; } - *U = *V = 0.487; - err = 1.0; - iter = 1; + for(int i = 0; i < NumInitGuess; i++){ + for(int j = 0; j < NumInitGuess; j++){ + + *U = init[i]; + *V = init[j]; + err = 1.0; + iter = 1; + + while(err > Precision && iter < MaxIter) { + P = InterpolateSurface(s, *U, *V, 0, 0); + D_u = InterpolateSurface(s, *U, *V, 1, 1); + D_v = InterpolateSurface(s, *U, *V, 1, 2); + + mat[0][0] = D_u.Pos.X; + mat[0][1] = D_u.Pos.Y; + mat[0][2] = D_u.Pos.Z; + mat[1][0] = D_v.Pos.X; + mat[1][1] = D_v.Pos.Y; + mat[1][2] = D_v.Pos.Z; + mat[2][0] = 0.; + mat[2][1] = 0.; + mat[2][2] = 0.; + invert_singular_matrix3x3(mat, jac); + + Unew = *U + relax * + (jac[0][0] * (X - P.Pos.X) + jac[1][0] * (Y - P.Pos.Y) + + jac[2][0] * (Z - P.Pos.Z)); + Vnew = *V + relax * + (jac[0][1] * (X - P.Pos.X) + jac[1][1] * (Y - P.Pos.Y) + + jac[2][1] * (Z - P.Pos.Z)); + + err = DSQR(Unew - *U) + DSQR(Vnew - *V); + + iter++; + *U = Unew; + *V = Vnew; + } - while(err > Precision && iter < MaxIter) { - P = InterpolateSurface(s, *U, *V, 0, 0); - D_u = InterpolateSurface(s, *U, *V, 1, 1); - D_v = InterpolateSurface(s, *U, *V, 1, 2); - - mat[0][0] = D_u.Pos.X; - mat[0][1] = D_u.Pos.Y; - mat[0][2] = D_u.Pos.Z; - mat[1][0] = D_v.Pos.X; - mat[1][1] = D_v.Pos.Y; - mat[1][2] = D_v.Pos.Z; - mat[2][0] = 0.; - mat[2][1] = 0.; - mat[2][2] = 0.; - invert_singular_matrix3x3(mat, jac); - - Unew = *U + relax * - (jac[0][0] * (X - P.Pos.X) + jac[1][0] * (Y - P.Pos.Y) + - jac[2][0] * (Z - P.Pos.Z)); - Vnew = - *V + relax * (jac[0][1] * (X - P.Pos.X) + jac[1][1] * (Y - P.Pos.Y) + - jac[2][1] * (Z - P.Pos.Z)); - - err = DSQR(Unew - *U) + DSQR(Vnew - *V); - - iter++; - *U = Unew; - *V = Vnew; + if(iter < MaxIter && err <= Precision && + Unew <= umax && Vnew <= vmax && + Unew >= umin && Vnew >= vmin){ + //printf("converged for i=%d j=%d (err=%g iter=%d)\n", i, j, err, iter); + return; + } + } } - if(iter == MaxIter || - (Unew > umax || Vnew > vmax || Unew < umin || Vnew < vmin)) { - if(relax < 1.e-12) - Msg(GERROR, "Could not converge: surface mesh will be wrong"); - else { - Msg(INFO, "Relaxation factor = %g", 0.75 * relax); - XYZtoUV(s, X, Y, Z, U, V, 0.75 * relax); - } + if(relax < 1.e-6) + Msg(GERROR, "Could not converge: surface mesh will be wrong"); + else { + Msg(INFO, "Relaxation factor = %g", 0.75 * relax); + XYZtoUV(s, X, Y, Z, U, V, 0.75 * relax); } } @@ -426,6 +438,7 @@ void XYtoUV(Surface * s, double *X, double *Y, int iter; Vertex D_u, D_v, P; double umin, umax, vmin, vmax; + double init[NumInitGuess] = {0.487, 0.6, 0.4, 0.7, 0.3, 0.8, 0.2, 0.9, 0.1}; if(s->Typ == MSH_SURF_NURBS) { umin = s->ku[0]; @@ -438,72 +451,78 @@ void XYtoUV(Surface * s, double *X, double *Y, umax = vmax = 1.0; } - *U = *V = 0.487; - err = 1.0; - iter = 1; - - while(err > Precision && iter < MaxIter) { - P = InterpolateSurface(s, *U, *V, 0, 0); - D_u = InterpolateSurface(s, *U, *V, 1, 1); - D_v = InterpolateSurface(s, *U, *V, 1, 2); - mat[0][0] = D_u.Pos.X; - mat[0][1] = D_u.Pos.Y; - mat[1][0] = D_v.Pos.X; - mat[1][1] = D_v.Pos.Y; - det = mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]; - - if(det == 0.0) { - iter = MaxIter; - break; - } - - jac[0][0] = mat[1][1] / det; - jac[0][1] = -mat[0][1] / det; - jac[1][0] = -mat[1][0] / det; - jac[1][1] = mat[0][0] / det; - - Unew = - *U + relax * (jac[0][0] * (*X - P.Pos.X) + jac[1][0] * (*Y - P.Pos.Y)); - Vnew = - *V + relax * (jac[0][1] * (*X - P.Pos.X) + jac[1][1] * (*Y - P.Pos.Y)); + for(int i = 0; i < NumInitGuess; i++){ + for(int j = 0; j < NumInitGuess; j++){ + + *U = init[i]; + *V = init[j]; + err = 1.0; + iter = 1; + + while(err > Precision && iter < MaxIter) { + P = InterpolateSurface(s, *U, *V, 0, 0); + D_u = InterpolateSurface(s, *U, *V, 1, 1); + D_v = InterpolateSurface(s, *U, *V, 1, 2); + mat[0][0] = D_u.Pos.X; + mat[0][1] = D_u.Pos.Y; + mat[1][0] = D_v.Pos.X; + mat[1][1] = D_v.Pos.Y; + det = mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]; + + if(det == 0.0) { + iter = MaxIter; + break; + } + + jac[0][0] = mat[1][1] / det; + jac[0][1] = -mat[0][1] / det; + jac[1][0] = -mat[1][0] / det; + jac[1][1] = mat[0][0] / det; + + Unew = *U + relax * (jac[0][0] * (*X - P.Pos.X) + jac[1][0] * (*Y - P.Pos.Y)); + Vnew = *V + relax * (jac[0][1] * (*X - P.Pos.X) + jac[1][1] * (*Y - P.Pos.Y)); + + err = DSQR(Unew - *U) + DSQR(Vnew - *V); + + iter++; + *U = Unew; + *V = Vnew; + } - err = DSQR(Unew - *U) + DSQR(Vnew - *V); + *Z = P.Pos.Z; - iter++; - *U = Unew; - *V = Vnew; + if(iter < MaxIter && err <= Precision && + Unew <= umax && Vnew <= vmax && + Unew >= umin && Vnew >= vmin){ + //printf("converged for i=%d j=%d (err=%g iter=%d)\n", i, j, err, iter); + return; + } + } } - *Z = P.Pos.Z; - - int thresh = Unew > umax || Vnew > vmax || Unew < umin || Vnew < vmin; - - if(iter == MaxIter || thresh) { - if(relax < 1.e-6) { - Msg(GERROR, "Could not converge: surface mesh will probably be wrong"); - if(Unew > umax) - *U = umax; - if(Vnew > vmax) - *V = vmax; - if(Unew < umin) - *U = umin; - if(Vnew < vmin) - *V = vmin; - find_bestuv(s, *X, *Y, U, V, Z, 30); - P = InterpolateSurface(s, *U, *V, 0, 0); - *X = P.Pos.X; - *Y = P.Pos.Y; - *Z = P.Pos.Z; - } - else { - Msg(INFO, "Relaxation factor = %g", 0.75 * relax); - XYtoUV(s, X, Y, U, V, Z, 0.75 * relax); - } + if(relax < 1.e-6) { + Msg(GERROR, "Could not converge: surface mesh will probably be wrong"); + if(Unew > umax) + *U = umax; + if(Vnew > vmax) + *V = vmax; + if(Unew < umin) + *U = umin; + if(Vnew < vmin) + *V = vmin; + find_bestuv(s, *X, *Y, U, V, Z, 30); + P = InterpolateSurface(s, *U, *V, 0, 0); + *X = P.Pos.X; + *Y = P.Pos.Y; + *Z = P.Pos.Z; + } + else { + Msg(INFO, "Relaxation factor = %g", 0.75 * relax); + XYtoUV(s, X, Y, U, V, Z, 0.75 * relax); } } - int Oriente(List_T * cu, double n[3]) { int N, i, a, b, c;