diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp index fb5c2b61559d60dfc5a004c2f9c084d2865c5120..cc4b6e3a6519b1566a130170839ef9bf2ed58da9 100644 --- a/Geo/GFaceCompound.cpp +++ b/Geo/GFaceCompound.cpp @@ -223,8 +223,8 @@ static void computeCGKernelPolygon(std::map<MVertex*,SPoint3> &coordinates, } } -static SPoint3 myNeighVert(std::map<MVertex*,SPoint3> &coordinates, - std::vector<MElement*> &vTri) +static SPoint3 myNeighVert(MVertex *vCav, std::map<MVertex*,SPoint3> &coordinates, + std::vector<MElement*> &vTri) { std::set<MVertex*> vN; vN.clear(); @@ -232,13 +232,14 @@ static SPoint3 myNeighVert(std::map<MVertex*,SPoint3> &coordinates, MTriangle *t = (MTriangle*) vTri[i]; for(int iV = 0; iV < 3; iV++) { MVertex *v = t->getVertex(iV); + //if (v != vCav && v->onWhat()->dim() < 2) vN.insert(v); if (v->onWhat()->dim() < 2) vN.insert(v); } } - // if (vN.size()!=3) { - // printf("ARGG more than 3 points on line =%d \n", vN.size()); - // exit(1); - // } + if (vN.size()!=3){ + SPoint3 vsp = coordinates[vCav]; + return SPoint3(vsp.x(), vsp.y(), 0.0); + } double ucg = 0.0; double vcg = 0.0; @@ -248,8 +249,35 @@ static SPoint3 myNeighVert(std::map<MVertex*,SPoint3> &coordinates, ucg += vsp.x(); vcg += vsp.y(); } - ucg/=3.0; vcg/=3.0; + ucg/=3.0; vcg/=3.0; return SPoint3(ucg,vcg, 0.0); + + // std::set<MVertex*>::iterator it = vN.begin(); + // MVertex *v1 = *it; it++; + // MVertex *v2 = *it; + // SPoint3 uv0 = coordinates[vCav]; + // SPoint3 uv1 = coordinates[v1]; + // SPoint3 uv2 = coordinates[v2]; + // SVector3 P0 (uv0.x(),uv0.y(), uv0.z()); + // SVector3 P1 (uv1.x(),uv1.y(), uv1.z()); + // SVector3 P2 (uv2.x(),uv2.y(), uv2.z()); + // SVector3 a = P1-P0; + // SVector3 b = P2-P0; + // double a_para = dot(a,b)/norm(b); + // double a_perp = norm(crossprod(a,b))/norm(b); + // double theta = myacos(a_para/norm(a)); + // SVector3 P3,P1b; + // if (theta > 0.5*M_PI){ + // P3= P0 + (a_para/norm(b))*b; + // P1b = P1 + 1.1*(P3-P1); + // } + // else{ + // P3= P0 + 0.5*(P2-P0); + // P1b = P1 + 1.1*(P3-P1); + // } + // SPoint3 uv1_new(P1b.x(),P1b.y(),P1b.z()); + // return uv1_new; + } static void myPolygon(std::vector<MElement*> &vTri, std::vector<MVertex*> &vPoly) { @@ -295,6 +323,7 @@ bool checkCavity(std::vector<MElement*> &vTri, std::map<MVertex*, SPoint2> &vCoo unsigned int nbV = vTri.size(); double a_old = 0.0, a_new; + double nnew, nold; for(unsigned int i = 0; i < nbV; ++i){ MTriangle *t = (MTriangle*) vTri[i]; SPoint2 v1 = vCoord[t->getVertex(0)]; @@ -305,8 +334,9 @@ bool checkCavity(std::vector<MElement*> &vTri, std::map<MVertex*, SPoint2> &vCoo double p3[2] = {v3[0],v3[1]}; a_new = robustPredicates::orient2d(p1, p2, p3); if(i == 0) a_old=a_new; - if(a_new*a_old < 0.) badCavity = true; - //a_old = a_new; + if (a_new != 0.0) nnew = a_new/std::abs(a_new); + if (a_old != 0.0) nold = a_old/std::abs(a_old); + if(nnew*nold < 0.) badCavity = true; } return badCavity; @@ -544,6 +574,7 @@ bool GFaceCompound::checkOrientation(int iter, bool moveBoundaries) const double a_old = 0.0, a_new=0.0; bool oriented = true; int count = 0; + double nTot = 0.0; for( ; it != _compound.end(); ++it){ for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){ MTriangle *t = (*it)->triangles[i]; @@ -555,10 +586,11 @@ bool GFaceCompound::checkOrientation(int iter, bool moveBoundaries) const double p2[2] = {v3[0],v3[1]}; a_new = robustPredicates::orient2d(p0, p1, p2); if(count == 0) a_old=a_new; - double nnew = 1.0, nold = 1.0; - if (a_new != 0.0) nnew = std::abs(a_new); - if (a_old != 0.0) nold = std::abs(a_old); - if(a_new/nnew*a_old/nold < 0.0){ + double nnew = 0.0, nold = 0.0; + if (a_new != 0.0) nnew = a_new/std::abs(a_new); + if (a_old != 0.0) nold = a_old/std::abs(a_old); + nTot += nnew; + if(nnew*nold < 0.0){ oriented = false; break; } @@ -571,9 +603,19 @@ bool GFaceCompound::checkOrientation(int iter, bool moveBoundaries) const int iterMax = 15; if(!oriented && iter < iterMax){ - if (iter == 0) Msg::Info("--- Flipping : applying cavity checks."); - Msg::Debug("--- Cavity Check - iter %d -",iter); - one2OneMap(moveBoundaries); + if (moveBoundaries){ + if (iter ==0) Msg::Info("--- Flipping : moving boundaries."); + Msg::Info("--- Moving Boundary - iter %d -",iter); + convexBoundary(nTot/fabs(nTot)); + one2OneMap(false); + one2OneMap(true); + printStuff(iter); + } + else if (!moveBoundaries){ + if (iter ==0) Msg::Info("--- Flipping : applying cavity checks."); + Msg::Debug("--- Cavity Check - iter %d -",iter); + one2OneMap(moveBoundaries); + } return checkOrientation(iter+1, moveBoundaries); } else if (iter > 0 && iter < iterMax){ @@ -581,6 +623,125 @@ bool GFaceCompound::checkOrientation(int iter, bool moveBoundaries) const } return oriented; + +} +void GFaceCompound::convexBoundary(double nTot) const +{ +#if defined(HAVE_MESH) + if(adjv.size() == 0){ + std::vector<MTriangle*> allTri; + std::list<GFace*>::const_iterator it = _compound.begin(); + for( ; it != _compound.end(); ++it){ + allTri.insert(allTri.end(), (*it)->triangles.begin(), (*it)->triangles.end() ); + } + buildVertexToTriangle(allTri, adjv); + } + + //find normal of ordered loop + MVertex *v0 = _ordered[0]; + MVertex *v1 = _ordered[1]; + MVertex *v2; + v2t_cont :: iterator it0 = adjv.find (v0); + std::vector<MElement*> vTri0 = it0->second; + MElement *myTri; + for (unsigned int j = 0; j < vTri0.size(); j++){ + MVertex *vt0 = vTri0[j]->getVertex(0); + MVertex *vt1 = vTri0[j]->getVertex(1); + MVertex *vt2 = vTri0[j]->getVertex(2); + bool found0 = (vt0==v0 || vt1 ==v0 || vt2 ==v0) ? true: false; + bool found1 = (vt0==v1 || vt1 ==v1 || vt2 ==v1) ? true: false; + if (found0 && found1) { myTri = vTri0[j]; break; } + } + for (unsigned int j = 0; j < 3; j++){ + MVertex *vj = myTri->getVertex(j); + if (vj!=v0 && vj!=v1) { v2 = vj; break;} + } + bool inverted = false; + SPoint3 c0 = coordinates[myTri->getVertex(0)]; + SPoint3 c1 = coordinates[myTri->getVertex(1)]; + SPoint3 c2 = coordinates[myTri->getVertex(2)]; + double p0[2] = {c0[0],c0[1]}; + double p1[2] = {c1[0],c1[1]}; + double p2[2] = {c2[0],c2[1]}; + double normTri = robustPredicates::orient2d(p0,p1,p2); + if (nTot*normTri < 0) inverted = true; + double s = 1.0; + if (inverted) s = -1.0 ; + SPoint3 uv0 = coordinates[v0]; + SPoint3 uv1 = coordinates[v1]; + SPoint3 uv2 = coordinates[v2]; + SVector3 P0 (uv0.x(),uv0.y(), 0.0); + SVector3 P1 (uv1.x(),uv1.y(), 0.0); + SVector3 P2 (uv2.x(),uv2.y(), 0.0); + double myN = s*crossprod(P1-P0,P2-P1).z(); + SVector3 N (0,0,myN/fabs(myN)); + + //start loop + int nbPos = 0; + int nbNeg = 0; + for(int i = 0; i < _ordered.size(); i++){ + + MVertex *v0 = _ordered[i]; + MVertex *v1, *v2; + if (i == _ordered.size()-2){ + v1 = _ordered[i+1]; + v2 = _ordered[0]; + } + else if (i == _ordered.size()-1){ + v1= _ordered[0]; + v2= _ordered[1]; + } + else{ + v1 = _ordered[i+1]; + v2 = _ordered[i+2]; + } + + SPoint3 uv0 = coordinates[v0]; + SPoint3 uv1 = coordinates[v1]; + SPoint3 uv2 = coordinates[v2]; + SVector3 P0 (uv0.x(),uv0.y(), uv0.z()); + SVector3 P1 (uv1.x(),uv1.y(), uv1.z()); + SVector3 P2 (uv2.x(),uv2.y(), uv2.z()); + + SVector3 dir1 = P1-P0; + SVector3 dir2 = P2-P1; + double rot = dot(N, crossprod(dir1,dir2)); + + if (rot < -1.e-4){ + SVector3 a = P1-P0; + SVector3 b = P2-P0; + double a_para = dot(a,b)/norm(b); + double a_perp = norm(crossprod(a,b))/norm(b); + double theta = myacos(a_para/norm(a)); + SVector3 P3,P1b; + if (theta > 0.5*M_PI){ + P3= P0 + (a_para/norm(b))*b; + P1b = P1 + 1.7*(P3-P1); + } + else{ + P3= P0 + 0.5*(P2-P0); + P1b = P1 + 1.6*(P3-P1); + } + SPoint3 uv1_new(P1b.x(),P1b.y(),P1b.z()); + coordinates[v1] = uv1_new; + } + } + + // FILE * f2 = fopen("myBC.pos","w"); + // fprintf(f2, "View \"\"{\n"); + // for (int i = 0; i< _ordered.size()-1; i++){ + // SPoint3 uv0 = coordinates[_ordered[i]]; + // SPoint3 uv1 = coordinates[_ordered[i+1]]; + // fprintf(f2, "SL(%g,%g,%g,%g,%g,%g){%g,%g};\n", + // uv0.x(),uv0.y(), uv0.z(), + // uv1.x(),uv1.y(), uv1.z(), + // (double)i, (double)i+1); + // } + // fprintf(f2,"};\n"); + // fclose(f2); + + +#endif } void GFaceCompound::one2OneMap(bool moveBoundaries) const @@ -618,7 +779,7 @@ void GFaceCompound::one2OneMap(bool moveBoundaries) const coordinates[v] = p_cg; } else if (moveBoundaries && badCavity && !innerCavity){ - SPoint3 p_cg = myNeighVert(coordinates, vTri); + SPoint3 p_cg = myNeighVert(v, coordinates, vTri); coordinates[v] = p_cg; } } @@ -649,7 +810,17 @@ bool GFaceCompound::parametrize() const fillNeumannBCS(); parametrize(ITERU,CONVEX); parametrize(ITERV,CONVEX); - printStuff(111); + printStuff(11); + if (_type==MEANPLANE){ + checkOrientation(0, true); + // printStuff(22); + // _type = ALREADYFIXED; + // parametrize(ITERU,CONVEX); + // parametrize(ITERV,CONVEX); + // checkOrientation(0, true); + // printStuff(33); + } + printStuff(44); } // Laplace parametrization else if (_mapping == HARMONIC){ @@ -704,7 +875,9 @@ bool GFaceCompound::parametrize() const if (_mapping != RBF){ if (!checkOrientation(0)){ - Msg::Info("### parametrization switched to convex combination map"); + Msg::Info("### parametrization switched to 'convex map' onto circle"); + printStuff(33); + _type = UNITCIRCLE; coordinates.clear(); Octree_Delete(oct); fillNeumannBCS(); @@ -917,8 +1090,8 @@ GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, _mapping = HARMONIC; _type = UNITCIRCLE; if (toc == HARMONIC_CIRCLE) _mapping = HARMONIC; - else if(toc == CONFORMAL) _mapping = CONFORMAL; - else if(toc == RBF) _mapping = RBF; + else if(toc == CONFORMAL_SPECTRAL) _mapping = CONFORMAL; + else if(toc == RADIAL_BASIS) _mapping = RBF; else if (toc == HARMONIC_PLANE) _type = MEANPLANE; else if (toc == CONVEX_CIRCLE) _mapping = CONVEX; else if (toc == CONVEX_PLANE){ @@ -954,8 +1127,8 @@ GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, _mapping = HARMONIC; _type = UNITCIRCLE; if (toc == HARMONIC_CIRCLE) _mapping = HARMONIC; - else if(toc == CONFORMAL) _mapping = CONFORMAL; - else if(toc == RBF) _mapping = RBF; + else if(toc == CONFORMAL_SPECTRAL) _mapping = CONFORMAL; + else if(toc == RADIAL_BASIS) _mapping = RBF; else if (toc == HARMONIC_PLANE) _type = MEANPLANE; else if (toc == CONVEX_CIRCLE) _mapping = CONVEX; else if (toc == CONVEX_PLANE){ @@ -1153,6 +1326,15 @@ void GFaceCompound::parametrize(iterationStep step, typeOfMapping tom) const else if(step == ITERV) myAssembler.fixVertex(v, 0, 1, pointsUV[i][1]); } } + else if (_type == ALREADYFIXED){ + printf("already fixed boundaries \n"); + for(unsigned int i = 0; i < _ordered.size(); i++){ + MVertex *v = _ordered[i]; + SPoint3 uv = coordinates[v]; + if(step == ITERU) myAssembler.fixVertex(v, 0, 1, uv[0]); + else if(step == ITERV) myAssembler.fixVertex(v, 0, 1, uv[1]); + } + } else{ Msg::Error("Unknown type of parametrization"); return; @@ -1243,11 +1425,11 @@ bool GFaceCompound::parametrize_conformal_spectral() const myAssembler.numberVertex(v, 0, 2); } - // for(std::set<MVertex *>::iterator itv = fillNodes.begin(); itv !=fillNodes.end() ; ++itv){ - // MVertex *v = *itv; - // myAssembler.numberVertex(v, 0, 1); - // myAssembler.numberVertex(v, 0, 2); - // } + for(std::set<MVertex *>::iterator itv = fillNodes.begin(); itv !=fillNodes.end() ; ++itv){ + MVertex *v = *itv; + myAssembler.numberVertex(v, 0, 1); + myAssembler.numberVertex(v, 0, 2); + } laplaceTerm laplace1(model(), 1, ONE); laplaceTerm laplace2(model(), 2, ONE); @@ -1280,13 +1462,13 @@ bool GFaceCompound::parametrize_conformal_spectral() const myAssembler.assemble(v, 0, 2, v, 0, 2, epsilon); } } - // for(std::set<MVertex *>::iterator itv = fillNodes.begin(); itv !=fillNodes.end() ; ++itv){ - // MVertex *v = *itv; - // if (std::find(_ordered.begin(), _ordered.end(), v) == _ordered.end() ){ - // myAssembler.assemble(v, 0, 1, v, 0, 1, epsilon); - // myAssembler.assemble(v, 0, 2, v, 0, 2, epsilon); - // } - // } + for(std::set<MVertex *>::iterator itv = fillNodes.begin(); itv !=fillNodes.end() ; ++itv){ + MVertex *v = *itv; + if (std::find(_ordered.begin(), _ordered.end(), v) == _ordered.end() ){ + myAssembler.assemble(v, 0, 1, v, 0, 1, epsilon); + myAssembler.assemble(v, 0, 2, v, 0, 2, epsilon); + } + } myAssembler.setCurrentMatrix("B"); diff --git a/Geo/GFaceCompound.h b/Geo/GFaceCompound.h index 17a093b7f9cbf94c9d9e51537ae6d98282b10c78..1424595bc00445d384750e7f646c84211455bbc2 100644 --- a/Geo/GFaceCompound.h +++ b/Geo/GFaceCompound.h @@ -56,7 +56,7 @@ class GFaceCompound : public GFace { typedef enum {HARMONIC_CIRCLE=0, CONFORMAL_SPECTRAL=1, RADIAL_BASIS=2, HARMONIC_PLANE=3, CONVEX_CIRCLE=4,CONVEX_PLANE=5, HARMONIC_SQUARE=6} typeOfCompound; typedef enum {HARMONIC=0,CONFORMAL=1, RBF=2, CONVEX=3} typeOfMapping; - typedef enum {UNITCIRCLE, MEANPLANE, SQUARE} typeOfIsomorphism; + typedef enum {UNITCIRCLE, MEANPLANE, SQUARE, ALREADYFIXED} typeOfIsomorphism; void computeNormals(std::map<MVertex*, SVector3> &normals) const; protected: mutable std::set<MVertex *> ov; @@ -90,6 +90,7 @@ class GFaceCompound : public GFace { bool checkOrientation(int iter, bool moveBoundaries=false) const; bool checkOverlap(std::vector<MVertex *> &vert) const; void one2OneMap(bool moveBoundaries=false) const; + void convexBoundary(double nTot) const; double checkAspectRatio() const; void computeNormals () const; void getBoundingEdges(); @@ -144,7 +145,7 @@ class GFaceCompound : public GFace { private: mutable typeOfCompound _toc; mutable typeOfMapping _mapping; - typeOfIsomorphism _type; + mutable typeOfIsomorphism _type; int _allowPartition; }; @@ -158,7 +159,7 @@ class GFaceCompound : public GFace { typedef enum {HARMONIC_CIRCLE=0, CONFORMAL_SPECTRAL=1, RADIAL_BASIS=2, HARMONIC_PLANE=3, CONVEX_CIRCLE=4,CONVEX_PLANE=5, HARMONIC_SQUARE=6} typeOfCompound; typedef enum {HARMONIC=0,CONFORMAL=1, RBF=2, CONVEX=3} typeOfMapping; - typedef enum {UNITCIRCLE, MEANPLANE, SQUARE} typeOfIsomorphism; + typedef enum {UNITCIRCLE, MEANPLANE, SQUARE, ALREADYFIXED} typeOfIsomorphism; GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound, std::list<GEdge*> &U0, typeOfMapping typ = HARMONIC, int allowPartition=1,