diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt index f241e458cd25c51fe188f5ab89e1a8b8684af4e5..baaa04f621e6cd8ea7cc9eb18cdadff2a3fc10e8 100644 --- a/Geo/CMakeLists.txt +++ b/Geo/CMakeLists.txt @@ -5,7 +5,6 @@ set(SRC boundaryLayersData.cpp - distanceToMesh.cpp intersectCurveSurface.cpp GEntity.cpp STensor3.cpp GVertex.cpp GEdge.cpp GFace.cpp GRegion.cpp diff --git a/Geo/distanceToMesh.cpp b/Geo/distanceToMesh.cpp deleted file mode 100644 index 195cdf1c7709bd23898283e1132f448cf11cd80e..0000000000000000000000000000000000000000 --- a/Geo/distanceToMesh.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "distanceToMesh.h" -#include "MElement.h" -#include "Numeric.h" - -distanceToMesh::distanceToMesh(GModel *gm, std::string physical, int nbClose) - : _computed (false) , _gm(gm), _nbClose(nbClose) -{ - std::map<int, std::vector<GEntity*> > groups [4]; - gm->getPhysicalGroups(groups); - for (GModel::piter it = gm->firstPhysicalName() ; - it != gm->lastPhysicalName() ; ++it){ - if (it->second == physical){ - _entities = groups[it->first.first][it->first.second]; - } - } -} - - -#if defined(HAVE_ANN) -distanceToMesh::~distanceToMesh() -{ - if (_computed){ - delete [] _index; - delete [] _dist; - delete _kdtree; - annDeallocPts (_nodes); - } -} - -void distanceToMesh::setup() -{ - _computed = true; - std::set<MVertex *> _all; - for (unsigned int i=0;i<_entities.size();i++){ - for (unsigned int k = 0; k < _entities[i]->getNumMeshElements(); k++) { - for (int j = 0; j< _entities[i]->getMeshElement(k)->getNumVertices();j++){ - _all.insert(_entities[i]->getMeshElement(k)->getVertex(j)); - _v2e.insert (std::make_pair(_entities[i]->getMeshElement(k)->getVertex(j), - _entities[i]->getMeshElement(k))); - } - } - } - _nodes = annAllocPts(_all.size(), 3); - std::set<MVertex*>::iterator itp = _all.begin(); - int ind = 0; - while (itp != _all.end()){ - MVertex* pt = *itp; - _nodes[ind][0] = pt->x(); - _nodes[ind][1] = pt->y(); - _nodes[ind][2] = pt->z(); - _vertices.push_back(pt); - itp++; ind++; - } - _kdtree = new ANNkd_tree(_nodes, _all.size(), 3); - _index = new ANNidx[_nbClose]; - _dist = new ANNdist[_nbClose]; -} - -double distanceToMesh::operator () (double x, double y, double z) -{ - if (!_computed) setup(); - double point[3] = {x,y,z}; - _kdtree->annkSearch(point, _nbClose, _index, _dist); - std::set<MElement*> elements; - for (int i=0;i<_nbClose;i++){ - int iVertex = _index [i]; - MVertex *v = _vertices[iVertex]; - for (std::multimap<MVertex*,MElement*>::iterator itm = - _v2e.lower_bound(v); itm != _v2e.upper_bound(v); ++itm) - elements.insert (itm->second); - } - double minDistance = 1.e22; - SPoint3 closest; - for (std::set<MElement*>::iterator it = elements.begin(); - it != elements.end();++it){ - double distance; - MVertex *v1 = (*it)->getVertex(0); - MVertex *v2 = (*it)->getVertex(1); - SPoint3 p1(v1->x(), v1->y(), v1->z()); - SPoint3 p2(v2->x(), v2->y(), v2->z()); - if ((*it)->getDim() == 1){ - SPoint3 pt; - signedDistancePointLine(p1, p2,SPoint3(x,y,z),distance,pt); - if (fabs(distance) < fabs(minDistance)){ - minDistance=distance; - } - } - } - return minDistance; -} -#else -double distanceToMesh::operator () (double x, double y, double z) -{ - Msg::Fatal ("impossible to compute distance to a mesh without ANN"); -} -#endif diff --git a/Geo/distanceToMesh.h b/Geo/distanceToMesh.h deleted file mode 100644 index e89be2b3bc3dae6b4343575d9774d017a88e2614..0000000000000000000000000000000000000000 --- a/Geo/distanceToMesh.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _DISTANCE_TO_MESH_ -#define _DISTANCE_TO_MESH_ -#include <ANN/ANN.h> -#include "GModel.h" -#include "simpleFunction.h" -class distanceToMesh : public simpleFunction <double> -{ - bool _computed; - GModel * _gm; - const int _nbClose; -#if defined(HAVE_ANN) - std::vector<GEntity*> _entities; - std::vector<MVertex*> _vertices; - std::multimap<MVertex*,MElement*> _v2e; - ANNkd_tree *_kdtree; - ANNpointArray _nodes; - ANNidxArray _index; - ANNdistArray _dist; - void setup (); -#endif -public : - distanceToMesh(GModel *gm, std::string physical, int nbClose = 5); - double operator () (double x, double y, double z); -#if defined(HAVE_ANN) - ~distanceToMesh(); -#endif -}; - -#endif diff --git a/Geo/gmshLevelset.cpp b/Geo/gmshLevelset.cpp index c8a24255f827c6488cabf579fb98fdf57d275e1d..33521a7305b1a25d697b1b8299b0607656c4e3f9 100644 --- a/Geo/gmshLevelset.cpp +++ b/Geo/gmshLevelset.cpp @@ -16,6 +16,7 @@ #include "MElement.h" #include "Numeric.h" #include "cartesian.h" +#include <ANN/ANN.h> void insertActiveCells(double x, double y, double z, double rmax, cartesianBox<double> &box) @@ -848,16 +849,6 @@ double gLevelsetMathEvalAll::operator() (const double x, const double y, const d if(_expr->eval(values, res)) return res[0]; return 1.; } -std::vector<double> gLevelsetMathEvalAll::getValueAndGradients (const double x, const double y, const double z) const -{ - std::vector<double> values(3), res(13); - values[0] = x; - values[1] = y; - values[2] = z; - if(_expr->eval(values, res)) return res; - return res; -} - void gLevelsetMathEvalAll::gradient (double x, double y, double z, double & dfdx, double & dfdy, double & dfdz) const { @@ -897,123 +888,108 @@ void gLevelsetMathEvalAll::hessian (double x, double y, double z, } } -gLevelsetDistGeom::gLevelsetDistGeom(std::string box, std::string geom, int tag) - : gLevelsetPrimitive(tag), _box(NULL) +gLevelsetDistMesh::gLevelsetDistMesh(GModel *gm, std::string physical, int nbClose) + : _gm(gm), _nbClose(nbClose) { - modelBox = new GModel(); - modelBox->load(box+std::string(".msh")); - modelGeom = new GModel(); - modelGeom->load(geom); - - //EMI FIXME THIS - int levels = 3; - // double rmax = 0.1; - // double sampling = std::min(rmax, std::min(lx, std::min(ly, lz))); - - //FILLING POINTS FROM GEOMBOX - std::vector<SPoint3> points; - std::vector<SPoint3> refinePoints; - for(GModel::viter vit = modelBox->firstVertex(); vit != modelBox->lastVertex(); vit++){ - for(unsigned int k = 0; k < (*vit)->getNumMeshVertices(); k++){ - MVertex *v = (*vit)->getMeshVertex(k); - SPoint3 p(v->x(), v->y(), v->z()); - points.push_back(p); + std::map<int, std::vector<GEntity*> > groups [4]; + gm->getPhysicalGroups(groups); + for (GModel::piter it = gm->firstPhysicalName() ; + it != gm->lastPhysicalName() ; ++it){ + if (it->second == physical){ + _entities = groups[it->first.first][it->first.second]; } } - for (GModel::eiter eit = modelBox->firstEdge(); eit != modelBox->lastEdge(); eit++){ - for(unsigned int k = 0; k < (*eit)->getNumMeshVertices(); k++){ - MVertex *ve = (*eit)->getMeshVertex(k); - SPoint3 pe(ve->x(), ve->y(), ve->z()); - points.push_back(pe); - } + if (_entities.size() == 0){ + Msg::Error("distanceToMesh: the physical name '%s' does not exist in the GModel", physical.c_str()); } - //FILLING POINTS FROM STL - for (GModel::fiter fit = modelGeom->firstFace(); fit != modelGeom->lastFace(); fit++){ - for(unsigned int k = 0; k < (*fit)->getNumMeshVertices(); k++){ - MVertex *vf = (*fit)->getMeshVertex(k); - SPoint3 pf(vf->x(), vf->y(), vf->z()); - points.push_back(pf); - } - for(unsigned int k = 0; k < (*fit)->getNumMeshElements(); k++){ - MElement *e = (*fit)->getMeshElement(k); - if (e->getType() == TYPE_TRI){ - MVertex *v1 = e->getVertex(0); - MVertex *v2 = e->getVertex(1); - MVertex *v3 = e->getVertex(2); - SPoint3 cg( (v1->x()+v2->x()+v3->x())/3., - (v1->y()+v2->y()+v3->y())/3., - (v1->z()+v2->z()+v3->z())/3.); - refinePoints.push_back(cg); + //setup + std::set<MVertex *> _all; + for (unsigned int i=0;i<_entities.size();i++){ + for (unsigned int k = 0; k < _entities[i]->getNumMeshElements(); k++) { + MElement *e = _entities[i]->getMeshElement(k); + for (int j = 0; j< e->getNumVertices();j++){ + MVertex *v = _entities[i]->getMeshElement(k)->getVertex(j); + _all.insert(v); + _v2e.insert (std::make_pair(v,e)); } } } - //FOR CAD - //for (GModel::fiter fit = modelGeom->firstFace(); fit != modelGeom->lastFace(); fit++) - // (*fit)->fillPointCloud(sampling, &points); - - if (points.size() == 0) {Msg::Fatal("No points on surfaces \n"); }; - - SBoundingBox3d bb; - for(unsigned int i = 0; i < points.size(); i++) bb += points[i]; - for(unsigned int i = 0; i < refinePoints.size(); i++) bb += refinePoints[i]; - //bb.scale(1.01, 1.01, 1.01); - SVector3 range = bb.max() - bb.min(); - double minLength = std::min( range.x(), std::min(range.y(), range.z())); - double hmin = minLength / 5; - int NX = range.x() / hmin; - int NY = range.y() / hmin; - int NZ = range.z() / hmin; - if(NX < 2) NX = 2; - if(NY < 2) NY = 2; - if(NZ < 2) NZ = 2; - double rtube = 2.*hmin; //std::max(lx, std::max(ly, lz))*2.; - - Msg::Info(" bounding box min: %g %g %g -- max: %g %g %g", - bb.min().x(), bb.min().y(), bb.min().z(), - bb.max().x(), bb.max().y(), bb.max().z()); - Msg::Info(" Nx=%d Ny=%d Nz=%d", NX, NY, NZ); - - _box = new cartesianBox<double>(bb.min().x(), bb.min().y(), bb.min().z(), - SVector3(range.x(), 0, 0), - SVector3(0, range.y(), 0), - SVector3(0, 0, range.z()), - NX, NY, NZ, levels); - for (int i = 0; i < NX; i++) - for (int j = 0; j < NY; j++) - for (int k = 0; k < NZ; k++) - _box->insertActiveCell(_box->getCellIndex(i, j, k)); - - cartesianBox<double> *parent = _box, *child; - while((child = parent->getChildBox())){ - //Msg::Info(" level %d ", child->getLevel()); - for(unsigned int i = 0; i < refinePoints.size(); i++) - insertActiveCells(refinePoints[i].x(), refinePoints[i].y(), refinePoints[i].z(), - rtube / pow(2., (levels - child->getLevel())), *child); - parent = child; + _nodes = annAllocPts(_all.size(), 3); + std::set<MVertex*>::iterator itp = _all.begin(); + int ind = 0; + while (itp != _all.end()){ + MVertex* pt = *itp; + _nodes[ind][0] = pt->x(); + _nodes[ind][1] = pt->y(); + _nodes[ind][2] = pt->z(); + _vertices.push_back(pt); + itp++; ind++; } + _kdtree = new ANNkd_tree(_nodes, _all.size(), 3); + _index = new ANNidx[_nbClose]; + _dist = new ANNdist[_nbClose]; - //Msg::Info("Removing cells to match mesh topology constraints"); - removeBadChildCells(_box); - removeParentCellsWithChildren(_box); - - //Msg::Info("Initializing nodal values in the cartesian grid"); - _box->createNodalValues(); - //Msg::Info("Computing levelset on the cartesian grid"); - computeLevelset(modelGeom, *_box); +} - //Msg::Info("Renumbering mesh vertices across levels"); - _box->renumberNodes(); +#if defined(HAVE_ANN) +gLevelsetDistMesh::~gLevelsetDistMesh() +{ + delete [] _index; + delete [] _dist; + if (_kdtree) delete _kdtree; + if (_nodes) annDeallocPts (_nodes); - _box->writeMSH("yeah.msh", false); } -double gLevelsetDistGeom::operator() (const double x, const double y, const double z) const +double gLevelsetDistMesh::operator () (const double x, const double y, const double z) const +{ + double point[3] = {x,y,z}; + _kdtree->annkSearch(point, _nbClose, _index, _dist); + std::set<MElement*> elements; + for (int i=0;i<_nbClose;i++){ + int iVertex = _index [i]; + MVertex *v = _vertices[iVertex]; + for (std::multimap<MVertex*,MElement*>::const_iterator itm = + _v2e.lower_bound(v); itm != _v2e.upper_bound(v); ++itm) + elements.insert (itm->second); + } + double minDistance = 1.e22; + SPoint3 closest; + for (std::set<MElement*>::iterator it = elements.begin(); + it != elements.end();++it){ + double distance; + MVertex *v1 = (*it)->getVertex(0); + MVertex *v2 = (*it)->getVertex(1); + SPoint3 p1(v1->x(), v1->y(), v1->z()); + SPoint3 p2(v2->x(), v2->y(), v2->z()); + SPoint3 pt; + if ((*it)->getDim() == 1){ + signedDistancePointLine(p1, p2,SPoint3(x,y,z),distance,pt); + } + else if ((*it)->getDim() == 2){ + MVertex *v3 = (*it)->getVertex(2); + SPoint3 p3(v3->x(), v3->y(), v3->z()); + signedDistancePointTriangle(p1, p2, p3,SPoint3(x,y,z),distance,pt); + } + else if ((*it)->getDim() == 2){ + Msg::Error("Cannot compute a dsitance to an entity of dim \n"); + } + if (fabs(distance) < fabs(minDistance)){ + minDistance=distance; + } + } + return -1.0*minDistance; +} +#else +double gLevelsetDistMesh::operator () (double x, double y, double z) { - double dist = _box->getValueContainingPoint(x,y,z); - return dist; + Msg::Fatal ("impossible to compute distance to a mesh without ANN"); } +#endif + + #if defined (HAVE_POST) gLevelsetPostView::gLevelsetPostView(int index, int tag) diff --git a/Geo/gmshLevelset.h b/Geo/gmshLevelset.h index d6716c50b151afbb80c3813578312754f3d09b1b..d62a5e849735e134d1e7e74928d89881c2dc82a7 100644 --- a/Geo/gmshLevelset.h +++ b/Geo/gmshLevelset.h @@ -22,7 +22,9 @@ #include "cartesian.h" #include "simpleFunction.h" - +#if defined(HAVE_ANN) +#include "ANN/ANN.h" +#endif #if defined(HAVE_POST) #include "PView.h" #include "OctreePost.h" @@ -306,7 +308,6 @@ public: gLevelsetMathEvalAll(std::vector<std::string> f, int tag=1); ~gLevelsetMathEvalAll(){ if (_expr) delete _expr; } double operator() (const double x, const double y, const double z) const; - std::vector<double> getValueAndGradients(const double x, const double y, const double z) const; void gradient (double x, double y, double z, double & dfdx, double & dfdy, double & dfdz) const; void hessian (double x, double y, double z, @@ -331,21 +332,29 @@ public: int type() const { return UNKNOWN; } }; -class gLevelsetDistGeom: public gLevelsetPrimitive +class gLevelsetDistMesh: public gLevelsetPrimitive { - cartesianBox<double> *_box; - GModel *modelBox, *modelGeom; -public: - gLevelsetDistGeom(std::string g, std::string f, int tag=1); - ~gLevelsetDistGeom(){ - delete modelBox; - delete modelGeom; - if (_box) delete _box; - } + GModel * _gm; + const int _nbClose; +#if defined(HAVE_ANN) + std::vector<GEntity*> _entities; + std::vector<MVertex*> _vertices; + std::multimap<MVertex*,MElement*> _v2e; + ANNkd_tree *_kdtree; + ANNpointArray _nodes; + ANNidxArray _index; + ANNdistArray _dist; +#endif +public : + gLevelsetDistMesh(GModel *gm, std::string physical, int nbClose = 5); double operator () (const double x, const double y, const double z) const; +#if defined(HAVE_ANN) + ~gLevelsetDistMesh(); +#endif int type() const { return UNKNOWN; } }; + #if defined(HAVE_POST) class gLevelsetPostView : public gLevelsetPrimitive { @@ -630,7 +639,6 @@ public: gLevelsetNACA00(double x0, double y0, double c, double t); ~gLevelsetNACA00() {} double operator () (const double x, const double y, const double z) const; -// std::vector<double> getValueAndGradients(const double x, const double y, const double z) const; void gradient (double x, double y, double z, double & dfdx, double & dfdy, double & dfdz) const; void hessian (double x, double y, double z, diff --git a/Mesh/meshMetric.cpp b/Mesh/meshMetric.cpp index 4a41e97ec28dbc0ab702672f5458b978086df13e..ad9c500eba1c80eead023bfbd991daa0c91d9801 100644 --- a/Mesh/meshMetric.cpp +++ b/Mesh/meshMetric.cpp @@ -707,12 +707,12 @@ void meshMetric::scaleMetric( int nbElementsTarget, SMetric3 m3 = nmt[e->getVertex(2)]; if (_dim == 2){ SMetric3 m = interpolation(m1,m2,m3,0.3333,0.3333); - N += sqrt(m.determinant()) * e->getVolume() * 3.0; + N += sqrt(m.determinant()) * e->getVolume() * 4./sqrt(3.0); //3.0 } else{ SMetric3 m4 = nmt[e->getVertex(3)]; SMetric3 m = interpolation(m1,m2,m3,m4,0.25,0.25,0.25); - N += sqrt(m.determinant()) * e->getVolume() * 4.0; + N += sqrt(m.determinant()) * e->getVolume() * 12./sqrt(2.0); //4.0; } } double scale = pow ((double)nbElementsTarget/N,2.0/_dim); diff --git a/Numeric/Numeric.cpp b/Numeric/Numeric.cpp index 0dd9bc3f03d206fffe03c58cc50458a07deabe66..d89a17ee96ca43fc2e0e98a762b825600b4b7d86 100644 --- a/Numeric/Numeric.cpp +++ b/Numeric/Numeric.cpp @@ -667,15 +667,15 @@ bool newton_fd(void (*func)(fullVector<double> &, fullVector<double> &, void *), fullVector<double> f(N), feps(N), dx(N); for (int iter = 0; iter < MAXIT; iter++){ - func(x, f, data); + func(x, f, data); - bool isZero = false; - for (int k=0; k<N; k++) { - if (f(k) == 0. ) isZero = true; - else isZero = false; - if (isZero == false) break; - } - if (isZero) break; + bool isZero = false; + for (int k=0; k<N; k++) { + if (f(k) == 0. ) isZero = true; + else isZero = false; + if (isZero == false) break; + } + if (isZero) break; for (int j = 0; j < N; j++){ double h = EPS * fabs(x(j)); @@ -707,9 +707,9 @@ bool newton_fd(void (*func)(fullVector<double> &, fullVector<double> &, void *), } /* -min_a f(x+a*d); + min_a f(x+a*d); -f(x+a*d) = f(x) + f'(x) ( + f(x+a*d) = f(x) + f'(x) ( */ @@ -739,11 +739,11 @@ void gmshLineSearch(double (*func)(fullVector<double> &, void *), void* data, if (temp > test) test = temp; } /* - for (int j=0;j<100;j++){ + for (int j=0;j<100;j++){ double sx = (double)j/99; for (i=0;i<n;i++) x(i)=xold(i)+10*sx*p(i); double jzede = (*func)(x,data); - } + } */ alamin = TOLX / test; @@ -752,7 +752,7 @@ void gmshLineSearch(double (*func)(fullVector<double> &, void *), void* data, for (i = 0; i < n; i++) x(i) = xold(i) + alam*p(i); f = (*func)(x, data); // printf("f = %g x = %g %g alam = %g p = %g %g\n",f,x(0),x(1),alam,p(0),p(1)); - if (alam < alamin) { + if (alam < alamin) { for (i = 0; i <n; i++) x(i) = xold(i); // printf("ALERT : alam %g alamin %g\n",alam,alamin); check = 1; @@ -825,48 +825,101 @@ double minimize_grad_fd(double (*func)(fullVector<double> &, void *), } /* -P(p) = p1 + t1 xi + t2 eta + P(p) = p1 + t1 xi + t2 eta -t1 = (p2-p1) ; t2 = (p3-p1) ; + t1 = (p2-p1) ; t2 = (p3-p1) ; -(P(p) - p) = d n + (P(p) - p) = d n -(p1 + t1 xi + t2 eta - p) = d n -t1 xi + t2 eta + d n = p - p1 + (p1 + t1 xi + t2 eta - p) = d n + t1 xi + t2 eta + d n = p - p1 -| t1x t2x -nx | |xi | |px-p1x| -| t1y t2y -ny | |eta | = |py-p1y| -| t1z t2z -nz | |d | |pz-p1z| + | t1x t2x -nx | |xi | |px-p1x| + | t1y t2y -ny | |eta | = |py-p1y| + | t1z t2z -nz | |d | |pz-p1z| -distance to segment + distance to segment - P(p) = p1 + t (p2-p1) + P(p) = p1 + t (p2-p1) - (p - P(p)) * (p2-p1) = 0 - (p - p1 - t (p2-p1) ) * (p2-p1) = 0 - - t ||p2-p1||^2 + (p-p1)(p2-p1) = 0 + (p - P(p)) * (p2-p1) = 0 + (p - p1 - t (p2-p1) ) * (p2-p1) = 0 + - t ||p2-p1||^2 + (p-p1)(p2-p1) = 0 - t = (p-p1)*(p2-p1)/||p2-p1||^2 + t = (p-p1)*(p2-p1)/||p2-p1||^2 */ -void signedDistancesPointsTriangle(std::vector<double> &distances, - std::vector<SPoint3> &closePts, - const std::vector<SPoint3> &pts, - const SPoint3 &p1, - const SPoint3 &p2, - const SPoint3 &p3) +void signedDistancePointTriangle(const SPoint3 &p1,const SPoint3 &p2, const SPoint3 &p3, + const SPoint3 &p, double &d, SPoint3 &closePt) + { + SVector3 t1 = p2 - p1; SVector3 t2 = p3 - p1; SVector3 t3 = p3 - p2; SVector3 n = crossprod(t1, t2); n.normalize(); - + const double n2t1 = dot(t1, t1); + const double n2t2 = dot(t2, t2); + const double n2t3 = dot(t3, t3); double mat[3][3] = {{t1.x(), t2.x(), -n.x()}, {t1.y(), t2.y(), -n.y()}, {t1.z(), t2.z(), -n.z()}}; double inv[3][3]; double det = inv3x3(mat, inv); + if(det == 0.0) return; + + double u, v; + SVector3 pp1 = p - p1; + u = (inv[0][0] * pp1.x() + inv[0][1] * pp1.y() + inv[0][2] * pp1.z()); + v = (inv[1][0] * pp1.x() + inv[1][1] * pp1.y() + inv[1][2] * pp1.z()); + d = (inv[2][0] * pp1.x() + inv[2][1] * pp1.y() + inv[2][2] * pp1.z()); + double sign = (d > 0) ? 1. : -1.; + if (d == 0) sign = 1.e10; + if (u >= 0 && v >= 0 && 1.-u-v >= 0.0){ + closePt = SPoint3(0.,0.,0.);//TO DO + } + else { + const double t12 = dot(pp1, t1) / n2t1; + const double t13 = dot(pp1, t2) / n2t2; + SVector3 pp2 = p - p2; + const double t23 = dot(pp2, t3) / n2t3; + d = 1.e10; + SPoint3 closePt; + if (t12 >= 0 && t12 <= 1.){ + d = sign * std::min(fabs(d), p.distance(p1 + (p2 - p1) * t12)); + closePt = p1 + (p2 - p1) * t12; + } + if (t13 >= 0 && t13 <= 1.){ + if (p.distance(p1 + (p3 - p1) * t13) < fabs(d)) closePt = p1 + (p3 - p1) * t13; + d = sign * std::min(fabs(d), p.distance(p1 + (p3 - p1) * t13)); + } + if (t23 >= 0 && t23 <= 1.){ + if (p.distance(p2 + (p3 - p2) * t23) < fabs(d)) closePt = p2 + (p3 - p2) * t23; + d = sign * std::min(fabs(d), p.distance(p2 + (p3 - p2) * t23)); + } + if (p.distance(p1) < fabs(d)){ + closePt = p1; + d = sign * std::min(fabs(d), p.distance(p1)); + } + if (p.distance(p2) < fabs(d)){ + closePt = p2; + d = sign * std::min(fabs(d), p.distance(p2)); + } + if (p.distance(p3) < fabs(d)){ + closePt = p3; + d = sign * std::min(fabs(d), p.distance(p3)); + } + } + +} +void signedDistancesPointsTriangle(std::vector<double> &distances, + std::vector<SPoint3> &closePts, + const std::vector<SPoint3> &pts, + const SPoint3 &p1, + const SPoint3 &p2, + const SPoint3 &p3) +{ const unsigned pts_size = pts.size(); distances.clear(); distances.resize(pts_size); @@ -876,15 +929,28 @@ void signedDistancesPointsTriangle(std::vector<double> &distances, for (unsigned int i = 0; i < pts_size; ++i) distances[i] = 1.e22; - if(det == 0.0) return; - + SVector3 t1 = p2 - p1; + SVector3 t2 = p3 - p1; + SVector3 t3 = p3 - p2; + SVector3 n = crossprod(t1, t2); + n.normalize(); const double n2t1 = dot(t1, t1); const double n2t2 = dot(t2, t2); const double n2t3 = dot(t3, t3); + double mat[3][3] = {{t1.x(), t2.x(), -n.x()}, + {t1.y(), t2.y(), -n.y()}, + {t1.z(), t2.z(), -n.z()}}; + double inv[3][3]; + double det = inv3x3(mat, inv); + if(det == 0.0) return; - double u, v, d; - for (unsigned int i = 0; i < pts_size; ++i){ + for (unsigned int i = 0; i < pts.size(); i++) { + double d; + SPoint3 closePt; const SPoint3 &p = pts[i]; + + //signedDistancePointTrianglePrecomputed(p1, p2, p3, p, d, closePt); + double u, v; SVector3 pp1 = p - p1; u = (inv[0][0] * pp1.x() + inv[0][1] * pp1.y() + inv[0][2] * pp1.z()); v = (inv[1][0] * pp1.x() + inv[1][1] * pp1.y() + inv[1][2] * pp1.z()); @@ -892,8 +958,7 @@ void signedDistancesPointsTriangle(std::vector<double> &distances, double sign = (d > 0) ? 1. : -1.; if (d == 0) sign = 1.e10; if (u >= 0 && v >= 0 && 1.-u-v >= 0.0){ - distances[i] = d; - closePts[i] = SPoint3(0.,0.,0.);//TO DO + closePt = SPoint3(0.,0.,0.);//TO DO } else { const double t12 = dot(pp1, t1) / n2t1; @@ -901,43 +966,41 @@ void signedDistancesPointsTriangle(std::vector<double> &distances, SVector3 pp2 = p - p2; const double t23 = dot(pp2, t3) / n2t3; d = 1.e10; - //bool found = false; SPoint3 closePt; if (t12 >= 0 && t12 <= 1.){ - d = sign * std::min(fabs(d), p.distance(p1 + (p2 - p1) * t12)); - closePt = p1 + (p2 - p1) * t12; - //found = true; + d = sign * std::min(fabs(d), p.distance(p1 + (p2 - p1) * t12)); + closePt = p1 + (p2 - p1) * t12; } if (t13 >= 0 && t13 <= 1.){ - if (p.distance(p1 + (p3 - p1) * t13) < fabs(d)) closePt = p1 + (p3 - p1) * t13; - d = sign * std::min(fabs(d), p.distance(p1 + (p3 - p1) * t13)); - //found = true; + if (p.distance(p1 + (p3 - p1) * t13) < fabs(d)) closePt = p1 + (p3 - p1) * t13; + d = sign * std::min(fabs(d), p.distance(p1 + (p3 - p1) * t13)); } if (t23 >= 0 && t23 <= 1.){ - if (p.distance(p2 + (p3 - p2) * t23) < fabs(d)) closePt = p2 + (p3 - p2) * t23; - d = sign * std::min(fabs(d), p.distance(p2 + (p3 - p2) * t23)); - //found = true; + if (p.distance(p2 + (p3 - p2) * t23) < fabs(d)) closePt = p2 + (p3 - p2) * t23; + d = sign * std::min(fabs(d), p.distance(p2 + (p3 - p2) * t23)); } if (p.distance(p1) < fabs(d)){ - closePt = p1; - d = sign * std::min(fabs(d), p.distance(p1)); - } + closePt = p1; + d = sign * std::min(fabs(d), p.distance(p1)); + } if (p.distance(p2) < fabs(d)){ - closePt = p2; - d = sign * std::min(fabs(d), p.distance(p2)); - } + closePt = p2; + d = sign * std::min(fabs(d), p.distance(p2)); + } if (p.distance(p3) < fabs(d)){ - closePt = p3; - d = sign * std::min(fabs(d), p.distance(p3)); + closePt = p3; + d = sign * std::min(fabs(d), p.distance(p3)); } - //d = sign * std::min(fabs(d), std::min(std::min(p.distance(p1), - // p.distance(p2)),p.distance(p3))); - distances[i] = d; - closePts[i] = closePt; } + //end signedDistance + + distances[i] = d; + closePts[i] = closePt; } } + + void signedDistancePointLine(const SPoint3 &p1, const SPoint3 &p2, const SPoint3 &p, double &d, SPoint3 &closePt) { diff --git a/Numeric/Numeric.h b/Numeric/Numeric.h index 678bd2aa60404803e944f0a031d9586b50bb113b..91e5cfc2f6343d25b2d946e4a280e1772c5a840f 100644 --- a/Numeric/Numeric.h +++ b/Numeric/Numeric.h @@ -110,12 +110,17 @@ bool newton_fd(void (*func)(fullVector<double> &, fullVector<double> &, void *), fullVector<double> &x, void *data, double relax=1., double tolx=1.e-6); double minimize_grad_fd(double (*func)(fullVector<double> &, void *), fullVector<double> &x, void *data); + +void signedDistancePointTriangle(const SPoint3 &p1,const SPoint3 &p2, const SPoint3 &p3, + const SPoint3 &p, double &d, SPoint3 &closePt); + void signedDistancesPointsTriangle(std::vector<double> &distances, std::vector<SPoint3> &closePts, const std::vector<SPoint3> &pts, const SPoint3 &p1, const SPoint3 &p2, const SPoint3 &p3); + void signedDistancePointLine(const SPoint3 &p1, const SPoint3 &p2, const SPoint3 &p, double &distance, SPoint3 &closePt); void signedDistancesPointsLine (std::vector<double>&distances, diff --git a/wrappers/gmshpy/gmshGeo.i b/wrappers/gmshpy/gmshGeo.i index 512247447dedd8dd6f63bbe83ef94c8986727447..6390afe4355942a9e2431f7538357c49ceddb10e 100644 --- a/wrappers/gmshpy/gmshGeo.i +++ b/wrappers/gmshpy/gmshGeo.i @@ -37,7 +37,6 @@ #include "SBoundingBox3d.h" #include "Curvature.h" #include "simpleFunction.h" - #include "distanceToMesh.h" #include "GeomMeshMatcher.h" %} @@ -96,7 +95,6 @@ namespace std { %include "SBoundingBox3d.h" %include "Curvature.h" %include "gmshLevelset.h" -%include "distanceToMesh.h" %include "GeomMeshMatcher.h"