diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp index 2b362254c9f4399596ca491ffb8ea66672f55f5f..aaf2ec1072b769e086e3de2d5785c7f268c59fbd 100644 --- a/Geo/GFace.cpp +++ b/Geo/GFace.cpp @@ -410,6 +410,57 @@ void GFace::writeGEO(FILE *fp) void GFace::computeMeanPlane() { std::vector<SPoint3> pts; + + if(geomType() == Plane) { + // Special case for planar surfaces: we first try to compute the + // parametrization in a way that is more robust with respect to + // perturbations of the boundary. This is crucial for sensitivity analyses + // and GFace::relocateMeshVertices(): after perturbation of the boundary, we + // want a parametrization of the surface that is "close" to the original + // one. If this fails, we fallback to the classical (SVD-based) algorithm. + std::list<GEdge*> edg = edges(); + for(std::list<GEdge*>::const_iterator ite = edg.begin(); ite != edg.end(); ite++){ + const GEdge *e = *ite; + Range<double> b = e->parBounds(0); + GPoint p1 = e->point(b.low() + 0.333 * (b.high() - b.low())); + pts.push_back(SPoint3(p1.x(), p1.y(), p1.z())); + GPoint p2 = e->point(b.low() + 0.666 * (b.high() - b.low())); + pts.push_back(SPoint3(p2.x(), p2.y(), p2.z())); + } + bool ok = false; + double res[4] = {0., 0., 0., 0.}, xm = 0., ym = 0., zm = 0.; + if(pts.size() >= 3){ + SVector3 d01(pts[0], pts[1]); + for(unsigned int i = 2; i < pts.size(); i++){ + SVector3 d0i(pts[0], pts[i]); + SVector3 n = crossprod(d01, d0i); + if(norm(n) > 1e-12){ + res[0] = n.x(); res[1] = n.y(); res[2] = n.z(); + xm = pts[0].x(); ym = pts[0].y(); zm = pts[0].z(); + ok = true; + break; + } + } + } + if(ok){ + double ex[3], t1[3], t2[3]; + ex[0] = ex[1] = ex[2] = 0.0; + if(res[0] == 0.) + ex[0] = 1.0; + else if(res[1] == 0.) + ex[1] = 1.0; + else + ex[2] = 1.0; + prodve(res, ex, t1); + norme(t1); + prodve(t1, res, t2); + norme(t2); + res[3] = (xm * res[0] + ym * res[1] + zm * res[2]); + fillMeanPlane(res, t1, t2, meanPlane); + return; + } + } + std::list<GVertex*> verts = vertices(); std::list<GVertex*>::const_iterator itv = verts.begin(); for(; itv != verts.end(); itv++){ @@ -552,30 +603,7 @@ void GFace::computeMeanPlane(const std::vector<SPoint3> &points) end: res[3] = (xm * res[0] + ym * res[1] + zm * res[2]); - for(int i = 0; i < 3; i++) - meanPlane.plan[0][i] = t1[i]; - for(int i = 0; i < 3; i++) - meanPlane.plan[1][i] = t2[i]; - for(int i = 0; i < 3; i++) - meanPlane.plan[2][i] = res[i]; - - meanPlane.a = res[0]; - meanPlane.b = res[1]; - meanPlane.c = res[2]; - meanPlane.d = res[3]; - - meanPlane.x = meanPlane.y = meanPlane.z = 0.; - if(fabs(meanPlane.a) >= fabs(meanPlane.b) && - fabs(meanPlane.a) >= fabs(meanPlane.c) ){ - meanPlane.x = meanPlane.d / meanPlane.a; - } - else if(fabs(meanPlane.b) >= fabs(meanPlane.a) && - fabs(meanPlane.b) >= fabs(meanPlane.c)){ - meanPlane.y = meanPlane.d / meanPlane.b; - } - else{ - meanPlane.z = meanPlane.d / meanPlane.c; - } + fillMeanPlane(res, t1, t2, meanPlane); Msg::Debug("Surface: %d", tag()); Msg::Debug("SVD : %g,%g,%g (min=%d)", svd[0], svd[1], svd[2], min); diff --git a/Numeric/Numeric.cpp b/Numeric/Numeric.cpp index 784c023f3318caeafeecb1468fa9eec3bca3747e..1810e3fd00f3625bc902bb3094713e39b65ea61b 100644 --- a/Numeric/Numeric.cpp +++ b/Numeric/Numeric.cpp @@ -1378,6 +1378,33 @@ int intersection_segments(const SPoint3 &p1, const SPoint3 &p2, return false; } +void fillMeanPlane(double res[4], double t1[3], double t2[3], mean_plane &meanPlane) +{ + for(int i = 0; i < 3; i++) + meanPlane.plan[0][i] = t1[i]; + for(int i = 0; i < 3; i++) + meanPlane.plan[1][i] = t2[i]; + for(int i = 0; i < 3; i++) + meanPlane.plan[2][i] = res[i]; + + meanPlane.a = res[0]; + meanPlane.b = res[1]; + meanPlane.c = res[2]; + meanPlane.d = res[3]; + + meanPlane.x = meanPlane.y = meanPlane.z = 0.; + if(fabs(meanPlane.a) >= fabs(meanPlane.b) && + fabs(meanPlane.a) >= fabs(meanPlane.c) ){ + meanPlane.x = meanPlane.d / meanPlane.a; + } + else if(fabs(meanPlane.b) >= fabs(meanPlane.a) && + fabs(meanPlane.b) >= fabs(meanPlane.c)){ + meanPlane.y = meanPlane.d / meanPlane.b; + } + else{ + meanPlane.z = meanPlane.d / meanPlane.c; + } +} void computeMeanPlaneSimple(const std::vector<SPoint3> &points, mean_plane &meanPlane) { @@ -1434,30 +1461,7 @@ void computeMeanPlaneSimple(const std::vector<SPoint3> &points, mean_plane &mean res[3] = (xm * res[0] + ym * res[1] + zm * res[2]); - for(int i = 0; i < 3; i++) - meanPlane.plan[0][i] = t1[i]; - for(int i = 0; i < 3; i++) - meanPlane.plan[1][i] = t2[i]; - for(int i = 0; i < 3; i++) - meanPlane.plan[2][i] = res[i]; - - meanPlane.a = res[0]; - meanPlane.b = res[1]; - meanPlane.c = res[2]; - meanPlane.d = res[3]; - - meanPlane.x = meanPlane.y = meanPlane.z = 0.; - if(fabs(meanPlane.a) >= fabs(meanPlane.b) && - fabs(meanPlane.a) >= fabs(meanPlane.c) ){ - meanPlane.x = meanPlane.d / meanPlane.a; - } - else if(fabs(meanPlane.b) >= fabs(meanPlane.a) && - fabs(meanPlane.b) >= fabs(meanPlane.c)){ - meanPlane.y = meanPlane.d / meanPlane.b; - } - else{ - meanPlane.z = meanPlane.d / meanPlane.c; - } + fillMeanPlane(res, t1, t2, meanPlane); } void projectPointToPlane(const SPoint3 &pt, SPoint3 &ptProj, const mean_plane &meanPlane) diff --git a/Numeric/Numeric.h b/Numeric/Numeric.h index 17aad6e177cea6f15a2a7aa3485e6de01ef2ffba..795ddcb9b81eb2b3dfa7926356dbb25497612232 100644 --- a/Numeric/Numeric.h +++ b/Numeric/Numeric.h @@ -160,10 +160,13 @@ int intersection_segments (const SPoint2 &p1, const SPoint2 &p2, double x[2]); //tools for projection onto plane +void fillMeanPlane(double res[4], double t1[3], double t2[3], mean_plane &meanPlane); void computeMeanPlaneSimple(const std::vector<SPoint3> &points, mean_plane &meanPlane); void projectPointToPlane(const SPoint3 &pt, SPoint3 &ptProj, const mean_plane &meanPlane); -void projectPointsToPlane(const std::vector<SPoint3> &pts, std::vector<SPoint3> &ptsProj, const mean_plane &meanPlane); -void transformPointsIntoOrthoBasis(const std::vector<SPoint3> &ptsProj, std::vector<SPoint3> &pointsUV, +void projectPointsToPlane(const std::vector<SPoint3> &pts, std::vector<SPoint3> &ptsProj, + const mean_plane &meanPlane); +void transformPointsIntoOrthoBasis(const std::vector<SPoint3> &ptsProj, + std::vector<SPoint3> &pointsUV, const SPoint3 &ptCG, const mean_plane &meanPlane); #endif