00001
00002
00003
00004
00005 #include "sps.H"
00006 #include <queue>
00007
00008 static bool debug = Config::get_var_bool("DEBUG_SPS",false);
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 void
00023 generate_samples(BMESHptr mesh,
00024 Bface_list& flist,
00025 ARRAY<Wvec>& blist,
00026 int height, double min_dist, double regularity)
00027 {
00028 Bvert_list verts;
00029 OctreeNode* n = sps(mesh, height, regularity, min_dist, flist, blist);
00030 delete n;
00031 }
00032
00033
00034
00035
00036 void
00037 generate_samples(BMESHptr mesh, double min_spacing,
00038 Bface_list& flist, ARRAY<Wvec>& blist)
00039 {
00040 flist.clear(); blist.clear();
00041 int height = 6;
00042 double regularity = 20;
00043
00044 clock_t start, end;
00045 double duration;
00046
00047 BBOX box = mesh->get_bb();
00048 OctreeNode* root = new OctreeNode(box.min(), box.max(), 1, NULL);
00049 if (height == 1) {
00050 root->set_leaf(true);
00051 root->set_disp(true);
00052 }
00053 root->intersects() = (mesh->faces());
00054
00055 start = clock();
00056 root->build_octree(height);
00057 end = clock();
00058 duration = (double)(end - start) / CLOCKS_PER_SEC;
00059 err_adv(debug, "step 1 time: %f", duration);
00060
00061 start = clock();
00062 visit(root, regularity, flist, blist);
00063 end = clock();
00064 duration = (double)(end - start) / CLOCKS_PER_SEC;
00065 err_adv(debug, "step 2 time: %f", duration);
00066
00067
00068 start = clock();
00069 root->set_neibors();
00070 root->set_terms();
00071 remove_nodes(flist, blist, min_spacing, root->terms());
00072 end = clock();
00073 duration = (double)(end - start) / CLOCKS_PER_SEC;
00074 err_adv(debug, "step 3 time: %f", duration);
00075 err_adv(debug, "no of points: %d", flist.num());
00076
00077 delete root;
00078 }
00079
00080 OctreeNode*
00081 sps(BMESHptr mesh, int height, double regularity, double min_dist,
00082 Bface_list& flist, ARRAY<Wvec>& blist)
00083 {
00084 clock_t start, end;
00085 double duration;
00086 flist.clear(); blist.clear();
00087
00088 BBOX box = mesh->get_bb();
00089 OctreeNode* root = new OctreeNode(box.min(), box.max(), 1, NULL);
00090 if (height == 1) {
00091 root->set_leaf(true);
00092 root->set_disp(true);
00093 }
00094 root->intersects() = (mesh->faces());
00095
00096
00097
00098 start = clock();
00099 root->build_octree(height);
00100 end = clock();
00101
00102 duration = (double)(end - start) / CLOCKS_PER_SEC;
00103 err_adv(debug, "step 1 time: %f", duration);
00104
00105 start = clock();
00106 visit(root, regularity, flist, blist);
00107 end = clock();
00108 duration = (double)(end - start) / CLOCKS_PER_SEC;
00109 err_adv(debug, "step 2 time: %f", duration);
00110
00111
00112 start = clock();
00113 double dist = min_dist * box.dim().length() / (1<<(height-1));
00114
00115 root->set_neibors();
00116
00117 root->set_terms();
00118
00119 remove_nodes(flist, blist, dist, root->terms());
00120 end = clock();
00121 duration = (double)(end - start) / CLOCKS_PER_SEC;
00122 err_adv(debug, "step 3 time: %f", duration);
00123 err_adv(debug, "no of points: %d", flist.num());
00124
00125 return root;
00126 }
00127
00128 inline
00129 Wpt
00130 center (Wpt_list& pts, ARRAY<int>& N)
00131 {
00132 Wpt ret = Wpt(0);
00133 for (int i = 0; i < N.num(); i++) {
00134 ret += pts[N[i]];
00135 }
00136 return ret / N.num();
00137 }
00138
00139 class Priority{
00140 public:
00141
00142 bool operator< (const Priority& other) const { return _priority < other._priority;};
00143 int _index;
00144 double _priority;
00145 int _version;
00146 };
00147
00148 inline Wpt_list
00149 get_pts(Bface_list& flist, ARRAY<Wvec>& blist)
00150 {
00151 assert(flist.num() == blist.num());
00152 Wpt_list pts;
00153 for (int i = 0; i < flist.num(); i++) {
00154 Wpt pt;
00155 flist[i]->bc2pos(blist[i], pt);
00156 pts += pt;
00157 }
00158 return pts;
00159 }
00160
00161 void
00162 remove_nodes(Bface_list& flist, ARRAY<Wvec>& blist, double min_dist, ARRAY<OctreeNode*>& t)
00163 {
00164 assert(flist.num() == blist.num());
00165 Wpt_list pts = get_pts(flist, blist);
00166 ARRAY< ARRAY<int> > N;
00167 ARRAY<bool> to_remove;
00168 for (int i = 0; i < pts.num(); i++) {
00169 N += ARRAY<int>();
00170 to_remove += false;
00171 }
00172
00173 clock_t start;
00174
00175 for (int i = 0; i < pts.num(); i++) {
00176 for (int j = 0; j < t[i]->neibors().num(); j++) {
00177 int index = t[i]->neibors()[j]->get_term_index();
00178 if (pts[i].dist(pts[index]) < min_dist) {
00179 N[i] += index;
00180 N[index] += i;
00181 }
00182 }
00183 }
00184
00185 start = clock();
00186 priority_queue< Priority, vector<Priority> > queue;
00187 ARRAY<int> versions;
00188 for (int i = 0; i < pts.num(); i++) {
00189 if (!to_remove[i] && !N[i].empty()) {
00190 Priority p;
00191 p._priority = center(pts, N[i]).dist(pts[i]);
00192 p._index = i;
00193 p._version = 0;
00194 queue.push(p);
00195 }
00196 versions += 0;
00197 }
00198
00199 while (!queue.empty()) {
00200 Priority p = queue.top();
00201 queue.pop();
00202 int r = p._index;
00203 if (p._version == versions[r]) {
00204 to_remove[r] = true;
00205 for (int i = 0; i < N[r].num(); i++) {
00206 N[N[r][i]] -= r;
00207 versions[N[r][i]]++;
00208 if (!N[N[r][i]].empty()) {
00209 Priority q;
00210 q._priority = center(pts, N[N[r][i]]).dist(pts[N[r][i]]);
00211 q._index = N[r][i];
00212 q._version = versions[N[r][i]];
00213 queue.push(q);
00214 }
00215 }
00216 }
00217 }
00218 versions.clear();
00219
00220 Bface_list ftemp(flist);
00221 ARRAY<Wvec> btemp(blist);
00222 flist.clear();
00223 blist.clear();
00224 for (int i = 0; i < ftemp.num(); i++)
00225 if (!to_remove[i]) {
00226 flist += ftemp[i];
00227 blist += btemp[i];
00228 }
00229 }
00230
00231 inline
00232 double
00233 distr_func (double r, double d)
00234 {
00235 const double E = 2.71828183;
00236 return r * powf(E, -(float)r * (float)d);
00237 }
00238
00239
00240
00241 inline
00242 float dorand() {
00243 return double(rand()) / (RAND_MAX);
00244 }
00245
00246 inline
00247 int
00248 pick (ARRAY<QuadtreeNode*>& l)
00249 {
00250 int ret = -1;
00251 double total_w = 0.0;
00252 for (int i = 0; i < l.num(); i++) {
00253 total_w += l[i]->get_weight();
00254 }
00255 double r = dorand() * total_w;
00256
00257 total_w = 0.0;
00258 for (int i = 0; i < l.num(); i++) {
00259 total_w += l[i]->get_weight();
00260 if (total_w >= r) {
00261 ret = i;
00262 break;
00263 }
00264 }
00265 return ret;
00266 }
00267
00268 void
00269 assign_weights(ARRAY<QuadtreeNode*>& fs, double regularity, CWpt& pt)
00270 {
00271 double weight, d;
00272 QuadtreeNode* leaf;
00273 for (int i = 0; i < fs.num(); i++) {
00274 weight = 0.0;
00275 for (int j = 0; j < fs[i]->terms().num(); j++) {
00276 leaf = fs[i]->terms()[j];
00277 d = pt.dist(leaf->centroid());
00278 leaf->set_weight(distr_func(regularity, d) * leaf->area());
00279 weight += leaf->get_weight();
00280 }
00281 fs[i]->set_weight(weight);
00282 }
00283 }
00284
00285 void
00286 visit(OctreeNode* node,
00287 double regularity, Bface_list& flist, ARRAY<Wvec>& blist)
00288 {
00289 if (node->get_leaf()) {
00290 if (node->get_disp()) {
00291
00292 ARRAY<QuadtreeNode*> fs;
00293 Bface_list temp;
00294 for (int i = 0; i < node->intersects().num(); i++) {
00295 Bface* f = node->intersects()[i];
00296 temp += f;
00297 fs += new QuadtreeNode(f->v1()->loc(), f->v2()->loc(), f->v3()->loc());
00298 fs.last()->build_quadtree(node, regularity);
00299 fs.last()->set_terms();
00300 }
00301
00302
00303 assign_weights(fs, regularity, node->center());
00304
00305
00306 int t = pick(fs);
00307 flist += temp[t];
00308
00309
00310 int p = pick(fs[t]->terms());
00311 if (p != -1) {
00312 Wvec bc;
00313 temp[t]->project_barycentric(fs[t]->terms()[p]->urand_pick(), bc);
00314 blist += bc;
00315 }
00316
00317 for (int i = 0; i < fs.num(); i++)
00318 delete fs[i];
00319 fs.clear();
00320 }
00321 } else {
00322 for (int i = 0; i < 8; i++)
00323 visit(node->get_children()[i], regularity, flist, blist);
00324 }
00325 }
00326
00327 void
00328 OctreeNode::set_neibors()
00329 {
00330 OctreeNode* n;
00331 BBOX test_box = BBOX(min()-0.5*dim(), max()+0.5*dim());
00332
00333 if ((!_leaf || _display) && _height != 1) {
00334 for (int i = 0; i < 8; i++) {
00335 n = _parent->get_children()[i];
00336 if (n != this && (!n->get_leaf() || n->get_disp())) {
00337 _neibors += n;
00338 }
00339 }
00340
00341 _parent->neibors().num();
00342
00343 for (int i = 0; i < _parent->neibors().num(); i++) {
00344 n = _parent->neibors()[i];
00345 if (!n->get_leaf()) {
00346 for (int j = 0; j < 8; j++) {
00347 if (n->get_children()[j]->overlaps(test_box) &&
00348 (!n->get_children()[j]->get_leaf() ||
00349 n->get_children()[j]->get_disp())) {
00350
00351 _neibors += n->get_children()[j];
00352 }
00353 }
00354 }
00355 }
00356
00357 }
00358
00359 if (!_leaf) {
00360 for (int i = 0; i < 8; i++) {
00361 _children[i]->set_neibors();
00362 }
00363 }
00364 }
00365
00366 void
00367 OctreeNode::set_terms(ARRAY<OctreeNode*>& terms, int& count)
00368 {
00369 if (_leaf) {
00370 if (_display) {
00371 terms += this;
00372 _term_index = count;
00373 count++;
00374 }
00375 } else {
00376 for (int i = 0; i < 8; i++)
00377 _children[i]->set_terms(terms, count);
00378 }
00379 }
00380
00381 void
00382 OctreeNode::set_terms()
00383 {
00384 _terms.clear();
00385 int count = 0;
00386 set_terms(_terms, count);
00387 }
00388
00389 void
00390 QuadtreeNode::set_terms(ARRAY<QuadtreeNode*>& terms)
00391 {
00392 if (_leaf) {
00393 if (_in_cell) {
00394 terms += this;
00395 }
00396 } else {
00397 for (int i = 0; i < 4; i++)
00398 _children[i]->set_terms(terms);
00399 }
00400 }
00401
00402 void
00403 QuadtreeNode::set_terms()
00404 {
00405 _terms.clear();
00406 set_terms(_terms);
00407 }
00408
00409 inline
00410 BBOX
00411 bface_bbox(QuadtreeNode* face)
00412 {
00413 BBOX ret = BBOX();
00414 ret.update(face->v1());
00415 ret.update(face->v2());
00416 ret.update(face->v3());
00417 return ret;
00418 }
00419
00420 inline
00421 BBOX
00422 bface_bbox(Bface* face)
00423 {
00424 BBOX ret = BBOX();
00425 ret.update(face->v1()->loc());
00426 ret.update(face->v2()->loc());
00427 ret.update(face->v3()->loc());
00428 return ret;
00429 }
00430
00431 void
00432 OctreeNode::build_octree(int height)
00433 {
00434
00435 if (_leaf || _height == height)
00436 return;
00437
00438 int i, j;
00439 Wpt_list pts;
00440 points(pts);
00441
00442 for (i = 0; i < 8; i++) {
00443 _children[i] = new OctreeNode((pts[0]+pts[i])/2, (pts[i]+pts[7])/2,
00444 _height+1, this);
00445 }
00446
00447 for (j = 0; j < _intersects.num(); j++) {
00448 Bface* f = _intersects[j];
00449
00450 for (i = 0; i < 8; i++) {
00451 OctreeNode* n = _children[i];
00452 if (n->contains(f->v1()->loc()) && n->contains(f->v2()->loc())
00453 && n->contains(f->v3()->loc())) {
00454 n->intersects() += f;
00455 break;
00456 } else if (n->overlaps(bface_bbox(f))) {
00457 n->intersects() += f;
00458 }
00459 }
00460 }
00461
00462 for (i = 0; i < 8; i++) {
00463 if (_height+1 == height) {
00464 _children[i]->set_leaf(true);
00465 _children[i]->set_disp(true);
00466 }
00467 if (_children[i]->intersects().empty()) {
00468 _children[i]->set_leaf(true);
00469 _children[i]->set_disp(false);
00470 }
00471 _children[i]->build_octree(height);
00472 }
00473
00474 }
00475
00476 void
00477 QuadtreeNode::subdivide(OctreeNode* o, double regularity)
00478 {
00479
00480 Wpt v4 = (_v1+_v2)/2;
00481 Wpt v5 = (_v2+_v3)/2;
00482 Wpt v6 = (_v3+_v1)/2;
00483 _children[0] = new QuadtreeNode(_v1, v4, v6);
00484 _children[0]->build_quadtree(o, regularity);
00485 _children[1] = new QuadtreeNode(v4, _v2, v5);
00486 _children[1]->build_quadtree(o, regularity);
00487 _children[2] = new QuadtreeNode(v6, v5, _v3);
00488 _children[2]->build_quadtree(o, regularity);
00489 _children[3] = new QuadtreeNode(v4, v5, v6);
00490 _children[3]->build_quadtree(o, regularity);
00491 }
00492
00493 void
00494 QuadtreeNode::build_quadtree(OctreeNode* o, double regularity)
00495 {
00496
00497 const double THRED_EDGE = 0.3 * o->dim().length();
00498
00499 if (!(o->contains(_v1) && o->contains(_v2))
00500 && o->contains(_v3)) {
00501 if (max(max(_v1.dist(_v2), _v2.dist(_v3)), _v3.dist(_v1))
00502 < THRED_EDGE || !o->overlaps(bface_bbox(this))) {
00503 _leaf = true;
00504 _in_cell = false;
00505 return;
00506 }
00507 }
00508
00509 if (area() < o->get_area()/20) {
00510 _leaf = true;
00511 return;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 subdivide(o, regularity);
00524 }
00525
00526 Wpt
00527 QuadtreeNode::nearest_pt(Wpt& p)
00528 {
00529 Wvec bc;
00530 bool on;
00531 Bvert* v1 = new Bvert(_v1);
00532 Bvert* v2 = new Bvert(_v2);
00533 Bvert* v3 = new Bvert(_v3);
00534 Bface f(v1, v2, v3, new Bedge(v1, v2), new Bedge(v2, v3), new Bedge(v3, v1));
00535 return f.nearest_pt(p, bc, on);
00536 }
00537
00538 Wpt
00539 QuadtreeNode::farthest_pt(Wpt& p)
00540 {
00541 Wpt ret = _v1;
00542 double max_dist = ret.dist(p);
00543 if (_v2.dist(p) > max_dist) {
00544 ret = _v2;
00545 max_dist = ret.dist(p);
00546 }
00547 if (_v3.dist(p) > max_dist) {
00548 ret = _v3;
00549 }
00550 return ret;
00551 }
00552
00553 Wpt
00554 QuadtreeNode::urand_pick()
00555 {
00556 Wvec vec1 = _v2 - _v1;
00557 Wvec vec2 = _v3 - _v1;
00558 double d1 = dorand(), d2 = dorand();
00559 Wpt pt = _v1 + d1 * vec1 + d2 * vec2;
00560 if (!contains(pt, 0.1))
00561 pt = (_v2 + _v3) + (-pt);
00562 return pt;
00563 }
00564
00565