00001
00002
00003
00004 #include "disp/ray.H"
00005 #include "disp/colors.H"
00006 #include "geom/world.H"
00007 #include "mlib/statistics.H"
00008 #include "std/config.H"
00009 #include "lpatch.H"
00010
00011 using namespace mlib;
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 LMESH::LMESH(int num_v, int num_e, int num_f) :
00029 BMESH(num_v, num_e, num_f),
00030 _parent_mesh(0),
00031 _cur_mesh(0),
00032 _subdiv_mesh(0),
00033 _subdiv_level(0),
00034 _loc_calc(new HybridLoc),
00035 _color_calc(new LoopColor)
00036 {
00037
00038
00039 _cur_mesh = this;
00040 _lmesh_tags = NULL;
00041 }
00042
00043 LMESH::~LMESH()
00044 {
00045 delete_elements();
00046 delete _loc_calc;
00047 delete _color_calc;
00048 }
00049
00050 void
00051 LMESH::set_subdiv_loc_calc(SubdivLocCalc* c)
00052 {
00053
00054 delete _loc_calc;
00055
00056
00057 _loc_calc = c;
00058
00059
00060
00061 mark_all_dirty();
00062
00063
00064
00065 if (_subdiv_mesh)
00066 _subdiv_mesh->set_subdiv_loc_calc(c->dup());
00067
00068
00069
00070 if (is_control_mesh())
00071 changed(RENDERING_CHANGED);
00072 }
00073
00074 void
00075 LMESH::set_subdiv_color_calc(SubdivColorCalc* c)
00076 {
00077
00078 delete _color_calc;
00079
00080
00081 _color_calc = c;
00082
00083
00084
00085 mark_all_dirty();
00086
00087
00088
00089 if (_subdiv_mesh)
00090 _subdiv_mesh->set_subdiv_color_calc(c->dup());
00091
00092
00093
00094 if (is_control_mesh())
00095 changed(RENDERING_CHANGED);
00096
00097
00098
00099 }
00100
00101 void
00102 LMESH::set_geom(GEOM *geom)
00103 {
00104 BMESH::set_geom(geom);
00105 if (_subdiv_mesh)
00106 _subdiv_mesh->set_geom(geom);
00107 }
00108
00109 int
00110 LMESH::draw(CVIEWptr &v)
00111 {
00112
00113 assert(is_control_mesh());
00114
00115
00116 update();
00117
00118
00119 return BMESH::draw(v);
00120 }
00121
00122 double
00123 LMESH::area() const
00124 {
00125
00126
00127
00128
00129
00130 ((LMESH*)this)->update();
00131
00132 return _cur_mesh->BMESH::area();
00133 }
00134
00135 double
00136 LMESH::volume() const
00137 {
00138
00139
00140
00141
00142
00143 ((LMESH*)this)->update();
00144
00145 return _cur_mesh->BMESH::volume();
00146 }
00147
00148 void
00149 LMESH::clear_creases()
00150 {
00151
00152 int count = 0;
00153 for (int i=0; i<nverts(); i++) {
00154 if (lv(i)->corner_value()) {
00155 lv(i)->set_corner(0);
00156 count++;
00157 }
00158 }
00159 if (count)
00160 changed(RENDERING_CHANGED);
00161
00162 err_msg("LMESH::clear_creases: cleared %d corners", count);
00163
00164
00165 BMESH::clear_creases();
00166 }
00167
00168
00169 Patch*
00170 LMESH::new_patch()
00171 {
00172 Patch* ret = new Lpatch(this);
00173
00174 _patches += ret;
00175 if (is_control_mesh())
00176 _drawables += ret;
00177 return ret;
00178 }
00179
00180
00181 Bedge*
00182 LMESH::new_edge(Bvert* u, Bvert* v) const
00183 {
00184 return new Ledge((Lvert*)u, (Lvert*)v);
00185 }
00186
00187 Bvert*
00188 LMESH::new_vert(CWpt& p) const
00189 {
00190 return new Lvert(p);
00191 }
00192
00193 Bface*
00194 LMESH::new_face(
00195 Bvert* u,
00196 Bvert* v,
00197 Bvert* w,
00198 Bedge* e,
00199 Bedge* f,
00200 Bedge* g) const
00201 {
00202 return new Lface((Lvert*)u, (Lvert*)v, (Lvert*)w,
00203 (Ledge*)e, (Ledge*)f, (Ledge*)g);
00204 }
00205
00206 int
00207 LMESH::remove_vertex(Bvert* bv)
00208 {
00209 assert(bv && bv->mesh() == this);
00210 Lvert* v = (Lvert*)bv;
00211
00212
00213 rem_dirty_vert(v);
00214
00215
00216 v->set_bit(Lvert::DEAD_BIT);
00217
00218 return BMESH::remove_vertex(v);
00219 }
00220
00221 int
00222 LMESH::remove_edge(Bedge* be)
00223 {
00224
00225
00226
00227
00228 assert(be && be->mesh() == this);
00229 Ledge* e = (Ledge*)be;
00230
00231 e->delete_subdiv_elements();
00232 return BMESH::remove_edge(e);
00233 }
00234
00235 int
00236 LMESH::remove_face(Bface* bf)
00237 {
00238
00239
00240
00241
00242 assert(bf && bf->mesh() == this);
00243 Lface* f = (Lface*)bf;
00244
00245 f->delete_subdiv_elements();
00246 return BMESH::remove_face(f);
00247 }
00248
00249 Bvert*
00250 LMESH::add_vertex(Bvert* v)
00251 {
00252 if (BMESH::add_vertex(v))
00253 add_dirty_vert((Lvert*)v);
00254 return v;
00255 }
00256
00257 Bvert*
00258 LMESH::add_vertex(CWpt& p)
00259 {
00260
00261
00262 return BMESH::add_vertex(p);
00263 }
00264
00265 BMESH&
00266 LMESH::operator =(CBMESH& m)
00267 {
00268 return BMESH::operator=(m);
00269 }
00270
00271 BMESH&
00272 LMESH::operator =(CLMESH& m)
00273 {
00274
00275 BMESH::operator=((CBMESH&)m);
00276
00277
00278 for (int k=0; k<nverts(); k++) {
00279 if (m.lv(k)->corner_value() > 0)
00280 lv(k)->set_corner(m.lv(k)->corner_value());
00281 }
00282
00283 return *this;
00284 }
00285
00286 BMESH&
00287 LMESH::operator =(BODY& b)
00288 {
00289 BMESH::operator=(b); return *((BMESH*)this);
00290 }
00291
00292 int
00293 LMESH::write_patches(ostream& os) const
00294 {
00295 return control_mesh()->BMESH::write_patches(os);
00296 }
00297
00298 void
00299 LMESH::changed(change_t change)
00300 {
00301 BMESH::changed(change);
00302
00303
00304
00305
00306 for (LMESH* m = _subdiv_mesh; m; m = m->_subdiv_mesh)
00307 m->BMESH::changed(change);
00308
00309
00310
00311 if (!is_control_mesh())
00312 control_mesh()->BMESH::changed(RENDERING_CHANGED);
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 }
00335
00336 int
00337 LMESH::size() const
00338 {
00339
00340
00341
00342
00343
00344
00345
00346 return (
00347 (nverts() * (sizeof(Lvert) + 6*sizeof(Bedge*) + 4)) +
00348 (nedges() * (sizeof(Ledge) + 4)) +
00349 (nfaces() * (sizeof(Lface) + 8)) +
00350 (npatches() * (sizeof(Lpatch) + 4)) +
00351 sizeof(LMESH)
00352 );
00353 }
00354 void
00355 LMESH::print() const
00356 {
00357 BMESH::print();
00358 err_msg("\tsubdiv level: %d", _subdiv_level);
00359 }
00360
00361 int
00362 LMESH::intersect(
00363 RAYhit &r,
00364 CWtransf &m,
00365 Wpt &nearpt,
00366 Wvec &n,
00367 double &d,
00368 double &d2d,
00369 XYpt &uvc
00370 ) const
00371 {
00372
00373
00374
00375
00376
00377 ((LMESH*)this)->update();
00378
00379 return _cur_mesh->BMESH::intersect(r,m,nearpt,n,d,d2d,uvc);
00380 }
00381
00382 void
00383 LMESH::transform(CWtransf &xform, CMOD& mod)
00384 {
00385
00386 BMESH::transform(xform, mod);
00387
00388
00389
00390
00391
00392
00393
00394
00395 if (_subdiv_mesh)
00396 _subdiv_mesh->transform(xform, mod);
00397 }
00398
00399 void
00400 LMESH::_merge(BMESH* bm)
00401 {
00402
00403
00404
00405
00406 LMESH* m = (LMESH*)bm;
00407
00408
00409
00410
00411 if (_subdiv_mesh && m->_subdiv_mesh)
00412 _subdiv_mesh->_merge(m->_subdiv_mesh);
00413 else
00414 m->delete_subdiv_mesh();
00415
00416
00417
00418 m->_dirty_verts.clear_bits(Lvert::DIRTY_VERT_LIST_BIT);
00419 while (!m->_dirty_verts.empty())
00420 add_dirty_vert((Lvert*)m->_dirty_verts.pop());
00421
00422
00423
00424 BMESH::_merge(bm);
00425 }
00426
00427 const BBOX&
00428 LMESH::get_bb()
00429 {
00430
00431
00432
00433
00434
00435 update();
00436
00437 return _cur_mesh->BMESH::get_bb();
00438 }
00439
00440
00441 inline void
00442 allocate_child_faces(Lface* f)
00443 {
00444 if (f && f->subdiv_dirty())
00445 f->allocate_subdiv_elements();
00446 }
00447
00448
00449 inline void
00450 allocate_adjacent_child_faces(Ledge* e)
00451 {
00452 if (!e) return;
00453
00454 allocate_child_faces(e->lf(1));
00455 allocate_child_faces(e->lf(2));
00456 if (e->is_multi()) {
00457 CBface_list& faces = *e->adj();
00458 for (int i=0; i<faces.num(); i++) {
00459 allocate_child_faces((Lface*)faces[i]);
00460 }
00461 }
00462 }
00463
00464
00465 inline void
00466 update_sub(Ledge* e, bool do_faces=true)
00467 {
00468 if (!e) return;
00469
00470
00471
00472 e->update_subdivision();
00473
00474
00475 if (do_faces) {
00476 allocate_adjacent_child_faces(e);
00477 }
00478 }
00479
00480
00481 inline void
00482 update_sub(Lvert* v, bool do_edges=true)
00483 {
00484 if (!v) return;
00485
00486
00487
00488 v->update_subdivision();
00489
00490
00491 if (do_edges) {
00492 for (int j=0; j<v->degree(); j++)
00493 update_sub(v->le(j));
00494 }
00495 }
00496
00497 bool
00498 LMESH::allocate_subdiv_mesh()
00499 {
00500
00501
00502
00503 if (_subdiv_mesh)
00504 return 1;
00505
00506
00507 _subdiv_mesh = new LMESH(
00508 nverts() + nedges(),
00509 2*nedges() + 3*nfaces(),
00510 4*nfaces()
00511 );
00512
00513 if (!_subdiv_mesh) {
00514
00515 err_ret( "LMESH::allocate_subdiv_mesh: can't allocate subdiv mesh");
00516 return 0;
00517 }
00518
00519
00520 _subdiv_mesh->_type = _type;
00521 _subdiv_mesh->_geom = _geom;
00522 _subdiv_mesh->set_parent(this);
00523 _subdiv_mesh->set_subdiv_loc_calc(_loc_calc->dup());
00524 _subdiv_mesh->set_subdiv_color_calc(_color_calc->dup());
00525
00526
00527 BMESHobs::broadcast_subdiv_gen(this);
00528
00529 return 1;
00530 }
00531
00532 const char*
00533 face_type(Bface* f)
00534 {
00535 if (!f) return "NULL ";
00536 else if (f->is_primary()) return "primary ";
00537 else return "secondary ";
00538 }
00539
00540 inline void
00541 check(Ledge* e)
00542 {
00543 if (!e) {
00544 cerr << "null edge" << endl;
00545 return;
00546 }
00547 if (e->subdiv_mask() == Ledge::REGULAR_SMOOTH_EDGE && e->nfaces() < 2) {
00548 cerr << "bad edge found." << endl;
00549 cerr << " faces: "
00550 << face_type(e->f1())
00551 << face_type(e->f2());
00552 if (e->adj()) {
00553 CBface_list& adj = *e->adj();
00554 for (int i=0; i<adj.num(); i++)
00555 cerr << face_type(adj[i]);
00556 }
00557 cerr << endl;
00558 WORLD::show(e->v1()->loc(), e->v2()->loc());
00559 e->mask_changed();
00560 e->set_mask();
00561 }
00562 }
00563
00564 inline void
00565 debug_check_verts(Cstr_ptr& msg, CBvert_list& verts, CBvert_list& dirty_verts)
00566 {
00567 Bvert_list A = verts.filter(BitSetSimplexFilter(Lvert::DIRTY_VERT_LIST_BIT));
00568 if (!dirty_verts.contains_all(A)) {
00569 Bvert_list bad = A.minus(dirty_verts);
00570 cerr << msg << ": found " << bad.num()
00571 << " vertices missing from dirty list" << endl;
00572 WORLD::show_pts(bad.pts(), 8, Color::red);
00573 }
00574 Bvert_list B = verts.filter(BitClearSimplexFilter(Lvert::DIRTY_VERT_LIST_BIT));
00575 if (dirty_verts.contains_any(B)) {
00576 Bvert_list bad = dirty_verts.minus(B);
00577 cerr << msg << ": found " << bad.num()
00578 << " unexpected vertices in dirty list" << endl;
00579 WORLD::show_pts(bad.pts(), 8, Color::blue);
00580 }
00581 }
00582
00583 inline str_ptr
00584 get_name(LMESH* m)
00585 {
00586 return (m && m->geom()) ? m->geom()->name() :
00587 (m ? "null geom" : "null mesh");
00588 }
00589
00590 bool
00591 LMESH::update_subdivision(int level)
00592 {
00593
00594
00595
00596
00597
00598
00599
00600
00601 bool ret = !_dirty_verts.empty();
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612 BMESHobs::broadcast_update_request(this);
00613
00614
00615
00616 if (level <= 0 || !allocate_subdiv_mesh()) {
00617 if (cur_mesh() == this)
00618 return false;
00619 control_mesh()->set_cur_mesh(this);
00620 return true;
00621 }
00622
00623
00624 static bool debug = Config::get_var_bool("DEBUG_SUBDIVISION",false);
00625 static uint fnum = 0;
00626 if (debug && ret) {
00627 if (fnum != VIEW::stamp()) {
00628 fnum = VIEW::stamp();
00629 cerr << "******** frame " << fnum << " ********" << endl;
00630 }
00631 if (level > 0 && ret) {
00632 err_adv(debug, "%s: level %d updating subdiv mesh",
00633 **get_name(this), _subdiv_level);
00634 }
00635 }
00636 err_adv(ret && debug,
00637 "level %d to level %d: %d faces, updating %d of %d vertices using %s",
00638 subdiv_level(),
00639 level,
00640 _faces.num(),
00641 _dirty_verts.num(),
00642 _verts.num(),
00643 **_loc_calc->name());
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 if (debug && ret) {
00658 err_adv(0, "level %d: %d faces, updating %d of %d vertices using %s",
00659 subdiv_level(),
00660 _faces.num(),
00661 _dirty_verts.num(),
00662 _verts.num(),
00663 **_loc_calc->name());
00664 debug_check_verts(" before", _verts, _dirty_verts);
00665 }
00666 while (!_dirty_verts.empty()) {
00667 Lvert* v = (Lvert*)_dirty_verts.pop();
00668 v->clear_bit(Lvert::DIRTY_VERT_LIST_BIT);
00669
00670 update_sub(v);
00671 }
00672 if (debug && ret) {
00673 debug_check_verts(" after", _verts, _dirty_verts);
00674 }
00675
00676 if (0 && ret && debug)
00677 _subdiv_mesh->print();
00678
00679 ret = _subdiv_mesh->update_subdivision(level-1) || ret;
00680
00681 if (ret && is_control_mesh())
00682 changed(RENDERING_CHANGED);
00683 return ret;
00684 }
00685
00686 inline void
00687 update_verts(CBvert_list& verts)
00688 {
00689
00690 for (int i=0; i<verts.num(); i++)
00691 ((Lvert*)verts[i])->update_subdivision();
00692 }
00693
00694 inline void
00695 update_edges(CBedge_list& edges)
00696 {
00697
00698 for (int i=0; i<edges.num(); i++)
00699 ((Ledge*)edges[i])->update_subdivision();
00700 }
00701
00702 inline void
00703 update_faces(CBface_list& faces, bool debug)
00704 {
00705
00706
00707 err_adv(debug, "updating verts");
00708 update_verts(faces.get_verts());
00709
00710 err_adv(debug, "updating edges");
00711 update_edges(faces.get_edges());
00712
00713 err_adv(debug, "updating faces");
00714 for (int i=0; i<faces.num(); i++)
00715 allocate_child_faces((Lface*)faces[i]);
00716 }
00717
00718 bool
00719 LMESH::update_subdivision(CBface_list& faces, int k)
00720 {
00721 static bool debug = Config::get_var_bool("DEBUG_BFACE_LIST_SUBDIVISION",false);
00722
00723 if (debug) {
00724 cerr << "LMESH::update_subdivision: " << faces.num()
00725 << " faces to level "<< k << endl;
00726 }
00727
00728 if (k < 0)
00729 return false;
00730
00731 if (faces.empty())
00732 return true;
00733
00734 LMESH* m = LMESH::upcast(faces.mesh());
00735 if (!m) {
00736 err_adv(debug, " error: non-LMESH");
00737 return false;
00738 }
00739
00740
00741 BMESHobs::broadcast_update_request(m);
00742
00743 if (k == 0)
00744 return true;
00745
00746
00747 if (!m->allocate_subdiv_mesh()) {
00748 err_adv(debug, " error: can't allocate subdiv mesh");
00749 return false;
00750 }
00751
00752
00753 update_faces(faces.one_ring_faces(), debug);
00754 update_faces(faces.secondary_faces(), debug);
00755
00756 assert(m->subdiv_mesh());
00757 m->subdiv_mesh()->changed(VERT_POSITIONS_CHANGED);
00758
00759
00760 return update_subdivision(get_subdiv_faces(faces,1), k-1);
00761 }
00762
00763 void
00764 LMESH::subdivide_in_place()
00765 {
00766 if (is_control_mesh()) {
00767
00768
00769 refine();
00770
00771
00772
00773 LMESHptr sub = new LMESH;
00774 *sub = *_subdiv_mesh;
00775
00776
00777
00778 *this = *sub;
00779 } else
00780 err_msg("LMESH::subdivide_in_place: error: this not control mesh");
00781 }
00782
00783 void
00784 LMESH::delete_subdiv_mesh()
00785 {
00786
00787 BMESHobs::broadcast_sub_delete(this);
00788
00789 if (is_control_mesh() && _subdiv_mesh) {
00790 int k;
00791 for (k = 0; k < nfaces(); k++)
00792 lf(k)->delete_subdiv_elements();
00793 for(k = 0; k < nedges(); k++)
00794 le(k)->delete_subdiv_elements();
00795 for(k = 0; k < nverts(); k++)
00796 lv(k)->delete_subdiv_vert();
00797 for(k = 0; k < _patches.num(); k++)
00798 ((Lpatch*)_patches[k])->clear_subdiv_strips(1);
00799 }
00800 if (is_control_mesh())
00801 set_cur_mesh(this);
00802 _subdiv_mesh = 0;
00803 }
00804
00805 void
00806 LMESH::delete_elements()
00807 {
00808 delete_subdiv_mesh();
00809 BMESH::delete_elements();
00810 }
00811
00812 void
00813 LMESH::set_cur_mesh(LMESH* cur)
00814 {
00815 if (is_control_mesh()) {
00816 if (_cur_mesh != cur) {
00817 bool coi = is_center_of_interest(_cur_mesh);
00818 _cur_mesh = cur;
00819 if (coi)
00820 set_center_of_interest(_cur_mesh);
00821 changed(RENDERING_CHANGED);
00822 }
00823 } else
00824 err_msg("LMESH::set_cur_mesh: error: called on non-control mesh");
00825 }
00826
00827 void
00828 LMESH::refine()
00829 {
00830
00831
00832
00833
00834
00835 if (!is_control_mesh())
00836 return;
00837
00838 if (is_control_mesh()) {
00839
00840 int new_level = _cur_mesh->subdiv_level() + 1;
00841
00842
00843 update_subdivision(new_level);
00844 }
00845 }
00846
00847 void
00848 LMESH::unrefine()
00849 {
00850 if (is_control_mesh() && _cur_mesh != this) {
00851 set_cur_mesh(_cur_mesh->_parent_mesh);
00852 while (edit_level() > cur_level())
00853 dec_edit_level();
00854 }
00855 }
00856
00857 void
00858 LMESH::inc_edit_level()
00859 {
00860 int prev_edit_level = edit_level();
00861
00862 control_mesh()->BMESH::inc_edit_level();
00863 if (is_control_mesh() && cur_level() < edit_level())
00864 update_subdivision(edit_level());
00865 else
00866 control_mesh()->changed(RENDERING_CHANGED);
00867
00868 MeshGlobal::edit_level_changed(control_mesh(),
00869 prev_edit_level,
00870 control_mesh()->edit_level());
00871 }
00872
00873 void
00874 LMESH::dec_edit_level()
00875 {
00876 int prev_edit_level = edit_level();
00877
00878 control_mesh()->BMESH::dec_edit_level();
00879 control_mesh()->changed(RENDERING_CHANGED);
00880
00881 MeshGlobal::edit_level_changed(control_mesh(),
00882 prev_edit_level,
00883 control_mesh()->edit_level());
00884 }
00885
00886 bool
00887 LMESH::set_edit_level(int level)
00888 {
00889
00890
00891
00892
00893 while (level > edit_level())
00894 control_mesh()->inc_edit_level();
00895 while (level < edit_level())
00896 control_mesh()->dec_edit_level();
00897
00898 return true;
00899 }
00900
00901 void
00902 LMESH::mark_all_dirty()
00903 {
00904 int i;
00905 for (i=0; i<nverts(); i++)
00906 lv(i)->mark_dirty(Lvert::SUBDIV_LOC_VALID_BIT);
00907 for (i=0; i<nedges(); i++)
00908 le(i)->clear_bit(Ledge::SUBDIV_LOC_VALID_BIT);
00909 if (_subdiv_mesh)
00910 _subdiv_mesh->mark_all_dirty();
00911 }
00912
00913 void
00914 LMESH::fit(ARRAY<Lvert*>& verts, bool do_gauss_seidel)
00915 {
00916 static bool debug = Config::get_var_bool("DEBUG_LMESH_FIT",false);
00917 static bool move_along_normal =
00918 Config::get_var_bool("FITTING_MOVE_ALONG_NORMAL",false);
00919
00920 if (verts.empty())
00921 return;
00922
00923
00924 BBOX box;
00925 int i;
00926 for (i=0; i<verts.num(); i++)
00927 box.update(verts[i]->loc());
00928
00929 double max_err = box.dim().length() * 1e-5;
00930
00931 int n = verts.num();
00932
00933
00934 ARRAY<Wpt> C(n);
00935 ARRAY<Wpt> L(n);
00936 for (i=0; i<n; i++) {
00937 C += verts[i]->loc();
00938 L += Wpt::Origin();
00939 }
00940
00941 if(debug) {
00942 cerr << "LMESH::fit- fitting " << n << " vertices"<<endl;
00943 cerr << "Max_err = " << max_err <<endl;
00944 }
00945
00946
00947 double prev_err = 0;
00948 ARRAY<double> errors;
00949 for (int k=0; k<50; k++) {
00950
00951 errors.clear();
00952
00953 double err = 0;
00954
00955 if (do_gauss_seidel) {
00956
00957
00958
00959 for (int j=0; j<n; j++) {
00960
00961 Wpt limit;
00962 verts[j]->limit_loc(limit);
00963 Wvec delt = C[j] - limit;
00964 errors+=delt.length();
00965 err += delt.length();
00966 if(move_along_normal)
00967 delt = delt*verts[j]->norm()*verts[j]->norm();
00968 verts[j]->offset_loc(delt);
00969 }
00970
00971 } else {
00972
00973
00974 int j;
00975 for (j=0; j<n; j++)
00976 verts[j]->limit_loc(L[j]);
00977
00978 for (j=0; j<n; j++) {
00979 Wvec delt = C[j] - L[j];
00980
00981 err += delt.length();
00982 errors+=delt.length();
00983 if(move_along_normal)
00984 delt = delt*verts[j]->norm()*verts[j]->norm();
00985 verts[j]->offset_loc(delt);
00986 }
00987 }
00988
00989 err /= n;
00990
00991 double avg,std_d,max,min;
00992 if (debug) {
00993 if (prev_err != 0) {
00994 err_msg("Iter %d: avg error: %f, reduction: %f",
00995 k, err, err/prev_err);
00996 statistics(errors,true,&avg,&std_d,&max,&min);
00997 } else {
00998 err_msg("Iter %d: avg error: %f", k, err);
00999 statistics(errors,true,&avg,&std_d,&max,&min);
01000 }
01001 } else
01002 statistics(errors,false,&avg,&std_d,&max,&min);
01003
01004 prev_err = err;
01005
01006 if (max < max_err) {
01007 if(debug) cerr << "Terminating at " << k <<" th iterations"<<endl;
01008 return;
01009 }
01010 }
01011 }
01012
01013 inline void
01014 add_p(Lvert* v, Bvert_list& vp, Bedge_list& ep)
01015 {
01016
01017
01018
01019
01020
01021 assert(v);
01022
01023 Bsimplex* p = v->parent();
01024 if (!p)
01025 return;
01026 if (is_vert(p))
01027 vp += (Bvert*)p;
01028 else if (is_edge(p))
01029 ep += (Bedge*)p;
01030 else
01031 assert(0);
01032 }
01033
01034 inline void
01035 get_parents(CBvert_list& verts, Bvert_list& vp, Bedge_list& ep)
01036 {
01037
01038
01039
01040
01041 if (verts.empty())
01042 return;
01043
01044 assert(LMESH::isa(verts.mesh()));
01045
01046 for (int i=0; i<verts.num(); i++)
01047 add_p((Lvert*)verts[i], vp, ep);
01048 }
01049
01050 inline void
01051 clear_face_flags(CBvert_list& verts)
01052 {
01053
01054
01055
01056
01057
01058 Bface_list star;
01059 for (int i=0; i<verts.num(); i++) {
01060 verts[i]->get_q_faces(star);
01061 star.clear_flags();
01062 }
01063 }
01064
01065 inline void
01066 try_append(Bface_list& A, Bface* f)
01067 {
01068
01069
01070 if (f && !f->flag()) {
01071 f->set_flag();
01072 A += f;
01073 }
01074 }
01075
01076 inline void
01077 try_append(Bface_list& A, CBface_list& B)
01078 {
01079
01080
01081
01082
01083
01084 for (int i=0; i<B.num(); i++)
01085 try_append(A, B[i]);
01086 }
01087
01088 inline Bface_list
01089 get_q_faces(CBvert_list& verts)
01090 {
01091
01092
01093
01094
01095
01096 Bface_list ret, star;
01097 for (int i=0; i<verts.num(); i++) {
01098 verts[i]->get_q_faces(star);
01099 try_append(ret, star);
01100 }
01101 return ret;
01102 }
01103
01104 Bvert_list
01105 LMESH::get_subdiv_inputs(CBvert_list& verts)
01106 {
01107 static bool debug = Config::get_var_bool("DEBUG_LMESH_SUBDIV_INPUTS",false);
01108
01109
01110
01111
01112
01113
01114
01115
01116 if (!isa(verts.mesh()))
01117 return Bvert_list();
01118
01119
01120 Bvert_list vp;
01121 Bedge_list ep;
01122 get_parents(verts, vp, ep);
01123
01124 err_adv(debug, "%d verts: parents: %d verts, %d edges",
01125 verts.num(), vp.num(), ep.num());
01126
01127
01128 clear_face_flags(vp);
01129 ep.clear_flag02();
01130
01131
01132 Bface_list faces = get_q_faces(vp);
01133 err_adv(debug, "parent faces from verts: %d", faces.num());
01134 try_append(faces, ep.get_primary_faces());
01135 err_adv(debug, "parent faces from edges too: %d", faces.num());
01136
01137
01138 return faces.get_verts();
01139 }
01140
01141 void
01142 LMESH::send_update_notification()
01143 {
01144
01145
01146 BMESH::send_update_notification();
01147
01148
01149
01150 update();
01151 }
01152
01153 inline LMESHptr
01154 bmesh_to_lmesh(BMESHptr mesh)
01155 {
01156
01157
01158
01159
01160 if (!mesh) return 0;
01161 LMESHptr ret = LMESH::upcast(&*mesh);
01162 if (!ret) {
01163 ret = new LMESH;
01164 *ret = *mesh;
01165 }
01166 return ret;
01167 }
01168
01169 LMESHptr
01170 LMESH::read_jot_stream(istream& in)
01171 {
01172
01173
01174
01175 return bmesh_to_lmesh(BMESH::read_jot_stream(in));
01176 }
01177
01178 LMESHptr
01179 LMESH::read_jot_file(char* filename)
01180 {
01181
01182
01183
01184 return bmesh_to_lmesh(BMESH::read_jot_file(filename));
01185 }
01186
01187 CTAGlist &
01188 LMESH::tags() const
01189 {
01190 return BMESH::tags();
01191 }
01192
01193