diff --git a/Geo/GEdgeCompound.cpp b/Geo/GEdgeCompound.cpp index 8248973bf92f86eeb01382f97670380f7a4e6a64..bd70e94b536f2041442a242e440fa9aed08f2148 100644 --- a/Geo/GEdgeCompound.cpp +++ b/Geo/GEdgeCompound.cpp @@ -271,7 +271,7 @@ double GEdgeCompound::curvatures(const double par, SVector3 *dirMax, SVector3 *d double cMax[2]; SVector3 dMin[2]; SVector3 dMax[2]; - curvature.edgeNodalValuesAndDirections(mline, dMax, dMin, cMax, cMin, 0); + curvature.edgeNodalValuesAndDirections(mline, dMax, dMin, cMax, cMin, 1); *dirMax = (1-tLocMLine)*dMax[0] + tLocMLine*dMax[1]; *dirMin = (1-tLocMLine)*dMin[0] + tLocMLine*dMin[1]; diff --git a/Mesh/BackgroundMesh.cpp b/Mesh/BackgroundMesh.cpp index a7a0f011e8b3632c17d93a61342237823cd8ff02..d8a56c26025dd0c9da630ea07fb3305bf62e8cba 100644 --- a/Mesh/BackgroundMesh.cpp +++ b/Mesh/BackgroundMesh.cpp @@ -151,23 +151,23 @@ static double max_surf_curvature(const GEdge *ge, double u) return val; } -/* -static double max_surf_curvature(const GVertex *gv) -{ - double val = 0; - std::list<GEdge*> l_edges = gv->edges(); - for (std::list<GEdge*>::const_iterator ite = l_edges.begin(); - ite != l_edges.end(); ++ite){ - GEdge *_myGEdge = *ite; - Range<double> bounds = _myGEdge->parBounds(0); - if (gv == _myGEdge->getBeginVertex()) - val = std::max(val, max_surf_curvature(_myGEdge, bounds.low())); - else - val = std::max(val, max_surf_curvature(_myGEdge, bounds.high())); - } - return val; -} -*/ + +// static double max_surf_curvature_vertex(const GVertex *gv) +// { +// double val = 0; +// std::list<GEdge*> l_edges = gv->edges(); +// for (std::list<GEdge*>::const_iterator ite = l_edges.begin(); +// ite != l_edges.end(); ++ite){ +// GEdge *_myGEdge = *ite; +// Range<double> bounds = _myGEdge->parBounds(0); +// if (gv == _myGEdge->getBeginVertex()) +// val = std::max(val, max_surf_curvature(_myGEdge, bounds.low())); +// else +// val = std::max(val, max_surf_curvature(_myGEdge, bounds.high())); +// } +// return val; +// } + SMetric3 metric_based_on_surface_curvature(const GFace *gf, double u, double v, bool surface_isotropic, @@ -180,10 +180,10 @@ SMetric3 metric_based_on_surface_curvature(const GFace *gf, double u, double v, cmax = gf->curvatures(SPoint2(u, v),&dirMax, &dirMin, &cmax,&cmin); if (cmin == 0)cmin =1.e-12; if (cmax == 0)cmax =1.e-12; - double lambda2 = ((2 * M_PI) /( fabs(cmax) * CTX::instance()->mesh.minCircPoints ) ); double lambda1 = ((2 * M_PI) /( fabs(cmin) * CTX::instance()->mesh.minCircPoints ) ); + double lambda2 = ((2 * M_PI) /( fabs(cmax) * CTX::instance()->mesh.minCircPoints ) ); SVector3 Z = crossprod(dirMax,dirMin); - if (surface_isotropic) lambda2 = lambda1 = std::min(lambda2,lambda1); + if (surface_isotropic) lambda2 = lambda1 = std::min(lambda2,lambda1); dirMin.normalize(); dirMax.normalize(); Z.normalize(); @@ -209,8 +209,8 @@ static SMetric3 metric_based_on_surface_curvature(const GEdge *ge, double u, boo 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; + if (cmin == 0)cmin =1.e-12; + if (cmax == 0)cmax =1.e-12; 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); @@ -221,7 +221,7 @@ static SMetric3 metric_based_on_surface_curvature(const GEdge *ge, double u, boo lambda2 = std::min(lambda2, CTX::instance()->mesh.lcMax); SMetric3 curvMetric (1. / (lambda1 * lambda1), 1. / (lambda2 * lambda2), - 1.e-5, dirMin, dirMax, Z); + 1.e-12, dirMin, dirMax, Z); return curvMetric; } else{ @@ -240,6 +240,7 @@ static SMetric3 metric_based_on_surface_curvature(const GEdge *ge, double u, boo } ++it; } + return curvMetric; } } @@ -283,7 +284,7 @@ static double LC_MVertex_CURV(GEntity *ge, double U, double V) switch(ge->dim()){ case 0: Crv = max_edge_curvature((const GVertex *)ge); - // Crv = std::max(max_surf_curvature((const GVertex *)ge), Crv); + //Crv = std::max(max_surf_curvature_vertex((const GVertex *)ge), Crv); // Crv = max_surf_curvature((const GVertex *)ge); break; case 1: @@ -448,7 +449,8 @@ SMetric3 BGM_MeshMetric(GEntity *ge, } SMetric3 LC(1./(lc*lc)); - SMetric3 m = intersection_conserveM1(intersection_conserveM1 (l4, LC),l3); + //SMetric3 m = intersection_conserveM1(intersection_conserveM1 (l4, LC),l3); + SMetric3 m = intersection(intersection (l4, LC),l3); //printf("%g %g %g %g %g %g\n",m(0,0),m(1,1),m(2,2),m(0,1),m(0,2),m(1,2)); { fullMatrix<double> V(3,3); diff --git a/Mesh/CenterlineField.cpp b/Mesh/CenterlineField.cpp index 88dbe9e8c45fab2176f7b751ae51727d17ba32c1..490e1dc09f7ec8b9ee3f628050c451d263e6145c 100644 --- a/Mesh/CenterlineField.cpp +++ b/Mesh/CenterlineField.cpp @@ -18,6 +18,7 @@ #include <fstream> #include <sstream> #include <iostream> +#include <math.h> #include "OS.h" #include "GModel.h" #include "MElement.h" @@ -1078,7 +1079,7 @@ double Centerline::operator() (double x, double y, double z, GEntity *ge) void Centerline::operator() (double x, double y, double z, SMetric3 &metr, GEntity *ge) { - if (update_needed){ + if (update_needed){ std::ifstream input; input.open(fileName.c_str()); if(StatFile(fileName)) @@ -1088,10 +1089,10 @@ void Centerline::operator() (double x, double y, double z, SMetric3 &metr, GEnt update_needed = false; } - double xyz[3] = {x,y,z}; - //take xyz = closest point on boundary in case we are on the planar IN/OUT - //FACES or in VOLUME + //take xyz = closest point on boundary in case we are on + //the planar IN/OUT FACES or in VOLUME + double xyz[3] = {x,y,z}; bool onTubularSurface = true; double ds = 0.0; bool isCompound = (ge->dim() == 2 && ge->geomType() == GEntity::CompoundSurface) ? @@ -1122,6 +1123,13 @@ void Centerline::operator() (double x, double y, double z, SMetric3 &metr, GEnt delete[]index2; delete[]dist2; + //dir_a = direction along the centerline + //dir_n = normal direction of the disk + //dir_t = tangential direction of the disk + SVector3 dir_a = p1-p0; dir_a.normalize(); + SVector3 dir_n(xyz[0]-p0.x(), xyz[1]-p0.y(), xyz[2]-p0.z()); dir_n.normalize(); + SVector3 dir_cross = crossprod(dir_a,dir_n); dir_cross.normalize(); + //find discrete curvature at closest vertex Curvature& curvature = Curvature::getInstance(); if( !Curvature::valueAlreadyComputed() ) { @@ -1131,60 +1139,75 @@ void Centerline::operator() (double x, double y, double z, SMetric3 &metr, GEnt } double curv, cMin, cMax; SVector3 dMin, dMax; - curvature.vertexNodalValuesAndDirections(vertices[index[0]],&dMax, &dMin, &cMax, &cMin, 1); - curvature.vertexNodalValues(vertices[index[0]], curv, 0); - - double sign = (curv > 0.0) ? -1.0: 1.0; - double beta = CTX::instance()->mesh.smoothRatio; //beta = 1.25 better ! - double ratio = 1.1; - + int isAbs = 1.0; + curvature.vertexNodalValuesAndDirections(vertices[index[0]],&dMax, &dMin, &cMax, &cMin, isAbs); + curvature.vertexNodalValues(vertices[index[0]], curv, 1); + if (cMin == 0) cMin =1.e-12; + if (cMax == 0) cMax =1.e-12; + double rhoMin = 1./cMin; + double rhoMax = 1./cMax; + double signMin = (rhoMin > 0.0) ? -1.0: 1.0; + double signMax = (rhoMax > 0.0) ? -1.0: 1.0; + + //user-defined parameters + double beta = 1.2; //CTX::instance()->mesh.smoothRatio; double thickness = radMax/3.; - double rho = radMax; - double hwall_n = thickness/20.; - double hwall_t = 2*M_PI*rho/nbPoints; - double hfar = radMax/4.; - double lc_a = 3.*hwall_t; - - //dir_a = direction along the centerline - //dir_n = normal direction of the disk - //dir_t = tangential direction of the disk - SVector3 dir_a = p1-p0; dir_a.normalize(); - SVector3 dir_n(xyz[0]-p0.x(), xyz[1]-p0.y(), xyz[2]-p0.z()); dir_n.normalize(); - SVector3 dir_cross = crossprod(dir_a,dir_n); dir_cross.normalize(); - SVector3 dir_t1, dir_t2, dir_a1, dir_a2; - buildOrthoBasis2(dir_n, dir_t1, dir_t2); - buildOrthoBasis2(dir_a, dir_a1, dir_a2); - - double ll1 = ds*(ratio-1) + hwall_n; - double lc_n = std::min(ll1,hfar); - double ll2 = hwall_t *(rho+sign*ds)/rho ; //sign * ds*(ratio-1) + hwall_t; - if (ds > thickness) ll2 = hwall_t *(rho+sign*thickness)/rho ; //lc_a; //hfar - double lc_t = std::min(lc_n*CTX::instance()->mesh.anisoMax, ll2); //std::min(ll2,hfar)); - - lc_n = std::max(lc_n, CTX::instance()->mesh.lcMin); - lc_n = std::min(lc_n, CTX::instance()->mesh.lcMax); - lc_t = std::max(lc_t, CTX::instance()->mesh.lcMin); - lc_t = std::min(lc_t, CTX::instance()->mesh.lcMax); + double hwall_t = 2*M_PI*radMax/nbPoints; + double h_far = radMax/2.; + double h_a = radMax; //3.*hwall_t; + + //define h_n, h_t1, and h_t2 + double h_n_0 = thickness/20.; + double h_n = std::min( (h_n_0+ds*log(beta)), h_far); + //double h_n = ds*(beta-1) + hwall_n; + //if (ds > thickness) h_n = hwall_t *(rho+sign*thickness)/rho ; + + double oneOverD2_min = 1./(2.*rhoMin*rhoMin*(beta*beta-1)) * + (sqrt(1+ (4.*rhoMin*rhoMin*(beta*beta-1))/(h_n*h_n))-1.); + double oneOverD2_max = 1./(2.*rhoMax*rhoMax*(beta*beta-1)) * + (sqrt(1+ (4.*rhoMax*rhoMax*(beta*beta-1))/(h_n*h_n))-1.); + double h_t1_0 = sqrt(1./oneOverD2_min); + double h_t2_0 = sqrt(1./oneOverD2_max); + double h_t1 = (h_t1_0+signMin*ds*log(beta)); + double h_t2 = (h_t2_0+signMax*ds*log(beta)); + //double ll2 = hwall_t *(rho+sign*ds)/rho ; //sign * ds*(ratio-1) + hwall_t; + //if (ds > thickness) ll2 = hwall_t *(rho+sign*thickness)/rho ; + + //printf("************* rhoMin =%g rhoMax=%g \n", rhoMin, rhoMax); + //printf("h_n_0 =%g h_n =%g\n", h_n_0 , h_n); + //printf("h_t1_0 =%g h_t2_0=%g ds=%g\n", h_t1_0, h_t2_0, ds); + //printf("h_t1 =%g h_t2=%g radMax=%g h_a=%g\n", h_t1, h_t2, radMax, h_a); + + //length between min and max + double lcMin = ((2 * M_PI *radMax) /( 20*nbPoints )); //CTX::instance()->mesh.lcMin; + double lcMax = lcMin*2000.; //CTX::instance()->mesh.lcMax; + h_n = std::max(h_n, lcMin); + h_n = std::min(h_n, lcMax); + h_t1 = std::max(h_t1, lcMin); + h_t1 = std::min(h_t1, lcMax); + h_t2 = std::max(h_t2, lcMin); + h_t2 = std::min(h_t2, lcMax); //curvature metric SMetric3 curvMetric, curvMetric1, curvMetric2; - if (ds <= thickness){ - metr = metricBasedOnSurfaceCurvature(dMin, dMax, cMin, cMax, radMax, - beta, lc_n, lc_t, hwall_t); + if (onInOutlets){ + metr = buildMetricTangentToCurve(dir_n,h_n,h_t2); } - else if (ds > thickness && onInOutlets){ - metr = buildMetricTangentToCurve(dir_n,lc_n,lc_t); - } - else if (ds > thickness && !onInOutlets){ - //metr = buildMetricTangentToCurve(dir_n,lc_n,lc_t); - //curvMetric = metricBasedOnSurfaceCurvature(dMin, dMax, cMin, cMax, radMax, beta, lc_n, lc_t, hwall_t); - curvMetric1 = buildMetricTangentToCurve(dir_n,lc_n,lc_a); //lc_t - curvMetric2 = buildMetricTangentToCurve(dir_cross,lc_t,lc_a); //lc_t - curvMetric = intersection(curvMetric1,curvMetric2); - //metr = SMetric3(1./(lc_a*lc_a), 1./(hfar*hfar),1./(hfar*hfar), dir_a, dir_a1, dir_a2); - metr = SMetric3(1./(lc_a*lc_a), 1./(lc_n*lc_n), 1./(lc_t*lc_t), dir_a, dir_n, dir_cross); - metr = intersection_conserveM1(metr,curvMetric); - //metr = intersection(metr,curvMetric); + else { + if (ds <= thickness ){ + metr = metricBasedOnSurfaceCurvature(dMin, dMax, cMin, cMax, h_n, h_t1, h_t2); + } + else { + //printf("in volume \n"); + curvMetric = metricBasedOnSurfaceCurvature(dMin, dMax, cMin, cMax, h_n, h_t1, h_t2); + //curvMetric1 = buildMetricTangentToCurve(dir_n,lc_n,lc_a); //lc_t + //curvMetric2 = buildMetricTangentToCurve(dir_cross,lc_t,lc_a); //lc_t + //curvMetric = intersection(curvMetric1,curvMetric2); + metr = SMetric3(1./(h_a*h_a), 1./(h_far*h_far), 1./(h_far*h_far), dir_a, dir_n, dir_cross); + //metr = intersection_conserveM1(metr,curvMetric); + metr = intersection_conserve_mostaniso(metr, curvMetric); + //metr = intersection(metr,curvMetric); + } } return; @@ -1192,39 +1215,13 @@ void Centerline::operator() (double x, double y, double z, SMetric3 &metr, GEnt } SMetric3 Centerline::metricBasedOnSurfaceCurvature(SVector3 dirMin, SVector3 dirMax, - double cmin, double cmax, double radMax, - double beta, double lc_n, double lc_t, - double hwall_t) + double cmin, double cmax, + double h_n, double h_t1, double h_t2) { - double lcMin = ((2 * M_PI *radMax) /( 20*nbPoints )); //CTX::instance()->mesh.lcMin; - double lcMax = ((2 * M_PI *radMax) /( 0.05*nbPoints)); //CTX::instance()->mesh.lcMax; - if (cmin == 0) cmin =1.e-12; - if (cmax == 0) cmax =1.e-12; - double lambda1 = ((2 * M_PI) /( fabs(cmin) * nbPoints ) ); - double lambda2 = ((2 * M_PI) /( fabs(cmax) * nbPoints ) ); - - double betaM = 1*beta; - double rhoMin = 1./cmin; - double rhoMax = 1./cmax; - double oneOverD2_min = 1./(2.*rhoMin*rhoMin*(betaM*betaM-1)) * - (sqrt(1+ (4.*rhoMin*rhoMin*(betaM*betaM-1))/(lc_n*lc_n))-1.); - double oneOverD2_max = 1./(2.*rhoMax*rhoMax*(beta*beta-1)) * - (sqrt(1+ (4.*rhoMax*rhoMax*(beta*beta-1))/(lc_n*lc_n))-1.); - - lambda1 = sqrt(1./oneOverD2_min); - lambda2 = sqrt(1./oneOverD2_max); SVector3 dirNorm = crossprod(dirMax,dirMin); - dirMin.normalize(); - dirMax.normalize(); - dirNorm.normalize(); - lambda1 = std::max(lambda1, lcMin); - lambda2 = std::max(lambda2, lcMin); - lambda1 = std::min(lambda1, lcMax); - lambda2 = std::min(lambda2, lcMax); - - SMetric3 curvMetric (1./(lambda1*lambda1),1./(lambda2*lambda2), - 1./(lc_n*lc_n), dirMin, dirMax, dirNorm); // 1.e-6 + SMetric3 curvMetric (1./(h_t1*h_t1),1./(h_t2*h_t2), + 1./(h_n*h_n), dirMin, dirMax, dirNorm); return curvMetric; } diff --git a/Mesh/CenterlineField.h b/Mesh/CenterlineField.h index ae0429b364f8db67ff0b727b8c10fd6570dbe2ec..cd1b6834c1cb52b77db996a0265011e86f851433 100644 --- a/Mesh/CenterlineField.h +++ b/Mesh/CenterlineField.h @@ -159,8 +159,8 @@ class Centerline : public Field{ //Print for debugging void printSplit() const; - SMetric3 metricBasedOnSurfaceCurvature(SVector3 dMin, SVector3 dMax, double cMin, double cMax, double radMax, - double beta, double lc_n, double lc_t, double hwall_t); + SMetric3 metricBasedOnSurfaceCurvature(SVector3 dMin, SVector3 dMax, double cMin, double cMax, + double lc_n, double lc_t1, double lc_t2); }; #else diff --git a/benchmarks/centerlines/aorta_centerlines.geo b/benchmarks/centerlines/aorta_centerlines.geo index 645bc2cf90969926931764f52ca9fcb76874a7de..99d8274a67ddfce7e6b466e9bc46ac8f67783559 100644 --- a/benchmarks/centerlines/aorta_centerlines.geo +++ b/benchmarks/centerlines/aorta_centerlines.geo @@ -1,16 +1,16 @@ -Mesh.Algorithm = 8; //(1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=bamg, 8=delquad) +Mesh.Algorithm = 7; //(1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=bamg, 8=delquad) Mesh.Algorithm3D = 7; //(1=tetgen, 4=netgen, 5=FrontalDel, 6=FrontalHex, 7=MMG3D, 9=R-tree Mesh.LcIntegrationPrecision = 1.e-3; -Mesh.RecombineAll = 1; -Mesh.Bunin = 60; +//Mesh.RecombineAll = 1; +//Mesh.Bunin = 60; Merge "aorta2.stl"; Field[1] = Centerline; Field[1].FileName = "centerlinesAORTA.vtk"; -Field[1].nbPoints = 25; +Field[1].nbPoints = 20; Field[1].nbElemLayer = 4; Field[1].hLayer = 0.2;//percent of vessel radius diff --git a/benchmarks/centerlines/bypass_centerlines.geo b/benchmarks/centerlines/bypass_centerlines.geo index 916b8a5aaa5ecd0779f1e5e66309b0fa3ae287f8..c49694ad77b619c3888d67f3d4009f042edbd0d7 100644 --- a/benchmarks/centerlines/bypass_centerlines.geo +++ b/benchmarks/centerlines/bypass_centerlines.geo @@ -10,7 +10,7 @@ Merge "bypass.stl"; Field[1] = Centerline; Field[1].FileName = "centerlinesBYPASS.msh"; -Field[1].nbPoints = 15; +Field[1].nbPoints = 25; Field[1].nbElemLayer = 4; Field[1].hLayer = 0.2;//percent of vessel radius diff --git a/benchmarks/centerlines/cyl_centerlines.geo b/benchmarks/centerlines/cyl_centerlines.geo index 8e88efc01c467e184f870e54b97f2ecbd8dac5be..09309bff8c20d3dd7e6d8c70984327040b9aeda8 100644 --- a/benchmarks/centerlines/cyl_centerlines.geo +++ b/benchmarks/centerlines/cyl_centerlines.geo @@ -1,11 +1,11 @@ -Mesh.Algorithm = 8; //(1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=bamg, 8=delquad) +Mesh.Algorithm = 7; //(1=MeshAdapt, 2=Automatic, 5=Delaunay, 6=Frontal, 7=bamg, 8=delquad) Mesh.Algorithm3D = 7; //(1=tetgen, 4=netgen, 7=mmg3D -Mesh.LcIntegrationPrecision = 1.e-2; +Mesh.LcIntegrationPrecision = 1.e-3; Merge "cylemi.stl"; -Mesh.RecombineAll = 1; +//Mesh.RecombineAll = 1; //Mesh.Bunin = 100; Field[1] = Centerline;