diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp index e9e41e535a505747853a074192f9bef708df3db9..9a53fc187e6f6495e875707ce83d547dff6fff67 100644 --- a/Geo/GFace.cpp +++ b/Geo/GFace.cpp @@ -271,14 +271,6 @@ SOrientedBoundingBox GFace::getOBB() return SOrientedBoundingBox(_obb); } -surface_params GFace::getSurfaceParams() const -{ - surface_params p; - p.radius = p.radius2 = p.height = p.cx = p.cy = p.cz = 0.; - Msg::Error("Empty surface parameters for this type of surface"); - return p; -} - std::vector<MVertex*> GFace::getEmbeddedMeshVertices() const { std::set<MVertex*> tmp; @@ -1106,7 +1098,7 @@ GPoint GFace::closestPoint(const SPoint3 &queryPoint, const double initialGuess[ #endif } -bool GFace::containsParam(const SPoint2 &pt) const +bool GFace::containsParam(const SPoint2 &pt) { Range<double> uu = parBounds(0); Range<double> vv = parBounds(1); @@ -1279,51 +1271,6 @@ bool GFace::fillVertexArray(bool force) return true; } -// by default we assume that straight lines are geodesics -SPoint2 GFace::geodesic(const SPoint2 &pt1, const SPoint2 &pt2, double t) -{ - if(CTX::instance()->mesh.secondOrderExperimental && geomType() != GEntity::Plane ){ - // FIXME: this is buggy -- remove the CTX option once we do it in - // a robust manner - GPoint gp1 = point(pt1.x(), pt1.y()); - GPoint gp2 = point(pt2.x(), pt2.y()); - SPoint2 guess = pt1 + (pt2 - pt1) * t; - GPoint gp = closestPoint(SPoint3(gp1.x() + t * (gp2.x() - gp1.x()), - gp1.y() + t * (gp2.y() - gp1.y()), - gp1.z() + t * (gp2.z() - gp1.z())), - (double*)guess); - if (gp.g()) - return SPoint2(gp.u(), gp.v()); - else - return pt1 + (pt2 - pt1) * t; - } - else{ - return pt1 + (pt2 - pt1) * t; - } -} - - -// length of a curve drawn on a surface -// S = (X(u,v), Y(u,v), Z(u,v) ); -// u = u(t) , v = v(t) -// C = C ( u(t), v(t) ) -// dC/dt = dC/du du/dt + dC/dv dv/dt -double GFace::length(const SPoint2 &pt1, const SPoint2 &pt2, int nbQuadPoints) -{ - double *t = 0, *w = 0; - double L = 0.0; - gmshGaussLegendre1D(nbQuadPoints, &t, &w); - for (int i = 0; i < nbQuadPoints; i++){ - const double ti = 0.5 * (1. + t[i]); - SPoint2 pi = geodesic(pt1, pt2, ti); - Pair<SVector3, SVector3> der2 = firstDer(pi); - SVector3 der = der2.left() * (pt2.x() - pt1.x()) + der2.right() * (pt2.y() - pt1.y()); - const double d = norm(der); - L += d * w[i] ; - } - return L; -} - int GFace::genusGeom() const { int nSeams = 0; @@ -1456,7 +1403,7 @@ void GFace::lloyd(int nbiter, int infn) void GFace::replaceEdges(std::list<GEdge*> &new_edges) { - replaceEdgesInternal(new_edges); + // replaceEdgesInternal(new_edges); std::list<GEdge*>::iterator it = l_edges.begin(); std::list<GEdge*>::iterator it2 = new_edges.begin(); std::list<int>::iterator it3 = l_dirs.begin(); diff --git a/Geo/GFace.h b/Geo/GFace.h index a9ac73c2f704ed8060d8f014227540a41e112133..b55a4b71382452b1c63bb7ce005c25c21d69685c 100644 --- a/Geo/GFace.h +++ b/Geo/GFace.h @@ -26,11 +26,6 @@ class MPolygon; class ExtrudeParams; class GFaceCompound; -struct surface_params -{ - double radius, radius2, height, cx, cy, cz; -}; - class GRegion; // A model face. @@ -46,9 +41,6 @@ class GFace : public GEntity { std::list<GVertex *> embedded_vertices; GFaceCompound *compound; // this model face belongs to a compound - // replace edges (for gluing) for specific modelers, we have to - // re-create internal data - virtual void replaceEdgesInternal(std::list<GEdge*> &){} BoundaryLayerColumns _columns; public: // this will become protected or private @@ -154,9 +146,6 @@ class GFace : public GEntity { // get the oriented bounding box virtual SOrientedBoundingBox getOBB(); - // retrieve surface params - virtual surface_params getSurfaceParams() const; - // compute the genus G of the surface virtual int genusGeom() const; virtual bool checkTopology() const { return true; } @@ -165,14 +154,6 @@ class GFace : public GEntity { virtual GPoint point(double par1, double par2) const = 0; virtual GPoint point(const SPoint2 &pt) const { return point(pt.x(), pt.y()); } - // compute, in parametric space, the interpolation from pt1 to pt2 - // along a geodesic of the surface - virtual SPoint2 geodesic(const SPoint2 &pt1, const SPoint2 &pt2, double t); - - // compute the length of a geodesic between two points in parametric - // space - virtual double length(const SPoint2 &pt1, const SPoint2 &pt2, int n=4); - // if the mapping is a conforming mapping, i.e. a mapping that // conserves angles, this function returns the eigenvalue of the // metric at a given point this is a special feature for @@ -190,7 +171,7 @@ class GFace : public GEntity { virtual SPoint2 parFromPoint(const SPoint3 &, bool onSurface=true) const; // true if the parameter value is interior to the face - virtual bool containsParam(const SPoint2 &pt) const; + virtual bool containsParam(const SPoint2 &pt); // return the point on the face closest to the given point virtual GPoint closestPoint(const SPoint3 & queryPoint, diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp index cd14f1a54a6e4549da3901932a182f25cc1d0e53..144e06aac163f3927932f2b5fbfdd570aa05e1fd 100644 --- a/Geo/GModel.cpp +++ b/Geo/GModel.cpp @@ -3561,242 +3561,6 @@ void GModel::setPhysicalNumToEntitiesInBox(int EntityDimension, int PhysicalNumb setPhysicalNumToEntitiesInBox(EntityDimension, PhysicalNumber, box); } -static void computeDuplicates(GModel *model, - std::multimap<GVertex*, GVertex*> &Unique2Duplicates, - std::map<GVertex*, GVertex*> &Duplicates2Unique, - const double &eps) -{ - // FIXME: currently we use a greedy algorithm in n^2 (use e.g. MVertexRTree) - - // FIXME: add option to remove orphaned entities after duplicate check - std::list<GVertex*> v; - v.insert(v.begin(), model->firstVertex(), model->lastVertex()); - - while(!v.empty()){ - GVertex *pv = *v.begin(); - v.erase(v.begin()); - bool found = false; - for (std::multimap<GVertex*,GVertex*>::iterator it = Unique2Duplicates.begin(); - it != Unique2Duplicates.end(); ++it){ - GVertex *unique = it->first; - const double d = sqrt((unique->x() - pv->x()) * (unique->x() - pv->x()) + - (unique->y() - pv->y()) * (unique->y() - pv->y()) + - (unique->z() - pv->z()) * (unique->z() - pv->z())); - if (d <= eps && pv->geomType() == unique->geomType()) { - found = true; - Unique2Duplicates.insert(std::make_pair(unique, pv)); - Duplicates2Unique[pv] = unique; - break; - } - } - if (!found) { - Unique2Duplicates.insert(std::make_pair(pv, pv)); - Duplicates2Unique[pv] = pv; - } - } -} - -static void glueVerticesInEdges(GModel *model, - std::multimap<GVertex*, GVertex*> &Unique2Duplicates, - std::map<GVertex*, GVertex*> &Duplicates2Unique) -{ - Msg::Debug("Gluing Edges"); - for (GModel::eiter it = model->firstEdge(); it != model->lastEdge(); ++it){ - GEdge *e = *it; - GVertex *v1 = e->getBeginVertex(); - GVertex *v2 = e->getEndVertex(); - GVertex *replacementOfv1 = Duplicates2Unique[v1]; - GVertex *replacementOfv2 = Duplicates2Unique[v2]; - if ((v1 != replacementOfv1) || (v2 != replacementOfv2)){ - Msg::Debug("Model Edge %d is re-build", e->tag()); - e->replaceEndingPoints (replacementOfv1, replacementOfv2); - } - } -} - -static void computeDuplicates(GModel *model, - std::multimap<GEdge*, GEdge*> &Unique2Duplicates, - std::map<GEdge*,GEdge*> &Duplicates2Unique, - const double &eps) -{ - std::list<GEdge*> e; - e.insert(e.begin(), model->firstEdge(), model->lastEdge()); - - while(!e.empty()){ - GEdge *pe = *e.begin(); - e.erase(e.begin()); - bool found = false; - for (std::multimap<GEdge*,GEdge*>::iterator it = Unique2Duplicates.begin(); - it != Unique2Duplicates.end(); ++it ){ - GEdge *unique = it->first; - // first check edges that have same endpoints - if (((unique->getBeginVertex() == pe->getBeginVertex() && - unique->getEndVertex() == pe->getEndVertex()) || - (unique->getEndVertex() == pe->getBeginVertex() && - unique->getBeginVertex() == pe->getEndVertex())) && - unique->geomType() == pe->geomType()){ - if ((unique->geomType() == GEntity::Line && pe->geomType() == GEntity::Line) || - unique->geomType() == GEntity::DiscreteCurve || - pe->geomType() == GEntity::DiscreteCurve || - unique->geomType() == GEntity::BoundaryLayerCurve || - pe->geomType() == GEntity::BoundaryLayerCurve){ - found = true; - Unique2Duplicates.insert(std::make_pair(unique,pe)); - Duplicates2Unique[pe] = unique; - break; - } - // compute a point - Range<double> r = pe->parBounds(0); - GPoint gp = pe->point(0.5 * (r.low() + r.high())); - double t; - GPoint gp2 = pe->closestPoint(SPoint3(gp.x(),gp.y(),gp.z()),t); - const double d = sqrt((gp.x() - gp2.x()) * (gp.x() - gp2.x()) + - (gp.y() - gp2.y()) * (gp.y() - gp2.y()) + - (gp.z() - gp2.z()) * (gp.z() - gp2.z())); - if (t >= r.low() && t <= r.high() && d <= eps) { - found = true; - Unique2Duplicates.insert(std::make_pair(unique,pe)); - Duplicates2Unique[pe] = unique; - break; - } - } - } - if (!found) { - Unique2Duplicates.insert(std::make_pair(pe,pe)); - Duplicates2Unique[pe] = pe; - } - } -} - -static void glueEdgesInFaces(GModel *model, - std::multimap<GEdge*, GEdge*> &Unique2Duplicates, - std::map<GEdge*, GEdge*> &Duplicates2Unique) -{ - Msg::Debug("Gluing Model Faces"); - for (GModel::fiter it = model->firstFace(); it != model->lastFace(); ++it){ - GFace *f = *it; - bool aDifferenceExists = false; - std::list<GEdge*> old = f->edges(), enew; - for (std::list<GEdge*>::iterator eit = old.begin(); eit !=old.end(); eit++){ - GEdge *temp = Duplicates2Unique[*eit]; - enew.push_back(temp); - if (temp != *eit){ - aDifferenceExists = true; - } - } - if (aDifferenceExists){ - Msg::Debug("Model Face %d is re-build", f->tag()); - f->replaceEdges(enew); - } - } -} - -static void computeDuplicates(GModel *model, - std::multimap<GFace*, GFace*> &Unique2Duplicates, - std::map<GFace*,GFace*> &Duplicates2Unique, - const double &eps) -{ - std::list<GFace*> f; - f.insert(f.begin(),model->firstFace(),model->lastFace()); - - while(!f.empty()){ - GFace *pf = *f.begin(); - Range<double> r = pf->parBounds(0); - Range<double> s = pf->parBounds(1); - f.erase(f.begin()); - std::list<GEdge*> pf_edges = pf->edges(); - pf_edges.sort(); - bool found = false; - for (std::multimap<GFace*,GFace*>::iterator it = Unique2Duplicates.begin(); - it != Unique2Duplicates.end(); ++it){ - GFace *unique = it->first; - std::list<GEdge*> unique_edges = unique->edges(); - if (pf->geomType() == unique->geomType() && - unique_edges.size() == pf_edges.size()){ - unique_edges.sort(); - std::list<GEdge*>::iterator it_pf = pf_edges.begin(); - std::list<GEdge*>::iterator it_unique = unique_edges.begin(); - bool all_similar = true; - // first check faces that have same edges - for (; it_pf != pf_edges.end() ; ++it_pf,it_unique++){ - if (*it_pf != *it_unique) all_similar = false; - } - if (all_similar){ - if (unique->geomType() == GEntity::Plane && pf->geomType() == GEntity::Plane){ - found = true; - Unique2Duplicates.insert(std::make_pair(unique,pf)); - Duplicates2Unique[pf] = unique; - break; - } - double t[2]={0,0}; - // FIXME: evaluate a point on the surface (use e.g. buildRepresentationCross) - const double d = 1.0; - if (t[0] >= r.low() && t[0] <= r.high() && - t[1] >= s.low() && t[1] <= s.high() && d <= eps) { - found = true; - Unique2Duplicates.insert(std::make_pair(unique,pf)); - Duplicates2Unique[pf] = unique; - break; - } - } - } - } - if (!found) { - Unique2Duplicates.insert(std::make_pair(pf,pf)); - Duplicates2Unique[pf] = pf; - } - } -} - -static void glueFacesInRegions(GModel *model, - std::multimap<GFace*, GFace*> &Unique2Duplicates, - std::map<GFace*, GFace*> &Duplicates2Unique) -{ - Msg::Debug("Gluing Regions"); - for (GModel::riter it = model->firstRegion(); it != model->lastRegion();++it){ - GRegion *r = *it; - bool aDifferenceExists = false; - std::list<GFace*> old = r->faces(), fnew; - for (std::list<GFace*>::iterator fit = old.begin(); fit != old.end(); fit++){ - std::map<GFace*, GFace*>::iterator itR = Duplicates2Unique.find(*fit); - if (itR == Duplicates2Unique.end()){ - Msg::Error("Error in the gluing process"); - return; - } - GFace *temp = itR->second;; - fnew.push_back(temp); - if (temp != *fit){ - aDifferenceExists = true; - } - } - if (aDifferenceExists){ - Msg::Debug("Model Region %d is re-build", r->tag()); - r->replaceFaces (fnew); - } - } -} - -void GModel::glue(double eps) -{ - { - std::multimap<GVertex*,GVertex*> Unique2Duplicates; - std::map<GVertex*,GVertex*> Duplicates2Unique; - computeDuplicates(this, Unique2Duplicates, Duplicates2Unique, eps); - glueVerticesInEdges(this, Unique2Duplicates, Duplicates2Unique); - } - { - std::multimap<GEdge*,GEdge*> Unique2Duplicates; - std::map<GEdge*,GEdge*> Duplicates2Unique; - computeDuplicates(this, Unique2Duplicates, Duplicates2Unique, eps); - glueEdgesInFaces(this, Unique2Duplicates, Duplicates2Unique); - } - { - std::multimap<GFace*,GFace*> Unique2Duplicates; - std::map<GFace*,GFace*> Duplicates2Unique; - computeDuplicates(this, Unique2Duplicates, Duplicates2Unique, eps); - glueFacesInRegions(this, Unique2Duplicates, Duplicates2Unique); - } -} GEdge *getNewModelEdge(GFace *gf1, GFace *gf2, std::map<std::pair<int, int>, GEdge*> &newEdges) diff --git a/Geo/GModel.h b/Geo/GModel.h index b37ed3715174d4a968d805eae56ba4c54b2bdd43..bce806399c748ae0d89dd3fe0ee14dd9980124a4 100644 --- a/Geo/GModel.h +++ b/Geo/GModel.h @@ -493,7 +493,7 @@ class GModel { // vertices that are too close, then merge edges, faces and // regions). Warning: the gluer changes the geometric model, so that // some pointers could become invalid. - void glue(double eps); + // void glue(double eps); // change the entity creation factory void setFactory(std::string name); diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp index 5562e4f98132ef63eb7b6bfda76657efa7ffea32..23ac5442e5e62df8baffb697967d6c8bce9a0f2f 100644 --- a/Geo/GModelIO_OCC.cpp +++ b/Geo/GModelIO_OCC.cpp @@ -3285,8 +3285,9 @@ bool OCC_Internals::_makeFaceSTL(TopoDS_Face s, #if (OCC_VERSION_MAJOR >= 7) BRepMesh_FastDiscret::Parameters parameters; parameters.Deflection = 0.1; - parameters.Angle = 0.35; - parameters.Relative = Standard_True; + parameters.Angle = 0.1; + // parameters.InternalVerticesMode = Standard_False; + parameters.Relative = Standard_False; BRepMesh_FastDiscret aMesher(aBox, parameters); #else BRepMesh_FastDiscret aMesher(0.1, 0.35, aBox, Standard_False, Standard_False, diff --git a/Geo/OCCEdge.cpp b/Geo/OCCEdge.cpp index d2674dbc0097d3f359db1043fdbf714300340af5..ea980a29670301215a6d59462fdbf8dedbe96629 100644 --- a/Geo/OCCEdge.cpp +++ b/Geo/OCCEdge.cpp @@ -124,20 +124,34 @@ SPoint2 OCCEdge::reparamOnFace(const GFace *face, double epar, int dir) const if (CTX::instance()->geom.reparamOnFaceRobust){ GPoint p1 = point(epar); GPoint p2 = face->point(u, v); - const double dx = p1.x()-p2.x(); - const double dy = p1.y()-p2.y(); - const double dz = p1.z()-p2.z(); + double dx = p1.x()-p2.x(); + double dy = p1.y()-p2.y(); + double dz = p1.z()-p2.z(); if(sqrt(dx * dx + dy * dy + dz * dz) > CTX::instance()->geom.tolerance){ - Msg::Warning("Reparam on face was inaccurate for curve %d on surface %d at point %g", + Msg::Debug("Reparam on face was inaccurate for curve %d on surface %d at point %g", tag(), face->tag(), epar); - Msg::Warning("On the face %d local (%g %g) global (%g %g %g)", + Msg::Debug("On the face %d local (%g %g) global (%g %g %g)", face->tag(), u, v, p2.x(), p2.y(), p2.z()); - Msg::Warning("On the edge %d local (%g) global (%g %g %g)", + Msg::Debug("On the edge %d local (%g) global (%g %g %g)", tag(), epar, p1.x(), p1.y(), p1.z()); double guess [2] = {u,v}; GPoint pp = face->closestPoint(SPoint3(p1.x(),p1.y(),p1.z()), guess); u = pp.u(); v = pp.v(); + + GPoint p2 = face->point(u, v); + dx = p1.x()-p2.x(); + dy = p1.y()-p2.y(); + dz = p1.z()-p2.z(); + if(sqrt(dx * dx + dy * dy + dz * dz) > CTX::instance()->geom.tolerance){ + Msg::Error("Closest Point was inaccurate for curve %d on surface %d at point %g", + tag(), face->tag(), epar); + Msg::Error("On the face %d local (%g %g) global (%g %g %g)", + face->tag(), u, v, p2.x(), p2.y(), p2.z()); + Msg::Error("On the edge %d local (%g) global (%g %g %g)", + tag(), epar, p1.x(), p1.y(), p1.z()); + } + else Msg::Info("OK"); } } return SPoint2(u, v); diff --git a/Geo/OCCFace.cpp b/Geo/OCCFace.cpp index c9628090372666b55bac8fc90159c88105961e01..a33daa00033738a85b03738427b92bc3bd51462e 100644 --- a/Geo/OCCFace.cpp +++ b/Geo/OCCFace.cpp @@ -13,6 +13,7 @@ #include "OCCFace.h" #include "Numeric.h" #include "Context.h" +#include "robustPredicates.h" #if defined(HAVE_OCC) @@ -37,9 +38,10 @@ #include <TopExp_Explorer.hxx> #include <TopoDS.hxx> #include <gp_Pln.hxx> +#include <gp_Sphere.hxx> OCCFace::OCCFace(GModel *m, TopoDS_Face _s, int num) - : GFace(m, num), s(_s) +: GFace(m, num), s(_s),_radius(-1) { setup(); if(model()->getOCCInternals()) @@ -111,7 +113,11 @@ void OCCFace::setup() BRepAdaptor_Surface surface(s); _periodic[0] = surface.IsUPeriodic(); _periodic[1] = surface.IsVPeriodic(); + if (_periodic[0]) _period[0]=surface.UPeriod(); + if (_periodic[1]) _period[1]=surface.VPeriod(); + + ShapeAnalysis::GetFaceUVBounds(s, umin, umax, vmin, vmax); Msg::Debug("OCC Face %d with %d parameter bounds (%g,%g)(%g,%g)", tag(), l_edges.size(), umin, umax, vmin, vmax); @@ -138,6 +144,14 @@ void OCCFace::setup() embedded_vertices.push_back(v); } } + + if (geomType()==GEntity::Sphere){ + BRepAdaptor_Surface surface(s); + gp_Sphere sphere = surface.Sphere(); + _radius = sphere.Radius(); + gp_Pnt loc = sphere.Location(); + _center = SPoint3(loc.X(),loc.Y(),loc.Z()); + } } SBoundingBox3d OCCFace::bounds() const @@ -389,24 +403,9 @@ bool OCCFace::containsPoint(const SPoint3 &pt) const return false; } -surface_params OCCFace::getSurfaceParams() const -{ - surface_params p; - switch(geomType()){ - case GEntity::Cylinder: - p.radius = Handle(Geom_CylindricalSurface)::DownCast(occface)->Radius(); - break; - case GEntity::Sphere: - p.radius = Handle(Geom_SphericalSurface)::DownCast(occface)->Radius(); - break; - default: - break; - } - return p; -} - bool OCCFace::buildSTLTriangulation(bool force) { + if(stl_triangles.size()){ if(force){ stl_vertices.clear(); @@ -456,112 +455,14 @@ bool OCCFace::buildSTLTriangulation(bool force) return true; } -void OCCFace::replaceEdgesInternal(std::list<GEdge*> &new_edges) -{ - // we simply replace old edges by new edges in the structure - Handle(IntTools_Context) myContext = new IntTools_Context; - - // make a copy of s - TopoDS_Face copy_of_s_forward = s; - copy_of_s_forward.Orientation(TopAbs_FORWARD); - // make a copy of occface - TopLoc_Location location; - Handle(Geom_Surface) copy_of_occface = BRep_Tool::Surface(copy_of_s_forward, location); - // check periodicity - bool bIsUPeriodic = _periodic[0]; - // get tolerance - double tolerance = BRep_Tool::Tolerance(copy_of_s_forward); - - BRep_Builder aBB; - TopoDS_Face newFace; - aBB.MakeFace(newFace, copy_of_occface, location, tolerance); - // expolore the face - TopExp_Explorer aExpW, aExpE; - aExpW.Init(copy_of_s_forward, TopAbs_WIRE); - for (; aExpW.More(); aExpW.Next()) { - TopoDS_Wire newWire; - aBB.MakeWire(newWire); - const TopoDS_Wire& aW=TopoDS::Wire(aExpW.Current()); - aExpE.Init(aW, TopAbs_EDGE); - for (; aExpE.More(); aExpE.Next()) { - const TopoDS_Edge& aE=TopoDS::Edge(aExpE.Current()); - std::list<GEdge*>::iterator it = l_edges.begin(); - std::list<GEdge*>::iterator it2 = new_edges.begin(); - TopoDS_Edge aER; - Msg::Debug("trying to replace %d by %d",(*it)->tag(),(*it2)->tag()); - for ( ; it != l_edges.end(); ++it, ++it2){ - OCCEdge *occEd = dynamic_cast<OCCEdge*>(*it); - TopoDS_Edge olde = occEd->getTopoDS_Edge(); - if (olde.IsSame(aE)){ - aER = *((TopoDS_Edge*)(*it2)->getNativePtr()); - } - else { - olde = occEd->getTopoDS_EdgeOld(); - if (olde.IsSame(aE)){ - aER = *((TopoDS_Edge*)(*it2)->getNativePtr()); - } - } - } - if (aER.IsNull()){ - Msg::Error("cannot find an edge for gluing a face"); - } - aER.Orientation(TopAbs_FORWARD); - if (!BRep_Tool::Degenerated(aER)) { - if (bIsUPeriodic) { - Standard_Real aT1, aT2, aTx, aUx; - BRep_Builder aBB_; - Handle(Geom2d_Curve) aC2D = - BRep_Tool::CurveOnSurface(aER, copy_of_s_forward, aT1, aT2); - if (!aC2D.IsNull()) { - if (BRep_Tool::IsClosed(aER, copy_of_s_forward)) { - continue; - } - else{ - aTx = BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2); - gp_Pnt2d aP2D; - aC2D->D0(aTx, aP2D); - aUx=aP2D.X(); - if (aUx < umin || aUx > umax) { - // need to rebuild - Handle(Geom2d_Curve) aC2Dx; - aBB_.UpdateEdge(aER, aC2Dx, copy_of_s_forward , BRep_Tool::Tolerance(aE)); - } - } - } - } - BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aER, copy_of_s_forward); - // orient image - Standard_Boolean bIsToReverse = - BOPTools_AlgoTools::IsSplitToReverse(aER, aE, myContext); - if (bIsToReverse) { - aER.Reverse(); - } - } - else { - aER.Orientation(aE.Orientation()); - } - aBB.Add(newWire, aER); - } - aBB.Add(newFace, newWire); - } - _replaced = s; - s = newFace; - - setup(); - if(model()->getOCCInternals()) - model()->getOCCInternals()->bind(_replaced, tag()); -} bool OCCFace::isSphere (double &radius, SPoint3 ¢er) const { switch(geomType()){ case GEntity::Sphere: { - radius = Handle(Geom_SphericalSurface)::DownCast(occface)->Radius(); - gp_Ax3 pos = Handle(Geom_SphericalSurface)::DownCast(occface)->Position(); - gp_Ax1 axis = pos.Axis(); - gp_Pnt loc = axis.Location(); - center = SPoint3(loc.X(),loc.Y(),loc.Z()); + radius = _radius; + center = _center; } return true; default: @@ -569,4 +470,47 @@ bool OCCFace::isSphere (double &radius, SPoint3 ¢er) const } } +bool OCCFace::containsParam(const SPoint2 &pt) { + // return GFace::containsParam(pt); + if (! buildSTLTriangulation(false) ) { + Msg::Warning ("Inacurate computation in OCCFace::containsParam"); + return GFace::containsParam(pt); + } + // FILE *F = fopen("HOP.pos","w"); + // fprintf(F,"View \" \"{\n"); + /// fprintf(F,"SP(%g,%g,%g){2,2,2};\n",pt.x(),pt.y(),1.0); + SPoint2 mine = pt; + + // bool ok = false; + + for(unsigned int i = 0; i < stl_triangles.size(); i += 3){ + SPoint2 gp1 = stl_vertices[stl_triangles[i]]; + SPoint2 gp2 = stl_vertices[stl_triangles[i + 1]]; + SPoint2 gp3 = stl_vertices[stl_triangles[i + 2]]; + + double s1 = robustPredicates::orient2d (gp1,gp2,mine); + double s2 = robustPredicates::orient2d (gp2,gp3,mine); + double s3 = robustPredicates::orient2d (gp3,gp1,mine); + /* + fprintf(F,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){1,1,1};\n", + gp1.x(),gp1.y(),0.0, + gp2.x(),gp2.y(),0.0, + gp3.x(),gp3.y(),0.0); + + printf("%g %g %g\n",s1,s2,s3); + */ + if (s1*s2 >= 0 && s1*s3 >=0){ + //ok = true; + return true; + } + } + // printf("gasp\n"); + // fprintf(F,"};\n"); + // fclose(F); + // return ok; + return false; + +} + + #endif diff --git a/Geo/OCCFace.h b/Geo/OCCFace.h index b8d7850e7b5d2741ff9ad0db7792a8fde888f030..734b9032b420fccc91b177747bd353efb6c845c1 100644 --- a/Geo/OCCFace.h +++ b/Geo/OCCFace.h @@ -22,10 +22,10 @@ class OCCFace : public GFace { Handle(Geom_Surface) occface; double umin, umax, vmin, vmax; bool _periodic[2]; + double _period[2]; bool buildSTLTriangulation(bool force=false); - void replaceEdgesInternal (std::list<GEdge*> &); + // void replaceEdgesInternal (std::list<GEdge*> &); void setup(); - bool _isSphere; double _radius; SPoint3 _center; public: @@ -47,11 +47,14 @@ class OCCFace : public GFace { virtual double curvatureMax(const SPoint2 ¶m) const; virtual double curvatures(const SPoint2 ¶m, SVector3 *dirMax, SVector3 *dirMin, double *curvMax, double *curvMin) const; - surface_params getSurfaceParams() const; TopoDS_Face getTopoDS_Face () { return s; } TopoDS_Face getTopoDS_FaceOld () { return _replaced; } // tells if it's a sphere, and if it is, returns parameters virtual bool isSphere (double &radius, SPoint3 ¢er) const; + virtual bool periodic(int dim) const { return _periodic[dim]; } + virtual double period(int dim) const { return _period[dim]; } + // true if the parameter value is interior to the face (taking into account boundaries) + virtual bool containsParam(const SPoint2 &pt) ; }; #endif diff --git a/Geo/gmshFace.cpp b/Geo/gmshFace.cpp index 68ca5d558581556b99f8f9fee40b7eeecff1debd..fdbbbaeb1dd5c6c7d64fdc4e1fc6e0fc5f68dc12 100644 --- a/Geo/gmshFace.cpp +++ b/Geo/gmshFace.cpp @@ -21,7 +21,7 @@ #endif gmshFace::gmshFace(GModel *m, Surface *face) - : GFace(m, face->Num), isSphere(false), radius(0.) + : GFace(m, face->Num) { resetNativePtr(face); resetMeshAttributes(); @@ -105,7 +105,6 @@ void gmshFace::resetNativePtr(Surface *face) // the bounding vertices) if(s->Typ == MSH_SURF_PLAN) computeMeanPlane(); - isSphere = IsRuledSurfaceASphere(s, center, radius); } double gmshFace::getMetricEigenvalue(const SPoint2 &pt) diff --git a/Geo/gmshFace.h b/Geo/gmshFace.h index 86eae0a2e937921ee724920d64b481fc33ba8499..076d079c72a5e66f5e5bfaba133806cb09087d50 100644 --- a/Geo/gmshFace.h +++ b/Geo/gmshFace.h @@ -13,9 +13,6 @@ class Surface; class gmshFace : public GFace { protected: Surface *s; - bool isSphere; - SPoint3 center; - double radius; bool buildSTLTriangulation(bool force); public: gmshFace(GModel *m, Surface *face); diff --git a/Mesh/BDS.cpp b/Mesh/BDS.cpp index a2a0a639960d7d1cf3f4ed67d4da97ef6771fd24..82a54fa1816e5d0f39bf85cdc262f4dd2110a018 100644 --- a/Mesh/BDS.cpp +++ b/Mesh/BDS.cpp @@ -103,13 +103,10 @@ void outputScalarField(std::list<BDS_Face*> t, const char *iii, int param, GFace gf->curvatureDiv(SPoint2(pts[3]->u, pts[3]->v))); } else{ - fprintf(f, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n", + fprintf(f, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%d,%d,%d};\n", pts[0]->X, pts[0]->Y, pts[0]->Z, pts[1]->X, pts[1]->Y, pts[1]->Z, - pts[2]->X, pts[2]->Y, pts[2]->Z, - gf->curvatureDiv(SPoint2(pts[0]->u, pts[0]->v)), - gf->curvatureDiv(SPoint2(pts[1]->u, pts[1]->v)), - gf->curvatureDiv(SPoint2(pts[2]->u, pts[2]->v))); + pts[2]->X, pts[2]->Y, pts[2]->Z,pts[0]->iD, pts[1]->iD, pts[2]->iD); } } } @@ -202,7 +199,7 @@ BDS_Point *BDS_Mesh::add_point(int num, double x, double y, double z) BDS_Point *BDS_Mesh::add_point(int num, double u, double v, GFace *gf) { - GPoint gp = gf->point(u*scalingU,v*scalingV); + GPoint gp = gf->point(u,v); BDS_Point *pp = new BDS_Point(num, gp.x(), gp.y(), gp.z()); pp->u = u; pp->v = v; @@ -1227,7 +1224,9 @@ bool BDS_Mesh::smooth_point_centroid(BDS_Point *p, GFace *gf, bool test_quality) } /* TEST */ - bool isSphere = gf->geomType() == GEntity::Sphere; + double radius; + SPoint3 center; + bool isSphere = gf->isSphere(radius, center); double XX=0,YY=0,ZZ=0; double U = 0; @@ -1269,11 +1268,13 @@ bool BDS_Mesh::smooth_point_centroid(BDS_Point *p, GFace *gf, bool test_quality) V = gp.v(); } else - gp = gf->point(U * scalingU, V * scalingV); + gp = gf->point(U , V ); if (!gp.succeeded()){ return false; } + // if (!gf->containsParam(SPoint2(U,V)))return false; + const double oldX = p->X; const double oldY = p->Y; const double oldZ = p->Z; @@ -1299,23 +1300,30 @@ bool BDS_Mesh::smooth_point_centroid(BDS_Point *p, GFace *gf, bool test_quality) // printf("%22.15E %22.15E\n", snew, sold); if(snew < .1 * sold) return false; - if(1 || test_quality){ - p->X = gp.x(); - p->Y = gp.y(); - p->Z = gp.z(); - newWorst = std::min(newWorst, qmTriangle::gamma(*it)); - double norm1[3],norm2[3]; - normal_triangle(n[0], n[1], n[2], norm1); - p->X = oldX; - p->Y = oldY; - p->Z = oldZ; - normal_triangle(n[0], n[1], n[2], norm2); - oldWorst = std::min(oldWorst, qmTriangle::gamma(*it)); - double ps; + p->X = gp.x(); + p->Y = gp.y(); + p->Z = gp.z(); + newWorst = std::min(newWorst, qmTriangle::gamma(*it)); + double norm1[3],norm2[3]; + normal_triangle(n[0], n[1], n[2], norm1); + p->X = oldX; + p->Y = oldY; + p->Z = oldZ; + normal_triangle(n[0], n[1], n[2], norm2); + oldWorst = std::min(oldWorst, qmTriangle::gamma(*it)); + double ps; + if (isSphere){ + double dx = center.x() - gp.x(); + double dy = center.y() - gp.y(); + double dz = center.z() - gp.z(); + ps = dx*norm1[0]+dy*norm1[1]+dz*norm1[2]; + if (ps < 0)return false; + } + else{ prosca(norm1, norm2, &ps); - double threshold = (isSphere ? 0.95 : 0.5); + double threshold = 0.5; if(ps < threshold){ - return false; + return false; } } ++it; @@ -1386,7 +1394,7 @@ bool BDS_Mesh::smooth_point_parametric(BDS_Point *p, GFace *gf) ++it; } - GPoint gp = gf->point(U * scalingU, V * scalingV); + GPoint gp = gf->point(U, V); if (!gp.succeeded())return false; p->u = U; diff --git a/Mesh/BDS.h b/Mesh/BDS.h index 4144e84a9a0ee2ff37be36f6546cc7ef09363173..c6aa237557710a92f97600a4ebbb39f97bfff355 100644 --- a/Mesh/BDS.h +++ b/Mesh/BDS.h @@ -405,8 +405,7 @@ class BDS_Mesh public: int MAXPOINTNUMBER, SNAP_SUCCESS, SNAP_FAILURE; double Min[3], Max[3], LC; - double scalingU, scalingV; - BDS_Mesh(int _MAXX = 0) : MAXPOINTNUMBER(_MAXX),scalingU(1),scalingV(1){} + BDS_Mesh(int _MAXX = 0) : MAXPOINTNUMBER(_MAXX){} void load(GVertex *gv); // load in BDS all the meshes of the vertex void load(GEdge *ge); // load in BDS all the meshes of the edge void load(GFace *gf); // load in BDS all the meshes of the surface diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp index 99fe9736fa15468f466e92313c9e315b2b34643b..f1dc9d3130c3d511991ecf623aa7e35188e21abd 100644 --- a/Mesh/meshGFace.cpp +++ b/Mesh/meshGFace.cpp @@ -599,7 +599,7 @@ void BDS2GMSH(BDS_Mesh *m, GFace *gf, BDS_Point *p = *itp; if(recoverMap.find(p) == recoverMap.end()){ MVertex *v = new MFaceVertex - (p->X, p->Y, p->Z, gf, m->scalingU * p->u, m->scalingV * p->v); + (p->X, p->Y, p->Z, gf, p->u, p->v); recoverMap[p] = v; gf->mesh_vertices.push_back(v); } @@ -1097,8 +1097,6 @@ bool meshGenerator(GFace *gf, int RECUR_ITER, // Buid a BDS_Mesh structure that is convenient for doing the actual // meshing procedure BDS_Mesh *m = new BDS_Mesh; - m->scalingU = 1; - m->scalingV = 1; std::vector<BDS_Point*> points(all_vertices.size()); SBoundingBox3d bbox; @@ -1858,8 +1856,8 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, if(pp == 0){ double U, V; SPoint2 param = coords[i]; - U = param.x() / m->scalingU; - V = param.y() / m->scalingV; + U = param.x(); + V = param.y(); pp = m->add_point(count + countTot, U, V, gf); if (ge->dim() == 0){ pp->lcBGM() = BGM_MeshSize(ge, 0, 0, here->x(), here->y(), here->z()); @@ -1912,8 +1910,6 @@ static bool meshGeneratorPeriodic(GFace *gf, bool debug = true) // Buid a BDS_Mesh structure that is convenient for doing the actual // meshing procedure BDS_Mesh *m = new BDS_Mesh; - m->scalingU = 1; - m->scalingV = 1; std::vector<std::vector<BDS_Point*> > edgeLoops_BDS; SBoundingBox3d bbox; @@ -2306,7 +2302,7 @@ static bool meshGeneratorPeriodic(GFace *gf, bool debug = true) BDS_Point *p = *itp; if(recoverMap.find(p) == recoverMap.end()){ MVertex *v = new MFaceVertex - (p->X, p->Y, p->Z, gf, m->scalingU * p->u, m->scalingV * p->v); + (p->X, p->Y, p->Z, gf, p->u, p->v); recoverMap[p] = v; gf->mesh_vertices.push_back(v); } diff --git a/Mesh/meshGFaceBDS.cpp b/Mesh/meshGFaceBDS.cpp index c403a14215a974dfbdda855b59c05365efb7955b..16ccdeb59cef132730a3fe526d462428f881c485 100644 --- a/Mesh/meshGFaceBDS.cpp +++ b/Mesh/meshGFaceBDS.cpp @@ -35,19 +35,10 @@ double computeEdgeLinearLength(BDS_Point *p1, BDS_Point *p2) extern double lengthInfniteNorm(const double p[2], const double q[2], const double quadAngle); -inline double computeEdgeLinearLength(BDS_Point *p1, BDS_Point *p2, GFace *f, - double SCALINGU, double SCALINGV) +inline double computeEdgeLinearLength(BDS_Point *p1, BDS_Point *p2, GFace *f) { - // FIXME SUPER HACK - // if (CTX::instance()->mesh.recombineAll || f->meshAttributes.recombine || 1){ - // double quadAngle = backgroundMesh::current()->getAngle (0.5 * (p1->u + p2->u) * SCALINGU, 0.5 * (p1->v + p2->v) * SCALINGV,0); - // const double a [2] = {p1->u,p1->v}; - // const double b [2] = {p2->u,p2->v}; - // return lengthInfniteNorm(a,b, quadAngle); - // } - - GPoint GP = f->point(SPoint2(0.5 * (p1->u + p2->u) * SCALINGU, - 0.5 * (p1->v + p2->v) * SCALINGV)); + GPoint GP = f->point(SPoint2(0.5 * (p1->u + p2->u), + 0.5 * (p1->v + p2->v))); if (!GP.succeeded()) return computeEdgeLinearLength(p1,p2); @@ -63,16 +54,15 @@ inline double computeEdgeLinearLength(BDS_Point *p1, BDS_Point *p2, GFace *f, return l1 + l2; } -inline double computeEdgeLinearLength_new(BDS_Point *p1, BDS_Point *p2, GFace *f, - double SCALINGU, double SCALINGV) +inline double computeEdgeLinearLength_new(BDS_Point *p1, BDS_Point *p2, GFace *f) { const int nbSb = 10; GPoint GP[nbSb]; for (int i = 1; i < nbSb; i++){ double xi = (double)i / nbSb; - GP[i-1] = f->point(SPoint2(((1-xi) * p1->u + xi * p2->u) * SCALINGU, - ((1-xi) * p1->v + xi * p2->v) * SCALINGV)); + GP[i-1] = f->point(SPoint2(((1-xi) * p1->u + xi * p2->u), + ((1-xi) * p1->v + xi * p2->v))); if (!GP[i-1].succeeded()) return computeEdgeLinearLength(p1,p2); } @@ -100,14 +90,13 @@ inline double computeEdgeLinearLength_new(BDS_Point *p1, BDS_Point *p2, GFace * return l; } -inline double computeEdgeMiddleCoord(BDS_Point *p1, BDS_Point *p2, GFace *f, - double SCALINGU, double SCALINGV) +inline double computeEdgeMiddleCoord(BDS_Point *p1, BDS_Point *p2, GFace *f) { if (f->geomType() == GEntity::Plane) return 0.5; - GPoint GP = f->point(SPoint2(0.5 * (p1->u + p2->u) * SCALINGU, - 0.5 * (p1->v + p2->v) * SCALINGV)); + GPoint GP = f->point(SPoint2(0.5 * (p1->u + p2->u), + 0.5 * (p1->v + p2->v))); const double dx1 = p1->X - GP.x(); const double dy1 = p1->Y - GP.y(); @@ -124,14 +113,13 @@ inline double computeEdgeMiddleCoord(BDS_Point *p1, BDS_Point *p2, GFace *f, return 0.25 * (3 * l2 - l1) / l2; } -inline double computeEdgeLinearLength(BDS_Edge *e, GFace *f, - double SCALINGU, double SCALINGV) +inline double computeEdgeLinearLength(BDS_Edge *e, GFace *f) { // FIXME !!! if (f->geomType() == GEntity::Plane) return e->length(); else - return computeEdgeLinearLength(e->p1, e->p2, f, SCALINGU, SCALINGV); + return computeEdgeLinearLength(e->p1, e->p2, f); } double NewGetLc(BDS_Point *p) @@ -141,8 +129,7 @@ double NewGetLc(BDS_Point *p) std::min(p->lc(), p->lcBGM()) : p->lcBGM(); } -static double correctLC_(BDS_Point *p1,BDS_Point *p2, GFace *f, - double SCALINGU, double SCALINGV) +static double correctLC_(BDS_Point *p1,BDS_Point *p2, GFace *f) { double l1 = NewGetLc(p1); double l2 = NewGetLc(p2); @@ -152,14 +139,11 @@ static double correctLC_(BDS_Point *p1,BDS_Point *p2, GFace *f, double U = coord * p1->u + (1 - coord) * p2->u; double V = coord * p1->v + (1 - coord) * p2->v; - GPoint gpp = f->point(SCALINGU*U, SCALINGV*V); + GPoint gpp = f->point(U, V); double lmid = BGM_MeshSize(f, U, V, gpp.x(), gpp.y(), gpp.z()); l = std::min(l, lmid); if(CTX::instance()->mesh.lcFromCurvature){ - // GPoint GP = f->point(SPoint2(0.5 * (p1->u + p2->u) * SCALINGU, - // 0.5 * (p1->v + p2->v) * SCALINGV)); - // double l3 = BGM_MeshSize(f,GP.u(),GP.v(),GP.x(),GP.y(),GP.z()); double l3 = l; double lcmin = std::min(std::min(l1, l2), l3); l1 = std::min(lcmin*1.2,l1); @@ -170,18 +154,18 @@ static double correctLC_(BDS_Point *p1,BDS_Point *p2, GFace *f, return l; } -double NewGetLc(BDS_Edge *e, GFace *f, double SCALINGU, double SCALINGV) +double NewGetLc(BDS_Edge *e, GFace *f) { - double linearLength = computeEdgeLinearLength(e, f, SCALINGU, SCALINGV); - double l = correctLC_ (e->p1,e->p2,f, SCALINGU, SCALINGV); + double linearLength = computeEdgeLinearLength(e, f); + double l = correctLC_ (e->p1,e->p2,f); //printf("BDS correct lc =%g lreal=%g \n", l,linearLength); return linearLength / l; } -double NewGetLc(BDS_Point *p1, BDS_Point *p2, GFace *f, double su, double sv) +double NewGetLc(BDS_Point *p1, BDS_Point *p2, GFace *f) { - double linearLength = computeEdgeLinearLength(p1, p2, f, su, sv); - double l = correctLC_ (p1,p2,f, su, sv); + double linearLength = computeEdgeLinearLength(p1, p2, f); + double l = correctLC_ (p1,p2,f); return linearLength / l; } @@ -199,7 +183,7 @@ void computeMeshSizeFieldAccuracy(GFace *gf, BDS_Mesh &m, double &avg, double sqr2 = sqrt(2.); while (it != m.edges.end()){ if (!(*it)->deleted){ - double lone = NewGetLc(*it, gf, m.scalingU, m.scalingV); + double lone = NewGetLc(*it, gf); if (lone > oneoversqr2 && lone < sqr2) GS++; avg += lone >1 ? (1. / lone) - 1. : lone - 1.; max_e = std::max(max_e, lone); @@ -213,7 +197,7 @@ void computeMeshSizeFieldAccuracy(GFace *gf, BDS_Mesh &m, double &avg, // SWAP TESTS i.e. tell if swap should be done -bool edgeSwapTestAngle(BDS_Edge *e, double min_cos) +static bool edgeSwapTestAngle(BDS_Edge *e, double min_cos) { BDS_Face *f1 = e->faces(0); BDS_Face *f2 = e->faces(1); @@ -229,7 +213,7 @@ bool edgeSwapTestAngle(BDS_Edge *e, double min_cos) return cosa > min_cos; } -bool evalSwapForOptimize(BDS_Edge *e, GFace *gf, BDS_Mesh &m) +static bool evalSwapForOptimize(BDS_Edge *e, GFace *gf, BDS_Mesh &m) { if(e->numfaces() != 2) return false; @@ -268,9 +252,9 @@ bool evalSwapForOptimize(BDS_Edge *e, GFace *gf, BDS_Mesh &m) // bool smoothCouldSwap = !(cosb < cosa * .5); double la = computeEdgeLinearLength(p11, p12); - double la_ = computeEdgeLinearLength(p11, p12, gf, m.scalingU, m.scalingV); + double la_ = computeEdgeLinearLength(p11, p12, gf); double lb = computeEdgeLinearLength(p13, p23); - double lb_ = computeEdgeLinearLength(p13, p23, gf, m.scalingU, m.scalingV); + double lb_ = computeEdgeLinearLength(p13, p23, gf); double LA = (la_ -la) / la_; double LB = (lb_ -lb) / lb_; @@ -300,7 +284,7 @@ bool evalSwapForOptimize(BDS_Edge *e, GFace *gf, BDS_Mesh &m) return false; } -bool edgeSwapTestDelaunay(BDS_Edge *e, GFace *gf) +static bool edgeSwapTestDelaunay(BDS_Edge *e, GFace *gf) { BDS_Point *op[2]; @@ -324,16 +308,7 @@ bool edgeSwapTestDelaunay(BDS_Edge *e, GFace *gf) return result > 1e-12; } -bool edgeSwapTestHighOrder(BDS_Edge *e,GFace *gf) -{ - // must evaluate the swap with the perspectve of - // the generation of 2 high order elements - // The rationale is to consider the edges as - // exactly matching curves and surfaces - return false; -} - -bool edgeSwapTestDelaunayAniso(BDS_Edge *e, GFace *gf, std::set<swapquad> &configs) +static bool edgeSwapTestDelaunayAniso(BDS_Edge *e, GFace *gf, std::set<swapquad> &configs) { BDS_Point *op[2]; @@ -362,65 +337,48 @@ bool edgeSwapTestDelaunayAniso(BDS_Edge *e, GFace *gf, std::set<swapquad> &confi return true; } -bool evalSwap(BDS_Edge *e, double &qa, double &qb) +static int edgeSwapTest(GFace *gf, BDS_Edge *e) { BDS_Point *op[2]; - if(e->numfaces() != 2) return false; - e->oppositeof (op); - double qa1 = qmTriangle::gamma(e->p1, e->p2, op[0]); - double qa2 = qmTriangle::gamma(e->p1, e->p2, op[1]); - double qb1 = qmTriangle::gamma(e->p1, op[0], op[1]); - double qb2 = qmTriangle::gamma(e->p2, op[0], op[1]); - qa = std::min(qa1, qa2); - qb = std::min(qb1, qb2); - return true; -} - -int edgeSwapTestQuality(BDS_Edge *e, double fact=1.1, bool force=false) -{ - BDS_Point *op[2]; - - if (!force) - if(!e->p1->config_modified && ! e->p2->config_modified) return 0; - + if(!e->p1->config_modified && ! e->p2->config_modified) return 0; if(e->numfaces() != 2) return 0; - + e->oppositeof (op); - if (!force) - if (!edgeSwapTestAngle(e, cos(CTX::instance()->mesh.allowSwapEdgeAngle * M_PI / 180.))) - return -1; - + if (!edgeSwapTestAngle(e, cos(CTX::instance()->mesh.allowSwapEdgeAngle * M_PI / 180.))) + return -1; + double qa1 = qmTriangle::gamma(e->p1, e->p2, op[0]); double qa2 = qmTriangle::gamma(e->p1, e->p2, op[1]); double qb1 = qmTriangle::gamma(e->p1, op[0], op[1]); double qb2 = qmTriangle::gamma(e->p2, op[0], op[1]); double qa = std::min(qa1, qa2); double qb = std::min(qb1, qb2); - if(qb > fact * qa) return 1; - if(qb < qa / fact) return -1; + if(qb > qa) return 1; + if(qb < qa) return -1; return 0; } void swapEdgePass(GFace *gf, BDS_Mesh &m, int &nb_swap) { + return; int NN1 = m.edges.size(); int NN2 = 0; std::list<BDS_Edge*>::iterator it = m.edges.begin(); while (1){ if (NN2++ >= NN1) break; - // result = -1 => forbid swap because too badly shaped elements - // result = 0 => whatever - // result = 1 => oblige to swap because the quality is greatly improved if (!(*it)->deleted){ - double qual = (CTX::instance()->mesh.algo2d == ALGO_2D_MESHADAPT_OLD) ? 1 : 5; - int result = edgeSwapTestQuality(*it, qual); if (CTX::instance()->mesh.algo2d == ALGO_2D_MESHADAPT_OLD){ if (m.swap_edge(*it, BDS_SwapEdgeTestQuality(true))) nb_swap++; } - else if (result >= 0 && edgeSwapTestDelaunay(*it, gf)){ - if (m.swap_edge(*it, BDS_SwapEdgeTestQuality(false))) nb_swap++; + else if (edgeSwapTestDelaunay(*it, gf)){ + int result = edgeSwapTest(gf,*it); + // result = -1 => forbid swap because too badly shaped elements + // result = 0 => whatever + // result = 1 => oblige to swap because the quality is greatly improved + if (result >= 0) + if (m.swap_edge(*it, BDS_SwapEdgeTestQuality(false))) nb_swap++; } } ++it; @@ -429,6 +387,7 @@ void swapEdgePass(GFace *gf, BDS_Mesh &m, int &nb_swap) void delaunayizeBDS(GFace *gf, BDS_Mesh &m, int &nb_swap) { + // return; nb_swap = 0; std::set<swapquad> configs; while(1){ @@ -452,43 +411,6 @@ void delaunayizeBDS(GFace *gf, BDS_Mesh &m, int &nb_swap) } } -/* -static void midpointsphere(GFace *gf, double u1, double v1, double u2, double v2, - double &u12, double &v12, SPoint3 ¢er, double r) -{ - GPoint p1 = gf->point(u1, v1); - GPoint p2 = gf->point(u2, v2); - - SVector3 DIR ((p1.x()+p2.x())/2.0 - center.x(), - (p1.y()+p2.y())/2.0 - center.y(), - (p1.z()+p2.z())/2.0 - center.z()); - DIR.normalize(); - - double X,Y,Z; - - double guess [2] = {0.5 * (u1 + u2), 0.5 * (v1 + v2)}; - u12 = guess[0]; - v12 = guess[1]; - if ( (v1 > 0.7*M_PI/2 && v2 > 0.7*M_PI/2) || - (v1 < -0.7*M_PI/2 && v2 < -0.7*M_PI/2) ){ - X = center.x() + DIR.x() * r; - Y = center.y() + DIR.y() * r; - Z = center.z() + DIR.z() * r; - } - else{ - return; - X = center.x() - DIR.x() * r; - Y = center.y() - DIR.y() * r; - Z = center.z() - DIR.z() * r; - } - - GPoint proj = gf->closestPoint(SPoint3(X, Y, Z), guess); - if (proj.succeeded()){ - u12 = proj.u(); - v12 = proj.v(); - } -} -*/ bool edges_sort(std::pair<double, BDS_Edge*> a, std::pair<double, BDS_Edge*> b) { @@ -510,49 +432,39 @@ void splitEdgePass(GFace *gf, BDS_Mesh &m, double MAXE_, int &nb_split) { std::list<BDS_Edge*>::iterator it = m.edges.begin(); std::vector<std::pair<double, BDS_Edge*> > edges; - + while (it != m.edges.end()){ if(!(*it)->deleted && (*it)->numfaces() == 2 && (*it)->g->classif_degree == 2){ - double lone = NewGetLc(*it, gf, m.scalingU, m.scalingV); - if(lone > MAXE_){ - edges.push_back(std::make_pair(-lone, *it)); - } + double lone = NewGetLc(*it, gf); + if(lone > MAXE_)edges.push_back(std::make_pair(-lone, *it)); } ++it; } std::sort(edges.begin(), edges.end(), edges_sort); + bool isPeriodic = gf->periodic(0) || gf->periodic(1) ; + SPoint3 center; + double radius; + bool isSphere = gf->isSphere (radius, center); + for (unsigned int i = 0; i < edges.size(); ++i){ BDS_Edge *e = edges[i].second; if (!e->deleted){ - const double coord = 0.5; BDS_Point *mid ; - double U, V; - U = coord * e->p1->u + (1 - coord) * e->p2->u; - V = coord * e->p1->v + (1 - coord) * e->p2->v; - - GPoint gpp = gf->point(m.scalingU*U,m.scalingV*V); - if (gpp.succeeded()){ + double U = 0.5*(e->p1->u+e->p2->u); + double V = 0.5*(e->p1->v+e->p2->v); + GPoint gpp = gf->point(U,V); + + if ((!isPeriodic || gf->containsParam(SPoint2(U,V))) && gpp.succeeded()){ mid = m.add_point(++m.MAXPOINTNUMBER, gpp.x(),gpp.y(),gpp.z()); mid->u = U; mid->v = V; - if (backgroundMesh::current() && 0){ - mid->lc() = mid->lcBGM() = - backgroundMesh::current()->operator() - ((coord * e->p1->u + (1 - coord) * e->p2->u)*m.scalingU, - (coord * e->p1->v + (1 - coord) * e->p2->v)*m.scalingV, - 0.0); - } - else { - mid->lcBGM() = BGM_MeshSize - (gf, - (coord * e->p1->u + (1 - coord) * e->p2->u)*m.scalingU, - (coord * e->p1->v + (1 - coord) * e->p2->v)*m.scalingV, - mid->X,mid->Y,mid->Z); - mid->lc() = 0.5 * (e->p1->lc() + e->p2->lc()); - } - if(!m.split_edge(e, mid)) m.del_point(mid); + mid->lcBGM() = BGM_MeshSize (gf,U,V, mid->X,mid->Y,mid->Z); + mid->lc() = 0.5 * (e->p1->lc() + e->p2->lc()); + + // if (isSphere && !canWeSplitAnEdgeOnASphere (e, mid, center,radius))m.del_point(mid); + if(!m.split_edge(e, mid)) m.del_point(mid); else nb_split++; } } @@ -579,7 +491,7 @@ double getMaxLcWhenCollapsingEdge(GFace *gf, BDS_Mesh &m, BDS_Edge *e, BDS_Point } if(!newP1 || !newP2) break; // error BDS_Edge collapsedEdge = BDS_Edge(newP1, newP2); - maxLc = std::max(maxLc, NewGetLc(&collapsedEdge, gf, m.scalingU, m.scalingV)); + maxLc = std::max(maxLc, NewGetLc(&collapsedEdge, gf)); newP1->del(&collapsedEdge); newP2->del(&collapsedEdge); ++eit; @@ -595,7 +507,8 @@ void collapseEdgePass(GFace *gf, BDS_Mesh &m, double MINE_, int MAXNP, int &nb_c while (it != m.edges.end()){ if(!(*it)->deleted && (*it)->numfaces() == 2 && (*it)->g->classif_degree == 2){ - double lone = NewGetLc(*it, gf,m.scalingU,m.scalingV); + + double lone = NewGetLc(*it, gf); if(lone < MINE_){ edges.push_back (std::make_pair(lone, *it)); } @@ -654,7 +567,7 @@ void collapseEdgePassUnSorted(GFace *gf, BDS_Mesh &m, double MINE_, int MAXNP, if(NN2++ >= NN1) break; if(!(*it)->deleted){ - double lone = NewGetLc(*it, gf, m.scalingU, m.scalingV); + double lone = NewGetLc(*it, gf); if(!(*it)->deleted && (*it)->numfaces() == 2 && lone < MINE_){ bool res = false; if((*it)->p1->iD > MAXNP) @@ -672,7 +585,7 @@ void collapseEdgePassUnSorted(GFace *gf, BDS_Mesh &m, double MINE_, int MAXNP, void smoothVertexPass(GFace *gf, BDS_Mesh &m, int &nb_smooth, bool q) { // FIXME SUPER HACK - // return; + //return; std::set<BDS_Point*,PointLessThan>::iterator itp = m.points.begin(); while(itp != m.points.end()){ if(m.smooth_point_centroid(*itp, gf,q)) @@ -756,7 +669,7 @@ void refineMeshBDS(GFace *gf, BDS_Mesh &m, const int NIT, if (!(*it)->deleted){ (*it)->p1->config_modified = false; (*it)->p2->config_modified = false; - double lone = NewGetLc(*it, gf, m.scalingU, m.scalingV); + double lone = NewGetLc(*it, gf); maxL = std::max(maxL, lone); minL = std::min(minL, lone); } @@ -902,10 +815,13 @@ int solveInvalidPeriodic(GFace *gf, BDS_Mesh &m, coord * e->p1->u + (1 - coord) * e->p2->u, coord * e->p1->v + (1 - coord) * e->p2->v, gf); mid->lcBGM() = BGM_MeshSize(gf, - (coord * e->p1->u + (1 - coord) * e->p2->u) * m.scalingU, - (coord * e->p1->v + (1 - coord) * e->p2->v) * m.scalingV, + (coord * e->p1->u + (1 - coord) * e->p2->u), + (coord * e->p1->v + (1 - coord) * e->p2->v), mid->X, mid->Y, mid->Z); mid->lc() = 0.5 * (e->p1->lc() + e->p2->lc()); + + // printf("coucou\n"); + if(!m.split_edge(e, mid)) m.del_point(mid); } } diff --git a/tutorial/t17.geo b/tutorial/t17.geo index c5213165f13f9bfb9d7aad430659b9ee41a1aa38..8734c0526a642aae800df11f0e18b68126ec0e9e 100644 --- a/tutorial/t17.geo +++ b/tutorial/t17.geo @@ -32,4 +32,7 @@ Merge "t17.pos"; Background Mesh View[0]; // Use bamg +Mesh.SmoothRatio = 3; +Mesh.AnisoMax = 1000; + Mesh.Algorithm=7; \ No newline at end of file