void buildKdTree(KdNode *nodes, float *tmp, Item *items, int n, int depth, int thisNode, int &freeNode) { KdNode *node = nodes + thisNode; int keyIndex = depth%2; if (n==0) { node->child_node = -1; return; } if (n<2) { node->child_node = 0; node->leftBounds[0] = items->bbox[keyIndex][0]; node->leftBounds[1] = items->bbox[keyIndex][1]; *((void**)(node->rightBounds)) = items->data; if (this->maxDepth<depth) this->maxDepth = depth; return; } int medianIndex = n/2-1; for (size_t i=0; i<n; i++) tmp[i] = items[i].bbox[keyIndex][0]; std::sort(tmp, tmp+n); float median = tmp[n/2-1]; int l = 0; int r = n-1; while (l<r) { while (l<n && items[l].bbox[keyIndex][0]<=median) l++; while (r>=0 && items[r].bbox[keyIndex][0]>median) r--; if (l<r) std::swap(items[l], items[r]); } medianIndex = r; if (medianIndex==n-1) medianIndex = n-2; node->leftBounds[0] = node->rightBounds[0] = FLT_MAX; node->leftBounds[1] = node->rightBounds[1] = -FLT_MAX; for (unsigned i=0; i<=medianIndex; i++) { if (items[i].bbox[keyIndex][0]<node->leftBounds[0]) node->leftBounds[0] = items[i].bbox[keyIndex][0]; if (items[i].bbox[keyIndex][1]>node->leftBounds[1]) node->leftBounds[1] = items[i].bbox[keyIndex][1]; } for (unsigned i=medianIndex+1; i<n; i++) { if (items[i].bbox[keyIndex][0]<node->rightBounds[0]) node->rightBounds[0] = items[i].bbox[keyIndex][0]; if (items[i].bbox[keyIndex][1]>node->rightBounds[1]) node->rightBounds[1] = items[i].bbox[keyIndex][1]; } node->child_node = freeNode; freeNode += 2; buildKdTree(nodes, tmp, items, medianIndex+1, depth+1, node->child_node, freeNode); if (medianIndex<n-1) buildKdTree(nodes, tmp, items + medianIndex+1, n-medianIndex-1, depth+1, node->child_node+1, freeNode); else nodes[node->child_node+1].child_node = -1; }
void createKdTree(Item *items, int n) { this->maxDepth = 0; this->nodes.resize(std::max(n*4,1)); float *tmp = (float*)malloc(sizeof(float)*n); int freeNode = 1; buildKdTree(this->nodes.data(), tmp, items, n, 0, 0, freeNode); fprintf(stderr, "Created a Kd tree for bounding boxes with %d nodes and depth %d.\n", freeNode, this->maxDepth); free(tmp); }
void Centerline::run() { double t1 = Cpu(); if (update_needed){ std::ifstream input; //std::string pattern = FixRelativePath(fileName, "./"); //Msg::StatusBar(true, "Reading TEST '%s'...", pattern.c_str()); //input.open(pattern.c_str()); input.open(fileName.c_str()); if(StatFile(fileName)) Msg::Fatal("Centerline file '%s' does not exist ", fileName.c_str()); importFile(fileName); buildKdTree(); update_needed = false; } if (is_cut) cutMesh(); else{ GFace *gf = current->getFaceByTag(1); gf->addPhysicalEntity(1); current->setPhysicalName("wall", 2, 1);//tag 1 current->createTopologyFromMesh(); NV = current->getMaxElementaryNumber(0); NE = current->getMaxElementaryNumber(1); NF = current->getMaxElementaryNumber(2); NR = current->getMaxElementaryNumber(3); } //identify the boundary edges by looping over all discreteFaces std::vector<GEdge*> boundEdges; double dist_inlet = 1.e6; GEdge *gin = NULL; for (int i= 0; i< NF; i++){ GFace *gf = current->getFaceByTag(i+1); std::list<GEdge*> l_edges = gf->edges(); for(std::list<GEdge*>::iterator it = l_edges.begin(); it != l_edges.end(); it++){ std::vector<GEdge*>::iterator ite = std::find(boundEdges.begin(), boundEdges.end(), *it); if (ite != boundEdges.end()) boundEdges.erase(ite); else boundEdges.push_back(*it); GVertex *gv = (*it)->getBeginVertex(); SPoint3 pt(gv->x(), gv->y(), gv->z()); double dist = pt.distance(ptin); if(dist < dist_inlet){ dist_inlet = dist; gin = *it; } } } if (is_closed) createClosedVolume(gin, boundEdges); if (is_extruded) extrudeBoundaryLayerWall(gin, boundEdges); double t2 = Cpu(); Msg::Info("Centerline operators computed in %g (s) ",t2-t1); }
double Centerline::operator() (double x, double y, double z, GEntity *ge) { if (update_needed){ std::ifstream input; input.open(fileName.c_str()); if(StatFile(fileName)) Msg::Fatal("Centerline file '%s' does not exist", fileName.c_str()); importFile(fileName); buildKdTree(); 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 the volume bool isCompound = false; if(ge){ if (ge->dim() == 2 && ge->geomType() == GEntity::CompoundSurface) isCompound = true; std::list<GFace*> cFaces; if (isCompound) cFaces = ((GFaceCompound*)ge)->getCompounds(); if ( ge->dim() == 3 || (ge->dim() == 2 && ge->geomType() == GEntity::Plane) || (isCompound && (*cFaces.begin())->geomType() == GEntity::Plane) ){ const int num_neighbours = 1; ANNidx index[num_neighbours]; ANNdist dist[num_neighbours]; kdtreeR->annkSearch(xyz, num_neighbours, index, dist); ANNpointArray nodesR = kdtreeR->thePoints(); xyz[0] = nodesR[index[0]][0]; xyz[1] = nodesR[index[0]][1]; xyz[2] = nodesR[index[0]][2]; } } const int num_neighbours = 1; ANNidx index[num_neighbours]; ANNdist dist[num_neighbours]; kdtree->annkSearch(xyz, num_neighbours, index, dist); double rad = sqrt(dist[0]); //double cmax, cmin; //SVector3 dirMax,dirMin; //cmax = ge->curvatures(SPoint2(u, v),&dirMax, &dirMin, &cmax,&cmin); //cmax = ge->curvatureMax(SPoint2(u,v)); //double radC = 1./cmax; double lc = 2*M_PI*rad/nbPoints; if(!ge) { return rad;} else return lc; }
Centerline::Centerline(std::string fileName): kdtree(0), kdtreeR(0) { recombine = (CTX::instance()->mesh.recombineAll) || (CTX::instance()->mesh.recombine3DAll); nbPoints = 25; hLayer = 0.3; hSecondLayer = 0.3; nbElemLayer = 3; nbElemSecondLayer = 0; is_cut = 0; is_closed = 0; is_extruded = 0; importFile(fileName); buildKdTree(); update_needed = false; }
void MultiObjectSeg::addGraphEdge(PCloudGraph& pcGraph, Sample& smp) { IndexType nSize = smp.num_vertices(); unordered_map<IndexType,bool> recordEdges; buildKdTree(smp); IndexType gIndex = 0; const IndexType k = 6; IndexType neighbours[k]; ScalarType dist[k]; IndexType edNum = 0; for (; gIndex < nSize; ++ gIndex) { downSample->neighbours(gIndex,k,neighbours,dist); for (IndexType i = 1; i < k; ++i) { bool temp = recordEdges[frame_index_to_key(gIndex,neighbours[i]) ]; if (!temp) { PCEdgeProperty ep; ep.index = edNum; ep.start_ = gIndex; ep.end_ = neighbours[i]; ep.dist = dist[i]; boost::add_edge(gIndex,neighbours[i],ep,pcGraph); recordEdges[frame_index_to_key(neighbours[i],gIndex)] = true; ++ edNum; } } } }
void Centerline::operator() (double x, double y, double z, SMetric3 &metr, GEntity *ge) { if (update_needed){ std::ifstream input; input.open(fileName.c_str()); if(StatFile(fileName)) Msg::Fatal("Centerline file '%s' does not exist", fileName.c_str()); importFile(fileName); buildKdTree(); update_needed = false; } //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) ? true : false; bool onInOutlets = (ge->geomType() == GEntity::Plane) ? true: false; std::list<GFace*> cFaces; if (isCompound) cFaces = ((GFaceCompound*)ge)->getCompounds(); if ( ge->dim() == 3 || (ge->dim() == 2 && ge->geomType() == GEntity::Plane) || (isCompound && (*cFaces.begin())->geomType() == GEntity::Plane) ){ onTubularSurface = false; } ANNidx index[1]; ANNdist dist[1]; kdtreeR->annkSearch(xyz, 1, index, dist); if (! onTubularSurface){ ANNpointArray nodesR = kdtreeR->thePoints(); ds = sqrt(dist[0]); xyz[0] = nodesR[index[0]][0]; xyz[1] = nodesR[index[0]][1]; xyz[2] = nodesR[index[0]][2]; } ANNidx index2[2]; ANNdist dist2[2]; kdtree->annkSearch(xyz, 2, index2, dist2); double radMax = sqrt(dist2[0]); ANNpointArray nodes = kdtree->thePoints(); SVector3 p0(nodes[index2[0]][0], nodes[index2[0]][1], nodes[index2[0]][2]); SVector3 p1(nodes[index2[1]][0], nodes[index2[1]][1], nodes[index2[1]][2]); //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(); // if (ge->dim()==3){ // printf("coucou dim ==3 !!!!!!!!!!!!!!! \n"); // SVector3 d1,d2,d3; // computeCrossField(x,y,z,d1,d2,d3); // exit(1); // } //find discrete curvature at closest vertex Curvature& curvature = Curvature::getInstance(); if( !Curvature::valueAlreadyComputed() ) { Msg::Info("Need to compute discrete curvature"); Curvature::typeOfCurvature type = Curvature::RUSIN; curvature.computeCurvature(current, type); } double curv, cMin, cMax; SVector3 dMin, dMax; 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 //define h_n, h_t1, and h_t2 double thickness = radMax/3.; double h_far = radMax/5.; double beta = (ds <= thickness) ? 1.2 : 2.1; //CTX::instance()->mesh.smoothRatio; double ddist = (ds <= thickness) ? ds: thickness; double h_n_0 = thickness/20.; double h_n = std::min( (h_n_0+ds*log(beta)), h_far); double betaMin = 10.0; double betaMax = 3.1; double oneOverD2_min = 1./(2.*rhoMin*rhoMin*(betaMin*betaMin-1)) * (sqrt(1+ (4.*rhoMin*rhoMin*(betaMin*betaMin-1))/(h_n*h_n))-1.); double oneOverD2_max = 1./(2.*rhoMax*rhoMax*(betaMax*betaMax-1)) * (sqrt(1+ (4.*rhoMax*rhoMax*(betaMax*betaMax-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*(rhoMin+signMin*ddist)/rhoMin ; //double h_t2 = h_t2_0*(rhoMax+signMax*ddist)/rhoMax ; double h_t1 = std::min( (h_t1_0+(ddist*log(beta))), radMax); double h_t2 = std::min( (h_t2_0+(ddist*log(beta))), h_far); double dCenter = radMax-ds; double h_a_0 = 0.5*radMax; double h_a = h_a_0 - (h_a_0-h_t1_0)/(radMax)*dCenter; //length between min and max double lcMin = ((2 * M_PI *radMax) /( 50*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; SMetric3 centMetric1, centMetric2, centMetric; if (onInOutlets){ metr = buildMetricTangentToCurve(dir_n,h_n,h_t2); } else { //on surface and in volume boundary layer if ( ds < thickness ){ metr = metricBasedOnSurfaceCurvature(dMin, dMax, cMin, cMax, h_n, h_t1, h_t2); } //in volume else { //curvMetric = metricBasedOnSurfaceCurvature(dMin, dMax, cMin, cMax, h_n, h_t1, h_t2); metr = SMetric3( 1./(h_a*h_a), 1./(h_n*h_n), 1./(h_n*h_n), dir_a, dir_n, dir_cross); //metr = intersection_conserveM1_bis(metr, curvMetric); //metr = intersection_conserveM1(metr,curvMetric); //metr = intersection_conserve_mostaniso(metr, curvMetric); //metr = intersection(metr,curvMetric); } } return; }