inline BBOX bface_bbox(QuadtreeNode* face) { BBOX ret = BBOX(); ret.update(face->v1()); ret.update(face->v2()); ret.update(face->v3()); return ret; }
inline BBOX bface_bbox(Bface* face) { BBOX ret = BBOX(); ret.update(face->v1()->loc()); ret.update(face->v2()->loc()); ret.update(face->v3()->loc()); return ret; }
void LMESH::fit(vector<Lvert*>& verts, bool do_gauss_seidel) { static bool debug = Config::get_var_bool("DEBUG_LMESH_FIT",false); static bool move_along_normal = Config::get_var_bool("FITTING_MOVE_ALONG_NORMAL",false); if (verts.empty()) return; // calculate the bounding box of the vertices BBOX box; size_t i; for (i=0; i<verts.size(); i++) box.update(verts[i]->loc()); double max_err = box.dim().length() * 1e-5; size_t n = verts.size(); // get original control point locations vector<Wpt> C(n); // original control points vector<Wpt> L(n); // current limit points for (i=0; i<n; i++) { C[i] = verts[i]->loc(); L[i] = Wpt::Origin(); } if(debug) { cerr << "LMESH::fit- fitting " << n << " vertices"<<endl; cerr << "Max_err = " << max_err <<endl; } // do 50 iterations... double prev_err = 0; vector<double> errors; for (int k=0; k<50; k++) { errors.clear(); double err = 0; if (do_gauss_seidel) { // Gauss-Seidel iteration: use updated values from the // current iteration as they are computed... for (size_t j=0; j<n; j++) { // don't need that L[] array... Wpt limit; verts[j]->limit_loc(limit); Wvec delt = C[j] - limit; errors.push_back(delt.length()); err += delt.length(); if(move_along_normal) delt = delt*verts[j]->norm()*verts[j]->norm(); verts[j]->offset_loc(delt); } } else { // compute the new offsets from the offsets computed in the // previous iteration size_t j; for (j=0; j<n; j++) verts[j]->limit_loc(L[j]); for (j=0; j<n; j++) { Wvec delt = C[j] - L[j]; err += delt.length(); errors.push_back(delt.length()); if(move_along_normal) delt = delt*verts[j]->norm()*verts[j]->norm(); verts[j]->offset_loc(delt); } } // compute the average error: err /= n; double avg,std_d,max,min; if (debug) { if (prev_err != 0) { err_msg("Iter %d: avg error: %f, reduction: %f", k, err, err/prev_err); statistics(errors,true,&avg,&std_d,&max,&min); } else { err_msg("Iter %d: avg error: %f", k, err); statistics(errors,true,&avg,&std_d,&max,&min); } } else statistics(errors,false,&avg,&std_d,&max,&min); prev_err = err; if (max < max_err) { if(debug) cerr << "Terminating at " << k <<" th iterations"<<endl; return; } } }