diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp index bd79868215947c061d95d7a94dc6385c4f747bda..fa6bb9272c65a055680e8e69b006b0810ab9d639 100644 --- a/Geo/GFaceCompound.cpp +++ b/Geo/GFaceCompound.cpp @@ -517,6 +517,7 @@ void GFaceCompound::fillNeumannBCS_Plane() const if (_interior_loops.size()==1 && _type != SQUARE) return; GModel::current()->setFactory("Gmsh"); + //GModel::current()->setFactory("OpenCASCADE"); std::vector<std::vector<GFace *> > myFaceLoops; std::vector<GFace *> myFaces; for(std::list<std::list<GEdge*> >::const_iterator iloop = _interior_loops.begin(); @@ -2246,7 +2247,7 @@ bool GFaceCompound::checkTopology() const double D = H; if (_interior_loops.size() > 0) D = getSizeBB(_U0); int AR1 = (int) checkAspectRatio(); - int AR2 = (int) (H/D + 0.5); + int AR2 = (int) floor(H/D+0.5); int AR = std::max(AR1, AR2); if (G != 0 || Nb < 1){ diff --git a/Geo/SVector3.h b/Geo/SVector3.h index 0cd61b25c0de9f90c39aaea437108937a41cde7e..645058a3849be89edd3e532cfeda283c796c9830 100644 --- a/Geo/SVector3.h +++ b/Geo/SVector3.h @@ -142,6 +142,7 @@ inline void buildOrthoBasis_naive(SVector3 &dir, SVector3 &dir1, SVector3 &dir2) dir2.normalize(); } +//given a normal, build tangent and binormal inline void buildOrthoBasis(SVector3 &normal, SVector3 &tangent, SVector3 &binormal) { //pick any Unit-Vector that's not parallel to normal: @@ -164,4 +165,24 @@ inline void buildOrthoBasis(SVector3 &normal, SVector3 &tangent, SVector3 &binor } +//given a normal and guess tangent, build binormal +inline void buildOrthoBasis2(SVector3 &normal, SVector3 &tangent, SVector3 &binormal) +{ + + normal.normalize(); + tangent.normalize(); + + //build a binormal from tangent and normal: + binormal = crossprod(tangent, normal); + double t1 = binormal.normalize(); + + //and correct the tangent from the binormal and the normal. + tangent = crossprod(normal, binormal); + double t2 = tangent.normalize(); + + if (t1 == 0.0 || t2 == 0.0) + buildOrthoBasis_naive(normal, tangent, binormal); + +} + #endif diff --git a/Mesh/CenterlineField.cpp b/Mesh/CenterlineField.cpp index 9f2cb2e7943a7d011e7c9d72b6271e23142b534a..ab7111e6faadb90a07fac8414ce9da2cb80e2321 100644 --- a/Mesh/CenterlineField.cpp +++ b/Mesh/CenterlineField.cpp @@ -47,7 +47,7 @@ void erase(std::vector<MLine*>& lines, MLine* l) { double computeLength(std::vector<MLine*> lines){ double length= 0.0; - for (int i = 0; i< lines.size(); i++){ + for (unsigned int i = 0; i< lines.size(); i++){ length += lines[i]->getLength(); } return length; @@ -358,13 +358,14 @@ Centerline::~Centerline(){ if(nodesR) annDeallocPts(nodesR); delete[]index; delete[]dist; + } void Centerline::importFile(std::string fileName){ current = GModel::current(); std::vector<GFace*> currentFaces = current->bindingsGetFaces(); - for (int i = 0; i < currentFaces.size(); i++){ + for (unsigned int i = 0; i < currentFaces.size(); i++){ GFace *gf = currentFaces[i]; if (gf->geomType() == GEntity::DiscreteSurface){ for(unsigned int j = 0; j < gf->triangles.size(); j++) @@ -389,7 +390,7 @@ void Centerline::importFile(std::string fileName){ int maxN = 0.0; std::vector<GEdge*> modEdges = mod->bindingsGetEdges(); - for (int i = 0; i < modEdges.size(); i++){ + for (unsigned int i = 0; i < modEdges.size(); i++){ GEdge *ge = modEdges[i]; for(unsigned int j = 0; j < ge->lines.size(); j++){ MLine *l = ge->lines[j]; @@ -514,7 +515,7 @@ void Centerline::distanceToSurface(){ //COMPUTE WITH REVERSE ANN TREE (SURFACE POINTS IN TREE) std::set<MVertex*> allVS; - for(int j = 0; j < triangles.size(); j++) + for(unsigned int j = 0; j < triangles.size(); j++) for(int k = 0; k<3; k++) allVS.insert(triangles[j]->getVertex(k)); int nbSNodes = allVS.size(); nodesR = annAllocPts(nbSNodes, 3); @@ -592,12 +593,12 @@ void Centerline::buildKdTree(){ kdtree = new ANNkd_tree(nodes, nbNodes, 3); - for(unsigned int i = 0; i < nbNodes; ++i){ + for(int i = 0; i < nbNodes; ++i){ fprintf(f, "SP(%g,%g,%g){%g};\n", nodes[i][0], nodes[i][1],nodes[i][2],1.0); } fprintf(f,"};\n"); - fclose(f); + fclose(f); } @@ -611,7 +612,6 @@ void Centerline::createSplitCompounds(){ // Remesh new faces (Compound Lines and Compound Surfaces) Msg::Info("*** Starting parametrize compounds:"); - double t0 = Cpu(); //Parametrize Compound Lines for (int i=0; i < NE; i++){ @@ -673,7 +673,7 @@ void Centerline::cleanMesh(){ mySplitMesh->addPhysicalEntity(2*NF+1); current->setPhysicalName("surface mesh", 2, 2*NF+1); current->add(mySplitMesh); - for (int i=0; i < discFaces.size(); i++){ + for (unsigned int i=0; i < discFaces.size(); i++){ GFace *gfc = current->getFaceByTag(NF+i+1); for(unsigned int j = 0; j < gfc->triangles.size(); ++j){ MTriangle *t = gfc->triangles[j]; @@ -710,7 +710,7 @@ void Centerline::cleanMesh(){ GFace *gf = current->getFaceByTag(i+1); current->remove(gf); } - for (int i=0; i < discFaces.size(); i++){ + for (unsigned int i=0; i < discFaces.size(); i++){ GFace *gfc = current->getFaceByTag(NF+i+1); current->remove(gfc); } @@ -731,7 +731,6 @@ void Centerline::createFaces(){ for(unsigned int i = 0; i < triangles.size(); ++i) for(int j = 0; j < 3; j++) e2e.insert(std::make_pair(triangles[i]->getEdge(j), triangles[i])); - int iGroup = 0; while(!e2e.empty()){ std::set<MTriangle*> group; std::set<MEdge, Less_Edge> touched; @@ -754,7 +753,6 @@ void Centerline::createFaces(){ Msg::Info("Centerline action (cutMesh) has cut surface mesh in %d faces ", (int)faces.size()); //create discFaces - int numBef = current->getMaxElementaryNumber(2) + 1; for(unsigned int i = 0; i < faces.size(); ++i){ int numF = current->getMaxElementaryNumber(2) + 1; discreteFace *f = new discreteFace(current, numF); @@ -762,7 +760,7 @@ void Centerline::createFaces(){ discFaces.push_back(f); std::set<MVertex*> myVertices; std::vector<MTriangle*> myFace = faces[i]; - for(int j= 0; j< myFace.size(); j++){ + for(unsigned int j= 0; j< myFace.size(); j++){ MTriangle *t = myFace[j]; f->triangles.push_back(t); for (int k= 0; k< 3; k++){ @@ -794,7 +792,7 @@ void Centerline::createClosedVolume(){ current->setFactory("Gmsh"); std::vector<std::vector<GFace *> > myFaceLoops; std::vector<GFace *> myFaces; - for (int i = 0; i< boundEdges.size(); i++){ + for (unsigned int i = 0; i< boundEdges.size(); i++){ std::vector<std::vector<GEdge *> > myEdgeLoops; std::vector<GEdge *> myEdges; GEdge * gec = current->getEdgeByTag(NE+boundEdges[i]->tag()); @@ -867,7 +865,7 @@ void Centerline::cutMesh(){ int nbSplit = (int)floor(AR / 3. + 0.5); double li = L/nbSplit; double lc = 0.0; - for (int j= 0; j < lines.size(); j++){ + for (unsigned int j= 0; j < lines.size(); j++){ lc += lines[j]->getLength(); if (lc > li && nbSplit > 1) { MVertex *v1 = lines[j]->getVertex(0); @@ -1043,34 +1041,59 @@ void Centerline::operator() (double x, double y, double z, SMetric3 &metr, GEnt double xyz[3] = {x,y,z}; //take xyz = closest point on boundary in case we are on the planar IN/OUT FACES or in VOLUME + bool onTubularSurface = true; + double ds = 0.0; bool isCompound = (ge->dim() == 2 && ge->geomType() == GEntity::CompoundSurface) ? true: false; std::list<GFace*> cFaces; if (isCompound) cFaces = ((GFaceCompound*)ge)->getCompounds(); if ( ge->dim() == 3 || (ge->dim() == 2 && ge->geomType() == GEntity::Plane) || (isCompound && (*cFaces.begin())->geomType() == GEntity::Plane) ){ - int num_neighbours = 1; - kdtreeR->annkSearch(xyz, num_neighbours, index, dist); + onTubularSurface = false; + kdtreeR->annkSearch(xyz, 1, index, dist); + ds = sqrt(dist[0]); xyz[0] = nodesR[index[0]][0]; xyz[1] = nodesR[index[0]][1]; xyz[2] = nodesR[index[0]][2]; } - int num_neighbours = 2; - ANNidxArray index2 = new ANNidx[num_neighbours]; - ANNdistArray dist2 = new ANNdist[num_neighbours]; - kdtree->annkSearch(xyz, num_neighbours, index2, dist2); - double d = sqrt(dist2[0]); - double lc = 2*M_PI*d/nbPoints; + ANNidxArray index2 = new ANNidx[2]; + ANNdistArray dist2 = new ANNdist[2]; + kdtree->annkSearch(xyz, 2, index2, dist2); + double radMax = sqrt(dist2[0]); SVector3 p0(nodes[index2[0]][0], nodes[index2[0]][1], nodes[index2[0]][2]); SVector3 p1(nodes[index2[1]][0], nodes[index2[1]][1], nodes[index2[1]][2]); - SVector3 dir_t = p1-p0; - SVector3 dir_n1, dir_n2; - buildOrthoBasis(dir_t,dir_n1,dir_n2); - - double lc_t = 3.*lc; + + //dir_a = direction along the centerline + //dir_n = normal direction of the disk + //dir_t = tangential direction of the disk + SVector3 dir_a = p1-p0; + SVector3 dir_n(x-p0.x(), y-p0.y(), z-p0.z()); + SVector3 dir_t; + buildOrthoBasis2(dir_a, dir_n, dir_t); + + double lc = 2*M_PI*radMax/nbPoints; + double lc_a = 3.*lc; + double lc_n, lc_t; + if (onTubularSurface){ + lc_n = lc_t = lc; + } + else{ + double e = radMax/3.; + double hn = e/10.; + double rm = std::max(radMax-ds, radMax-e); + lc_t = 2*M_PI*rm/nbPoints; + //lc_n = lc_t = lc; + //double ratio = 1.02; //1. + (lc_t-hn)/e; + //printf("ratio =%g \n", ratio); + //lc_n = ds*(ratio-1) + hn; + if (ds < e) lc_n = hn; + else lc_n = lc_t; + } + double lam_a = 1./(lc_a*lc_a); + double lam_n = 1./(lc_n*lc_n); double lam_t = 1./(lc_t*lc_t); - double lam_n = 1./(lc*lc); - metr = SMetric3(lam_t,lam_n,lam_n, dir_t, dir_n1, dir_n2); + + metr = SMetric3(lam_a,lam_n,lam_t, dir_a, dir_n, dir_t); delete[]index2; delete[]dist2; diff --git a/Mesh/CenterlineField.h b/Mesh/CenterlineField.h index f43e6241fd2fc1d57dddf2eb27d821f16dca5609..efba5de307a36dd0d07529ebcb816adf121bbe7a 100644 --- a/Mesh/CenterlineField.h +++ b/Mesh/CenterlineField.h @@ -66,6 +66,7 @@ class Centerline : public Field{ bool is_cut; bool is_closed; + //all (unique) lines of centerlines std::vector<MLine*> lines; //the stuctured tree of the centerlines