void Octree::doIterate(int level, Node *node, const func_t &f) const{ f(level, node); if (node->hasChildren()) { for (int i = 0; i < 8; ++i) { doIterate(level + 1, node->children[i], f); } } }
//=========================================================================== // // Purpose : Given two parametric curve in a simple case situation, iterate // to the intersection point, if any. // // Written by : Sverre Briseid, SINTEF, Sep 2004 // //=========================================================================== int Par1FuncIntersector::updateIntersections() //=========================================================================== { // Fetch already existing intersection points vector<shared_ptr<IntersectionPoint> > int_pts; int_results_->getIntersectionPoints(int_pts); if (int_pts.size() > 0) { // At most one intersection point is expected. One or more points // exist already. Leave it like this. // @@sbr Do we expect object to be monotone? return 0; } // Iterate to an intersection point between the two curves double par, dist, tmin, tmax; doIterate(par, dist, tmin, tmax); if ((par != tmin) && (par != tmax) && (dist <= epsge_->getEpsge())) { // An intersection point is found. Represent it in the data // structure // @@@ vsk, In sisl there is a check if the found intersection // point is very close to the endpoints of the curve. In that case // it is dismissed since the intersections at the endpoints are found // already. Here we have already checked if there exist any // intersection points. Thus, we know that there does not exist any // intersection point at the endpoint. // @@sbr But for tangential intersections an endpoint may not be discovered ... // As the int_pts.size() == 0 and an intersection point nevertheless exist // this should be such a (or similar) situation. // @@sbr Another approach could be to avoid subdividing if the obj (2d) // is monotone in that direction. int_results_->addIntersectionPoint(func_int_, C_, getTolerance(), &par, NULL); return 1; // A new point is found } //#endif // 0 return 0; }
void Octree::iterateNodes(const func_t &f) const { doIterate(0, root, f); }
//=========================================================================== int Par1FuncIntersector::getSubdivisionParameter(int dir, double& par) //=========================================================================== { // Purpose : Return (what seems to be) the most suitable // subdivision param. int ki, kj, sgn; // int nmbdir1 = func_int_->numParams(); // int nmbdir2 = C_->numParams(); double ptol = 100.0*epsge_->getRelParRes(); double gtol = 100.0*epsge_->getEpsge(); //100.0*epsge_->getEpsge(); // Set pointer to the intersection object corresponding to the parameter // direction ParamFunctionInt *obj = func_int_.get(); int pdir = 0; double ta = obj->startParam(pdir); double tb = obj->endParam(pdir); double fac = 0.1; double del = fac*(tb - ta); // Get critical parameters // @@@ Critical parameters of different priority? Sorting? vector<double> critical_pars = obj->getCriticalVals(pdir); int size = (int)critical_pars.size(); int is_critical; if (size > 0) { // Check suitability of the critical parameters for (ki=0; ki<size; ki++) { // is_critical = int_results_->inInfluenceArea(pdir, critical_pars[ki]); // if (is_critical == 0 || is_critical == 2) par = critical_pars[ki]; if (par >= ta + del && par <= tb - del) { return 1; } } } // Look for a suitable knot in which to subdivide. First fetch // the knots sorted according to the distance to the mid-parameter vector<double> knot_vals = obj->getInnerKnotVals(pdir, true); size = (int)knot_vals.size(); if (size > 0) { // Check suitability of the knots for (ki=0; ki<size; ki++) { par = knot_vals[ki]; // is_critical = int_results_->inInfluenceArea(pdir, knot_vals[ki]); // if (is_critical == 0 || is_critical == 2) if (par >= ta + del && par <= tb - del) { return 2; } } } // Check for inner intersection points in which to subdivide vector<double> inner_ints = int_results_->getSortedInnerInts(pdir); size = (int)inner_ints.size(); if (size > 0) { // Check suitability of the intersection points for (ki=size/2, kj=1, sgn=-1; ki<size && ki>=0; ki+=sgn*kj, kj++, sgn*=-1) { par = inner_ints[ki]; // is_critical = int_results_->inInfluenceArea(pdir, inner_ints[ki]); // if (is_critical == 0 || is_critical == 2) if (par >= ta + del && par <= tb - del) { return 3; } } } // If a singularity exist we use that as a subdivision point. // Iterate for a closest point in which to subdivide if (singularity_info_.get() == 0) { // Make empty singularity info instance singularity_info_ = (shared_ptr<SingularityInfo>)(new SingularityInfo()); } // Check if a closest point exist already double dist = 2*gtol; // At least larger than gtol. if (singularity_info_->hasPoint()) { dist = 0.0; par = singularity_info_->getParam(dir); } else { // Iterate for a closest point double tmin, tmax; doIterate(par, dist, tmin, tmax); if (dist < gtol) { // We also check if the found parameter lies close to the iso-cv of an // existing int_pt in prev_intersector_. shared_ptr<IntersectionPool> prev_pool = prev_intersector_->getIntPool(); vector<shared_ptr<IntersectionPoint> > int_pts; prev_pool->getSortedIntersections(int_pts); Point c_pt; C_->point(c_pt, NULL); double max_knot_dist = epsge_->getEpsge(); //epsge_->getRelParRes(); @@sbr Too large value? for (size_t ki = 0; ki < int_pts.size(); ++ki) { const double* prev_par = int_pts[ki]->getPar1(); if (fabs(prev_par[dir] - par) < max_knot_dist) { // We check if par[dir] is close enough, i.e. within epsge_. Point func_pt; func_int_->point(func_pt, &prev_par[dir]); if (c_pt.dist(func_pt) < epsge_->getEpsge()) { par = prev_par[dir]; } } } singularity_info_->setSingularPoint(&par, 1); std::cout << setprecision(15) << "Singularity: " << par << std::endl; } } if (dist < gtol && par > ta+ptol && par < tb-ptol) { // Check the parameter value vector<shared_ptr<IntersectionPoint> > int_pts; is_critical = int_results_->inInfluenceArea(dir, par); if (is_critical == 0 || is_critical == 2) return 4; } // // Subdivide in the middle // par = 0.5*(ta+tb); // return true; // Subdivide at a suitable parameter double divpar = 0.5*(ta+tb); del = 0.1*(tb-ta); double tint = del; for (ki=0, sgn=-1; ki<9; ki++, divpar+=sgn*tint, tint+=del, sgn*=-1) { is_critical = int_results_->inInfluenceArea(dir, divpar); if (is_critical == 0 || is_critical == 2) { par = divpar; return 5; } } return 0; // No subdivision parameter found }