diff --git a/Mesh/BDS.cpp b/Mesh/BDS.cpp index dac13f771607c7cb907d5a76f10927c5e442a595..d5dd529e7eac696b1ceaf7107dd1af3e27e09a24 100644 --- a/Mesh/BDS.cpp +++ b/Mesh/BDS.cpp @@ -1,4 +1,4 @@ -// $Id: BDS.cpp,v 1.54 2006-07-25 12:08:23 remacle Exp $ +// $Id: BDS.cpp,v 1.55 2006-07-25 13:00:07 remacle Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -2445,6 +2445,8 @@ bool BDS_Mesh::smooth_point(BDS_Point * p, BDS_Mesh * geom_mesh) X += op->X; Y += op->Y; Z += op->Z; + // lengths are wrong; + (*eit)->target_length = -1; ++eit; } diff --git a/Mesh/BDS.h b/Mesh/BDS.h index 2f8710cc886d983b79b9ae76b36607c76ac10660..b9bdac72ea8272638e243e3e2e02cd2b0359f296 100644 --- a/Mesh/BDS.h +++ b/Mesh/BDS.h @@ -324,7 +324,7 @@ public: void oppositeof(BDS_Point * oface[2]) const; BDS_Edge(BDS_Point *A, BDS_Point *B) - : deleted(false), status(0),partition(0),target_length(1.0),g(0) + : deleted(false), status(0),partition(0),target_length(-1.0),g(0) { if(*A < *B){ p1=A; diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp new file mode 100644 index 0000000000000000000000000000000000000000..709f7252e6a2d724fbe26e94f8219b368e24fc37 --- /dev/null +++ b/Mesh/meshGFace.cpp @@ -0,0 +1,852 @@ +#include "meshGFace.h" +#include "GVertex.h" +#include "2D_Mesh.h" +#include "GEdge.h" +#include "GFace.h" +#include "MVertex.h" +#include "Context.h" +#include "Utils.h" +#include "GPoint.h" +#include "Message.h" +#include "Numeric.h" +#include "BDS.h" + +#if defined(HAVE_GSL) +#include <gsl/gsl_vector.h> +#include <gsl/gsl_linalg.h> +#else +#define NRANSI +#include "nrutil.h" +void dsvdcmp(double **a, int m, int n, double w[], double **v); +#endif + +/* + Le concept d'un plan moyen calcule au sens des moidres carres n'est + pas le bon pour les surfaces non-planes : imagine un quart de cercle + extrude d'une faible hauteur. Le plan moyen sera dans le plan du + cercle! En attendant mieux, il y a donc un test de coherence + supplementaire pour les surfaces non-planes. */ + + + +int Orientation (std::vector<MVertex*> &cu) +{ + int N, i, a, b, c; + double cosa, sina, sum, v[3], w[3], u[3]; + MVertex *ver[3]; + double n[3] = {0,0,1}; + + N = cu.size(); + + sum = 0.0; + for(i = 0; i < N; i++) { + if(i == N - 1) { + a = N - 1; + b = 1; + c = 2; + } + else if(i == N - 2) { + a = N - 2; + b = N - 1; + c = 1; + } + else { + a = i; + b = i + 1; + c = i + 2; + } + ver[0] = cu[a]; + ver[1] = cu[b]; + ver[2] = cu[c]; + + u[0] = ver[1]->x() - ver[0]->x(); + u[1] = ver[1]->y() - ver[0]->y(); + u[2] = ver[1]->z() - ver[0]->z(); + + v[0] = ver[2]->x() - ver[1]->x(); + v[1] = ver[2]->y() - ver[1]->y(); + v[2] = ver[2]->z() - ver[1]->z(); + norme(u); + norme(v); + prodve(u, v, w); + prosca(w, n, &sina); + prosca(u, v, &cosa); + sum += myatan2(sina, cosa); + } + + if(sum < 0) + return (1); + else + return (0); +} + + + +extern Context_T CTX; + +class fromCartesianToParametric +{ + GFace *gf; +public : + fromCartesianToParametric ( GFace *_gf ) + : gf(_gf){} + void operator () (MVertex * v) + { + SPoint2 param = gf->parFromPoint (SPoint3(v->x(),v->y(),v->z())); + v->x() = param.x(); + v->y() = param.y(); + v->z() = 0.0; + } +}; + +class fromParametricToCartesian +{ + GFace *gf; +public : + fromParametricToCartesian ( GFace *_gf ) + : gf(_gf){} + void operator () (MVertex * v) + { + GPoint coords = gf->point (SPoint2(v->x(),v->y())); + v->x() = coords.x(); + v->y() = coords.y(); + v->z() = coords.z(); + } +}; + + +void computeEdgeLoops (const GFace *gf, + std::vector<MVertex*> & all_mvertices, + std::vector<int> &indices) +{ + { + std::list<GEdge*> edges = gf->edges(); + std::list<int> ori = gf->orientations(); + std::list<GEdge*>::iterator it = edges.begin(); + std::list<int>::iterator ito = ori.begin(); + + indices.push_back(0); + GVertex *start = ((*ito) == 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + GVertex *v_end = ((*ito) != 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + all_mvertices.push_back(start->mesh_vertices[0]); + if (*ito == 1) + for (int i=0;i<(*it)->mesh_vertices.size();i++) + all_mvertices.push_back((*it)->mesh_vertices[i]); + else + for (int i=(*it)->mesh_vertices.size()-1;i>=0;i--) + all_mvertices.push_back((*it)->mesh_vertices[i]); + + GVertex *v_start = start; + while(1) + { + ++it; + ++ito; + if (v_end == start) + { + indices.push_back(all_mvertices.size()); + if (it == edges.end ())break; + start = ((*ito) == 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + v_end = ((*ito) != 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + v_start = start; + } + else + { + if (it == edges.end ())throw; + v_start = ((*ito) == 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + if(v_start != v_end)throw; + v_end = ((*ito) != 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + } + all_mvertices.push_back(v_start->mesh_vertices[0]); + if (*ito == 1) + for (int i=0;i<(*it)->mesh_vertices.size();i++) + all_mvertices.push_back((*it)->mesh_vertices[i]); + else + for (int i=(*it)->mesh_vertices.size()-1;i>=0;i--) + all_mvertices.push_back((*it)->mesh_vertices[i]); + } + } + +} + +void MeanPlane_bis(GFace *gf, const std::vector<MVertex*> &points) +{ + + int i, j, min, ndata, na; + double res[4], ex[3], t1[3], t2[3], svd[3]; + Vertex *v; + double xm = 0., ym = 0., zm = 0.; + + ndata = points.size(); + na = 3; + for(i = 0; i < ndata; i++) { + xm += points[i]->x(); + ym += points[i]->y(); + zm += points[i]->z(); + } + xm /= (double)ndata; + ym /= (double)ndata; + zm /= (double)ndata; + +#if defined(HAVE_GSL) + gsl_matrix *U = gsl_matrix_alloc(ndata, na); + gsl_matrix *V = gsl_matrix_alloc(na, na); + gsl_vector *W = gsl_vector_alloc(na); + gsl_vector *TMPVEC = gsl_vector_alloc(na); + for(i = 0; i < ndata; i++) { + gsl_matrix_set(U, i, 0, points[i]->x() - xm); + gsl_matrix_set(U, i, 1, points[i]->y() - ym); + gsl_matrix_set(U, i, 2, points[i]->z() - zm); + } + gsl_linalg_SV_decomp(U, V, W, TMPVEC); + svd[0] = gsl_vector_get(W, 0); + svd[1] = gsl_vector_get(W, 1); + svd[2] = gsl_vector_get(W, 2); + if(fabs(svd[0]) < fabs(svd[1]) && fabs(svd[0]) < fabs(svd[2])) + min = 0; + else if(fabs(svd[1]) < fabs(svd[0]) && fabs(svd[1]) < fabs(svd[2])) + min = 1; + else + min = 2; + res[0] = gsl_matrix_get(V, 0, min); + res[1] = gsl_matrix_get(V, 1, min); + res[2] = gsl_matrix_get(V, 2, min); + norme(res); + gsl_matrix_free(U); + gsl_matrix_free(V); + gsl_vector_free(W); + gsl_vector_free(TMPVEC); +#else + double **U = dmatrix(1, ndata, 1, na); + double **V = dmatrix(1, na, 1, na); + double *W = dvector(1, na); + for(i = 0; i < ndata; i++) { + U[i + 1][1] = points[i]->x() - xm; + U[i + 1][2] = points[i]->y() - ym; + U[i + 1][3] = points[i]->z() - zm; + } + dsvdcmp(U, ndata, na, W, V); + if(fabs(W[1]) < fabs(W[2]) && fabs(W[1]) < fabs(W[3])) + min = 1; + else if(fabs(W[2]) < fabs(W[1]) && fabs(W[2]) < fabs(W[3])) + min = 2; + else + min = 3; + svd[0] = W[1]; + svd[1] = W[2]; + svd[2] = W[3]; + res[0] = V[1][min]; + res[1] = V[2][min]; + res[2] = V[3][min]; + norme(res); + free_dmatrix(U, 1, ndata, 1, na); + free_dmatrix(V, 1, na, 1, na); + free_dvector(W, 1, na); +#endif + + // check coherence of results for non-plane surfaces + if(gf->geomType() != GEntity::Plane) { + double res2[3], c[3], cosc, sinc, angplan; + double eps = 1.e-3; + + GPoint v1 = gf->point( 0.5, 0.5); + GPoint v2 = gf->point( 0.5 + eps, 0.5); + GPoint v3 = gf->point( 0.5, 0.5 + eps); + t1[0] = v2.x() - v1.x(); + t1[1] = v2.y() - v1.y(); + t1[2] = v2.z() - v1.z(); + t2[0] = v3.x() - v1.x(); + t2[1] = v3.y() - v1.y(); + t2[2] = v3.z() - v1.z(); + norme(t1); + norme(t2); + // prodve(t1, t2, res2); + // Warning: the rest of the code assumes res = t2 x t1, not t1 x t2 (WTF?) + prodve(t2, t1, res2); + norme(res2); + prodve(res, res2, c); + prosca(res, res2, &cosc); + sinc = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]); + angplan = myatan2(sinc, cosc); + angplan = angle_02pi(angplan) * 180. / Pi; + if((angplan > 70 && angplan < 110) || (angplan > 260 && angplan < 280)) { + Msg(INFO, "SVD failed (angle=%g): using rough algo...", angplan); + res[0] = res2[0]; + res[1] = res2[1]; + res[2] = res2[2]; + goto end; + } + } + + 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); + +end: + res[3] = (xm * res[0] + ym * res[1] + zm * res[2]); + + for(i = 0; i < 3; i++) + gf->mp.plan[0][i] = t1[i]; + for(i = 0; i < 3; i++) + gf->mp.plan[1][i] = t2[i]; + for(i = 0; i < 3; i++) + gf->mp.plan[2][i] = res[i]; + + gf->mp.a = res[0]; + gf->mp.b = res[1]; + gf->mp.c = res[2]; + gf->mp.d = res[3]; + + gf->mp.x=gf->mp.y=gf->mp.z=0; + if (fabs(gf->mp.a) >= fabs(gf->mp.b) && fabs(gf->mp.a) >= fabs(gf->mp.c) ) + { + gf->mp.x = gf->mp.d/gf->mp.a; + } + else if (fabs(gf->mp.b) >= fabs(gf->mp.a) && fabs(gf->mp.b) >= fabs(gf->mp.c) ) + { + gf->mp.y = gf->mp.d/gf->mp.b; + } + else + { + gf->mp.z = gf->mp.d/gf->mp.c; + } + + + Msg(DEBUG1, "Surface: %d", gf->tag()); + Msg(DEBUG2, "SVD : %g,%g,%g (min=%d)", svd[0], svd[1], svd[2], min); + Msg(DEBUG2, "Plane : (%g x + %g y + %g z = %g)", gf->mp.a, gf->mp.b, gf->mp.c, gf->mp.d); + Msg(DEBUG2, "Normal : (%g , %g , %g )", gf->mp.a, gf->mp.b, gf->mp.c); + Msg(DEBUG3, "t1 : (%g , %g , %g )", t1[0], t1[1], t1[2]); + Msg(DEBUG3, "t2 : (%g , %g , %g )", t2[0], t2[1], t2[2]); + Msg(DEBUG3, "pt : (%g , %g , %g )", gf->mp.x, gf->mp.y, gf->mp.z); + + //check coherence for plane surfaces + if(gf->geomType() == GEntity::Plane) { + std::list<GVertex*> verts = gf->vertices(); + std::list<GVertex*>::const_iterator itv = verts.begin(); + + for (;itv!=verts.end();itv++) + { + const GVertex *v = *itv; + double d = + gf->mp.a * v->x() + gf->mp.b * v->y() + gf->mp.c * v->z() - gf->mp.d; + if(fabs(d) > CTX.lc * 1.e-3) { + Msg(GERROR1, "Plane surface %d (%gx+%gy+%gz+%g=0) is not plane!", + v->tag(), gf->mp.a, gf->mp.b, gf->mp.c, gf->mp.d); + Msg(GERROR3, "Control point %d = (%g,%g,%g), val=%g", + v->tag(), v->x(), v->y(), v->z(), d); + return; + } + } + } +} + + +void computeEdgeParameters ( double x1, double y1, double x2, double y2, GFace *gf , const int numberOfTestPoints, double &coordMiddle, double &edgeLength ) +{ + std::vector<GPoint> pts; + for (int i=0;i<numberOfTestPoints;++i) + { + double xi = (double)i/(double)(numberOfTestPoints-1); + double u = x1 * (1-xi) + x2 * xi; + double v = y1 * (1-xi) + y2 * xi; + pts.push_back(gf->point(u,v)); + } + edgeLength = 0; + for (int i=1;i<numberOfTestPoints;++i) + { + GPoint p1 = pts[i-1]; + GPoint p2 = pts[i]; + edgeLength += sqrt ( (p1.x() - p2.x())*(p1.x() - p2.x()) + + (p1.y() - p2.y())*(p1.y() - p2.y()) + + (p1.z() - p2.z())*(p1.z() - p2.z()) ); + } + double ll = 0; + for (int i=1;i<numberOfTestPoints;++i) + { + double xi = (double)(i-1)/(double)(numberOfTestPoints-1); + GPoint p1 = pts[i-1]; + GPoint p2 = pts[i]; + + double oldll = ll; + + ll += sqrt ( (p1.x() - p2.x())*(p1.x() - p2.x()) + + (p1.y() - p2.y())*(p1.y() - p2.y()) + + (p1.z() - p2.z())*(p1.z() - p2.z()) ); + + if (oldll <= 0.5*edgeLength && ll >= 0.5*edgeLength) + { + double xi2 = (0.5*edgeLength - oldll)/(ll-oldll); + coordMiddle = xi + xi2/ (double)(numberOfTestPoints-1); + return; + } + } +} + +double computeEdgeLinearLength ( BDS_Edge*e, BDS_Point *p1,BDS_Point *p2, std::map<BDS_Point*,BDS_Pos> &realCoordinates) +{ + if (e && e->target_length > 0) return e->target_length; + + const BDS_Pos & x1 = realCoordinates [p1]; + const BDS_Pos & x2 = realCoordinates [p2]; + const double l = sqrt ((x1.X-x2.X)*(x1.X-x2.X) +(x1.Y-x2.Y)*(x1.Y-x2.Y) +(x1.Z-x2.Z)*(x1.Z-x2.Z)); + if (e) e->target_length = l; + return l; +} + +bool edgeSwapTest(BDS_Edge *e, GFace *gf, std::map<BDS_Point*,BDS_Pos> &realCoordinates) +{ + BDS_Point *op[2]; + + if (e->numfaces() != 2)return false; + + e->oppositeof (op); + + double coordMiddle, edgeLength1, edgeLength2; + + + edgeLength1 = computeEdgeLinearLength ( e,e->p1,e->p2,realCoordinates); + edgeLength2 = computeEdgeLinearLength ( 0,op[0],op[1],realCoordinates); + /* + computeEdgeParameters ( e->p1->X, + e->p1->Y, + e->p2->X, + e->p2->Y, + gf , 2, coordMiddle, edgeLength1 ); + + computeEdgeParameters ( op[0]->X, + op[0]->Y, + op[1]->X, + op[1]->Y, + gf , 2, coordMiddle, edgeLength2 ); + */ + double el1 = 2*edgeLength1 / ( e->p1->radius_of_curvature +e->p2->radius_of_curvature ); + double el2 = 2*edgeLength2 / ( op[0]->radius_of_curvature + op[1]->radius_of_curvature ); + + double q1 = fabs (1-el1); + double q2 = fabs (1-el2); + + return q2 < 0.5*q1; + +} + + + +void NewMeshGenerator ( GFace *gf, + const std::vector<MVertex*> &points, + const std::vector<int> &indices) +{ + BDS_Mesh m; + std::map<MVertex*,int> numPoints; + std::map<BDS_Point*,BDS_Pos> realCoordinates; + int NUMP = 0; + + // fill the initial BDS Structure + + int nbEdgeLoops = indices.size()-1; + for(int i = 0; i < nbEdgeLoops; i++) { + int nbPtsOnEdgeLoop = indices[i+1] -indices[i]; + for(int j = indices[i]; j < indices[i+1]; j++) { + MVertex *here = points[j]; + MVertex *previous = (j == indices[i])?points[indices[i+1]-1] : points[j-1]; + MVertex *next = (j == indices[i+1]-1)?points[indices[i]] : points[j+1]; + + double coordMiddle, edgeLength1, edgeLength2; + computeEdgeParameters ( here->x(),here->y(), previous->x(),previous->y() , gf , 2, coordMiddle, edgeLength1 ); + computeEdgeParameters ( here->x(),here->y(), next->x(), next->y(), gf, 2, coordMiddle, edgeLength2 ); + double lc = 0.5 * (edgeLength1+edgeLength2); + BDS_Point *bds_p = m.add_point ( NUMP, here->x(), here->y(), here->z()); + GPoint gp = gf->point (here->x(), here->y()); + realCoordinates[bds_p] = BDS_Pos(gp.x(),gp.y(),gp.z()); + numPoints[here]=NUMP++; + bds_p->radius_of_curvature = lc; + } + } + // will not work correctly if points are present initially inside + // the domain. + for (int i=0;i<gf->mesh_vertices.size();++i) + { + MVertex *p = gf->mesh_vertices[i]; + m.add_point ( NUMP, p->x(), p->y(), p->z()); + numPoints[p]=NUMP++; + } + for (int i=0;i<gf->triangles.size();i+=3) + { + MVertex *p0 = gf->triangles[i]; + MVertex *p1 = gf->triangles[i+1]; + MVertex *p2 = gf->triangles[i+2]; + m.add_triangle ( numPoints[p0], numPoints[p1], numPoints[p2] ); + } + + // add points to the surface ... + const double errGeomTresh = 0.02; + int IT =0; + while (1) + { + std::list<BDS_Edge *> temp (m.edges); + std::list<BDS_Edge*>::iterator it = temp.begin(); + int NB_MODIF = 0; + while (it != temp.end()) + { + const int numberOfTestPoints = 8; + double coordMiddle=0.5, trueLength,linearLength; + /* computeEdgeParameters ( (*it)->p1->X, + (*it)->p1->Y, + (*it)->p2->X, + (*it)->p2->Y, + gf , numberOfTestPoints, coordMiddle, trueLength );*/ + linearLength = computeEdgeLinearLength ( (*it),(*it)->p1, + (*it)->p2,realCoordinates); + + + double l_wanted = 0.5*((*it)->p1->radius_of_curvature + (*it)->p2->radius_of_curvature); + + //double errGeom = fabs(trueLength - linearLength)/linearLength; + double errGeom = 0; + + // Msg(INFO,"le = %g lex = %g err %g",linearLength,trueLength,errGeom); + // if ((*it)->numfaces() == 2 && ( > 1000 || edgeLength > 1.4 * l_wanted)) + if ((*it)->numfaces() == 2 && (linearLength > 1.4 * l_wanted || errGeom > errGeomTresh *1.4)) + { + BDS_Point *ppp = m.split_edge ( *it, coordMiddle ); + ppp->radius_of_curvature = l_wanted; + GPoint gp = gf->point (ppp->X,ppp->Y); + realCoordinates[ppp] = BDS_Pos(gp.x(),gp.y(),gp.z()); + if(linearLength > 2.4 * l_wanted) NB_MODIF++; + } + ++it; + } + + + temp = m.edges; + it = temp.begin(); + while (it != temp.end()) + { + const int numberOfTestPoints = 8; + double coordMiddle=0.5, trueLength,linearLength; + /* computeEdgeParameters ( (*it)->p1->X, + (*it)->p1->Y, + (*it)->p2->X, + (*it)->p2->Y, + gf ,numberOfTestPoints, coordMiddle, trueLength );*/ + linearLength = computeEdgeLinearLength ( (*it),(*it)->p1, + (*it)->p2,realCoordinates); + double l_wanted = 0.5*((*it)->p1->radius_of_curvature + (*it)->p2->radius_of_curvature); + double errGeom = 0; + // Msg(INFO,"colll le = %g lex = %g err %g",linearLength,trueLength,errGeom); + + + if ((*it)->numfaces() == 2 && linearLength < 0.7 * l_wanted && errGeom < errGeomTresh * 0.7) + { + if ( (*it)->p1->iD >= points.size() ) + m.collapse_edge ( *it, (*it)->p1, 0); + else if ( (*it)->p2->iD >= points.size() ) + m.collapse_edge ( *it, (*it)->p2, 0); + if(linearLength < 0.35 * l_wanted) NB_MODIF++; + } + ++it; + + } + temp = m.edges; + it = temp.begin(); + while (it != temp.end()) + { + if (!(*it)->deleted && edgeSwapTest(*it,gf,realCoordinates)) + m.swap_edge ( *it , BDS_SwapEdgeTestPlanar()); + ++it; + } + + std::set<BDS_Point*,PointLessThan> PTS (m.points); + std::set<BDS_Point*,PointLessThan>::iterator itp = PTS.begin(); + while (itp != PTS.end()) + { + m.smooth_point(*itp); + GPoint gp = gf->point ((*itp)->X,(*itp)->Y); + realCoordinates[(*itp)] = BDS_Pos(gp.x(),gp.y(),gp.z()); + std::list < BDS_Triangle * >t; + (*itp)->getTriangles(t); + if ((t.size()==3 && (*itp)->edges.size() == 3)|| + (t.size()==4 && (*itp)->edges.size() == 4)) + m.collapse_edge ( *(*itp)->edges.begin(), (*itp), 0); + ++itp; + } + Msg(INFO,"surf %d NB_MODIF = %d EDGES=%d",gf->tag(),NB_MODIF,m.edges.size()); + if (IT++ > 25 || (double)(NB_MODIF) < .003*(double)m.edges.size())break; + } + + for (int i=0;i<gf->mesh_vertices.size();++i) + { + MVertex *p = gf->mesh_vertices[i]; + delete p; + } + gf->mesh_vertices.clear(); + + std::map<int,MVertex*> verts_; + { + std::set<BDS_Point*,PointLessThan>::iterator it = m.points.begin(); + while (it != m.points.end()) + { + if ( (*it)->iD >= points.size() ) + { + MFaceVertex *v = new MFaceVertex ( (*it)->X,(*it)->Y, 0.0, gf, 0,0); + gf->mesh_vertices.push_back(v); + verts_[(*it)->iD] = v; + } + ++it; + } + } + { + gf->triangles.clear(); + std::list<BDS_Triangle*>::iterator it = m.triangles.begin(); + while (it != m.triangles.end()) + { + if (!(*it)->deleted) + { + BDS_Point *n[3]; + (*it)->getNodes (n); + for (int i=0;i<3;i++) + { + if (n[i]->iD >= points.size()) + { + gf->triangles.push_back(verts_[n[i]->iD]); + } + else + { + gf->triangles.push_back(points[n[i]->iD]); + } + } + } + ++it; + } + } +} + +void OldMeshGenerator ( GFace *gf, + std::vector<MVertex*> &points, + std::vector<int> &indices, int initialOnly) +{ + + + // put the loops on the right sense, cause this stupid cannot + // handle non oriented loops + int nbEdgeLoops = indices.size()-1; + + for(int i = 0; i < nbEdgeLoops; i++) { + int nbPtsOnEdgeLoop = indices[i+1] -indices[i]; + std::vector<MVertex*> loop; + for(int j = indices[i]; j < indices[i+1]; j++)loop.push_back(points[j]); + // Msg(INFO, " %d %d %d %d",i,indices[i],indices[i+1],Orientation(loop)); + int k = 0; + int ori = Orientation(loop); + if (i == 0 && !ori) + for(int j = indices[i]; j < indices[i+1]; j++)points[j] = loop [nbPtsOnEdgeLoop-k++-1]; + else if (i != 0 && ori) + for(int j = indices[i]; j < indices[i+1]; j++)points[j] = loop [nbPtsOnEdgeLoop-k++-1]; + } + + extern PointRecord *gPointArray; + + + // FIX THAT !! + double LC2D = 1; + if (gf->geomType () == GEntity::Plane) + { + SBoundingBox3d bb = gf->bounds(); + SPoint3 _min = bb.min(); + SPoint3 _max = bb.max(); + + SVector3 diam (_min,_max); + LC2D = norm(diam); + } + + // Msg(INFO, "LC = %g",LC2D); + + maillage M; + ContourRecord *cp, **liste; + liste = (ContourPeek *) malloc(nbEdgeLoops * sizeof(ContourPeek)); + for(int i = 0; i < nbEdgeLoops; i++) { + cp = (ContourRecord *) malloc(sizeof(ContourRecord)); + int nbPtsOnEdgeLoop = indices[i+1] -indices[i]; + cp->oriented_points = + (PointRecord *) malloc(nbPtsOnEdgeLoop * sizeof(PointRecord)); + cp->perturbations = (MPoint *) malloc( nbPtsOnEdgeLoop * sizeof(MPoint)); + cp->numerocontour = i; + int k=0; + // Msg(INFO, " %d %d %d ",i,indices[i],indices[i+1]); + for(int j = indices[i]; j < indices[i+1]; j++) { + MVertex *here = points[j]; + cp->oriented_points[k].where.h = here->x(); + cp->oriented_points[k].where.v = here->y(); + cp->perturbations[k].h = CTX.mesh.rand_factor * LC2D * + (double)rand() / (double)RAND_MAX; + cp->perturbations[k].v = CTX.mesh.rand_factor * LC2D * + (double)rand() / (double)RAND_MAX; + cp->oriented_points[k].numcontour = i; + + MVertex *previous = (j == indices[i])?points[indices[i+1]-1] : points[j-1]; + MVertex *next = (j == indices[i+1]-1)?points[indices[i]] : points[j+1]; + + double lc = 0.5 * ( sqrt ( (here->x() - previous->x())*(here->x() - previous->x()) + + (here->y() - previous->y())*(here->y() - previous->y()) ) + + sqrt ( (here->x() - next->x())*(here->x() - next->x()) + + (here->y() - next->y())*(here->y() - next->y()) ) ); + + // Msg(INFO, " %g %g %g ",here->x(),here->y(),lc); + cp->oriented_points[k].quality = lc; + cp->oriented_points[k].permu = j; + cp->oriented_points[k].initial = j; + k++; + } + cp->numpoints = nbPtsOnEdgeLoop; + liste[i] = cp; + } + + int N; + int res_mesh_domain = mesh_domain(liste, nbEdgeLoops, &M, &N,initialOnly); + + // Msg(INFO, "result is %d",res_mesh_domain); + + MVertex ** verts_ = new MVertex* [M.numpoints]; + for(int i = 0; i < M.numpoints; i++) { + // Msg(INFO, "gpa[%d] = %g %g",i,gPointArray[i].where.h,gPointArray[i].where.v); + if(gPointArray[i].initial < 0) { + + verts_[i] = new MFaceVertex ( gPointArray[i].where.h, + gPointArray[i].where.v, 0.0, gf, + 0,0); + gf->mesh_vertices.push_back(verts_[i]); + } + else + { + verts_[i] = points[gPointArray[i].initial]; + } + } + + for(int i = 0; i < M.numtriangles; i++) + { + int a = M.listdel[i]->t.a; + int b = M.listdel[i]->t.b; + int c = M.listdel[i]->t.c; + // Msg(INFO, "tri[%d] = %d %d %d",i,a,b,c); + gf->triangles.push_back(verts_[a]); + gf->triangles.push_back(verts_[b]); + gf->triangles.push_back(verts_[c]); + } + + delete [] verts_; + if(res_mesh_domain >= 0) + free(M.listdel); + free(gPointArray); + + for(int i = 0; i < nbEdgeLoops; i++) { + free(liste[i]->perturbations); + free(liste[i]->oriented_points); + free(liste[i]); + } + free(liste); +} + + + + +void deMeshGFace :: operator() (GFace *gf) +{ + for (int i=0;i<gf->mesh_vertices.size();i++) delete gf->mesh_vertices[i]; + gf->mesh_vertices.clear(); +} + + +void meshGFace :: operator() (GFace *gf) +{ + + + // destroy the mesh if it exists + deMeshGFace dem; + dem(gf); + + // Only apply this technique to unknown surfaces or planar surfaces + // when it is unknown, try your best ... + + std::vector<MVertex*> points; + std::vector<int> indices; + // compute loops on the fly + // indices indicate start and end points of a loop + // loops are not yet oriented + computeEdgeLoops(gf,points,indices); + + //compute the mean plane, this is sometimes useful + MeanPlane_bis(gf,points); + + Msg(DEBUG1, "Face %d type %d with %d edge loops and %d points", gf->tag(),gf->geomType(),indices.size()-1,points.size()); + fromCartesianToParametric c2p ( gf ); + std::for_each (points.begin(),points.end(),c2p); + Msg(DEBUG1, "points were put in parametric coords ..."); + + + if (gf->geomType() == GEntity::Plane ) + { + OldMeshGenerator ( gf, + points, + indices,0); + } + else + { + OldMeshGenerator ( gf, + points, + indices,1); + NewMeshGenerator ( gf, points, indices ); + } + + Msg(DEBUG1, "type %d %d triangles generated, %d internal vertices", gf->geomType(),gf->triangles.size()/3,gf->mesh_vertices.size()); + + if(0){ + char name[256]; + sprintf(name,"view%d-N.pos",gf->tag()); + FILE *fff = fopen (name,"w"); + fprintf(fff,"View \" \" {\n"); + + std::vector<MVertex*> &triangles = gf->triangles; + for (int i=0;i<gf->triangles.size();i+=3) + { + fprintf(fff,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){1,1,1};\n", + triangles[i]->x(),triangles[i]->y(),triangles[i]->z(), + triangles[i+1]->x(),triangles[i+1]->y(),triangles[i+1]->z(), + triangles[i+2]->x(),triangles[i+2]->y(),triangles[i+2]->z()); + } + + fprintf(fff,"};\n"); + fclose(fff); + } + + fromParametricToCartesian p2c ( gf ); + std::for_each (points.begin(),points.end(),p2c); + std::for_each (gf->mesh_vertices.begin(),gf->mesh_vertices.end(),p2c); + + if(1){ + char name[256]; + sprintf(name,"view%d.pos",gf->tag()); + FILE *fff = fopen (name,"w"); + fprintf(fff,"View \" \" {\n"); + + std::vector<MVertex*> &triangles = gf->triangles; + for (int i=0;i<gf->triangles.size();i+=3) + { + fprintf(fff,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){1,1,1};\n", + triangles[i]->x(),triangles[i]->y(),triangles[i]->z(), + triangles[i+1]->x(),triangles[i+1]->y(),triangles[i+1]->z(), + triangles[i+2]->x(),triangles[i+2]->y(),triangles[i+2]->z()); + } + + fprintf(fff,"};\n"); + fclose(fff); + } + +} diff --git a/Mesh/meshGFace.h b/Mesh/meshGFace.h new file mode 100644 index 0000000000000000000000000000000000000000..ff781657296ee92ec25ef8df5e2640a453ad2842 --- /dev/null +++ b/Mesh/meshGFace.h @@ -0,0 +1,23 @@ +#ifndef _MESH_GFACE_H_ +#define _MESH_GFACE_H_ + +#include <map> +#include "SPoint2.h" + +class MVertex; +class GFace; +// Create the mesh of the face +class meshGFace +{ + public : + void operator () ( GFace * ); +}; + +// destroy the mesh of the face +class deMeshGFace +{ + public : + void operator () ( GFace * ); +}; + +#endif