diff --git a/Geo/GRbf.cpp b/Geo/GRbf.cpp index 8cc245f80cf1581615b54d9d76554868c5113c96..94195882f6738208ea46f4d00dc2d9643693695d 100644 --- a/Geo/GRbf.cpp +++ b/Geo/GRbf.cpp @@ -47,23 +47,42 @@ static void printNodes(std::set<MVertex *> myNodes){ fprintf(xyz,"View \"\"{\n"); for(std::set<MVertex *>::iterator itv = myNodes.begin(); itv !=myNodes.end() ; ++itv){ MVertex *v = *itv; - fprintf(xyz,"SP(%g,%g,%g){%g};\n", v->x(), v->y(), v->z(), 1.0); + fprintf(xyz,"SP(%g,%g,%g){%d};\n", v->x(), v->y(), v->z(), v->getNum()); } fprintf(xyz,"};\n"); fclose(xyz); } + +static void exportParametrizedMesh(fullMatrix<double> &UV, int nbNodes){ + + FILE *f = fopen ("UV.pos", "w"); + fprintf(f,"View \" uv \" {\n"); + + Msg::Info("*** RBF exporting 'UV.pos' "); + for(int id = 0; id < nbNodes; id++){ + fprintf(f,"SP(%g,%g,%g){%d};\n", UV(id,0), UV(id,1), 0.0, id); + } + fprintf(f,"};\n"); + + fclose(f); +} + GRbf::GRbf (double sizeBox, int variableEps, int rbfFun, std::map<MVertex*, SVector3> _normals, std::set<MVertex *> allNodes, std::vector<MVertex*> bcNodes) : sBox(sizeBox), variableShapeParam(variableEps), radialFunctionIndex (rbfFun), XYZkdtree(0), _inUV(0) { allCenters.resize(allNodes.size(),3); - double tol= 5.e-2*sBox; + double tol = 4.e-2*sBox; //remove duplicate vertices //add bc nodes - for(unsigned int i = 0; i < bcNodes.size(); i++) myNodes.insert(bcNodes[i]); + for(unsigned int i = 0; i < bcNodes.size(); i++){ + myNodes.insert(bcNodes[i]); + //if (bcNodes.size() > 20) i+=3; + } + //then create Mvertex position std::vector<MVertex*> vertices( allNodes.begin(), allNodes.end() ); MVertexPositionSet pos(vertices); @@ -99,7 +118,7 @@ GRbf::GRbf (double sizeBox, int variableEps, int rbfFun, std::map<MVertex*, SVec MVertex *v2 = *itv2; double dist = sqrt((v1->x()-v2->x())*(v1->x()-v2->x())+(v1->y()-v2->y())*(v1->y()-v2->y()) +(v1->z()-v2->z())*(v1->z()-v2->z()))/sBox; - if (dist<dist_min && *itv != *itv2) dist_min = dist; + if (dist<dist_min && *itv != *itv2 && dist > 1.e-6) dist_min = dist; } index++; } @@ -184,62 +203,47 @@ void GRbf::buildOctree(double radius){ buildXYZkdtree(); } +//compute curvature from level set +void GRbf::computeCurvature(std::map<MVertex*, SPoint3> &rbf_curv){ -void GRbf::curvature(double radius, - const fullMatrix<double> &cntrs, - const fullMatrix<double> &node, - fullMatrix<double> &curvature){ - -// fullMatrix<double> nodes_in_sph,local_normals,level_set_nodes,level_set_funvals, -// sx,sy,sz, sxx,syy,szz, sxy,sxz,syz,sLap; + fullMatrix<double> extX, surf, sx,sy,sz, sxx,syy,szz, sxy,sxz,syz,sLap; -// isLocal = true; -// curvature.resize(node.size1(), node.size1()); - -// if(nodesInSphere.size() == 0) buildOctree(radius); + isLocal = true; + fullMatrix<double> curvature(centers.size1(), 1); + + setup_level_set(centers,normals,extX, surf); + + evalRbfDer(1,extX,centers,surf,sx); + evalRbfDer(2,extX,centers,surf,sy); + evalRbfDer(3,extX,centers,surf,sz); + evalRbfDer(11,extX,centers,surf,sxx); + evalRbfDer(12,extX,centers,surf,sxy); + evalRbfDer(13,extX,centers,surf,sxz); + evalRbfDer(22,extX,centers,surf,syy); + evalRbfDer(23,extX,centers,surf,syz); + evalRbfDer(33,extX,centers,surf,szz); + evalRbfDer(222,extX,centers,surf,sLap); + + for (int i = 0; i < centers.size1(); i++) { + double norm_grad_s = sqrt(sx(i,0)*sx(i,0)+sy(i,0)*sy(i,0)+sz(i,0)*sz(i,0)); + double curv = -sLap(i,0)/norm_grad_s; //+(sx(i,0)*sx(i,0)*sxx(i,0)+sy(i,0)*sy(i,0)*syy(i,0)+sz(i,0)*sz(i,0)*szz(i,0)+2*sx(i,0)*sy(i,0)*sxy(i,0)+2*sy(i,0)*sz(i,0)*syz(i,0)+2*sx(i,0)*sz(i,0)*sxz(i,0))/ (norm_grad_s*norm_grad_s*norm_grad_s); + curvature(i,0) = fabs(curv)/sBox; + } -// for (int i = 0;i<node.size1() ; ++i){ -// #if defined (HAVE_ANN) -// double xyz[3] = {node(i,0), node(i,1), node(i,2) }; -// XYZkdtree->annkSearch(xyz, num_neighbours, index, dist); -// std::vector<int> &pts = nodesInSphere[index[0]]; -// #endif + //interpolate + fullMatrix<double> curvatureAll(allCenters.size1(), 1); + evalRbfDer(0,centers,allCenters,curvature,curvatureAll); -// fullMatrix<double> nodes_in_sph(pts.size(),3), local_normals(pts.size(),3); -// fullMatrix<double> LocalOper; + //fill rbf_curv + std::map<MVertex*, int>::iterator itm = _mapAllV.begin(); + for (; itm != _mapAllV.end(); itm++){ + int index = itm->second; + SPoint3 coords(curvatureAll(index,0), 0.0, 0.0); + rbf_curv.insert(std::make_pair(itm->first,coords)); + } -// for (int k=0; k< pts.size(); k++){ -// nodes_in_sph(k,0) = cntrs(pts[k],0); -// nodes_in_sph(k,1) = cntrs(pts[k],1); -// nodes_in_sph(k,2) = cntrs(pts[k],2); -// local_normals(k,0)=normals(pts[k],0); -// local_normals(k,1)=normals(pts[k],1); -// local_normals(k,2)=normals(pts[k],2); -// } - -// setup_level_set(nodes_in_sph,local_normals,level_set_nodes,level_set_funvals); - -// evalRbfDer(1,level_set_nodes,node,level_set_funvals,sx); -// evalRbfDer(2,level_set_nodes,node,level_set_funvals,sy); -// evalRbfDer(3,level_set_nodes,node,level_set_funvals,sz); -// evalRbfDer(11,level_set_nodes,node,level_set_funvals,sxx); -// evalRbfDer(12,level_set_nodes,node,level_set_funvals,sxy); -// evalRbfDer(13,level_set_nodes,node,level_set_funvals,sxz); -// evalRbfDer(22,level_set_nodes,node,level_set_funvals,syy); -// evalRbfDer(23,level_set_nodes,node,level_set_funvals,syz); -// evalRbfDer(33,level_set_nodes,node,level_set_funvals,szz); -// evalRbfDer(222,level_set_nodes,node,level_set_funvals,sLap); - -// double norm_grad_s = sqrt(sx(i,0)*sx(i,0)+sy(i,0)*sy(i,0)+sz(i,0)*sz(i,0)); -// double curv = -sLap(i,0)/norm_grad_s + -// (sx(i,0)*sx(i,0)*sxx(i,0)+sy(i,0)*sy(i,0)*syy(i,0)+sz(i,0)*sz(i,0)*szz(i,0)+2*sx(i,0)*sy(i,0)*sxy(i,0)+2*sy(i,0)*sz(i,0)*syz(i,0)+2*sx(i,0)*sz(i,0)*sxz(i,0))/ -// (norm_grad_s*norm_grad_s*norm_grad_s); -// curvature(i,0) = fabs(curv); -// } - } - double GRbf::evalRadialFnDer (int p, double dx, double dy, double dz, double ep){ double r2 = dx*dx+dy*dy+dz*dz; //r^2 @@ -283,7 +287,7 @@ fullMatrix<double> GRbf::generateRbfMat(int p, int n = nodes1.size1(); fullMatrix<double> rbfMat(m,n); - double eps =0.5/delta; //0.0677*(nbNodes^0.28)/min_dist; + double eps =0.5/delta; //0.0677*(nbNodes^0.28)/min_dist; //0.5 if (_inUV) eps = 0.4/deltaUV; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { @@ -298,6 +302,7 @@ fullMatrix<double> GRbf::generateRbfMat(int p, } +//DL matrix (B*inv A) void GRbf::RbfOp(int p, const fullMatrix<double> &cntrs, const fullMatrix<double> &nodes, @@ -326,7 +331,7 @@ void GRbf::RbfOp(int p, D.gemm(rbfMatB, rbfInvA, 1.0, 0.0); } -//Evaluates the RBF (p)th derivative w.r.t. the (q)th variable at the new nodes +//U = DL * U void GRbf::evalRbfDer(int p, const fullMatrix<double> &cntrs, const fullMatrix<double> &nodes, @@ -526,9 +531,10 @@ void GRbf::RbfLapSurface_local_CPM(bool isLow, } //NEW METHOD #1 CPM GLOBAL HIGH -void GRbf::RbfLapSurface_global_CPM_high(const fullMatrix<double> &cntrs, - const fullMatrix<double> &normals, - fullMatrix<double> &Oper){ +void GRbf::RbfLapSurface_global_CPM_high_2(const fullMatrix<double> &cntrs, + const fullMatrix<double> &normals, + fullMatrix<double> &Oper){ + Msg::Info("*** RBF ... building Laplacian operator"); int numNodes = cntrs.size1(); int nnTot = 3*numNodes; Oper.resize(nnTot,nnTot); @@ -575,16 +581,19 @@ void GRbf::RbfLapSurface_global_CPM_high(const fullMatrix<double> &cntrs, } A.invertInPlace(); Oper.gemm(AOper, A, 1.0, 0.0); + + Msg::Info("*** RBF builded Laplacian operator"); } //NEW METHOD #2 CPM GLOBAL HIGH //Produces a nxn differentiation matrix (like the projection method) //So the local method for this is the local projection method -void GRbf::RbfLapSurface_global_CPM_high_2(const fullMatrix<double> &cntrs, +void GRbf::RbfLapSurface_global_CPM_high(const fullMatrix<double> &cntrs, const fullMatrix<double> &normals, fullMatrix<double> &Oper){ + Msg::Info("*** RBF ... building Laplacian operator"); int numNodes = cntrs.size1(); int nnTot = 3*numNodes; Oper.resize(numNodes,numNodes); @@ -635,6 +644,8 @@ void GRbf::RbfLapSurface_global_CPM_high_2(const fullMatrix<double> &cntrs, Oper(i,j) = Temp(i,j); } } + + Msg::Info("*** RBF builded Laplacian operator"); } void GRbf::RbfLapSurface_global_CPM_low(const fullMatrix<double> &cntrs, @@ -685,8 +696,8 @@ void GRbf::RbfLapSurface_global_CPM_low(const fullMatrix<double> &cntrs, double del = (i == j) ? -1.0: 0.0; double pos1 = (i+numNodes == j) ? 1.0: 0.0; double pos2 = (i+2*numNodes == j) ? 1.0: 0.0; - Oper(i+numNodes,j) = del + Ix2extX(i,j);//+ pos1; // - Oper(i+2*numNodes,j) = del + Ix2extX(i+numNodes,j); //pos2; // + Oper(i+numNodes,j) = del +Ix2extX(i,j);//+ pos1; // + Oper(i+2*numNodes,j) = del + Ix2extX(i+numNodes,j); //+ pos2; // } } @@ -696,23 +707,64 @@ void GRbf::solveHarmonicMap(fullMatrix<double> Oper, std::vector<MVertex*> bcNodes, std::vector<double> coords, std::map<MVertex*, SPoint3> &rbf_param){ + Msg::Info("*** RBF ... solving map"); int nb = Oper.size2(); UV.resize(nb,2); fullMatrix<double> F(nb,2); F.scale(0.0); + + //UNIT CIRCLE for (int i=0; i < bcNodes.size(); i++){ - // std::set<MVertex *>::iterator itN = myNodes.find(bcNodes[i]); - // if (itN != myNodes.end()){ - std::map<MVertex*, int>::iterator itm = _mapV.find(bcNodes[i]); - double theta = 2 * M_PI * coords[i]; - int iFix = itm->second; - for (int j=0;j<nb ; ++j) Oper(iFix,j) = 0.0; - Oper(iFix,iFix) = 1.0; - F(iFix,0) = cos(theta); - F(iFix,1) = sin(theta); - //} + std::set<MVertex *>::iterator itN = myNodes.find(bcNodes[i]); + if (itN != myNodes.end()){ + std::map<MVertex*, int>::iterator itm = _mapV.find(bcNodes[i]); + double theta = 2 * M_PI * coords[i]; + int iFix = itm->second; + for (int j=0;j<nb ; ++j) Oper(iFix,j) = 0.0; + Oper(iFix,iFix) = 1.0; + F(iFix,0) = cos(theta); + F(iFix,1) = sin(theta); + } } + + //SQUARE + // for(std::set<MVertex *>::iterator itv = myNodes.begin(); itv !=myNodes.end() ; ++itv){ + // MVertex *v = *itv; + // if (v->getNum() == 1){ //2900){ + // std::map<MVertex*, int>::iterator itm = _mapV.find(v); + // int iFix = itm->second; + // for (int j=0;j<nb ; ++j) Oper(iFix,j) = 0.0; + // Oper(iFix,iFix) = 1.0; + // F(iFix,0) = 0.0; + // F(iFix,1) = 0.0; + // } + // if (v->getNum() == 2){//1911){ + // std::map<MVertex*, int>::iterator itm = _mapV.find(v); + // int iFix = itm->second; + // for (int j=0;j<nb ; ++j) Oper(iFix,j) = 0.0; + // Oper(iFix,iFix) = 1.0; + // F(iFix,0) = 1.0; + // F(iFix,1) = 0.0; + // } + // if (v->getNum() == 3){//4844){ + // std::map<MVertex*, int>::iterator itm = _mapV.find(v); + // int iFix = itm->second; + // for (int j=0;j<nb ; ++j) Oper(iFix,j) = 0.0; + // Oper(iFix,iFix) = 1.0; + // F(iFix,0) = 1.0; + // F(iFix,1) = 1.0; + // } + // if (v->getNum() == 4){//3187){ + // std::map<MVertex*, int>::iterator itm = _mapV.find(v); + // int iFix = itm->second; + // for (int j=0;j<nb ; ++j) Oper(iFix,j) = 0.0; + // Oper(iFix,iFix) = 1.0; + // F(iFix,0) = 0.0; + // F(iFix,1) = 1.0; + // } + // } + Oper.invertInPlace(); Oper.mult(F,UV); @@ -747,6 +799,7 @@ void GRbf::solveHarmonicMap(fullMatrix<double> Oper, } Msg::Info("*** RBF solved map"); + exportParametrizedMesh(UV, nbNodes); } @@ -754,14 +807,22 @@ bool GRbf::UVStoXYZ(const double u_eval, const double v_eval, double &XX, double &YY, double &ZZ, SVector3 &dXdu, SVector3& dXdv, int num_neighbours){ - num_neighbours = 30; - fullMatrix<double> u_vec(num_neighbours,3), xyz_local(num_neighbours,3); - fullMatrix<double> u_vec_eval(1, 3), nodes_eval(1,3), xu(1,3), xv(1,3); - u_vec_eval(0,0) = u_eval; - u_vec_eval(0,1) = v_eval; - u_vec_eval(0,2) = 0.0; + if (u_eval == lastU && v_eval == lastV){ + XX = lastX; + YY = lastY; + ZZ = lastZ; + dXdu = lastDXDU; + dXdv = lastDXDV; + return true; + } + + num_neighbours = std::min(100, nbNodes); + fullMatrix<double> u_vec(num_neighbours,3), xyz_local(num_neighbours,3); + fullMatrix<double> u_vec_eval(1, 3), nodes_eval(1,3), xu(1,3), xv(1,3); + u_vec_eval(0,0) = u_eval; + u_vec_eval(0,1) = v_eval; + u_vec_eval(0,2) = 0.0; - //printf("uvw=%g %g %g \n", u_eval, v_eval, 0.0); #if defined (HAVE_ANN) double uvw[3] = { u_eval, v_eval, 0.0 }; ANNidxArray index = new ANNidx[num_neighbours]; @@ -790,7 +851,7 @@ bool GRbf::UVStoXYZ(const double u_eval, const double v_eval, #endif _inUV = 1; - deltaUV = 0.6*dist_min; + deltaUV = 0.3*dist_min; evalRbfDer(0, u_vec, u_vec_eval,xyz_local, nodes_eval); evalRbfDer(1, u_vec, u_vec_eval,xyz_local, xu); evalRbfDer(2, u_vec, u_vec_eval,xyz_local, xv); @@ -802,6 +863,14 @@ bool GRbf::UVStoXYZ(const double u_eval, const double v_eval, dXdu = SVector3(xu(0,0)*sBox, xu(0,1)*sBox, xu(0,2)*sBox); dXdv = SVector3(xv(0,0)*sBox, xv(0,1)*sBox, xv(0,2)*sBox); + //store last computation + lastU = u_eval; + lastV = v_eval; + lastX = XX; + lastY = YY; + lastZ = ZZ; + lastDXDU = dXdu ; + lastDXDV = dXdv ; return true; } diff --git a/Geo/GRbf.h b/Geo/GRbf.h index c79f94c7c9e24c0d7b604b98db04920303b3df00..e849b725d8f7f5a62f81124d1c0ec8b5a13ad1bd 100644 --- a/Geo/GRbf.h +++ b/Geo/GRbf.h @@ -40,13 +40,16 @@ class GRbf { double radius; double sBox; + SVector3 lastDXDU, lastDXDV; + double lastX, lastY, lastZ, lastU, lastV; + int variableShapeParam; int radialFunctionIndex; // Index for the radial function used (0 - GA,1 - MQ, ... ) - std::set<MVertex *> myNodes; + std::set<MVertex *> myNodes; //Used mesh vertices for light rbf fullMatrix<double> centers; // Data centers (without duplicates) fullMatrix<double> allCenters; // Data centers - fullMatrix<double> normals; // Data normals + fullMatrix<double> normals; // Data normals(without Duplicates) fullMatrix<double> surfInterp;//level set fullMatrix<double> extendedX;//X values extend in and out fullMatrix<double> UV;//solution harmonic map laplu=0 and laplV=0 @@ -131,11 +134,8 @@ class GRbf { const fullMatrix<double> &normals, fullMatrix<double> &D); - // Calculates the curvature of a surface at a certain node - void curvature(double radius, - const fullMatrix<double> &cntrs, - const fullMatrix<double> &node, - fullMatrix<double> &curvature); + // Calculates the curvature of a surface at centers + void computeCurvature(std::map<MVertex*, SPoint3> &rbf_curv); //Finds the U,V,S (in the 0-level set) that are the 'num_neighbours' closest to u_eval and v_eval. //Thus in total, we're working with '3*num_neighbours' nodes