diff --git a/Geo/Curvature.cpp b/Geo/Curvature.cpp index 49b262a1e14848c8ce1f36125822a1a2fde6cffe..f77eeb18a37fa925e27d7b28ea047a7b54a00ae2 100644 --- a/Geo/Curvature.cpp +++ b/Geo/Curvature.cpp @@ -1439,6 +1439,64 @@ void Curvature::edgeNodalValues(MLine* edge, double& c0, double& c1, int isAbs) } +//======================================================================================================== + +void Curvature::edgeNodalValuesAndDirections(MLine* edge, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs) +{ + std::vector<MVertex*> LineVertices; + //LineVertices.resize(2); + edge->getEdgeVertices(0,LineVertices);//triangle->getVertex(0); + + int V0 = 0; + int V1 = 0; + + //LineVertices[0] is a pointer the first vertex of the edge + //LineVertices[1] is a pointer the second vertex of the edge + + + std::map<int,int>::iterator vertexIterator; + vertexIterator = _VertexToInt.find( LineVertices[0]->getNum() ); + if ( vertexIterator != _VertexToInt.end() ) V0 = (*vertexIterator).second; + else + std::cout << "Didn't find vertex with number " << LineVertices[0]->getNum() << " in _VertextToInt !" << std::endl; + + vertexIterator = _VertexToInt.find( LineVertices[1]->getNum() ); + if ( vertexIterator != _VertexToInt.end() ) V1 = (*vertexIterator).second; + else + std::cout << "Didn't find vertex with number " << LineVertices[1]->getNum() << " in _VertextToInt !" << std::endl; + + + if (isAbs){ + dMax[0] = _pdir1[V0]; + dMax[1] = _pdir1[V1]; + + dMin[0] = _pdir2[V0]; + dMin[1] = _pdir2[V1]; + + cMax[0] = std::abs(_curv1[V0]); + cMax[1] = std::abs(_curv1[V1]); + + cMin[0] = std::abs(_curv2[V0]); + cMin[1] = std::abs(_curv2[V1]); + + } + else{ + + dMax[0] = _pdir1[V0]; + dMax[1] = _pdir1[V1]; + + dMin[0] = _pdir2[V0]; + dMin[1] = _pdir2[V1]; + + cMax[0] = _curv1[V0]; + cMax[1] = _curv1[V1]; + + cMin[0] = _curv2[V0]; + cMin[1] = _curv2[V1]; + } +} + + //======================================================================================================== double Curvature::getAtVertex(const MVertex *v) const { diff --git a/Geo/Curvature.h b/Geo/Curvature.h index a4674916ac030a458932fe495557f268103982de..cda44bdcc993693e3feb7aea277945c347012bc7 100644 --- a/Geo/Curvature.h +++ b/Geo/Curvature.h @@ -209,10 +209,13 @@ public: void computeCurvature_RBF(); void triangleNodalValues(MTriangle* triangle, double& c0, double& c1, double& c2, int isAbs=0); + void triangleNodalValuesAndDirections(MTriangle* triangle, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs=0); void edgeNodalValues(MLine* edge, double& c0, double& c1, int isAbs=0); + void edgeNodalValuesAndDirections(MLine* edge, SVector3* dMax, SVector3* dMin, double* cMax, double* cMin, int isAbs=0); + void writeToMshFile( const std::string & filename); void writeToPosFile( const std::string & filename); diff --git a/Geo/GEdgeCompound.cpp b/Geo/GEdgeCompound.cpp index a5e44e97bd978d65c1d5b0a8b64c0731e7cbced1..6b79a31df1d92c4f1004cd07f9546ca77455b124 100644 --- a/Geo/GEdgeCompound.cpp +++ b/Geo/GEdgeCompound.cpp @@ -10,7 +10,9 @@ #include <stdlib.h> #include "GmshConfig.h" #include "GEdgeCompound.h" +#include "discreteEdge.h" #include "Numeric.h" +#include "Curvature.h" GEdgeCompound::GEdgeCompound(GModel *m, int tag, std::vector<GEdge*> &compound, std::vector<int> &orientation) @@ -241,6 +243,51 @@ double GEdgeCompound::curvature(double par) const return _compound[iEdge]->curvature(tLoc); } +double GEdgeCompound::curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin, + double *curvMax, double *curvMin) const +{ + double tLoc = -1.0; + int iEdge; + getLocalParameter(par,iEdge,tLoc); + + if( _compound[iEdge]->geomType() == GEntity::DiscreteCurve) + { + Curvature& curvature = Curvature::getInstance(); + if( !Curvature::valueAlreadyComputed() ) + { + Msg::Info("Need to compute discrete curvature for anisotropic remesh (in GFace)"); + Curvature::typeOfCurvature type = Curvature::RUSIN; //RBF + curvature.computeCurvature(model(), type); + } + double tLocMLine; + int iMLine; + discreteEdge* ptrEdge = dynamic_cast<discreteEdge*>(_compound[iEdge]); + ptrEdge->getLocalParameter(tLoc, iMLine, tLocMLine); + + //vector of MLines + MLine* mline = ptrEdge->lines[iMLine]; + + double cMin[2]; + double cMax[2]; + SVector3 dMin[2]; + SVector3 dMax[2]; + curvature.edgeNodalValuesAndDirections(mline, dMax, dMin, cMax, cMin, 0); + + *dirMax = (1-tLocMLine)*dMax[0] + tLocMLine*dMax[1]; + *dirMin = (1-tLocMLine)*dMin[0] + tLocMLine*dMin[1]; + *curvMax = (1-tLocMLine)*cMax[0] + tLocMLine*cMax[1]; + *curvMin = (1-tLocMLine)*cMin[0] + tLocMLine*cMin[1]; + + return *curvMax; + + } + else + { + Msg::Error("Case of CAD Geometry, don't know what to do here..."); + } + return 0.0; +} + GPoint GEdgeCompound::point(double par) const { double tLoc; diff --git a/Geo/GEdgeCompound.h b/Geo/GEdgeCompound.h index d30fb8fd83d986bc1a2a5512e20672870a458eee..9562588528b6d9473604a20dfbc28699cb986d7d 100644 --- a/Geo/GEdgeCompound.h +++ b/Geo/GEdgeCompound.h @@ -32,6 +32,8 @@ class GEdgeCompound : public GEdge { ModelType getNativeType() const { return GmshModel; } void * getNativePtr() const { return 0; } virtual double curvature(double t) const; + virtual double curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin, + double *curvMax, double *curvMin) const; virtual int minimumMeshSegments() const; virtual int minimumDrawSegments() const; std::vector<GEdge*> getCompounds() const { return _compound; } diff --git a/Geo/discreteEdge.cpp b/Geo/discreteEdge.cpp index 87039f8aa84634b11d906e66017cdfef27cfddca..fd8047b94e792b31a6d007d639b5b3b40d32cf77 100644 --- a/Geo/discreteEdge.cpp +++ b/Geo/discreteEdge.cpp @@ -20,6 +20,7 @@ #include "Geo.h" #include "OS.h" #include "Curvature.h" +#include "GEdgeCompound.h" discreteEdge::discreteEdge(GModel *model, int num, GVertex *_v0, GVertex *_v1) : GEdge(model, num, _v0, _v1) @@ -513,6 +514,18 @@ double discreteEdge::curvature(double par) const } +double discreteEdge::curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin, + double *curvMax, double *curvMin) const +{ + if (getCompound()){ + return getCompound()->curvatures(par, dirMax, dirMin, curvMax, curvMin); + } + else{ + Msg::Error("Cannot evaluate curvatures and curvature directions on discrete edge"); + return false; + } +} + Range<double> discreteEdge::parBounds(int i) const { return Range<double>(0, lines.size()); diff --git a/Geo/discreteEdge.h b/Geo/discreteEdge.h index a136f8c8cd3a2ace5ad4d7307f3386b23ff149f3..67fc1f7573700bec095a68843d9bb7c1a7e1425b 100644 --- a/Geo/discreteEdge.h +++ b/Geo/discreteEdge.h @@ -23,6 +23,7 @@ class discreteEdge : public GEdge { virtual GPoint point(double p) const; virtual SVector3 firstDer(double par) const; virtual double curvature(double par) const; + virtual double curvatures(const double par, SVector3 *dirMax, SVector3 *dirMin, double *curvMax, double *curvMin) const; virtual bool haveParametrization(){ return !_pars.empty(); } virtual Range<double> parBounds(int) const; diff --git a/Mesh/BackgroundMesh.cpp b/Mesh/BackgroundMesh.cpp index a846a8f1a03bf63edba7794e29f4eef6341b8637..02e05831927324c14e18439a994e1a1e574f9825 100644 --- a/Mesh/BackgroundMesh.cpp +++ b/Mesh/BackgroundMesh.cpp @@ -174,11 +174,35 @@ static SMetric3 metric_based_on_surface_curvature(const GFace *gf, double u, dou static SMetric3 metric_based_on_surface_curvature(const GEdge *ge, double u) { - SMetric3 mesh_size(1.e-12); - std::list<GFace *> faces = ge->faces(); - std::list<GFace *>::iterator it = faces.begin(); - int count = 0; - while(it != faces.end()){ + const GEdgeCompound* ptrCompoundEdge = dynamic_cast<const GEdgeCompound*>(ge); + if (ptrCompoundEdge) + { + double cmax, cmin; + SVector3 dirMax,dirMin; + cmax = ptrCompoundEdge->curvatures(u,&dirMax, &dirMin, &cmax,&cmin); + if (cmin == 0)cmin =1.e-5; + if (cmax == 0)cmax =1.e-5; + double lambda2 = ((2 * M_PI) /( fabs(cmax) * CTX::instance()->mesh.minCircPoints ) ); + double lambda1 = ((2 * M_PI) /( fabs(cmin) * CTX::instance()->mesh.minCircPoints ) ); + SVector3 Z = crossprod(dirMax,dirMin); + + lambda1 = std::max(lambda1, CTX::instance()->mesh.lcMin); + lambda2 = std::max(lambda2, CTX::instance()->mesh.lcMin); + lambda1 = std::min(lambda1, CTX::instance()->mesh.lcMax); + lambda2 = std::min(lambda2, CTX::instance()->mesh.lcMax); + + SMetric3 curvMetric (1./(lambda1*lambda1),1./(lambda2*lambda2),1.e-5,dirMin, dirMax, Z ); + return curvMetric; + } + + else + { + SMetric3 mesh_size(1.e-12); + std::list<GFace *> faces = ge->faces(); + std::list<GFace *>::iterator it = faces.begin(); + int count = 0; + while(it != faces.end()) + { if (((*it)->geomType() != GEntity::CompoundSurface) && ((*it)->geomType() != GEntity::DiscreteSurface)){ SPoint2 par = ge->reparamOnFace((*it), u, 1); @@ -193,42 +217,8 @@ static SMetric3 metric_based_on_surface_curvature(const GEdge *ge, double u) double lambda = ((2 * M_PI) /( fabs(Crv) * CTX::instance()->mesh.minCircPoints ) ); SMetric3 curvMetric (1./(lambda*lambda)); - return intersection(mesh_size,curvMetric); -} - -static SMetric3 metric_based_on_surface_curvature_ES(const GEdge *ge, double u) -{ - // If the curve is a compound curve, find the corresponding discrete curve. Then loop over all - // neighboring (discrete) surfaces and compute the metric as the intersection of the surface metrics - - SMetric3 mesh_size(1.e-12); - int iDiscEdge; - double tLoc; - if (ge->geomType() == GEntity::CompoundCurve) - { - const GEdgeCompound* ptrEdgeCompound = dynamic_cast<const GEdgeCompound*>(ge); - ptrEdgeCompound->getLocalParameter(u, iDiscEdge, tLoc); - std::vector <GEdge*> DiscreteEdge = ptrEdgeCompound->getCompounds(); //vector of pointers to GEdge - GEdge* ptrDiscEdge = DiscreteEdge[iDiscEdge]; //Single pointer to GEdge - - std::list<GFace *> faces = ptrDiscEdge->faces(); - std::list<GFace *>::iterator it = faces.begin(); - int count = 0; - while(it != faces.end()) - { - -// SMetric3 m = metric_based_on_surface_curvature(*it, u, v); //This doesn't work!!!! - SPoint2 par = ge->reparamOnFace((*it), u, 1); - SMetric3 m = metric_based_on_surface_curvature (*it, par.x(), par.y()); - if (!count) mesh_size = m; - else mesh_size = intersection(mesh_size, m); - count++; - - ++it; - } - } - - return mesh_size; + return intersection_conserve_mostaniso(mesh_size,curvMetric); + } } static SMetric3 metric_based_on_surface_curvature(const GVertex *gv) @@ -239,77 +229,27 @@ static SMetric3 metric_based_on_surface_curvature(const GVertex *gv) ite != l_edges.end(); ++ite){ GEdge *_myGEdge = *ite; Range<double> bounds = _myGEdge->parBounds(0); - if (gv == _myGEdge->getBeginVertex()) - mesh_size = intersection - (mesh_size, - metric_based_on_surface_curvature(_myGEdge, bounds.low())); - else - mesh_size = intersection - (mesh_size, - metric_based_on_surface_curvature(_myGEdge, bounds.high())); - } - return mesh_size; -} -static SMetric3 metric_based_on_surface_curvature_ES(const GVertex *gv) -{ - SMetric3 mesh_size(1.e-5); - std::list <GFace*>::const_iterator itf; - - int iDiscEdge; - double tLoc; - - std::list<GEdge*> l_edges = gv->edges(); - std::list<GFace*> l_faces; - for (std::list<GEdge*>::const_iterator ite = l_edges.begin(); ite != l_edges.end(); ++ite) - { - if ((*ite)->geomType() == GEntity::CompoundCurve) - { - const GEdgeCompound* ptrEdgeCompound = dynamic_cast<const GEdgeCompound*>(*ite); - Range<double> bounds = (*ite)->parBounds(0); - - if (gv == (*ite)->getBeginVertex()) - { - ptrEdgeCompound->getLocalParameter(bounds.low(), iDiscEdge, tLoc); - } - else - { - ptrEdgeCompound->getLocalParameter(bounds.high(), iDiscEdge, tLoc); - } - - std::vector <GEdge*> DiscreteEdge = ptrEdgeCompound->getCompounds(); //vector of pointers to GEdge - GEdge* ptrDiscEdge = DiscreteEdge[iDiscEdge]; //Single pointer to GEdge - - - std::list<GFace *> neighFaces = ptrDiscEdge->faces(); - for (itf = neighFaces.begin(); itf != neighFaces.end(); ++itf) - { - l_faces.push_back(*itf); - } - } - } - - l_faces.sort(); - l_faces.unique(); - - itf = l_faces.begin(); - int count = 0; - while(itf != l_faces.end()) - { - SPoint2 par = gv->reparamOnFace((*itf), 1); - SMetric3 m = metric_based_on_surface_curvature (*itf, par.x(), par.y()); - if (!count) mesh_size = m; - else mesh_size = intersection(mesh_size, m); - count++; + // ES: Added extra if condition to use the code below only with compund curves + // This is because we want to call the function + // metric_based_on_surface_curvature(const GEdge *ge, double u) for the case when + // ge is a compound edge + if (_myGEdge->geomType() == GEntity::CompoundCurve) + { + if (gv == _myGEdge->getBeginVertex()) + mesh_size = intersection + (mesh_size, + metric_based_on_surface_curvature(_myGEdge, bounds.low())); + else + mesh_size = intersection + (mesh_size, + metric_based_on_surface_curvature(_myGEdge, bounds.high())); + } - ++itf; } - return mesh_size; } - - // the mesh vertex is classified on a model vertex. we compute the // maximum of the curvature of model faces surrounding this point if // it is classified on a model edge, we do the same for all model