00001
00008 #ifdef HAVE_CONFIG_H
00009 #include <tumble-conf.h>
00010 #endif
00011
00012 #include <cassert>
00013 #include <cstdio>
00014 #include <cstdlib>
00015 #include <fstream>
00016 #include <iostream>
00017 #include <limits>
00018 #include <stack>
00019
00020 #include "beziermesh.h"
00021
00022 #include "boundarymesh.h"
00023 #include "datastore.h"
00024 #include "fibonacci_heap.h"
00025 #include "hash_map.h"
00026 #include "spline.h"
00027
00028 #include "sqpsmooth.h"
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #define VISUAL_DEBUG
00052
00053
00054
00055
00056 #ifdef DEBUG
00057 #include "meshio.h"
00058
00059
00060 #define DEBUG_INSERTS
00061
00062
00063
00064
00065 #ifdef CHECK_SMOOTH
00066
00067 #define DEBUG_SMOOTH
00068 #endif
00069 #ifdef CHECK_FLIP
00070
00071 #define DEBUG_FLIP
00072
00073
00074 #define DEBUG_DEVILLERS
00075 #endif
00076 #endif
00077
00078
00079 #if defined(DEBUG_SMOOTH) || defined(DEBUG_FLIP)
00080 #include "meshio.h"
00081 #endif
00082
00083 #ifdef VISUAL_DEBUG
00084 #include "visualization.h"
00085
00086 #ifdef DEBUG_SMOOTH
00087
00088 #define DRAW_SMOOTH
00089 #endif
00090
00091 #ifdef DEBUG_FLIP
00092
00093 #define DRAW_FLIP
00094 #endif
00095 #endif
00096
00097
00098 using namespace std;
00099 using namespace hashers;
00100 using namespace Tumble;
00101
00102 BezierMesh::BezierMesh(PersistantStore& pstore, DataStore *dstore)
00103 : BezierComplex(pstore)
00104 , boundarymesh(NULL), datastore(dstore)
00105 , linear_flips(false), func_angle_x_cuttoff(-1.0)
00106 {
00107 }
00108
00109 void BezierMesh::set_bdry_mesh(BoundaryMesh* bdry) {
00110 assert(!boundarymesh);
00111 boundarymesh = bdry;
00112 }
00113
00114 BezierMesh::~BezierMesh() {
00115 }
00116
00122 BezierVertex* BezierMesh::add_bezier_vertex( const Point2D &_p)
00123 {
00124 LinearData _d;
00125 return add_bezier_vertex(_p, _d);
00126 }
00127
00134 BezierVertex* BezierMesh::add_bezier_vertex( const Point2D &_p,
00135 const LinearData &_d )
00136 {
00137 return add_bezier_vertex(datastore->add_cp( _p ), _d);
00138 }
00139
00145 BezierVertex* BezierMesh::add_bezier_vertex(ControlPoint cp)
00146 {
00147 LinearData d;
00148 return add_bezier_vertex( cp, d );
00149 }
00150
00151
00158 BezierVertex* BezierMesh::add_bezier_vertex( ControlPoint cp, const LinearData &_d )
00159 {
00160 DataPoint dp = datastore->add_dp( cp, _d );
00161 BezierVertex * bv = new BezierVertex(get_store(), cp, dp);
00162 add_vertex( bv );
00163 return bv;
00164 }
00165
00173 BezierEdge* BezierMesh::add_bezier_edge( const Point2D &_p, BezierVertex *v0, BezierVertex *v1 )
00174 {
00175 LinearData _d;
00176 return add_bezier_edge(_p, _d, v0, v1);
00177 }
00178
00187 BezierEdge* BezierMesh::add_bezier_edge( const Point2D &_p, const LinearData &_d, BezierVertex *v0, BezierVertex *v1 )
00188 {
00189 ControlPoint cp = datastore->add_cp( _p );
00190 return add_bezier_edge(cp, _d, v0, v1);
00191 }
00192
00201 BezierEdge* BezierMesh::add_bezier_edge( ControlPoint cp, BezierVertex *v0, BezierVertex *v1 )
00202 {
00203 LinearData d;
00204 return add_bezier_edge(cp, d, v0, v1);
00205 }
00206
00216 BezierEdge* BezierMesh::add_bezier_edge( ControlPoint cp, const LinearData &_d, BezierVertex *v0, BezierVertex *v1 )
00217 {
00218
00219 datastore->add_dp( cp, _d );
00220 BezierEdge *be = new BezierEdge(get_store(), v0, v1, cp, *datastore);
00221
00222 assert(be->get_data_point(1) == datastore->get_data(cp));
00223 add_edge(be);
00224 return be;
00225 }
00226
00227
00228
00229
00230 BezierEdge* BezierMesh::add_straight_bezier_edge(BezierVertex *v1,
00231 BezierVertex *v2)
00232 {
00233 LinearData d = (v1->get_dp() + v2->get_dp()) / 2.0;
00234 return add_straight_bezier_edge(d, v1, v2);
00235 }
00236 BezierEdge* BezierMesh::add_straight_bezier_edge(const LinearData& d,
00237 BezierVertex *v1,
00238 BezierVertex *v2)
00239 {
00240 Point2D midpt = (v1->get_cp() + v2->get_cp()) / 2.0;
00241 return add_bezier_edge(midpt, d, v1, v2);
00242 }
00243
00256 BezierTriangle* BezierMesh::add_bezier_triangle( BoundaryFace *face, BezierEdge *e0, BezierEdge *e1, BezierEdge *e2, bool inverse_handed )
00257 {
00258 BezierEdge* es[3] = {e0, e1, e2};
00259
00260 BezierTriangle * bt = new BezierTriangle(get_store(), es, *datastore,inverse_handed);
00261 if (face) {
00262 bt->set_boundary_face(face);
00263 }
00264 add_face( bt, es, 3, inverse_handed );
00265 sample_id_map[bt] = sampler.size();
00266 sampler.push_back(bt);
00267 return bt;
00268 }
00269
00280 void BezierMesh::delete_vertex(BezierVertex *v)
00281 {
00282 datastore->rem_dp( v->get_control_point(), v->get_data_point() );
00283
00284
00285
00286
00287 if(!v->is_boundary()) {
00288 datastore->rem_cp(v->get_control_point());
00289 }
00290
00291
00292 while(v->num_edges() > 0) {
00293 delete_edge(v->get_any_edge());
00294 }
00295 BezierComplex::delete_vertex(v);
00296 }
00297
00305 void BezierMesh::delete_edge(BezierEdge *edge){
00306 datastore->rem_dp( edge->get_control_point(1), edge->get_data_point(1) );
00307
00308
00309
00310
00311
00312 if( !edge->is_boundary() ) datastore->rem_cp( edge->get_control_point(1) );
00313 BezierComplex::delete_edge( edge );
00314 }
00315
00320 void BezierMesh::delete_face(BezierTriangle *face){
00321
00322 assert(sample_id_map.count(face) != 0);
00323 int index = sample_id_map[face];
00324 sample_id_map.erase(face);
00325 sampler[index] = sampler.back();
00326 sampler.pop_back();
00327 sample_id_map[sampler[index]] = index;
00328
00329 BezierComplex::delete_face(face);
00330 }
00331
00338 void BezierMesh::replace_control_point(BezierVertex* v,
00339 const ControlPoint& newp)
00340 {
00341 ControlPoint oldp = v->get_control_point();
00342
00343
00344 v->replace_cp(newp);
00345
00346
00347 BezierTuple start = get_tuple(v);
00348 BezierTuple tup = start;
00349 do {
00350 tup.e->replace_cp(oldp, newp);
00351 tup.f->replace_cp(oldp, newp);
00352 tup = Switch(1, Switch(2, tup));
00353 } while(tup != start);
00354
00355
00356 datastore->replace_cp(oldp, newp);
00357 }
00358
00359 void BezierMesh::replace_control_point(BezierEdge* e,
00360 const ControlPoint& newp)
00361 {
00362 ControlPoint oldp = e->get_control_point(1);
00363 assert( oldp != newp );
00364
00365
00366 e->replace_cp(oldp, newp);
00367
00368
00369 BezierTuple tup = get_tuple(e);
00370 tup.f->replace_cp(oldp, newp);
00371 if(e->num_faces() == 2) {
00372 tup = Switch(2, tup);
00373 tup.f->replace_cp(oldp, newp);
00374 }
00375
00376
00377 datastore->replace_cp(oldp, newp);
00378 }
00379
00395 int BezierMesh::orient_edge_triangle(const BezierEdge *e, const BezierTriangle *t) const
00396 {
00397 assert( e->has_face(t) );
00398
00399 ControlPoint edge_cp0 = e->get_control_point(0);
00400 ControlPoint edge_cp2 = e->get_control_point(2);
00401 ControlPoint tri_cp0 = t->get_control_point( 0 );
00402 ControlPoint tri_cp2 = t->get_control_point( 2 );
00403 if ( tri_cp0 == edge_cp0 ) {
00404 if ( tri_cp2 == edge_cp2 ) return 0;
00405 else return 5;
00406 } else if ( tri_cp2 == edge_cp0 ) {
00407 if ( tri_cp0 == edge_cp2 ) return 3;
00408 else return 1;
00409 } else {
00410 if ( tri_cp0 == edge_cp2 ) return 2;
00411 return 4;
00412 }
00413 }
00414
00435 void BezierMesh::tri_cps_off_edge(BezierEdge *e, BezierTriangle *t, ControlPoint &cp3, ControlPoint &cp4, ControlPoint &cp5)
00436 {
00437 switch( orient_edge_triangle(e,t) ) {
00438 case 0:
00439 cp3 = t->get_control_point(3); cp4 = t->get_control_point(4); cp5 = t->get_control_point(5);
00440 return;
00441 case 1:
00442 cp3 = t->get_control_point(1); cp4 = t->get_control_point(3); cp5 = t->get_control_point(0);
00443 return;
00444 case 2:
00445 cp3 = t->get_control_point(4); cp4 = t->get_control_point(1); cp5 = t->get_control_point(2);
00446 return;
00447 case 3:
00448 cp3 = t->get_control_point(4); cp4 = t->get_control_point(3); cp5 = t->get_control_point(5);
00449 return;
00450 case 4:
00451 cp3 = t->get_control_point(3); cp4 = t->get_control_point(1); cp5 = t->get_control_point(0);
00452 return;
00453 case 5:
00454 cp3 = t->get_control_point(1); cp4 = t->get_control_point(4); cp5 = t->get_control_point(2);
00455 return;
00456 }
00457 }
00458
00470 void BezierMesh::edge_param_to_tri_param(const BezierEdge *e,
00471 const BezierTriangle *t,
00472 double u, double &alpha, double &beta )
00473 const
00474 {
00475 switch( orient_edge_triangle(e,t) ) {
00476 case 0:
00477 alpha = 0; beta = u;
00478 return;
00479 case 1:
00480 alpha = u; beta = 1 - u;
00481 return;
00482 case 2:
00483 alpha = 1 - u; beta = 0;
00484 return;
00485 case 3:
00486 alpha = 0; beta = 1 - u;
00487 return;
00488 case 4:
00489 alpha = 1 - u; beta = u;
00490 return;
00491 case 5:
00492 alpha = u; beta = 0;
00493 return;
00494 }
00495 assert(0);
00496 }
00497
00503 void BezierMesh::tri_param_to_edge_param(const BezierEdge *e,
00504 const BezierTriangle *t,
00505 double& u, double alpha, double beta)
00506 const
00507 {
00508
00509 switch( orient_edge_triangle(e,t) ) {
00510 case 0:
00511
00512 u = beta;
00513 return;
00514 case 1:
00515 u = alpha;
00516
00517 return;
00518 case 2:
00519 u = 1 - alpha;
00520
00521 return;
00522 case 3:
00523
00524 u = 1 - beta;
00525 return;
00526 case 4:
00527
00528 u = beta;
00529 return;
00530 case 5:
00531 u = alpha;
00532
00533 return;
00534 }
00535 assert(0);
00536 }
00537
00550 bool BezierMesh::robust_smooth( Point2D poly[], const Point2D &primary, const Point2D &secondary, Point2D &new_pt)
00551 {
00552 double x[6], y[6];
00553 for (int i = 0; i < 6 ;i++ ) {
00554 x[i] = poly[i][0];
00555 y[i] = poly[i][1];
00556 }
00557 if( smooth_point(x, y, primary, new_pt) ) return true;
00558 if( smooth_point(x, y, secondary, new_pt) ) return true;
00559 return false;
00560 }
00561
00562
00589 bool BezierMesh::smooth_point( double x[], double y[], const Point2D &p, Point2D &new_pt)
00590 {
00591 double optimal;
00592 double quality_values[12];
00593 int violator;
00594 int inform;
00595 int niterations;
00596
00597 Point2D area_pt;
00598 Point2D mean_ratio_pt;
00599 int star_valid;
00600
00601
00602 star_valid = smCheckStarValidity( x, y, 6, p.x(), p.y(), &violator );
00603
00604
00605 if( star_valid == SUCCESS ){
00606 mean_ratio_pt = p;
00607 smSmooth( SM_MEAN_RATIO, x, y, 6, &mean_ratio_pt.coords[0], &mean_ratio_pt.coords[1], &optimal, quality_values, &inform, &niterations );
00608 if ( inform == SUCCESS ) {
00609 new_pt = mean_ratio_pt;
00610 return true;
00611 } else {
00612
00613 WARNING(cout<<"BezierMesh::smooth_point -- Possible internal error in smoothing code - Fix This!"<<endl);
00614 WARNING(cout<<"In this case the polygon is star-shaped with a valid initial guess, yet smoothing does not converge."<<endl);
00615 WARNING(cout << "x is "<<p.x()<<" and y is "<<p.y()<<endl);
00616 for (int i=0;i<6;i++)
00617 {
00618 WARNING(cout << x[i] <<", "<<y[i]<<endl);
00619 }
00620 WARNING(cout << "Got back "<<mean_ratio_pt.x()<<", "<<mean_ratio_pt.y()<<endl);
00621 WARNING(cout << "Got back inform = "<<inform<<endl);
00622 }
00623
00624 }
00625
00626
00627
00628
00629
00630 area_pt = p;
00631 smSmooth( SM_AREA, x, y, 6, &area_pt.coords[0], &area_pt.coords[1], &optimal, quality_values, &inform, &niterations );
00632
00633
00634
00635 if( inform != SUCCESS ) {
00636 WARNING(cout<<"Informed returned "<<inform<<", see cfsqp (smoother) readme"<<endl);
00637 WARNING(cout<<"BezierMesh::smooth_point -- Polygon is not star-shaped Case 1 Failure!"<<endl
00638 <<" ** You are playing with inverted triangles, not a good idea!"<<endl);
00639 new_pt = p;
00640 return false;
00641 }
00642
00643
00644 star_valid = smCheckStarValidity( x, y, 6, area_pt.x(), area_pt.y(), &violator );
00645
00646
00647
00648 if( star_valid != SUCCESS ){
00649 cout<<"BezierMesh::smooth_point -- Polygon has no kernel"<<endl
00650 <<" ** Either a Type 'B' impossible flip, or an unsmoothable edge"<<endl;
00651 new_pt = p;
00652 return false;
00653 }
00654
00655
00656
00657 mean_ratio_pt = area_pt;
00658 smSmooth( SM_MEAN_RATIO, x, y, 6, &mean_ratio_pt.coords[0], &mean_ratio_pt.coords[1], &optimal, quality_values, &inform, &niterations );
00659
00660
00661 if( inform != SUCCESS ){
00662
00663 WARNING(cout<<"BezierMesh::smooth_point -- Area smooth claimed that it fixed star, but RATIO failed!"<<endl);
00664 WARNING(cout<<" ** Possible internal error in smoothing code - Fix This!"<<endl);
00665 new_pt = area_pt;
00666 return true;
00667 }
00668
00669 new_pt = mean_ratio_pt;
00670 return true;
00671 }
00672
00673
00682 bool BezierMesh::should_flip( BezierEdge *e )
00683 {
00684 assert(e!=NULL);
00685 if ( e->num_faces() != 2) return false;
00686 if ( e->is_boundary() ) return false;
00687
00688 BezierTuple bt = get_tuple( e );
00689 Point2D p1, p2, v1, v2;
00690 p1 = bt.v->get_cp();
00691 bt = Switch( 0, Switch( 1, bt ) );
00692 v1 = bt.v->get_cp();
00693 bt = Switch( 0, Switch( 1, bt ) );
00694 p2 = bt.v->get_cp();
00695 bt = Switch( 2, Switch( 1, bt ) );
00696 bt = Switch( 0, Switch( 1, bt ) );
00697 v2 = bt.v->get_cp();
00698 return v2.in_circle_test( p1, p2, v1 );
00699 }
00700
00701
00717 void BezierMesh::get_edge_neighbor_cells( BezierEdge *e, BezierVertex* vs[], BezierEdge* es[], BezierTriangle* ts[] )
00718 {
00719 assert( e && !e->is_boundary() );
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 BezierTuple tup = get_tuple( e );
00737 tup = Switch( 1, Switch( 0, tup ) );
00738 vs[0] = tup.v;
00739 es[0] = tup.e;
00740 ts[0] = tup.f;
00741 tup = Switch( 1, Switch( 0, tup ) );
00742 vs[1] = tup.v;
00743 es[1] = tup.e;
00744 tup = Switch( 1, Switch( 2, Switch( 1, Switch( 0, tup ) ) ) );
00745 vs[2] = tup.v;
00746 es[2] = tup.e;
00747 ts[1] = tup.f;
00748 tup = Switch( 1, Switch( 0, tup ) );
00749 vs[3] = tup.v;
00750 es[3] = tup.e;
00751 }
00752
00763 bool BezierMesh::can_flip( BezierEdge *e )
00764 {
00765 bool is_typeA, is_typeB;
00766 return can_flip(e, is_typeA, is_typeB);
00767 }
00768
00781 bool BezierMesh::can_flip( BezierEdge *e, bool &is_typeA, bool &is_typeB)
00782 {
00783 BezierVertex* vs[4];
00784 BezierEdge* es[4];
00785 BezierTriangle* ts[2];
00786
00787 get_edge_neighbor_cells(e, vs, es, ts);
00788 Point2D poly[6];
00789 Point2D primary = e->get_cp(1);
00790 Point2D secondary = (vs[1]->get_cp() + vs[3]->get_cp())*0.5;
00791 Point2D temp;
00792 get_flip_polygon(poly,vs,es);
00793
00794
00795 is_typeB = !robust_smooth( poly, primary, secondary, temp);
00796
00797
00798
00799 is_typeA = ! ( es[0]->get_cp(1).is_left_of(es[3]->get_cp(1), vs[0]->get_cp())
00800 && es[2]->get_cp(1).is_left_of(es[1]->get_cp(1), vs[2]->get_cp()) );
00801
00802 bool flippable = !is_typeB && !is_typeA;
00803
00804 return flippable;
00805 }
00806
00813 void BezierMesh::split_return_adjacent(BezierEdge *e, vector<BezierEdge*> &new_edges)
00814 {
00815 list<BezierEdge*> cavity_edges;
00816 find_adjacent_edges(e, cavity_edges);
00817
00818
00819 new_edges.insert(new_edges.end(), cavity_edges.begin(), cavity_edges.end());
00820
00821
00822 BezierVertex *v = insert_edge_midpoint(e, 0.5);
00823
00824
00825 upper(v, new_edges);
00826
00827 return;
00828 }
00829
00841 void BezierMesh::split_edge_near_unflippable(BezierEdge *e, vector<BezierEdge*> &new_edges )
00842 {
00843 assert(e->num_faces() == 2);
00844 list<BezierEdge*> cavity_edges;
00845 find_adjacent_edges(e, cavity_edges);
00846
00847
00848 list<BezierEdge*>::iterator i = cavity_edges.begin();
00849 BezierEdge* most_curved_cavity_edge = (*i);
00850 for (; i != cavity_edges.end(); ++i)
00851 {
00852 BezierEdge* current = (*i);
00853 if (current->curvature_angle() > most_curved_cavity_edge->curvature_angle())
00854 most_curved_cavity_edge = current;
00855 }
00856
00857
00858 double theta_bound = 0.5 * e->get_any_face()->get_min_angle();
00859 if (most_curved_cavity_edge->curvature_angle() > theta_bound)
00860 split_return_adjacent(most_curved_cavity_edge, new_edges);
00861 else
00862 split_return_adjacent(e, new_edges);
00863
00864 return;
00865 }
00866
00867
00876 bool BezierMesh::debug_flip( BezierEdge *e )
00877 {
00878 BezierVertex* vs[4];
00879 BezierEdge* es[4];
00880 BezierTriangle* ts[2];
00881
00882 get_edge_neighbor_cells(e, vs, es, ts);
00883 Point2D poly[6];
00884 Point2D primary = e->get_cp(1);
00885 Point2D secondary = (vs[1]->get_cp() + vs[3]->get_cp())*0.5;
00886 get_flip_polygon(poly,vs,es);
00887
00888 bool is_typeA, is_typeB;
00889 bool flippable = can_flip(e, is_typeA, is_typeB);
00890
00891 #ifdef DEBUG_FLIP
00892 if(!flippable){
00893 cout << "\nFLIPPING ERROR: ----------------------\n";
00894 cout << "Unable to flip edge: " << e << " with tris: "
00895 << ts[0] << " and " << ts[1] << endl;
00896 if(is_typeA) {
00897 cout << "Type A unflippable (outer flips cannot be done)\n";
00898 }
00899 if(is_typeB) {
00900 cout << "Type B unflippable (smoothing polygon is bad)\n";
00901 }
00902 for(int i = 0; i < 2; i++) {
00903 if(ts[i]->is_inverted()) {
00904 cout << ts[i] << " is inverted\n";
00905 }
00906 }
00907
00908 MeshBinaryOutput::write("dumped_flip.geo", this, boundarymesh);
00909
00910 #ifdef DRAW_FLIP
00911 if(ts[0]->is_inverted()) {
00912 cout << "Yellow Triangle is inverted\n";
00913 }
00914 if(ts[1]->is_inverted()) {
00915 cout << "Cyan Triangle is inverted\n";
00916 }
00917 draw_smooth_error("flip",e,poly,primary,secondary,ts);
00918 #endif
00919 }
00920 #endif
00921
00922 return flippable;
00923 }
00924
00933 bool BezierMesh::can_smooth( BezierEdge *e )
00934 {
00935 BezierVertex* vs[4];
00936 BezierEdge* es[4];
00937 BezierTriangle* ts[2];
00938 get_edge_neighbor_cells(e, vs, es, ts);
00939
00940 Point2D poly[6];
00941 Point2D primary = e->get_cp(1);
00942 Point2D secondary = (vs[0]->get_cp() + vs[2]->get_cp())*0.5;
00943 Point2D temp;
00944 get_smooth_polygon(poly, vs, es);
00945
00946 bool smoothable = robust_smooth( poly, primary, secondary, temp);
00947
00948 return smoothable;
00949 }
00950
00959 bool BezierMesh::debug_smooth( BezierEdge *e )
00960 {
00961 BezierVertex* vs[4];
00962 BezierEdge* es[4];
00963 BezierTriangle* ts[2];
00964 get_edge_neighbor_cells(e, vs, es, ts);
00965
00966 Point2D poly[6];
00967 Point2D primary = e->get_cp(1);
00968 Point2D secondary = (vs[0]->get_cp() + vs[2]->get_cp())*0.5;
00969 Point2D temp;
00970 get_smooth_polygon(poly, vs, es);
00971
00972 bool smoothable = robust_smooth( poly, primary, secondary, temp);
00973
00974 #ifdef DEBUG_SMOOTH
00975 if(!smoothable){
00976 WARNING(cout<<endl<<"SMOOTHING ERROR: ----------------------"<<endl);
00977 WARNING(cout<<"Unable to smooth edge: "<<*(e)<<" with tris: "<<*(ts[0])<<" and "<<*(ts[1])<<endl);
00978 if(ts[0]->is_inverted())
00979 {
00980 WARNING(cout<<"Yellow Triangle is inverted"<<endl);
00981 }
00982 if(ts[1]->is_inverted())
00983 {
00984 WARNING(cout<<"Cyan Triangle is inverted"<<endl);
00985 }
00986 #ifdef DRAW_SMOOTH
00987 draw_smooth_error("smooth",e,poly,primary,secondary,ts);
00988 #endif
00989 }
00990 #endif
00991
00992 return smoothable;
00993 }
00994
00995
01007 void BezierMesh::draw_smooth_error(const char *name, BezierEdge *e, Point2D poly[], const Point2D &primary, const Point2D &secondary, BezierTriangle* ts[])
01008 {
01009 #ifdef VISUAL_DEBUG
01010 static int jpeg_num=0;
01011
01012 Visualization vis(this, this->boundarymesh);
01013 vis.start_draw();
01014 vis.draw_smooth_debug(e, poly, primary, secondary);
01015 vis.finish_draw();
01016 char temp[80];
01017 snprintf(temp,80,"%s_error_%04u.ppm",name,jpeg_num);
01018 vis.write_ppm(temp);
01019 snprintf(temp,80,"%s_error_%04u.txt",name,jpeg_num);
01020 ofstream out(temp);
01021 out<<"Triangle 1:\n"<<*ts[0]<<"\n"
01022 <<"Triangle 2:\n"<<*ts[1]<<endl;
01023 out.close();
01024 cout<<"Dumped "<<temp<<", continuing... "<<endl<<endl;
01025 vis.zoomout();
01026 vis.start_draw();
01027 vis.draw(GREEN, BLUE);
01028 vis.finish_draw();
01029 jpeg_num++;
01030 #endif
01031 }
01032
01033 void BezierMesh::draw_insert_error(const char* name, BezierTriangle* bt)
01034 {
01035 cout<<"Drawing insert error"<<endl;
01036 #ifdef VISUAL_DEBUG
01037 static int jpeg_num=0;
01038 Visualization vis(this, this->boundarymesh);
01039 cout<<"Created visualization"<<endl;
01040 Point2D top, bot;
01041 vis.get_bbox(&bt,1,top,bot);
01042 vis.start_draw();
01043 vis.zoomin(top,bot);
01044 BezierTuple tup = get_tuple(bt);
01045 for (uint i=0;i<6;i++) { vis.draw_point(bt->get_cp(i),MAGENTA,7.0); }
01046 vis.draw_tuple(tup, RED, WHITE,GREEN);
01047 vis.draw_control_net(bt, BLUE);
01048 vis.finish_draw();
01049 char temp[80];
01050 snprintf(temp,80,"%s_error_%04u.ppm",name,jpeg_num);
01051 vis.write_ppm(temp);
01052 cout<<"Dumped:"<<temp<<", continuing.. "<<endl<<endl;
01053 jpeg_num++;
01054 #endif
01055 }
01056
01071 void BezierMesh::get_flip_polygon(Point2D poly[], BezierVertex* vs[], BezierEdge* es[])
01072 {
01073
01074 poly[ 0 ] = vs[1]->get_cp();
01075 poly[ 1 ] = es[1]->get_cp(1);
01076 poly[ 2 ] = es[2]->get_cp(1);
01077 poly[ 3 ] = vs[3]->get_cp();
01078 poly[ 4 ] = es[3]->get_cp(1);
01079 poly[ 5 ] = es[0]->get_cp(1);
01080 }
01081
01094 void BezierMesh::get_smooth_polygon(Point2D poly[], BezierVertex* vs[], BezierEdge* es[])
01095 {
01096
01097 poly[ 0 ] = vs[0]->get_cp();
01098 poly[ 1 ] = es[0]->get_cp(1);
01099 poly[ 2 ] = es[1]->get_cp(1);
01100 poly[ 3 ] = vs[2]->get_cp();
01101 poly[ 4 ] = es[2]->get_cp(1);
01102 poly[ 5 ] = es[3]->get_cp(1);
01103 }
01104
01121 bool BezierMesh::flip( BezierEdge *e, BezierTuple &tup )
01122 {
01123
01124 assert( e && "Flip attempted on NULL edge");
01125 assert( (!e->is_boundary()) && "Flip attempted on boundary edge" );
01126 assert( (e->num_faces() == 2) && "Flip attempted on edge without two triangles" );
01127
01128 BezierVertex *vs[4];
01129 BezierEdge *es[4];
01130 BezierTriangle *ts[2];
01131 get_edge_neighbor_cells(e, vs, es, ts);
01132
01133 #ifdef DEBUG_FLIP
01134 cout << "Debugging flip of " << *e;
01135 cout << "Cavity: " << vs[0] << ", " << vs[1] << ", "
01136 << vs[2] << ", " << vs[3] << endl;
01137 cout << "Flipping to:\n\t" << *vs[1] << "\t" << *vs[3];
01138 #endif
01139
01140 #ifdef CHECK_FLIP
01141 {
01142 bool bad = false;
01143 for(int i = 0; i < 2; i++) {
01144 if (ts[i]->is_definitely_inverted()) {
01145 cerr << "Flip input has Triangle ts[" << i
01146 << "] with negative jacobian\n" << *ts[i] << endl;
01147 bad = true;
01148 }
01149 }
01150 if( !debug_flip(e) ){
01151 cerr << "Could not flip edge\n";
01152 bad = true;
01153 }
01154 assert(!bad);
01155 }
01156 #endif
01157
01158
01159
01160
01161
01162
01163 Point2D new_point;
01164
01165 if(linear_flips){
01166 new_point = (vs[1]->get_cp() + vs[3]->get_cp())*0.5;
01167 } else {
01168 Point2D poly[6];
01169 get_flip_polygon(poly, vs, es);
01170 Point2D primary = e->get_cp(1);
01171 Point2D secondary = (vs[1]->get_cp() + vs[3]->get_cp()) * 0.5;
01172 if(!robust_smooth( poly, primary, secondary, new_point )){
01173
01174 WARNING(cout<<endl<<"BezierMesh::flip --- could not flip edge!"<<endl);
01175 #ifdef CHECK_FLIP
01176 cout<<"Darn, Still failed even though we checked for flipability!"<<endl;
01177 return false;
01178 #endif
01179
01180
01181 new_point = e->get_cp(1);
01182 }
01183 }
01184
01185
01186 GhostTriangle *oldts[2];
01187 GhostTriangle gt0(*ts[0]);
01188 GhostTriangle gt1(*ts[1]);
01189 oldts[0] = >0;
01190 oldts[1] = >1;
01191
01192
01193
01194
01195 LinearData new_data( e->get_dp(1).length );
01196 BoundaryFace *face = ts[0]->get_bdry_face_or_null();
01197 assert(face == ts[1]->get_bdry_face_or_null());
01198
01199 delete_edge( e );
01200
01201 BezierEdge *new_edge;
01202 BezierTriangle *newts[2];
01203
01204 new_edge = add_bezier_edge( new_point, new_data, vs[1], vs[3] );
01205 newts[0] = add_bezier_triangle( face, new_edge, es[3], es[0] );
01206 newts[1] = add_bezier_triangle( face, new_edge, es[1], es[2], true );
01207
01208 #ifdef DEBUG_FLIP
01209 cout << "Added new triangles and new edge "<<(*new_edge)<<endl;
01210 #endif
01211
01212
01213 #ifdef CHECK_FLIP
01214 {
01215 bool bad = false;
01216 for(int i = 0; i < 2; i++) {
01217 if (newts[i]->is_definitely_inverted()) {
01218 cerr << "Flip created Triangle newts[" << i
01219 << "] with negative jacobian\n" << *newts[i] << endl;
01220 bad = true;
01221 }
01222 }
01223 assert(!bad);
01224 }
01225 assert(print_check_inverted("flipping an edge"));
01226 #endif
01227
01228
01229 reinterpolate(new_edge, newts, oldts);
01230 tup=get_tuple(new_edge, newts[0]);
01231 return true;
01232 }
01233
01244 bool BezierMesh::smooth_edge( BezierEdge* e )
01245 {
01246
01247 assert( e && "Smooth attempted on NULL edge");
01248 if(e->is_boundary()) return false;
01249 if(e->num_faces() != 2) return false;
01250
01251 BezierVertex *vs[4];
01252 BezierEdge *es[4];
01253 BezierTriangle *ts[2];
01254 get_edge_neighbor_cells(e, vs, es, ts);
01255
01256 #ifdef CHECK_SMOOTH
01257 if( ts[0]->is_definitely_inverted() ){
01258
01259 }
01260 if( ts[1]->is_definitely_inverted() ){
01261
01262 }
01263
01264 if(!debug_smooth(e)){
01265 return false;
01266 }
01267 #endif
01268
01269 Point2D poly[6];
01270 Point2D new_center;
01271 Point2D primary = e->get_cp(1);
01272 Point2D secondary = (vs[0]->get_cp() + vs[2]->get_cp()) * 0.5;
01273 get_smooth_polygon(poly, vs, es);
01274 if(!robust_smooth( poly, primary, secondary, new_center )){
01275
01276 WARNING(cout<<endl<<"BezierMesh::smooth_edge --- could not smooth edge!"<<endl);
01277 #ifdef CHECK_SMOOTH
01278 cout<<"Darn, Still failed even though we checked for smoothability!"<<endl;
01279 #endif
01280 new_center = e->get_cp(1);
01281 return false;
01282 }
01283
01284 BezierTriangle* newts[2];
01285 GhostTriangle *oldts[2];
01286
01287
01288 assert(e->num_faces() == 2);
01289 newts[0] = *e->begin_faces();
01290 newts[1] = *++e->begin_faces();
01291
01292
01293 GhostTriangle gt0(*newts[0]);
01294 GhostTriangle gt1(*newts[1]);
01295 oldts[0] = >0;
01296 oldts[1] = >1;
01297
01298
01299 e->set_cp(new_center,1);
01300
01301 #ifdef CHECK_SMOOTH
01302 if( ts[0]->is_definitely_inverted() ){
01303
01304
01305 if(!debug_smooth(e)){
01306 return false;
01307 }
01308 }
01309 if( ts[1]->is_definitely_inverted() ){
01310
01311 if(!debug_smooth(e)){
01312 return false;
01313 }
01314 }
01315 #endif
01316
01317 reinterpolate(e, newts, oldts);
01318 return true;
01319 }
01320
01321
01322
01323
01336 BezierVertex* BezierMesh::insert_point( BezierTriangle *t, double u, double v )
01337 {
01338 Point2D new_p;
01339 LinearData new_d;
01340 Point2D c[ 3 ];
01341 LinearData d[ 3 ];
01342 t->evalIntermediate( u, v, new_p, c[ 0 ], c[ 1 ], c[ 2 ] );
01343 t->dataevalIntermediate( u, v, new_d, d[ 0 ], d[ 1 ], d[ 2 ] );
01344
01345 #ifdef DEBUG_INSERTS
01346 assert(check_consistency());
01347 #endif
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358 BezierVertex *v0, *v1, *v2;
01359 BezierEdge *e0, *e1, *e2;
01360 BezierTuple tup = get_tuple( t );
01361 v0 = tup.v;
01362 e0 = tup.e;
01363 tup = Switch( 1, Switch( 0, tup ) );
01364 v1 = tup.v;
01365 e1 = tup.e;
01366 tup = Switch( 1, Switch( 0, tup ) );
01367 v2 = tup.v;
01368 e2 = tup.e;
01369
01370
01371 BoundaryFace *face = t->get_bdry_face_or_null();
01372 delete_face( t );
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 BezierVertex *nv;
01389 BezierEdge *ne0, *ne1, *ne2;
01390 BezierTriangle *nt0, *nt1, *nt2;
01391
01392 nv = add_bezier_vertex( new_p, new_d );
01393 ne0 = add_bezier_edge( c[ 0 ], d[ 0 ], nv, v0 );
01394 ne1 = add_bezier_edge( c[ 2 ], d[ 2 ], nv, v1 );
01395 ne2 = add_bezier_edge( c[ 1 ], d[ 1 ], nv, v2 );
01396 nt0 = add_bezier_triangle( face, ne0, e0, ne1 );
01397 nt1 = add_bezier_triangle( face, ne1, e1, ne2 );
01398 nt2 = add_bezier_triangle( face, ne2, e2, ne0 );
01399
01400
01401
01402 if (nt0->is_inverted() || nt1->is_inverted() || nt2->is_inverted() )
01403 {
01404 smooth_edge(ne0);
01405 smooth_edge(ne1);
01406 smooth_edge(ne2);
01407 }
01408
01409 print_check_inverted("inserted a point");
01410 return nv;
01411 }
01412
01413
01430 BezierVertex* BezierMesh::insert_edge_midpoint( BezierEdge *e, double u )
01431 {
01432 BezierVertex * ev[2];
01433 BezierVertex * v0, *v1, *v2, *v3 = NULL;
01434 BezierEdge *e0, *e1, *e2 = NULL, *e3 = NULL;
01435 BezierTriangle *t0, *t1;
01436 BoundaryFace *t0face, *t1face = NULL;
01437 BezierTuple tup;
01438 double t0_alpha, t0_beta, t1_alpha, t1_beta;
01439 Point2D t0_newp, t1_newp;
01440 LinearData t0_newd, t1_newd;
01441 Point2D t0pc[ 3 ], t1pc[ 3 ];
01442 LinearData t0dc[ 3 ], t1dc[ 3 ];
01443 BoundaryEdge *bdry = NULL;
01444
01445 #ifndef NDEBUG
01446 Point2D insertpt = e->eval(u);
01447 #endif
01448
01449
01450
01451
01452 bool one_sided = false;
01453
01454
01455
01456
01457 bool is_bdry = false;
01458
01459 ev[0] = e->get_vertex(0);
01460 ev[1] = e->get_vertex(1);
01461
01462 tup = get_tuple(e);
01463 t0 = tup.f;
01464 t1 = Switch(2, tup).f;
01465 if (t0 == t1) {
01466 one_sided = true;
01467 }
01468
01469 if (e->is_boundary()) {
01470 is_bdry = true;
01471 bdry = e->get_bdry_edge();
01472 }
01473
01474 #ifdef DEBUG_INSERTS
01475 cout << "Inserting edge point with boundary="<<is_bdry<<" and one_side="<<one_sided<<endl;
01476 cout << "Trying to insert at "<<u<<" in "<<e<<" = "<<e->eval(u)<<endl;
01477 cout << "Midway through iemp with "<<e<<" = "<<(*e)<<endl;
01478 #endif
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494 tup = get_tuple( e, t0 );
01495 v2 = tup.v;
01496 tup = Switch( 1, Switch( 0, tup ) );
01497 e0 = tup.e;
01498 v0 = tup.v;
01499 tup = Switch( 1, Switch( 0, tup ) );
01500 v1 = tup.v;
01501 e1 = tup.e;
01502 tup = Switch( 0, tup );
01503
01504 edge_param_to_tri_param(e, t0, u, t0_alpha, t0_beta );
01505 t0face = t0->get_bdry_face_or_null();
01506 t0->evalIntermediate( t0_alpha, t0_beta, t0_newp, t0pc[ 0 ], t0pc[ 1 ], t0pc[ 2 ] );
01507 t0->dataevalIntermediate( t0_alpha, t0_beta, t0_newd, t0dc[ 0 ], t0dc[ 1 ], t0dc[ 2 ] );
01508
01509 if ( !one_sided ) {
01510
01511 tup = Switch( 0, Switch( 1, Switch( 2, Switch( 1, tup ) ) ) );
01512 v3 = tup.v;
01513 e2 = tup.e;
01514 tup = Switch( 1, tup );
01515 e3 = tup.e;
01516
01517 edge_param_to_tri_param(e, t1, u, t1_alpha, t1_beta );
01518 t1face = t1->get_bdry_face_or_null();
01519 t1->evalIntermediate( t1_alpha, t1_beta, t1_newp, t1pc[ 0 ], t1pc[ 1 ], t1pc[ 2 ] );
01520 t1->dataevalIntermediate( t1_alpha, t1_beta, t1_newd, t1dc[ 0 ], t1dc[ 1 ], t1dc[ 2 ] );
01521 }
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533 int ne0index, ne1index, ne2index;
01534 if ( t0_alpha == 0 ) {
01535 ne0index = 2;
01536 ne1index = 0;
01537 ne2index = 1;
01538 } else if ( t0_beta == 0 ) {
01539 ne0index = 0;
01540 ne1index = 1;
01541 ne2index = 2;
01542 } else {
01543 ne0index = 1;
01544 ne1index = 2;
01545 ne2index = 0;
01546 }
01547
01548
01549
01550
01551
01552
01553 int ne3index = 0;
01554 if ( !one_sided ) {
01555 if ( t1_alpha == 0 ) {
01556 ne3index = 1;
01557 } else if ( t1_beta == 0 ) {
01558 ne3index = 2;
01559 } else {
01560 ne3index = 0;
01561 }
01562 }
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572 delete_edge( e );
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592 BezierVertex *nv;
01593 BezierEdge *ne0, *ne1, *ne2, *ne3 = NULL;
01594 BezierTriangle *nt0, *nt1, *nt2, *nt3;
01595
01596 if ( is_bdry ) {
01597
01598
01599 ControlPoint cp0,cp1,cp2;
01600 double splineu, v0u = 0.0, v2u = 0.0;
01601
01602
01603 v0u = v0->get_u(bdry,v2);
01604 v2u = v2->get_u(bdry,v0);
01605
01606
01607 if (ev[0] == v0) {
01608
01609 splineu = v0u + u*(v2u - v0u);
01610 } else {
01611
01612 assert(ev[1] == v0);
01613 assert(ev[0] == v2);
01614
01615
01616 splineu = v2u + u*(v0u - v2u);
01617 }
01618
01619
01620 bdry->get_spline()->add_knot( splineu,cp0,cp1,cp2 );
01621
01622
01623 nv = add_bezier_vertex( cp1, t0_newd );
01624 nv->set_bdry( bdry, splineu );
01625
01626
01627 if(v0u > v2u){
01628 ne0 = add_bezier_edge( cp2, t0dc[ ne0index ], nv, v0 );
01629 ne1 = add_bezier_edge( cp0, t0dc[ ne1index ], nv, v2 );
01630 } else {
01631 ne0 = add_bezier_edge( cp0, t0dc[ ne0index ], nv, v0 );
01632 ne1 = add_bezier_edge( cp2, t0dc[ ne1index ], nv, v2 );
01633 }
01634
01635 ne0->set_bdry( bdry, splineu, v0u );
01636 ne1->set_bdry( bdry, splineu, v2u );
01637 }
01638
01639 else {
01640
01641 nv = add_bezier_vertex( t0_newp, t0_newd );
01642
01643
01644 ne0 = add_bezier_edge( t0pc[ ne0index ], t0dc[ ne0index ], nv, v0 );
01645 ne1 = add_bezier_edge( t0pc[ ne1index ], t0dc[ ne1index ], nv, v2 );
01646 }
01647
01648
01649
01650 ne2 = add_bezier_edge( t0pc[ ne2index ], t0dc[ ne2index ], nv, v1 );
01651 if ( !one_sided ) ne3 = add_bezier_edge( t1pc[ ne3index ], t1dc[ ne3index ], nv, v3 );
01652
01653
01654 nt0 = add_bezier_triangle( t0face, ne0, e0, ne2 );
01655 nt1 = add_bezier_triangle( t0face, ne2, e1, ne1 );
01656 if ( !one_sided ) {
01657 nt2 = add_bezier_triangle( t1face, ne1, e2, ne3 );
01658 nt3 = add_bezier_triangle( t1face, ne3, e3, ne0 );
01659 }
01660
01661 assert(print_check_inverted("inserted edge mindpoint"));
01662 return nv;
01663 }
01664
01673 void BezierMesh::flip_out_cavity( list<BezierEdge*> &cavity, list<BezierEdge*> &new_cavity, BezierVertex *v )
01674 {
01675 queue<BezierEdge*> todo;
01676 BezierEdge *e;
01677 BezierTuple tup;
01678 list<BezierEdge*>::iterator i;
01679 bool success;
01680 for(i = cavity.begin(); i != cavity.end(); ++i){
01681 todo.push(*i);
01682 while(!todo.empty()){
01683 e = todo.front();
01684 todo.pop();
01685 if(should_flip(e)){
01686 success = flip( e, tup );
01687 assert(success);
01688 if(tup.v != v) tup = Switch(2, Switch(0, tup));
01689 assert(tup.v == v);
01690 tup = Switch(1, Switch(0, tup));
01691 todo.push(tup.e);
01692 tup = Switch(1, Switch(2, Switch(1, tup)));
01693 todo.push(tup.e);
01694 } else {
01695 new_cavity.push_back(e);
01696 }
01697 }
01698 }
01699 assert(print_check_inverted("flipped a cavity"));
01700 }
01701
01719 BezierVertex* BezierMesh::clean_insert_point( BezierTriangle *t, double u, double v, bool force) {
01720 list<BezierEdge*> cavity, new_cavity;
01721 BezierVertex *new_vertex;
01722 Point2D p = t->eval(u, v);
01723 list<BezierEdge*>::iterator i;
01724
01725
01726 lower( t, cavity );
01727
01728
01729 if (!force)
01730 {
01731 for ( i = cavity.begin(); i != cavity.end(); ++i ) {
01732 BezierEdge *e = *i;
01733 if ( e->is_boundary() && e->is_encroached( p ) )
01734 return clean_insert_edge_midpoint( e, 0.5, true );
01735 }
01736 }
01737 #ifdef DEBUG_INSERTS
01738 cout << "[BezierMesh] inserting point " << p
01739 << " in triangle " << *t << " at (u,v)=(" << u << "," << v << ")\n";
01740 #endif
01741
01742
01743 new_vertex = insert_point( t, u, v );
01744 flip_out_cavity( cavity, new_cavity, new_vertex );
01745
01746 if (!force) {
01747
01748
01749
01750
01751 for ( i = new_cavity.begin(); i != new_cavity.end(); ++i ) {
01752 BezierEdge *e = *i;
01753 if ( e->is_boundary() && e->is_encroached(new_vertex->get_cp()) ) {
01754 #ifdef DEBUG_INSERTS
01755 printf("BezierMesh::clean_insert_point -- Backing out due to unforeseen encroachment\n");
01756 #endif
01757 remove_vertex( new_vertex );
01758 return clean_insert_edge_midpoint( e, 0.5, true);
01759 }
01760 }
01761 }
01762 return new_vertex;
01763 }
01764
01778 BezierVertex* BezierMesh::clean_insert_edge_midpoint( BezierEdge *e, double u, bool force)
01779 {
01780
01781
01782
01783 if (!force && e->is_boundary())
01784 u = 0.5;
01785 #ifdef DEBUG_INSERTS
01786 cout << "[BezierMesh:clean_insert_edge_mp] inserting point " << e->eval(u)
01787 << " on edge " << *e << " at u=" << u << endl;
01788 #endif
01789
01790 list<BezierEdge*> cavity, new_cavity;
01791 BezierVertex *new_vertex;
01792
01793
01794 for(BezierEdge::face_iterator it = e->begin_faces();
01795 it != e->end_faces(); ++it) {
01796 lower(*it, cavity);
01797 }
01798 cavity.remove( e );
01799
01800
01801 new_vertex = insert_edge_midpoint( e, u );
01802
01803
01804 #ifdef DEBUG_INSERTS
01805 cout << "Inserted edge midpoint, flipping out cavity around "<<(*new_vertex)<<" ... " << endl;
01806 #endif
01807
01808 flip_out_cavity( cavity, new_cavity, new_vertex );
01809
01810 if (!force && !e->is_boundary())
01811 {
01812
01813
01814
01815
01816 list<BezierEdge*>::iterator i;
01817 for ( i = new_cavity.begin(); i != new_cavity.end(); ++i ) {
01818 e = *i;
01819 if ( ( e->is_boundary() ) && ( e->is_encroached( new_vertex->get_cp() ) ) ){
01820 #ifdef DEBUG_INSERTS
01821 WARNING( printf("BezierMesh::clean_insert_edge_midpoint -- Warning: backing out due to unforeseen encroachment\n"); )
01822 #endif
01823 remove_vertex( new_vertex );
01824
01825 return clean_insert_edge_midpoint( e, 0.5, true);
01826 }
01827 }
01828 }
01829
01830 #ifdef DEBUG_INSERTS
01831 cout << "Returning from clean_insert_midpoint" << endl;
01832 #endif
01833
01834 return new_vertex;
01835 }
01836
01851 BezierVertex* BezierMesh::clean_insert_point(Point2D p,
01852 BezierTriangle* start_tri,
01853 bool over_bdry, bool force)
01854 {
01855 #ifdef DEBUG_INSERTS
01856 cout<<"Doing a clean insert of point "<<p<<endl;
01857 #endif
01858
01859 assert ((start_tri != NULL) || over_bdry);
01860 assert (over_bdry || !force);
01861 double u,v;
01862 int cd;
01863
01864 BezierTuple cellfound;
01865
01866 if (start_tri == NULL) {
01867 cd = blind_locate_point(p, cellfound, u, v);
01868 } else {
01869 cd = locate_point(p, start_tri, over_bdry, cellfound, u, v);
01870 }
01871
01872 switch(cd) {
01873 case 0:
01874
01875 cout << "Attempting to insert point "<<p<<" too close to an existing vertex." << endl;
01876 cout << "Insertion seems too close to "<<cellfound.v->get_cp()<<endl;
01877 assert(cd != 0);
01878 break;
01879
01880 case -1:
01881 case 1:
01882
01883
01884 assert(cellfound.e != NULL);
01885 assert(v == 0.0);
01886 #ifdef DEBUG_INSERTS
01887 cout<<" Strange location case" << cd << ". Was trying to insert "
01888 << p << " could only find it at u=" << u
01889 << " on edge " << *cellfound.e;
01890 #endif
01891 #ifndef NDEBUG
01892 if (cd == 1) {
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904 }
01905 #endif
01906 return clean_insert_edge_midpoint(cellfound.e, u, force);
01907
01908 case 2:
01909 assert(cellfound.f != NULL);
01910 #ifndef NDEBUG
01911 {
01912
01913 Point2D ev = cellfound.f->eval(u,v);
01914
01915
01916 }
01917 #endif
01918 return clean_insert_point(cellfound.f, u, v, force);
01919 };
01920 assert(0);
01921 return NULL;
01922 }
01923
01933 BezierVertex* BezierMesh::clean_insert_circumcenter(BezierTriangle *t)
01934 {
01935 return clean_insert_point(t->circumcenter(), t, false, false);
01936 }
01937
01951 void BezierMesh::get_link( BezierTuple start_tup, list<BezierVertex*> &link )
01952 {
01953 BezierTuple tup = start_tup;
01954 bool hit_bdry = false;
01955 BezierVertex *v0=NULL, *v=NULL;
01956
01957
01958 v0 = Switch( 0, tup ).v;
01959 link.push_back( v0 );
01960
01961
01962
01963
01964 do {
01965 if ( tup.e->is_boundary() ) {
01966 hit_bdry = true;
01967 } else {
01968 tup = Switch( 1, Switch( 2, tup ) );
01969 v = Switch( 0, tup ).v;
01970 if ( v != v0 )
01971 link.push_back( v );
01972 }
01973 } while ( ( v0 != v ) && ( !hit_bdry ) );
01974
01975
01976
01977
01978 if ( hit_bdry ) {
01979 link.reverse();
01980 hit_bdry = false;
01981 tup = Switch( 1, start_tup );
01982 link.push_back( Switch( 0, tup ).v );
01983 do {
01984 if ( tup.e->is_boundary() ) {
01985 hit_bdry = true;
01986 } else {
01987 tup = Switch( 1, Switch( 2, tup ) );
01988 link.push_back( Switch(0, tup).v );
01989 }
01990 } while ( !hit_bdry );
01991 }
01992
01993
01994 Point2D p0, lp0, lp1;
01995 p0 = start_tup.v->get_cp();
01996 lp0 = link.front()->get_cp();
01997 lp1 = ( *( ++link.begin() ) )->get_cp() ;
01998 if ( p0.is_right_of( lp0, lp1 ) ) link.reverse();
01999 }
02000
02001
02018 int BezierMesh::check_bdry_vertex_removal_degeneracies( list<BezierVertex*> &link, BezierVertex *v ) {
02019 Point2D vp = v->get_cp();
02020 Point2D lp_first = link.front()->get_cp();
02021 Point2D lp_last = link.back()->get_cp();
02022 double concave = vp.line_side_test( lp_first, lp_last );
02023
02024
02025 if ( concave < 0 )
02026 return 1;
02027
02028
02029
02030
02031 if ( link.size() == 2 )
02032 return 0;
02033
02034
02035
02036
02037 list<BezierVertex*>::iterator i;
02038 list<BezierVertex*>::iterator end = --link.end();
02039 for ( i = ++link.begin(); i != end; ++i ) {
02040 vp = (*i)->get_cp();
02041 if ( vp.line_side_test( lp_last, lp_first ) <= 0 )
02042 return -1;
02043 }
02044
02045
02046 if ( concave < 0.0001 )
02047 return 1;
02048
02049
02050 return 0;
02051 }
02052
02067 double BezierMesh::ear_priority( BezierVertex *v, list<BezierVertex*>::iterator ear, const list<BezierVertex*> &link ) {
02068 Matrix A(4,4);
02069 Matrix B(3,3);
02070
02071 Point2D p[ 4 ];
02072 int i;
02073 list<BezierVertex*>::iterator temp;
02074
02075
02076 temp = ear;
02077 if ( temp == link.begin() ) p[ 0 ] = link.back()->get_cp();
02078 else p[ 0 ] = (*( --temp ))->get_cp();
02079
02080
02081 p[ 1 ] = (*ear)->get_cp();
02082
02083
02084 temp = ear;
02085 if ( ++temp == link.end() ) p[ 2 ] = link.front()->get_cp();
02086 else p[ 2 ] = (*temp)->get_cp();
02087
02088
02089 double lineside = p[ 2 ].line_side_test( p[ 0 ], p[ 1 ] );
02090 if (lineside <= 0.0) {
02091 #ifdef DEBUG_DEVILLERS
02092 cout << "[Devillers] ear " << *ear << " concave\n";
02093 #endif
02094 return std::numeric_limits<double>::infinity();
02095 }
02096
02097
02098
02099 lineside = p[ 2 ].line_side_test( p[ 0 ], v->get_cp() );
02100 if (lineside >= 0.0) {
02101 #ifdef DEBUG_DEVILLERS
02102 cout << "[Devillers] ear " << *ear << " bad flip\n";
02103 #endif
02104 return std::numeric_limits<double>::infinity();
02105 }
02106
02107 p[ 3 ] = v->get_cp();
02108 for ( i = 0; i < 3; i++ ) {
02109 A.m[ i ][ 0 ] = p[ i ].coords[ 0 ];
02110 A.m[ i ][ 1 ] = p[ i ].coords[ 1 ];
02111 A.m[ i ][ 2 ] = p[ i ].magsq();
02112 A.m[ i ][ 3 ] = 1;
02113 B.m[ 0 ][ i ] = p[ i ].coords[ 0 ];
02114 B.m[ 1 ][ i ] = p[ i ].coords[ 1 ];
02115 B.m[ 2 ][ i ] = 1;
02116 }
02117 A.m[ 3 ][ 0 ] = p[ 3 ].coords[ 0 ];
02118 A.m[ 3 ][ 1 ] = p[ 3 ].coords[ 1 ];
02119 A.m[ 3 ][ 2 ] = p[ 3 ].magsq();
02120 A.m[ 3 ][ 3 ] = 1;
02121 #ifdef DEBUG_DEVILLERS
02122 cout << "[Devillers] ear " << *ear << " has weight "
02123 << A.det() / B.det() << endl;
02124 #endif
02125 return A.det() / B.det();
02126 }
02127
02145 int BezierMesh::devillers( BezierVertex *v, list<BezierVertex*> &link, int stop_degree ) {
02146 PQueue<list<BezierVertex*>::iterator> queue;
02147 list<BezierEdge*> edges_to_flip;
02148 list<BezierVertex*>::iterator i, beg, end, top, next, next_ear, prev_ear, temp;
02149 bool bdry, is_next_ear, is_prev_ear;
02150 int final_degree;
02151
02152 bdry = v->is_boundary();
02153
02154 assert( link.size() >= 2 );
02155 if ( link.size() <= (unsigned) stop_degree ) return link.size();
02156
02157
02158 beg = link.begin();
02159 for ( i = beg, next = ++link.begin(); i != link.end(); ++i, ++next ) {
02160 if ( !bdry || ( i != beg && next != link.end() ) )
02161 queue.push(i, ear_priority( v, i, link ));
02162 }
02163
02164 while ( queue.size() > stop_degree ) {
02165
02166 double topval = queue.front->p;
02167 queue.pop(top);
02168 assert( find_common_edge( v, *top) != NULL);
02169
02170
02171 if (topval == std::numeric_limits<double>::infinity()) {
02172 #ifdef DEBUG_DEVILLERS
02173 cout << "[Devillers] power distance " << topval << " ; not flipping "
02174 << *top << endl;
02175 #endif
02176 queue.push(top, topval);
02177 assert(queue.size() <= 4);
02178 break;
02179 }
02180 edges_to_flip.push_back( find_common_edge( v, *top ) );
02181 #ifdef DEBUG_DEVILLERS
02182 cout << "[Devillers] power distance " << topval << " ; flipping "
02183 << *top << " (edge " << edges_to_flip.back() << ")\n";
02184 #endif
02185 next = top;
02186 ++next;
02187
02188 beg = link.begin();
02189 end = link.end();
02190
02191 is_next_ear = false;
02192 is_prev_ear = false;
02193
02194
02195 if ( !bdry || next != end ) {
02196 is_next_ear = true;
02197 if ( next == end ) next_ear = beg;
02198 else next_ear = next;
02199 }
02200
02201
02202 temp = top;
02203 if ( !bdry || top != beg ) {
02204 is_prev_ear = true;
02205 if ( top == beg ){
02206 while(next != end){ temp = next++;}
02207 prev_ear = temp;
02208 assert(++temp == link.end());
02209 }
02210 else {
02211 prev_ear = --temp;
02212 }
02213 }
02214
02215
02216 link.erase( top );
02217
02218
02219 if ( is_next_ear && queue.remove( next_ear ) ) queue.push( next_ear, ear_priority( v, next_ear, link ));
02220 if ( is_prev_ear && queue.remove( prev_ear ) ) queue.push( prev_ear, ear_priority( v, prev_ear, link ));
02221 }
02222
02223 final_degree = queue.size();
02224
02225 #ifdef DEBUG_DEVILLERS
02226 while(queue.size() != 0) {
02227 double topval = queue.front->p;
02228 queue.pop(top);
02229 cout << "[Devillers] power distance " << topval << " ; won't flip "
02230 << *top << endl;
02231 }
02232 #endif
02233
02234
02235 #ifdef DEBUG_DEVILLERS
02236 cout << "Begin Devillers: stop degree " << stop_degree
02237 << "; actually stopping at " << final_degree << endl;
02238 #endif
02239 int nflips = 0;
02240 while( !edges_to_flip.empty() ){
02241 BezierTuple tup;
02242 bool success;
02243 BezierEdge *toflip = edges_to_flip.front();
02244 edges_to_flip.pop_front();
02245
02246 success = flip(toflip, tup);
02247 assert(success);
02248 nflips++;
02249 }
02250 #ifdef DEBUG_DEVILLERS
02251 cout << "End Devillers: stop degree " << stop_degree
02252 << "; actually stopped at " << final_degree
02253 << " after " << nflips << " flips.\n";
02254 #endif
02255 return final_degree;
02256 }
02257
02279 BezierTuple BezierMesh::remove_vertex(BezierVertex *v)
02280 {
02281 BezierTuple tup;
02282 list<BezierVertex*> link;
02283
02284
02285 switch(v->containment_dimension()) {
02286 case 0:
02287 return get_tuple(v);
02288
02289 case 1:
02290 {
02291 bool one_sided;
02292 int stop_degree1, stop_degree2=-1;
02293 BezierTuple tup2;
02294 list<BezierVertex*> link2;
02295 BezierVertex *top, *bot, *left=NULL, *right;
02296 BezierEdge *etop, *ebot, *espan, *nedge;
02297 BezierTriangle *nt_left, *nt_right;
02298 BoundaryFace *face1, *face2=NULL;
02299 BoundaryEdge *bdryedge;
02300 QBSpline *spline;
02301 ControlPoint nedge_center_cp;
02302 LinearData newd;
02303 double knot_to_remove;
02304 double u0, u1;
02305
02306 bdryedge = v->get_bdry_edge();
02307 spline = bdryedge->get_spline();
02308 knot_to_remove = v->get_u();
02309
02310
02311 if((spline->closed && spline->get_num_deboor() < 6) || (spline->get_num_deboor() < 4)) return tup;
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330 tup = get_tuple(v);
02331 face1 = tup.f->get_bdry_face_or_null();
02332 get_link(tup,link);
02333
02334 top=link.back();
02335 bot=link.front();
02336 etop=find_common_edge(v, top);
02337 ebot=find_common_edge(v, bot);
02338
02339 newd = (etop->get_dp(1) + ebot->get_dp(1))*0.5;
02340
02341
02342
02343 stop_degree1 = check_bdry_vertex_removal_degeneracies(link, v);
02344 if( stop_degree1 < 0) return tup;
02345
02346
02347 one_sided = ebot->num_faces() < 2;
02348
02349 if(!one_sided){
02350
02351
02352 tup2 = Switch(2, get_tuple(v, ebot));
02353 face2 = tup2.f->get_bdry_face_or_null();
02354 get_link(tup2,link2);
02355
02356
02357 assert(link2.back() == link.front());
02358 assert(link2.front() == link.back());
02359
02360
02361 stop_degree2 = check_bdry_vertex_removal_degeneracies(link2, v);
02362 if( stop_degree2 < 0) return tup;
02363
02364
02365 assert(stop_degree1>0 || stop_degree2>0);
02366 }
02367
02368 devillers(v, link, stop_degree1);
02369 if(!one_sided) devillers(v, link2, stop_degree2);
02370
02371 tup=get_tuple(v, ebot);
02372 if(!one_sided){
02373 tup2=get_tuple(v, etop);
02374 }
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400 espan=NULL;
02401 if(stop_degree1==0){
02402 tup = Switch(2, Switch(1, Switch(0, tup)));
02403 espan = tup.e;
02404 }
02405 tup = Switch(0, Switch(1, tup));
02406 right = tup.v;
02407
02408 if(!one_sided){
02409 if(stop_degree2==0){
02410 tup2 = Switch(2, Switch(1, Switch(0, tup2)));
02411 espan = tup2.e;
02412 }
02413 tup2 = Switch(0, Switch(1, tup2));
02414 left = tup2.v;
02415 }
02416
02417 if(espan) delete_edge(espan);
02418 delete_vertex(v);
02419
02420
02421
02422
02423
02424
02425 spline->remove_knot(knot_to_remove, nedge_center_cp, u0, u1 );
02426
02427
02428 nedge = add_bezier_edge(nedge_center_cp, newd, bot, top);
02429 nedge->set_bdry(bdryedge, bot->get_u(bdryedge,top), top->get_u(bdryedge,bot));
02430
02431 nt_right = add_bezier_triangle(face1, nedge, find_common_edge(bot, right), find_common_edge(top, right), true);
02432 if(!one_sided) nt_left = add_bezier_triangle(face2, nedge, find_common_edge(bot, left), find_common_edge(top, left));
02433
02434 return get_tuple(top, nt_right);
02435 }
02436
02437 case 2:
02438 {
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448 tup = get_tuple(v);
02449 get_link(tup, link);
02450 int stop_degree = devillers(v, link, 3);
02451 assert(stop_degree == 3 || stop_degree == 4);
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464 tup = get_tuple(v);
02465 BoundaryFace *face = tup.f->get_bdry_face_or_null();
02466 BezierVertex *vlink[stop_degree];
02467 BezierEdge *elink[stop_degree];
02468 tup=Switch(1, Switch(0, tup));
02469 for(int i = 0; i < stop_degree; i++) {
02470 vlink[i] = tup.v;
02471 elink[i] = tup.e;
02472 tup=Switch(1, Switch(2, Switch(1, Switch(0, tup))));
02473 }
02474 assert(tup.v == vlink[0]);
02475
02476
02477 delete_vertex(v);
02478
02479
02480
02481
02482 bool e0_is_cw = (elink[0]->get_canon_vertex() != vlink[0]);
02483
02484
02485
02486
02487 if (stop_degree == 3) {
02488
02489 BezierTriangle *t = add_bezier_triangle(face, elink[0], elink[1], elink[2], e0_is_cw);
02490
02491 return get_tuple(t);
02492 }
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504 if (vlink[0]->get_cp().in_circle_test(vlink[1]->get_cp(),
02505 vlink[2]->get_cp(), vlink[3]->get_cp())) {
02506
02507
02508 BezierEdge *cross = add_straight_bezier_edge(vlink[0], vlink[2]);
02509 add_bezier_triangle(face, elink[0], elink[1], cross, e0_is_cw);
02510 add_bezier_triangle(face, cross, elink[2], elink[3]);
02511
02512
02513
02514 tup = get_tuple(cross);
02515 } else {
02516
02517 BezierEdge *cross = add_straight_bezier_edge(vlink[3], vlink[1]);
02518 add_bezier_triangle(face, elink[0], cross, elink[3], e0_is_cw);
02519 add_bezier_triangle(face, cross, elink[1], elink[2]);
02520
02521 tup = get_tuple(cross);
02522 }
02523 return tup;
02524 }
02525 }
02526
02527
02528 assert(0);
02529 return get_tuple();
02530 }
02531
02544 int BezierMesh::blind_locate_point(Point2D pt, BezierTuple& cellfound,
02545 double &u, double &v)
02546 {
02547 return locate_point(pt, find_start_triangle(pt), true, cellfound, u, v);
02548 }
02549
02550
02561 BezierTriangle* BezierMesh::find_start_triangle(const Point2D &pt)
02562 {
02563 BezierTriangle *start=NULL;
02564 double best_dist = std::numeric_limits<double>::infinity();
02565 int num_to_check;
02566
02567 if(get_num_faces() == 0) return NULL;
02568
02569
02570 num_to_check = (int)pow(get_num_faces(), 1.0 / 3.0);
02571 if(num_to_check < 2) num_to_check=2;
02572
02573
02574
02575 std::stack<pair<BezierTriangle*,int> > sampler_recovery;
02576 for(int i=0; i<num_to_check; i++) {
02577 int r = random() % sampler.size();
02578 BezierTriangle *t = sampler[r];
02579 sampler[r] = sampler.back();
02580 sampler.pop_back();
02581 sampler_recovery.push(make_pair(t, r));
02582
02583 Point2D lin_center = (t->get_cp(0) + t->get_cp(2) + t->get_cp(5)) / 3.0;
02584 double dist = (lin_center - pt).magsq();
02585 if(dist < best_dist) {
02586 start = t;
02587 best_dist = dist;
02588 }
02589 }
02590 while(!sampler_recovery.empty()) {
02591 BezierTriangle *t = sampler_recovery.top().first;
02592 int index = sampler_recovery.top().second;
02593 sampler_recovery.pop();
02594
02595 sampler.push_back(sampler[index]);
02596 sampler[index] = t;
02597 }
02598 return start;
02599 }
02600
02630 int BezierMesh::locate_point( Point2D pt,
02631 BezierTriangle *start,
02632 bool over_bdry,
02633 BezierTuple& cellfound,
02634 double &u,
02635 double &v )
02636 {
02637 assert(start != NULL);
02638
02639
02640 u=0.0;
02641 v=0.0;
02642
02643
02644 switch (locate_point_in_linear_mesh(pt, start, over_bdry, cellfound)) {
02645 case -1:
02646
02647 u = 0.5;
02648 return -1;
02649
02650 case 0:
02651
02652
02653 return 0;
02654
02655 case 1:
02656 case 2:
02657
02658 break;
02659
02660 default:
02661
02662 assert(0);
02663 return 0;
02664 }
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674 #ifdef DEBUG_LOCATOR
02675 cout << "[BezierMesh]: considering triangle "<< *cellfound.f;
02676 #endif
02677
02678 int rval = locate_point_in_quadratic_triangle(pt, cellfound.f, cellfound, u, v);
02679 #ifdef DEBUG_LOCATOR
02680 cout << "[BezierMesh]: CD("<<pt<<") = " << rval << endl;
02681 #endif
02682 return rval;
02683 }
02684
02685
02697 int BezierMesh::locate_point_in_quadratic_triangle(const Point2D &pt,
02698 BezierTriangle *t,
02699 BezierTuple& cellfound,
02700 double &u,
02701 double &v)
02702 {
02703 double alpha, beta;
02704 int niter;
02705 int edge_num;
02706
02707
02708 u=0.0;
02709 v=0.0;
02710
02711 bool found = t->newton_find(pt, alpha, beta, niter, edge_num);
02712 assert(edge_num >= -1); assert(edge_num < 3);
02713
02714 if (!found) {
02715 u = 0.5;
02716 if (edge_num >= 0) {
02717 assert(niter >= 0);
02718 cellfound = get_tuple(t->get_edge(edge_num));
02719 } else {
02720 assert(niter < 0);
02721 cellfound = get_tuple(t);
02722 }
02723 return -1;
02724 } else {
02725 assert(niter >= 0);
02726
02727 double w[3];
02728 w[0] = 1.0 - (beta + alpha);
02729 w[1] = beta;
02730 w[2] = alpha;
02731 bool is_zero[3];
02732 int num_zero = 0;
02733 for(int i = 0; i < 3; i++) {
02734 if (fabs(w[i]) < 1e-6) {
02735 is_zero[i] = true;
02736 num_zero++;
02737 } else {
02738 is_zero[i] = false;
02739 }
02740 }
02741 assert(num_zero >= 0); assert(num_zero < 3);
02742
02743 switch(num_zero) {
02744 case 2:
02745
02746 {
02747
02748
02749
02750 static const int cp_idx[3] = { 0, 2, 5 };
02751 for(int i = 0; i < 3; i++) {
02752 if (!is_zero[i]) {
02753 ControlPoint cpi = t->get_control_point(cp_idx[i]);
02754
02755 BezierTuple tup = get_tuple(t);
02756 cellfound = tup;
02757 do {
02758 if (cellfound.v->get_control_point() == cpi) {
02759 return 0;
02760 }
02761 cellfound = Switch(1, Switch(0, cellfound));
02762 } while(cellfound != tup);
02763 assert(0);
02764 }
02765 }
02766 assert(0);
02767 return 0;
02768 }
02769
02770 case 1:
02771
02772 assert(edge_num >= 0);
02773 cellfound = get_tuple(t->get_edge(edge_num), t);
02774 tri_param_to_edge_param(cellfound.e, cellfound.f, u, alpha, beta);
02775 v = 0.0;
02776
02777 #ifdef DEBUG_LOCATOR
02778
02779 {
02780 double a, b;
02781 edge_param_to_tri_param(cellfound.e, cellfound.f, u, a, b);
02782 {
02783 cout << "u = " << u << "; edge_num = " << edge_num
02784 << " => " << *cellfound.e << endl;
02785 cout << *cellfound.f << endl;
02786 cout << "alpha = " << alpha << "; beta = " << beta << endl;
02787 cout << "a = " << a << "; b = " << b << endl;
02788 cout << "pt = " << pt
02789 << "; (alpha,beta) = " << cellfound.f->eval(alpha,beta)
02790 << "; (a,b) = " << cellfound.f->eval(a,b)
02791 << "; (u) = " << cellfound.e->eval(u) << endl;
02792 cout << "t = " << cellfound.f << "; e = " << cellfound.e << endl;
02793 cout << "t = " << *cellfound.f;
02794 cout << "e = " << *cellfound.e;
02795 }
02796
02797
02798 Point2D p2 = cellfound.f->eval(alpha, beta);
02799
02800
02801 p2 = cellfound.e->eval(u);
02802
02803
02804 }
02805 #endif
02806 return 1;
02807
02808 case 0:
02809
02810 u = alpha;
02811 v = beta;
02812 cellfound = get_tuple(t);
02813 return 2;
02814
02815 default:
02816
02817 assert(0);
02818 return 0;
02819 }
02820 }
02821 }
02822
02823
02842 int BezierMesh::locate_point_in_linear_mesh(const Point2D &pt,
02843 BezierTriangle *start,
02844 bool over_bdry,
02845 BezierTuple& cellfound)
02846 {
02847 BezierTuple tup;
02848 BezierEdge *first_e;
02849 int hits = 0;
02850
02851 assert(start);
02852 #ifdef DEBUG_LOCATOR
02853 cout << "[BezierMesh]: looking for " << pt << " starting at " << *start
02854 << endl;
02855 #endif
02856
02857
02858
02859
02860
02861
02862
02863 tup = get_tuple( start );
02864 first_e=tup.e;
02865 while(1) {
02866 hits++;
02867 assert(hits <= 3 * get_num_faces());
02868 BezierVertex *v0 = tup.v;
02869 BezierVertex *v1 = Switch(0,tup).v;
02870 #ifdef DEBUG_LOCATOR
02871 cout << "[BezierMesh]: considering " << *v0 << ", " << *v1 << endl;
02872 #endif
02873
02874 if (v0->get_cp().machine_equal(pt)) {
02875 cellfound = get_tuple(v0);
02876 return 0;
02877 } else if (v1->get_cp().machine_equal(pt)) {
02878 cellfound = get_tuple(v1);
02879 return 0;
02880 }
02881
02882 double test = pt.line_side_test(v0->get_cp(), v1->get_cp());
02883
02884 if(test == 0.0) {
02885
02886
02887
02888
02889
02890
02891 Point2D b = v1->get_cp();
02892 Point2D ab = v0->get_cp() - b;
02893 Point2D cb = pt - b;
02894 double alpha;
02895 if (is_zero(ab.x())) {
02896 assert(!is_zero(ab.y()));
02897 alpha = (cb.y() / ab.y());
02898 } else {
02899 alpha = (cb.x() / ab.x());
02900 }
02901 if (alpha >= 0.0 && alpha <= 1.0) {
02902 cellfound = get_tuple(tup.e);
02903 #ifdef DEBUG_LOCATOR
02904 cout << "[BezierMesh]: on edge\n";
02905 #endif
02906 return 1;
02907 }
02908
02909 }
02910 if(test < 0.0) {
02911
02912
02913 BezierEdge *e = tup.e;
02914 #ifdef DEBUG_LOCATOR
02915 cout << "[BezierMesh]: outside triangle\n";
02916 #endif
02917
02918 if (e->num_faces() == 1) {
02919
02920 cellfound = get_tuple(e);
02921 return -1;
02922 }
02923
02924 if (e->is_boundary() && !over_bdry) {
02925
02926 cellfound = get_tuple(e);
02927 return -1;
02928 }
02929
02930
02931
02932 tup = Switch(1, Switch(2, tup));
02933 first_e = e;
02934 } else {
02935 #ifdef DEBUG_LOCATOR
02936 cout << "[BezierMesh]: maybe inside triangle\n";
02937 #endif
02938
02939 tup = Switch(1, Switch(0, tup));
02940
02941
02942
02943 if(tup.e == first_e){
02944 #ifdef DEBUG_LOCATOR
02945 cout << "[BezierMesh]: definitely inside triangle\n";
02946 #endif
02947 cellfound = get_tuple(tup.f);
02948 return 2;
02949 }
02950 }
02951 }
02952
02953 assert(0);
02954 return 0;
02955 }
02956
02957
02958 #ifdef false
02959
02960
02961
02962
02963
02964
02965 void reinterpolate(list<BezierTriangle*> new_triangles,list<GhostTriangle*> old_triangles)
02966 {
02967 int i,j;
02968 list<LinearData*> new_data;
02969
02970 list<BezierEdge*> free_edges;
02971
02972 for (list<BezierTriangle*>::iterator it = new_triangles.begin();
02973 it != new_triangles.end(); ++it)
02974 {
02975 BezierTriangle *bt = *it;
02976 for (int j = 0; j < 3; j++)
02977 {
02978 BezierEdge *be = bt->get_edge(i);
02979 BezierTuple *t = get_tuple(be,bt);
02980 t = Switch(2,t);
02981 BezierTriangle *ot = t.f;
02982 list<BezierTriangle*>::iterator result = find(new_triangles.begin(),new_triangles.end(),ot);
02983 if (result != new_triangles.end())
02984 {
02985 free_edges.push_back(be);
02986 }
02987 }
02988 }
02989 free_edges.unique();
02990
02991
02992
02993 list<BezierVertex*> free_vertices;
02994
02995 for (list<BezierTriangle*>::iterator it = new_triangles.begin();
02996 it != new_triangles.end(); ++it)
02997 {
02998 BezierTriangle *bt = *it;
02999 for (int j = 0; j < 3; j++)
03000 {
03001 BezierVertex *be = bt->get_vertex(i);
03002 BezierTuple *t = get_tuple(be,bv);
03003
03004 bool free = true;
03005
03006
03007 {
03008 list<BezierTriangle*>::iterator result = find(new_triangles.begin(),new_triangles.end(),ot);
03009 if (result == new_triangles.end())
03010 {
03011 free = false;
03012 break;
03013 }
03014 }
03015 }
03016 }
03017 free_vertices.unique();
03018
03019
03020 for (list<BezierEdge*>::iterator it = free_edges.begin();
03021 it != free_edges.end(); it++)
03022 {
03023 BezierEdge *fe = *it;
03024 LinearData data = &fe->access_dp(1);
03025 data->zero();
03026 }
03027 for (list<BezierVertex*>::iterator it = free_vertices.begin();
03028 it != free_vertices.end(); it++)
03029 {
03030 BezierEdge *fv = *it;
03031 LinearData data = &fv->access_dp();
03032 data->zero();
03033 }
03034
03035
03036
03037
03038
03039
03040 bool tri_orientation[2][3];
03041 double v0alpha,v0beta, v1alpha,v1beta;
03042 for(i=0; i< 2; i++){
03043 edge_param_to_tri_param(e,newt[i],0,v0alpha,v0beta);
03044 edge_param_to_tri_param(e,newt[i],1,v1alpha,v1beta);
03045 tri_orientation[i][0]= (v0alpha != v1alpha);
03046 tri_orientation[i][1]= (v0beta != v1beta);
03047 tri_orientation[i][2]= !(tri_orientation[i][0] && tri_orientation[i][1]);
03048 }
03049
03050
03051
03052
03053 double jacobian_det;
03054 double alpha, beta;
03055 BezierTriangle *t;
03056
03057 double final_weight = 1.0;
03058 LinearData interp_err(data->length);
03059 bool successful_interpolation;
03060
03061 LinearData ErrInt(data->length);
03062 double PhiInt=0.0;
03063
03064 LinearData TotalErrInt(data->length);
03065 double TotalPhiInt=0.0;
03066
03067 for(i=0; i < 2; i++){
03068 t = newt[i];
03069 for(j=0; j < 7; j++){
03070 alpha = ALPHA[j];
03071 beta = BETA[j];
03072 jacobian_det = fabs(t->jacobian(alpha, beta)) * WEIGHT[j];
03073
03074
03075
03076
03077
03078 successful_interpolation = interpolant_error(t, oldt, alpha, beta, interp_err);
03079 if(successful_interpolation){
03080 ErrInt += interp_err * jacobian_det;
03081 PhiInt += phi_evaluate(tri_orientation[i], alpha, beta) * jacobian_det;
03082 }
03083 else {
03084 final_weight -= WEIGHT[j];
03085 }
03086 }
03087
03088
03089
03090 TotalErrInt += ErrInt * final_weight;
03091 TotalPhiInt += PhiInt * final_weight;
03092 }
03093
03094
03095 *data = TotalErrInt * (1.0 / TotalPhiInt);
03096 }
03097 #endif
03098
03099
03117 void BezierMesh::reinterpolate(BezierEdge* e, BezierTriangle **newt, GhostTriangle **oldt){
03118 int i,j;
03119 LinearData *data;
03120
03121 data = &e->access_dp(1);
03122 data->zero();
03123
03124
03125 if(data->length==0) return;
03126
03127
03128
03129
03130
03131
03132
03133 bool tri_orientation[2][3];
03134 double v0alpha,v0beta, v1alpha,v1beta;
03135 for(i=0; i< 2; i++){
03136 edge_param_to_tri_param(e,newt[i],0,v0alpha,v0beta);
03137 edge_param_to_tri_param(e,newt[i],1,v1alpha,v1beta);
03138 tri_orientation[i][0]= (v0alpha != v1alpha);
03139 tri_orientation[i][1]= (v0beta != v1beta);
03140 tri_orientation[i][2]= !(tri_orientation[i][0] && tri_orientation[i][1]);
03141 }
03142
03143
03144
03145
03146 double jacobian_det;
03147 double alpha, beta;
03148 BezierTriangle *t;
03149
03150 double final_weight = 1.0;
03151 LinearData interp_err(data->length);
03152 bool successful_interpolation;
03153
03154 LinearData ErrInt(data->length);
03155 double PhiInt=0.0;
03156
03157 LinearData TotalErrInt(data->length);
03158 double TotalPhiInt=0.0;
03159
03160 for(i=0; i < 2; i++){
03161 t = newt[i];
03162 for(j=0; j < 7; j++){
03163 alpha = ALPHA[j];
03164 beta = BETA[j];
03165 jacobian_det = fabs(t->jacobian(alpha, beta)) * WEIGHT[j];
03166
03167
03168
03169
03170
03171 successful_interpolation = interpolant_error(t, oldt, alpha, beta, interp_err);
03172 if(successful_interpolation){
03173 ErrInt += interp_err * jacobian_det;
03174 PhiInt += phi_evaluate(tri_orientation[i], alpha, beta) * jacobian_det;
03175 }
03176 else {
03177 final_weight -= WEIGHT[j];
03178 }
03179 }
03180
03181
03182
03183 TotalErrInt += ErrInt * final_weight;
03184 TotalPhiInt += PhiInt * final_weight;
03185 }
03186
03187
03188 *data = TotalErrInt * (1.0 / TotalPhiInt);
03189 }
03190
03192 double BezierMesh::phi_evaluate(bool *tri_orientation, double alpha, double beta){
03193 double val;
03194 val=2.0;
03195 if(tri_orientation[0]) val *= alpha;
03196 if(tri_orientation[1]) val *= beta;
03197 if(tri_orientation[2]) val *= 1-alpha-beta;
03198 return val;
03199 }
03200
03217 bool BezierMesh::interpolant_error(BezierTriangle *t, GhostTriangle **oldt, double alpha, double beta, LinearData &interp_err){
03218 Point2D pt;
03219 int ghost_triangle_index;
03220 double oldt_alpha, oldt_beta;
03221 LinearData oldt_data;
03222
03223 pt = t->eval(alpha,beta);
03224 ghost_triangle_index = 0;
03225
03226 if( !oldt[ ghost_triangle_index ]->newton_find(pt, oldt_alpha, oldt_beta) ){
03227 ghost_triangle_index++;
03228 if( !oldt[ghost_triangle_index]->newton_find(pt,oldt_alpha,oldt_beta)){
03229 return false;
03230 }
03231 }
03232
03233 interp_err = oldt[ghost_triangle_index]->dataeval(oldt_alpha, oldt_beta) - t->dataeval(alpha,beta);
03234 return true;
03235 }
03236
03248 double BezierMesh::function_angle(BezierEdge *e, double u, int func_idx)
03249 {
03250 if (e->num_faces() < 2) {
03251
03252 return 0.0;
03253 }
03254
03255 double v = 1.0 - u;
03256 BezierTriangle *t0 = *e->begin_faces();
03257 BezierTriangle *t1 = *++e->begin_faces();
03258 if( !(t0 && t1) ) return 0.0;
03259
03260
03261 ControlPoint dummy;
03262 ControlPoint t0_cp3, t0_cp4;
03263 ControlPoint t1_cp3, t1_cp4;
03264 tri_cps_off_edge(e, t0, t0_cp3, t0_cp4, dummy);
03265 tri_cps_off_edge(e, t1, t1_cp3, t1_cp4, dummy);
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275 double data;
03276 data = (*datastore->get_data(t0_cp3))[func_idx]*u
03277 + (*datastore->get_data(t0_cp4))[func_idx]*v;
03278 Vec3D p0( ((*t0_cp3)*u + (*t0_cp4)*v), data);
03279
03280 data = e->get_dp(0)[func_idx] * u
03281 + e->get_dp(1)[func_idx] * v;
03282 Vec3D p1( (e->get_cp(0)*u + e->get_cp(1)*v), data);
03283
03284 data = e->get_dp(1)[func_idx] * u
03285 + e->get_dp(2)[func_idx] * v;
03286 Vec3D p2( (e->get_cp(1)*u + e->get_cp(2)*v), data);
03287
03288 data = (*datastore->get_data(t1_cp3))[func_idx]*u
03289 + (*datastore->get_data(t1_cp4))[func_idx]*v;
03290 Vec3D p3( ((*t1_cp3)*u + (*t1_cp4)*v), data);
03291
03292 Vec3D v0 = p0-p1;
03293 Vec3D v1 = p2-p1;
03294 Vec3D v2 = p3-p1;
03295 return (v0.cross(v1)).angle(v1.cross(v2));
03296 }
03297
03314 int BezierMesh::smooth_mesh(double jacobian_bound, int passes)
03315 {
03316 int num_smoothed = 0;
03317 BezierMesh::Bezier_Face_Hash_T::iterator i;
03318 BezierTriangle *t;
03319 BezierEdge *e;
03320 int j;
03321 double min_jacobian, max_jacobian, area;
03322 double jacobian_diff1, jacobian_diff2;
03323
03324 for(int p=0; p<passes; p++){
03325 for(i = get_faces_begin(); i != get_faces_end(); ++i){
03326 t = *i;
03327 t->bound_jacobian(min_jacobian, max_jacobian, area);
03328 jacobian_diff1 = 1 - min_jacobian/area;
03329 jacobian_diff2 = max_jacobian/area - 1;
03330 if((min_jacobian < 0) || (max_jacobian < 0) ||
03331 (jacobian_diff1 >= jacobian_bound) || (jacobian_diff2 >= jacobian_bound)) {
03332
03333
03334 for(j=0; j<3; ++j){
03335 e = t->get_edge(j);
03336 if(!e->is_boundary()) {
03337 smooth_edge( e );
03338 num_smoothed++;
03339 }
03340 }
03341 }
03342 }
03343 }
03344 return num_smoothed;
03345 }
03346
03347
03348 int BezierMesh::make_delaunay()
03349 {
03350 return make_delaunay(0.0,0.0);
03351 }
03352
03353 int BezierMesh::make_delaunay(deque<BezierEdge*> flip_list)
03354 {
03355 return make_delaunay(flip_list, 0.0, 0.0);
03356 }
03357
03358
03369 int BezierMesh::make_delaunay(double angle_const, double min_area_const)
03370 {
03371 deque<BezierEdge*> flip_list;
03372
03373 flip_list.insert(flip_list.begin(), get_edges_begin(), get_edges_end());
03374
03375 return make_delaunay(flip_list, angle_const, min_area_const);
03376 }
03377
03378
03379
03380
03381 int BezierMesh::make_delaunay(deque<BezierEdge*> flip_list, double angle_const, double min_area_const)
03382 {
03383 int num_flips=0;
03384
03385 BezierEdge *e;
03386 BezierTuple tup;
03387 bool success;
03388
03389
03390
03391 list<BezierEdge*> local_edges;
03392 vector<BezierEdge*> new_edges;
03393 list<BezierEdge*>::iterator i;
03394 vector<BezierEdge*>::iterator j;
03395
03396
03397
03398 keep_trash();
03399 while( !flip_list.empty() ){
03400 e = flip_list.front();
03401 flip_list.pop_front();
03402 if( !is_member(e) ) continue;
03403 if( e->is_boundary() ) continue;
03404 if( !should_flip(e) ) continue;
03405
03406 #ifdef NEW_DELAUNAY_ALG
03407
03408 if(check_func_angles && should_refine_func_angle(e, angle_const, min_area_const)){
03409 num_splits++;
03410 split_edge_near_unflippable(e, new_edges);
03411 continue;
03412 }
03413 #endif
03414
03415 success = flip(e, tup);
03416
03417 #ifdef NEW_DELAUNAY_ALG
03418
03419 if(!success){
03420 num_failures++;
03421 num_splits++;
03422 split_edge_near_unflippable(e, new_edges);
03423 } else {
03424 num_flips++;
03425 find_adjacent_edges(tup.e, flip_list);
03426 }
03427 #else
03428 num_flips++;
03429 find_adjacent_edges(tup.e, flip_list);
03430 #endif
03431 }
03432 empty_trash();
03433 return num_flips;
03434 }
03435
03445 int BezierMesh::protect_boundarys()
03446 {
03447 int num_refines=0;
03448 deque<BezierEdge*> edges_list;
03449 BezierEdge *e;
03450 BezierVertex *v;
03451 BezierTuple tup;
03452 bool double_sided;
03453 Point2D p0, p1;
03454
03455 keep_trash();
03456 copy(get_edges_begin(), get_edges_end(), back_inserter(edges_list));
03457 while( !edges_list.empty() ){
03458 e = edges_list.front();
03459 edges_list.pop_front();
03460 if( !is_member(e) || !e->is_boundary() ) continue;
03461
03462
03463 tup = Switch(0, Switch(1, get_tuple(e)));
03464 if( tup.e->is_boundary() || Switch(1, tup).e->is_boundary())
03465 continue;
03466 p0 = tup.v->get_cp();
03467
03468
03469 double_sided = e->num_faces() == 2;
03470 if(double_sided) {
03471 tup = Switch(0, Switch(1, Switch(2, get_tuple(e))));
03472 if(tup.e->is_boundary() || Switch(1, tup).e->is_boundary())
03473 continue;
03474 p1 = tup.v->get_cp();
03475 }
03476
03477 if(e->is_encroached(p0) || (double_sided && e->is_encroached(p1)) ){
03478 v = clean_insert_edge_midpoint(e, 0.5);
03479 num_refines++;
03480 enqueue_edges(v, edges_list);
03481 }
03482 }
03483 empty_trash();
03484 return num_refines;
03485 }
03486
03497 int BezierMesh::remove_small_angles()
03498 {
03499 int num_refines=0;
03500 deque<BezierTriangle*> refine_queue;
03501 BezierTriangle *t;
03502 BezierVertex *vert;
03503
03504
03505 copy(get_faces_begin(), get_faces_end(), back_inserter( refine_queue ));
03506
03507
03508
03509 keep_trash();
03510 while( !refine_queue.empty() ){
03511 t = refine_queue.front();
03512 refine_queue.pop_front();
03513 if( !is_member(t) ) continue;
03514 if( !t->small_angle() ) continue;
03515
03516
03517 num_refines++;
03518 vert = clean_insert_circumcenter(t);
03519 assert(vert != NULL);
03520
03521 enqueue_faces(vert, refine_queue);
03522 }
03523 empty_trash();
03524 return num_refines;
03525 }
03526
03536 int BezierMesh::remove_large_triangles(double size_const)
03537 {
03538 int num_refines=0;
03539 deque<BezierTriangle*> refine_queue;
03540 BezierVertex *vert;
03541
03542
03543 copy(get_faces_begin(), get_faces_end(), back_inserter( refine_queue ));
03544
03545
03546 keep_trash();
03547 while( !refine_queue.empty() ){
03548 BezierTriangle *t = refine_queue.front();
03549 refine_queue.pop_front();
03550 if( !is_member(t) ) continue;
03551
03552
03553
03554
03555
03556 if( t->area() < 2.0 * PI * size_const ) continue;
03557
03558
03559 num_refines++;
03560 vert = clean_insert_circumcenter(t);
03561 assert(vert != NULL);
03562 if (vert != NULL) enqueue_faces(vert, refine_queue);
03563 }
03564 empty_trash();
03565 return num_refines;
03566 }
03567
03568
03569
03570
03571
03572
03607 int BezierMesh::coarsen_const_size(double size_const, double lip_const, double nn_const, double dp_epsilon)
03608 {
03609 EdgeLengthMapT edge_length;
03610 BallRadiusMapT radius;
03611 VertexSetT keep;
03612 CoarsenQueueT queue(get_num_vertices());
03613 CoarsenKillListT tokill;
03614 int num_coarsens;
03615
03616 #ifdef CHECK_COARSEN
03617 cout<<"Called Coarsen_Const_Size"<<endl;
03618 #endif
03619
03620 coarsen_calculate_edge_lengths(edge_length);
03621 coarsen_keep_boundary(dp_epsilon, keep);
03622 coarsen_approximate_sizing_func(size_const, nn_const, queue, keep, edge_length);
03623 coarsen_make_lipshitz(lip_const, queue, edge_length, radius);
03624 #ifdef CHECK_COARSEN
03625 cout<<"Finished Coarsening Function Determination"<<endl;
03626 coarsen_draw_debug(keep, radius, tokill);
03627 #endif
03628 coarsen_find_verts_to_remove(keep, edge_length, radius, tokill);
03629 #ifdef CHECK_COARSEN
03630 cout<<"Selected a Delete Set"<<endl;
03631 coarsen_draw_debug(keep, radius, tokill);
03632 #endif
03633 num_coarsens = coarsen_remove_verts(tokill);
03634 return num_coarsens;
03635 }
03636
03656 int BezierMesh::coarsen_func_angle(double size_const, double lip_const, double nn_const, double dp_epsilon,
03657 double angle_const, double min_area_const)
03658 {
03659 EdgeLengthMapT edge_length;
03660 BallRadiusMapT radius;
03661 VertexSetT keep;
03662 CoarsenQueueT queue(get_num_vertices());
03663 CoarsenKillListT tokill;
03664 int num_coarsens;
03665
03666 coarsen_calculate_edge_lengths(edge_length);
03667 coarsen_keep_boundary(dp_epsilon, keep);
03668 coarsen_keep_large_function_angles(angle_const, min_area_const, keep);
03669 coarsen_approximate_sizing_func(size_const, nn_const, queue, keep, edge_length);
03670 coarsen_make_lipshitz(lip_const, queue, edge_length, radius);
03671 #ifdef CHECK_COARSEN
03672 coarsen_draw_debug(keep, radius, tokill);
03673 #endif
03674 coarsen_find_verts_to_remove(keep, edge_length, radius, tokill);
03675 #ifdef CHECK_COARSEN
03676 coarsen_draw_debug(keep, radius, tokill);
03677 #endif
03678 num_coarsens = coarsen_remove_verts(tokill);
03679 return num_coarsens;
03680 }
03681
03682 int BezierMesh::coarsen_func_angle_debug(double size_const, double lip_const, double nn_const, double dp_epsilon,
03683 double angle_const, double min_area_const)
03684 {
03685 EdgeLengthMapT edge_length;
03686 BallRadiusMapT radius;
03687 VertexSetT keep;
03688 CoarsenQueueT queue(get_num_vertices());
03689 CoarsenKillListT tokill;
03690 int num_coarsens;
03691
03692 coarsen_calculate_edge_lengths(edge_length);
03693 coarsen_keep_boundary(dp_epsilon, keep);
03694 coarsen_keep_large_function_angles(angle_const, min_area_const, keep);
03695 coarsen_approximate_sizing_func(size_const, nn_const, queue, keep, edge_length);
03696 coarsen_make_lipshitz(lip_const, queue, edge_length, radius);
03697 coarsen_draw_debug(keep, radius, tokill);
03698 coarsen_find_verts_to_remove(keep, edge_length, radius, tokill);
03699 coarsen_draw_debug(keep, radius, tokill);
03700 num_coarsens = coarsen_remove_verts(tokill);
03701 return num_coarsens;
03702 }
03703
03711 void BezierMesh::coarsen_calculate_edge_lengths(EdgeLengthMapT &edge_length)
03712 {
03713
03714
03715 for(Edge_Hash_T::iterator edge_iter = get_edges_begin();
03716 edge_iter != get_edges_end(); ++edge_iter) {
03717 BezierEdge *e = *edge_iter;
03718 BezierVertex *v0, *v1;
03719 v0 = e->get_vertex(0);
03720 v1 = e->get_vertex(1);
03721 edge_length[e] = (v0->get_cp() - v1->get_cp()).mag();
03722 }
03723 }
03724
03734 void BezierMesh::coarsen_keep_boundary(double dp_epsilon, VertexSetT &keep)
03735 {
03736 BoundaryMesh::Boundary_Vertex_Hash_T::iterator bdry_vert_iter;
03737 BoundaryMesh::Boundary_Edge_Hash_T::iterator bdry_edge_iter;
03738
03739
03740 for(bdry_vert_iter = boundarymesh->get_vertexs_begin();
03741 bdry_vert_iter != boundarymesh->get_vertexs_end(); ++bdry_vert_iter) {
03742 keep.insert( (*bdry_vert_iter)->get_bezier() );
03743 }
03744
03745
03746 for(bdry_edge_iter = boundarymesh->get_edges_begin();
03747 bdry_edge_iter != boundarymesh->get_edges_end(); ++bdry_edge_iter) {
03748 (*bdry_edge_iter)->get_spline()->douglas_peucker(dp_epsilon, keep);
03749 }
03750 }
03751
03752
03753
03754
03766 void BezierMesh::coarsen_keep_large_function_angles(double angle_const,
03767 double min_area_const,
03768 VertexSetT &keep)
03769 {
03770
03771
03772
03773
03774
03775
03776 double angle_adj=0.50;
03777
03778
03779
03780 double area_adj=0.80;
03781
03782 angle_const *= angle_adj;
03783 min_area_const *= area_adj;
03784
03785 for(Edge_Hash_T::iterator edge_iter = get_edges_begin();
03786 edge_iter != get_edges_end(); ++edge_iter) {
03787 BezierEdge *e = *edge_iter;
03788 if( !should_refine_func_angle(e, angle_const, min_area_const) ) {
03789 continue;
03790 }
03791
03792
03793
03794 for(int i = 0; i < 2 ; ++i) {
03795 keep.insert(e->get_vertex(i));
03796 }
03797 }
03798 }
03799
03815 void BezierMesh::coarsen_approximate_sizing_func(double size_const, double nn_const, CoarsenQueueT &queue,
03816 VertexSetT &keep, EdgeLengthMapT &edge_length)
03817 {
03818 double radius_const = sqrt(size_const);
03819
03820
03821
03822
03823
03824
03825
03826 for(Vertex_Hash_T::iterator vert_iter = get_vertexs_begin();
03827 vert_iter != get_vertexs_end(); ++vert_iter) {
03828 BezierVertex *v = *vert_iter;
03829
03830
03831 if(keep.find(v) != keep.end()){
03832
03833 double min = std::numeric_limits<double>::infinity();
03834 for(BezierVertex::edge_iterator it = v->begin_edges();
03835 it != v->end_edges(); ++it) {
03836 BezierEdge *e = *it;
03837 double dist = edge_length[e] * 0.49;
03838 if(dist < min) min = dist;
03839 }
03840 queue.decrease(v, min);
03841 }
03842
03843
03844
03845
03846
03847
03848 else {
03849 double min = radius_const;
03850 for(BezierVertex::edge_iterator it = v->begin_edges();
03851 it != v->end_edges(); ++it) {
03852 BezierEdge *e = *it;
03853 double dist = edge_length[e] * nn_const;
03854 if( dist < min) min = dist;
03855 }
03856 queue.decrease(v, min);
03857 }
03858 }
03859 }
03860
03861
03876 void BezierMesh::coarsen_make_lipshitz(double lip_const, CoarsenQueueT &queue,
03877 EdgeLengthMapT &edge_length, BallRadiusMapT &radius)
03878 {
03879 BezierEdge *e;
03880 BezierVertex *v= NULL;
03881 BezierVertex *v0;
03882 double r = 0.0;
03883
03884 while( !queue.empty() ){
03885 queue.rem_min(v, r);
03886 for(BezierVertex::edge_iterator it = v->begin_edges();
03887 it != v->end_edges(); ++it) {
03888 e = *it;
03889 v0 = get_opposite_vertex(e, v);
03890 queue.decrease(v0, r + lip_const * edge_length[e]);
03891 }
03892 radius[v] = r;
03893 }
03894 }
03895
03907 void BezierMesh::coarsen_find_verts_to_remove(VertexSetT &keep, EdgeLengthMapT &edge_length,
03908 BallRadiusMapT &radius, CoarsenKillListT &tokill)
03909 {
03910
03911
03912
03913 for(Vertex_Hash_T::iterator vert_iter = get_vertexs_begin();
03914 vert_iter != get_vertexs_end(); ++vert_iter) {
03915 BezierVertex *v = *vert_iter;
03916 if(keep.find(v) != keep.end()) continue;
03917
03918 bool should_keep = true;
03919 double r = radius[v];
03920 for(BezierVertex::edge_iterator it = v->begin_edges();
03921 it != v->end_edges(); ++it) {
03922 BezierEdge *e = *it;
03923 BezierVertex *v0 = get_opposite_vertex(e, v);
03924 if(keep.find(v0) != keep.end()){
03925 if(r + radius[v0] > edge_length[e]){
03926 should_keep=false;
03927 break;
03928 }
03929 }
03930 }
03931 if(should_keep) keep.insert(v);
03932 else tokill.push_back(v);
03933 }
03934 }
03935
03936
03942 int BezierMesh::coarsen_remove_verts(CoarsenKillListT &tokill)
03943 {
03944 int num_coarsens=0;
03945 BezierVertex *v;
03946
03947
03948 while(!tokill.empty()){
03949 v = tokill.front();
03950 tokill.pop_front();
03951 num_coarsens++;
03952 remove_vertex(v);
03953 }
03954 return num_coarsens;
03955 }
03956
03958 void BezierMesh::coarsen_draw_debug(VertexSetT &keep, BallRadiusMapT &radius, CoarsenKillListT &tokill)
03959 {
03960 #ifdef VISUAL_DEBUG
03961 VertexSetT killset;
03962 CoarsenKillListT::iterator i;
03963
03964 Visualization vis(this, this->boundarymesh, false);
03965 vis.start_draw();
03966 vis.draw(GREEN,BLUE);
03967 for(Vertex_Hash_T::iterator vert_iter = get_vertexs_begin();
03968 vert_iter != get_vertexs_end(); ++vert_iter) {
03969 BezierVertex *v = *vert_iter;
03970
03971
03972 for(i=tokill.begin(); i!=tokill.end(); ++i){
03973 if(*i == v){
03974 killset.insert(v);
03975 break;
03976 }
03977 }
03978 }
03979
03980
03981
03982 for(Vertex_Hash_T::iterator vert_iter = get_vertexs_begin();
03983 vert_iter != get_vertexs_end(); ++vert_iter) {
03984 BezierVertex *v = *vert_iter;
03985 if(killset.find(v) != killset.end()) vis.draw_point(v->get_cp(), GRAY4, 3.0);
03986 else vis.draw_circle(RED, v->get_cp(), radius[v]);
03987
03988 if(keep.find(v) != keep.end()) vis.draw_point(v->get_cp(), RED, 3.0);
03989 }
03990 vis.finish_draw();
03991
03992
03993
03994 vis.start_draw();
03995 vis.draw(GREEN, BLUE);
03996 vis.finish_draw();
03997 #endif
03998 }
03999
04012 int BezierMesh::function_angle_refine(double angle_const, double min_area_const)
04013 {
04014 list<BezierTriangle*> todo;
04015 int num_refines=0;
04016
04017
04018 for(Edge_Hash_T::iterator edge_iter = get_edges_begin();
04019 edge_iter != get_edges_end(); ++edge_iter) {
04020 BezierEdge *e = *edge_iter;
04021 if( !should_refine_func_angle(e, angle_const, min_area_const) ) {
04022 continue;
04023 }
04024
04025
04026 todo.insert(todo.end(), e->begin_faces(), e->end_faces());
04027 }
04028
04029
04030
04031
04032
04033 list<BezierTriangle*>::iterator i;
04034 keep_trash();
04035 for(i=todo.begin(); i!= todo.end(); ++i){
04036 BezierTriangle *t = *i;
04037 if(!is_member(t)) continue;
04038 clean_insert_circumcenter(t);
04039 num_refines++;
04040 }
04041 empty_trash();
04042 return num_refines;
04043 }
04044
04057 bool BezierMesh::should_refine_func_angle(BezierEdge *e, double angle_const, double min_area_const)
04058 {
04059 if(e->is_boundary()) return false;
04060 if(e->num_faces() != 2) return false;
04061
04062 if(func_angle_x_cuttoff > 0.0 && (e->get_cp(0).x() > func_angle_x_cuttoff || e->get_cp(2).x() > func_angle_x_cuttoff)) return false;
04063
04064 double xangle = (function_angle(e,0.0,0) + function_angle(e,1.0,0) + function_angle(e,0.5,0)) / 3.0;
04065 double yangle = (function_angle(e,0.0,1) + function_angle(e,1.0,1) + function_angle(e,0.5,1)) / 3.0;
04066
04067
04068 if((xangle < angle_const) && (yangle < angle_const)) return false;
04069
04070
04071 for(BezierEdge::face_iterator it = e->begin_faces();
04072 it != e->end_faces(); ++it) {
04073 if((*it)->area() < min_area_const) {
04074 return false;
04075 }
04076 }
04077
04078
04079 return true;
04080 }
04081
04092 int BezierMesh::find_inverted_triangles(vector<BezierTriangle*> &inverted)
04093 {
04094 int num_inverted=0;
04095 BezierTriangle *t;
04096
04097 for(Face_Hash_T::iterator it = get_faces_begin();
04098 it != get_faces_end(); ++it) {
04099 t = *it;
04100
04101
04102 if (! (t->is_definitely_not_inverted()) )
04103 {
04104 num_inverted++;
04105 inverted.push_back(t);
04106 }
04107 }
04108 return num_inverted;
04109 }
04110
04120 int BezierMesh::classify_inverted_triangles(vector<BezierTriangle*> &normal, vector<BezierTriangle*> &inverted, vector<BezierTriangle*> &unknown)
04121 {
04122 int num_inverted=0;
04123 int num_unknown=0;
04124 int num_normal=0;
04125 int num_errors=0;
04126 BezierTriangle *t;
04127 int status;
04128
04129 for(Face_Hash_T::iterator it = get_faces_begin();
04130 it != get_faces_end(); ++it) {
04131 t = *it;
04132 status = t->is_inverted();
04133 switch(status){
04134 case 1:
04135 num_inverted++;
04136 inverted.push_back(t);
04137 break;
04138 case 0:
04139 num_normal++;
04140 normal.push_back(t);
04141 break;
04142 case -1:
04143 num_unknown++;
04144 unknown.push_back(t);
04145 break;
04146 case -2:
04147 num_errors++;
04148 }
04149 }
04150 return num_inverted;
04151 }
04152
04153
04161 bool BezierMesh::check_consistency() const
04162 {
04163
04164
04165 bool is_good = true;
04166 for(Face_Hash_T::const_iterator it = get_faces_begin();
04167 it != get_faces_end(); ++it) {
04168 const BezierTriangle *t = *it;
04169
04170 for(int i=0; i<2; i++){
04171 const BezierEdge *e = t->get_edge(i);
04172 int orient = orient_edge_triangle(e,t);
04173
04174 static const int orderings[6][3] = {
04175 { 0, 1, 2 },
04176 { 2, 4, 5 },
04177 { 5, 3, 0 },
04178 { 2, 1, 0 },
04179 { 5, 4, 2 },
04180 { 0, 3, 5 }
04181 };
04182 assert(orient >= 0); assert(orient < 6);
04183 if (!consistency_check_helper(t,e,orderings[orient])) {
04184 cerr << "Orientation was: " << orient << endl;
04185 is_good = false;
04186 }
04187 }
04188 }
04189
04190
04191 int mismatch = 0;
04192 for(vector<BezierTriangle*>::const_iterator it = sampler.begin();
04193 it != sampler.end(); ++it) {
04194 if (!is_member(*it)) {
04195 mismatch++;
04196 cerr << "bad triangle in sampler: " << **it;
04197 }
04198 }
04199 if (mismatch != 0) {
04200 is_good = false;
04201 cerr << mismatch << " bad triangles in sampler\n";
04202 }
04203 if (sampler.size() != (unsigned)get_num_faces()) {
04204 is_good = false;
04205 cerr << "size mismatch in sampler: " << sampler.size() << " should be "
04206 << get_num_faces() << endl;
04207 }
04208
04209
04210 int switch_sizes[3] = {
04211 get_num_edges() * 2,
04212 get_num_faces() * 6,
04213 get_num_faces() * 3
04214 };
04215 for(int i = 0; i < 3; i++) {
04216 if (switch_size(i) != switch_sizes[i]) {
04217 is_good = false;
04218 cerr << "switch"<<i<<" has size " << switch_size(i) << " should be "
04219 << switch_sizes[i] << endl;
04220 }
04221 }
04222
04223
04224 {
04225 hash_set<BezierVertex*> vertices;
04226 hash_set<BezierEdge*> edges;
04227 hash_set<BezierTriangle*> triangles;
04228 stack<BezierTriangle*> todo;
04229 todo.push(get_tuple().f);
04230 while(!todo.empty()) {
04231 BezierTriangle *t = todo.top();
04232 todo.pop();
04233 if (triangles.count(t) != 0) {
04234 continue;
04235 }
04236 triangles.insert(t);
04237
04238 BezierTuple start = get_tuple(t);
04239 BezierTuple current = start;
04240 do {
04241 BezierTriangle *opposite = Switch(2, current).f;
04242
04243 if (!is_member(current.v)) {
04244 is_good = false;
04245 cerr << current.v << " not a member\n";
04246 }
04247 if (!is_member(current.e)) {
04248 is_good = false;
04249 cerr << current.e << " not a member\n";
04250 }
04251 if (!is_member(current.f)) {
04252 is_good = false;
04253 cerr << current.f << " not a member\n";
04254 }
04255 if (!is_member(opposite)) {
04256 is_good = false;
04257 cerr << opposite << " not a member\n";
04258 }
04259
04260 vertices.insert(current.v);
04261 edges.insert(current.e);
04262 todo.push(opposite);
04263 current = Switch(1, Switch(0, current));
04264 } while(current != start);
04265 }
04266
04267 if (vertices.size() != (unsigned)get_num_vertices()) {
04268 is_good = false;
04269 cerr << "only " << vertices.size() << " vertices reached out of "
04270 << get_num_vertices() << endl;
04271 }
04272 if (edges.size() != (unsigned)get_num_edges()) {
04273 is_good = false;
04274 cerr << "only " << edges.size() << " edges reached out of "
04275 << get_num_edges() << endl;
04276 }
04277 if (triangles.size() != (unsigned)get_num_faces()) {
04278 is_good = false;
04279 cerr << "only " << triangles.size() << " triangles reached out of "
04280 << get_num_faces() << endl;
04281 }
04282 }
04283
04284 #ifdef DEBUG
04285 if (!is_good) {
04286 static int writes = 0;
04287 char name[4096];
04288 snprintf(name, sizeof(name), "check_consistency%03d.geo", writes++);
04289 MeshBinaryOutput::write(name, const_cast<BezierMesh*>(this),
04290 const_cast<BoundaryMesh*>(boundarymesh));
04291 }
04292 #endif
04293
04294 return is_good;
04295 }
04296
04303 bool BezierMesh::consistency_check_helper(const BezierTriangle *t,
04304 const BezierEdge *e,
04305 const int p[3]) const
04306 {
04307 const BezierVertex *v0, *v1;
04308 v0 = e->get_vertex(0);
04309 v1 = e->get_vertex(1);
04310 ControlPoint v0cp = v0->get_control_point();
04311 ControlPoint v1cp = v1->get_control_point();
04312 DataPoint v0dp = v0->get_data_point();
04313 DataPoint v1dp = v1->get_data_point();
04314
04315
04316 for(int i = 0; i < 3; ++i) {
04317 if (e->get_control_point(i) != t->get_control_point(p[i])) {
04318 cout<<"Edge control points don't coorespond to triangle's"<<endl
04319 <<"T: "<<*t<<endl
04320 <<"E: "<<*e<<endl<<endl;
04321 return false;
04322 }
04323 }
04324 if( (v0cp != e->get_control_point(0)) || (v1cp != e->get_control_point(2))){
04325 cout<<"Vertex control points don't coorespond to edges's"<<endl
04326 <<"E: "<<*e<<endl
04327 <<"V0: "<<*v0<<endl
04328 <<"V1: "<<*v1<<endl;
04329 return false;
04330 }
04331 if((v0cp != t->get_control_point(p[0])) || (v1cp != t->get_control_point(p[2]))){
04332 cout<<"Vertex control points don't coorespond to triangle's"<<endl
04333 <<"T: "<<*t<<endl
04334 <<"E: "<<*e<<endl
04335 <<"V0: "<<*v0<<endl
04336 <<"V1: "<<*v1<<endl;
04337 return false;
04338 }
04339
04340
04341
04342 for(int i = 0; i < 3; ++i) {
04343 if (e->get_data_point(i) != t->get_data_point(p[i])) {
04344 cout<<"Edge data points don't coorespond to triangle's"<<endl
04345 <<"T: "<<*t<<endl
04346 <<"E: "<<*e<<endl<<endl;
04347 return false;
04348 }
04349 }
04350 if( (v0dp != e->get_data_point(0)) || (v1dp != e->get_data_point(2))){
04351 cout<<"Vertex data points don't coorespond to edges's"<<endl
04352 <<"E: "<<*e<<endl
04353 <<"V0: "<<*v0<<endl
04354 <<"V1: "<<*v1<<endl;
04355 return false;
04356 }
04357 if((v0dp != t->get_data_point(p[0])) || (v1dp != t->get_data_point(p[2]))){
04358 cout<<"Vertex data points don't coorespond to triangle's"<<endl
04359 <<"T: "<<*t<<endl
04360 <<"E: "<<*e<<endl
04361 <<"V0: "<<*v0<<endl
04362 <<"V1: "<<*v1<<endl;
04363 return false;
04364 }
04365 return true;
04366 }
04367
04374 bool BezierMesh::print_check_inverted(const char *message, int expected)
04375 {
04376 #ifdef DEBUG
04377 static int writes = 0;
04378 vector<BezierTriangle*> inverts;
04379 find_inverted_triangles(inverts);
04380 int inverted = inverts.size();
04381 if (!inverts.empty()) {
04382 cout<< " INVERTED TRIANGLES CREATED\n";
04383 cout << " -> " << message << endl;
04384 for (vector<BezierTriangle*>::iterator i = inverts.begin();
04385 i != inverts.end(); ++i) {
04386 BezierTriangle *t = *i;
04387 draw_insert_error("InvertedTriangle",t);
04388 cout << "Inverted Triangle (" << t->is_inverted() << "): "
04389 <<(*t)<<endl;
04390 if(t->is_inverted() == -1) {
04391 inverted--;
04392 }
04393 }
04394 char name[4096];
04395 sprintf(name, "print_check_inverted%03d.geo", writes++);
04396 MeshBinaryOutput::write(name, this, boundarymesh);
04397 }
04398 return check_consistency() && inverted == expected;
04399 #endif
04400 return true;
04401 }
04402
04404 ostream& operator<<( ostream &stream, const BezierMesh &bm)
04405 {
04406 stream<<"BezierMesh"<<endl;
04407 stream<<" boundarymesh:"<<bm.boundarymesh<<endl;
04408 stream<<" datastore:"<<bm.datastore<<endl;
04409 stream<<" CellComplex:"<<endl;
04410 stream<<*((BezierComplex*)(&bm))<<endl;
04411 return stream;
04412 }
04413
04414 int BezierMesh::data_length() const {
04415 return datastore->data_length();
04416 }
04417