void EdgeStrip::get_chains(ARRAY<Bvert_list>& chains) const { // Return a list of distinct chains of edges, in the form // of a set of Bvert_lists. chains.clear(); Bvert_list chain; for (int k=0; get_chain(k, chain); ) chains += chain; }
void visit(OctreeNode* node, double regularity, Bface_list& flist, ARRAY<Wvec>& blist) { if (node->get_leaf()) { if (node->get_disp()) { // subdivision ARRAY<QuadtreeNode*> fs; Bface_list temp; for (int i = 0; i < node->intersects().num(); i++) { Bface* f = node->intersects()[i]; temp += f; fs += new QuadtreeNode(f->v1()->loc(), f->v2()->loc(), f->v3()->loc()); fs.last()->build_quadtree(node, regularity); fs.last()->set_terms(); } // assign weights assign_weights(fs, regularity, node->center()); // pick a triangle int t = pick(fs); // moved below; want to ensure flist and blist stay in sync: // flist += temp[t]; //set node face Bface_list ftemp; ftemp += temp[t]; node->set_face(ftemp); // pick a point int p = pick(fs[t]->terms()); if (p != -1) { Wvec bc; temp[t]->project_barycentric(fs[t]->terms()[p]->urand_pick(), bc); blist += bc; flist += temp[t]; // moved from above node->set_point(bc); } for (int i = 0; i < fs.num(); i++) delete fs[i]; fs.clear(); } } else { for (int i = 0; i < 8; i++) visit(node->get_children()[i], regularity, flist, blist); } }
void remove_nodes(Bface_list& flist, ARRAY<Wvec>& blist, double min_dist, ARRAY<OctreeNode*>& t) { // if (flist.num() != blist.num()) { // return; // } assert(flist.num() == blist.num()); Wpt_list pts = get_pts(flist, blist); ARRAY< ARRAY<int> > N; ARRAY<bool> to_remove; for (int i = 0; i < pts.num(); i++) { N += ARRAY<int>(); to_remove += false; } for (int i = 0; i < pts.num(); i++) { for (int j = 0; j < t[i]->neibors().num(); j++) { int index = t[i]->neibors()[j]->get_term_index(); if (index < pts.num()) { if (pts[i].dist(pts[index]) < min_dist) { N[i] += index; N[index] += i; } } else { //cerr << "Sps Warning, index > pts.num()" << endl; } } } priority_queue< Priority, vector<Priority> > queue; ARRAY<int> versions; for (int i = 0; i < pts.num(); i++) { if (!to_remove[i] && !N[i].empty()) { Priority p; p._priority = center(pts, N[i]).dist(pts[i]); p._index = i; p._version = 0; queue.push(p); } versions += 0; } while (!queue.empty()) { Priority p = queue.top(); queue.pop(); int r = p._index; if (p._version == versions[r]) { to_remove[r] = true; for (int i = 0; i < N[r].num(); i++) { N[N[r][i]] -= r; versions[N[r][i]]++; if (!N[N[r][i]].empty()) { Priority q; q._priority = center(pts, N[N[r][i]]).dist(pts[N[r][i]]); q._index = N[r][i]; q._version = versions[N[r][i]]; queue.push(q); } } } } versions.clear(); Bface_list ftemp(flist); ARRAY<Wvec> btemp(blist); flist.clear(); blist.clear(); for (int i = 0; i < ftemp.num(); i++) if (!to_remove[i]) { flist += ftemp[i]; blist += btemp[i]; } }
void LMESH::fit(ARRAY<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; int i; for (i=0; i<verts.num(); i++) box.update(verts[i]->loc()); double max_err = box.dim().length() * 1e-5; int n = verts.num(); // get original control point locations ARRAY<Wpt> C(n); // original control points ARRAY<Wpt> L(n); // current limit points for (i=0; i<n; i++) { C += verts[i]->loc(); L += Wpt::Origin(); } if(debug) { cerr << "LMESH::fit- fitting " << n << " vertices"<<endl; cerr << "Max_err = " << max_err <<endl; } // do 50 iterations... double prev_err = 0; ARRAY<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 (int j=0; j<n; j++) { // don't need that L[] array... Wpt limit; verts[j]->limit_loc(limit); Wvec delt = C[j] - limit; errors+=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 int 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+=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; } } }