beziermesh.C

Go to the documentation of this file.
00001 
00008 #ifdef HAVE_CONFIG_H
00009 #include <tumble-conf.h>
00010 #endif /* HAVE_CONFIG_H */
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 /* Turn on several debugging flags, for even more rigour and lots of printing */
00032 //#define DEBUG
00033 
00034 /* All the debug flags */
00035 
00036 //#define DEBUG_FLIP
00037 //#define DEBUG_SMOOTH
00038 //#define DEBUG_INSERTS
00039 //#define DEBUG_LOCATOR
00040 //#define DEBUG_DEVILLERS
00041 
00042 /* Turn on several flags to do more rigorous assertions. */
00043 
00044 //#define CHECK_COARSEN
00045 //#define CHECK_INVERTED
00046 //#define CHECK_SMOOTH
00047 //#define CHECK_FLIP
00048 
00049 
00050 /* allow for visual debugging */
00051 #define VISUAL_DEBUG
00052 
00053 /* use a new delaunay algortithm */
00054 //#define NEW_DELAUNAY_ALG
00055 
00056 #ifdef DEBUG
00057     #include "meshio.h"
00058 
00059     /* check on insertions */
00060     #define DEBUG_INSERTS
00061 
00062     /* debug the point locator */
00063     //#define DEBUG_LOCATOR
00064 
00065     #ifdef CHECK_SMOOTH
00066         /* Turn on smooth debugging */
00067         #define DEBUG_SMOOTH
00068     #endif
00069     #ifdef CHECK_FLIP
00070         /* Turn on flip debugging */
00071        #define DEBUG_FLIP
00072 
00073        /* Turn on  devilliers debugging */
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         /* Draw smooth output */
00088         #define DRAW_SMOOTH
00089     #endif
00090 
00091     #ifdef DEBUG_FLIP
00092         /* Draw flip output */
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     // Add the datapoint first, since the BezierEdge will then go find it.
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     /* if this vertex is on the bdry then the spline or vertex in the bdry mesh
00285      * owns the control point, so leave it alone
00286      */
00287     if(!v->is_boundary()) {
00288       datastore->rem_cp(v->get_control_point());
00289     }
00290 
00291     // this is copied from the CellComplex, which is obviously wrong.
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     /* If this edge is on the bdry then its get_cp(1) is owned by a
00309      * spline in the bdry mesh, we will let the spline deal with
00310      * it when it removes a knot
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   /* Remove the face from the list of faces, and update the indices */
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   /* replace in the BezierVertex's control point */
00344   v->replace_cp(newp);
00345 
00346   /* replace for all the BezierEdge's and BezierTriangles's ControlPoint lists*/
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   /* resync the data_hash mapping in the datastore */
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   /* replace in the edge's control point list */
00366   e->replace_cp(oldp, newp);
00367 
00368   /* replace the poin in the ControlPoint lists of the faces */
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   /* resync the data_hash mapping in the datastore */
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) ); /* ensure that e and t are related */
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   /* A failed assertion means alpha/beta do not correspond to e */
00509   switch( orient_edge_triangle(e,t) ) {
00510     case 0:
00511       //assert(is_zero(alpha));
00512       u = beta;
00513       return;
00514     case 1:
00515       u = alpha;
00516       //assert(are_equal(beta, 1.0 - alpha));
00517       return;
00518     case 2:
00519       u = 1 - alpha;
00520       //assert(is_zero(beta));
00521       return;
00522     case 3:
00523       //assert(is_zero(alpha));
00524       u = 1 - beta;
00525       return;
00526     case 4:
00527       //assert(are_equal(alpha, 1.0 - beta));
00528       u = beta;
00529       return;
00530     case 5:
00531       u = alpha;
00532       //assert(is_zero(beta));
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     /* First check that the given star is valid*/
00602     star_valid = smCheckStarValidity( x, y, 6, p.x(), p.y(), &violator );
00603 
00604     /* Case 4: This is a good point in the kernel, the smooth should not fail here */
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             /* This case might be indicative of internal errors in the smoothing code */
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     /* Now we have a point that is not in the kernel of the ploy
00628      * try to use an AREA smooth to get a point in the kernel
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     /* Case 1 failure: The polygon is not star-shaped */
00634     /* Smoothing is impossible */
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     /* Check to see if the point from AREA smooth is in kernel */
00644     star_valid = smCheckStarValidity( x, y, 6, area_pt.x(), area_pt.y(), &violator );
00645 
00646     /* Case 2 failure: The polygon has no kernel */
00647     /* Smoothing is impossible */
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     /* Case 3:  Poly is OK, initial point was outside kernel, but we fixed it with AREA smooth */
00656     /* Essentially we now have turned Case 3 into Case 4*/
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         /* This case might be indicative of internal errors in the smoothing code */
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      *       v1
00722      *       /\
00723      *      /  \
00724      *    e1    e0
00725      *    /  t0  \
00726      *   /        \
00727      * v2----e-----v0
00728      *   \        /
00729      *    \  t1  /
00730      *    e2    e3
00731      *      \  /
00732      *       \/
00733      *       v3
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     /* Check if we are a type B */
00795     is_typeB = !robust_smooth( poly, primary, secondary, temp);
00796 
00797     /* Check if we are a type A */
00798     /* Check that the outised flips in the control mesh are possible */
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   // Add the cavity edges to the list
00819   new_edges.insert(new_edges.end(), cavity_edges.begin(), cavity_edges.end());
00820 
00821   // Split the edge
00822   BezierVertex *v = insert_edge_midpoint(e, 0.5);
00823 
00824   // Add the spokes from the new vertex to the list
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     // Find the most curved cavity edge
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     // Split a cavity edge if it is more curved than theta (currently uses theta = alpha* / 2)
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     /* counter-clockwise ordering */
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     /* counter-clockwise ordering */
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     /* Check preconditions */
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     /* if linear flips are on then do not use the smoother to get
01161      * the new control point.  instead, make new edge linear
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             /* Hopefully we will never get here */
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             /* Try to keep going if possible */
01181             new_point = e->get_cp(1);
01182         }
01183     }
01184 
01185     /* Create ghost triangles for reinterpolation */
01186     GhostTriangle *oldts[2];
01187     GhostTriangle gt0(*ts[0]);
01188     GhostTriangle gt1(*ts[1]);
01189     oldts[0] = &gt0;
01190     oldts[1] = &gt1;
01191 
01192     /* Use zeroed data as required by reinterpolate.
01193      * reinterpolate will set this correctly later
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] ); // ccw: tp517 4-16-07
01206     newts[1] = add_bezier_triangle( face, new_edge, es[1], es[2], true ); //cw: tp517 4-16-07
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     /* Reset new_edge->dp[1] via reinterpolation code */
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     /* Check preconditions */
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       //WARNING(cout<<"Smooth given Triangle ts[0] with negative jacobian"<<endl);
01259     }
01260     if( ts[1]->is_definitely_inverted() ){
01261       //WARNING(cout<<"Smooth created Triangle ts[1] with negative jacobian"<<endl);
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         /* Hopefully we will never get here */
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     /* Get current triangles */
01288     assert(e->num_faces() == 2);
01289     newts[0] = *e->begin_faces();
01290     newts[1] = *++e->begin_faces();
01291 
01292     /* Copy current triangles to ghost triangles before update*/
01293     GhostTriangle gt0(*newts[0]);
01294     GhostTriangle gt1(*newts[1]);
01295     oldts[0] = &gt0;
01296     oldts[1] = &gt1;
01297 
01298     /* Update edge cp */
01299     e->set_cp(new_center,1);
01300 
01301 #ifdef CHECK_SMOOTH
01302     if( ts[0]->is_definitely_inverted() ){
01303       //WARNING(cout<<"Smooth created Triangle ts[0] with negative jacobian"<<endl);
01304 
01305     if(!debug_smooth(e)){
01306       return false;
01307     }
01308     }
01309     if( ts[1]->is_definitely_inverted() ){
01310       //WARNING(cout<<"Smooth created Triangle ts[1] with negative jacobian"<<endl);
01311     if(!debug_smooth(e)){
01312       return false;
01313     }
01314     }
01315 #endif
01316     /* Let reinterpolate set data for new point*/
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     /* Enumerate vertexs and sides
01350      *
01351      *         v2
01352      *         /\
01353      *     e2 /  \ e1
01354      *       /    \
01355      *   v0 /______\v1
01356      *         e0
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     /* Delete face */
01371     BoundaryFace *face = t->get_bdry_face_or_null();
01372     delete_face( t );
01373 
01374      /* Create new vertex, edges and triangles
01375      *
01376      *          v2
01377      *          /|\
01378      *         / |n\
01379      *        /  |e \
01380      *       /   |2  \
01381      *    e2/    nv   \e1
01382      *     /nt2 / \ nt1\
01383      *    /   /     \   \
01384      *   /  /ne0   ne1\  \
01385      *  / /     nt0     \ \
01386      * v0-----------------v1
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 ); //ccw: tp517 4-16-07
01397     nt1 = add_bezier_triangle( face, ne1, e1, ne2 ); //ccw: tp517 4-16-07
01398     nt2 = add_bezier_triangle( face, ne2, e2, ne0 ); //ccw: tp517 4-16-07
01399 
01400 
01401     // On a really bent triangle, we'll give it the old college try (smooth)
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     /* Is there a triangle on only one side of this edge?
01450      * If not, than there are two triangle to worry about
01451      */
01452     bool one_sided = false;
01453 
01454     /* Is this edge on the boundary?
01455      * If so we need to ensure a knot is added to the spline, and boundary information is updated
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     /* enumerate first triangle's vertices and edges
01481     *  x=initial tup
01482     *         v1
01483     *         /\
01484     *     e1 /  \ e0
01485     *       / t0 \
01486     *   v2 /x_____\v0
01487     *      \  e   /
01488     *     e2\    /e3
01489     *        \t1/
01490     *         \/
01491     *         v3
01492     * Second triangle may not exist if on boundary
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         /* Number second triangle's points and edges */
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       #ifdef DEBUG_INSERTS
01525       cout << "Orienting t0a = "<<t0_alpha<< " t0b = "<<t0_beta <<endl;
01526       cout << "Orienting t1a = "<<t1_alpha<< " t1b = "<<t1_beta <<endl;
01527       #endif
01528     */
01529 
01530     /* These indexes are used to match up the center point of the new edges with
01531      * the appropriate t0 evalIntermediate data.
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     /* this index is for ne3, the only edge created from the t1 evaluation data(note inefficiency).
01550      * this must be the edge that does not duplicate ne0 or ne1, so we need to
01551      * figure out the orientation, to select the right edge
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        #ifdef DEBUG_INSERTS
01566        cout << "Decided on keeping split midpoints "<<t0pc[ne0index]<<" and "<<t0pc[ne1index]<<endl;
01567        cout << "Decided on keeping cross midpoints "<<t0pc[ne2index]<<" and "<<t1pc[ne3index]<<endl;
01568        #endif 
01569     */
01570 
01571      /* Delete e, t0, and t1 */
01572     delete_edge( e );
01573 
01574 
01575     /* Now it's time to create new vertex, edges, and triangles
01576      *
01577      *           v1
01578      *           /|\
01579      *          /n| \
01580      *         / e|  \
01581      *     e1 /  2|   \ e0
01582      *       /nt1 | nt0\
01583      *   v2 /_____|_____\v0
01584      *      \ ne1 | ne0 /     nv=new center vertex
01585      *     e2\nt2 | nt3/e3    one_sided insertion ignores bottom of image
01586      *        \  n|   /
01587      *         \ e|  /
01588      *          \3| /
01589      *           \|/
01590      *            v3
01591      */
01592     BezierVertex *nv;
01593     BezierEdge *ne0, *ne1, *ne2, *ne3 = NULL;
01594     BezierTriangle *nt0, *nt1, *nt2, *nt3;
01595 
01596      if ( is_bdry ) {
01597        /* if we are on the bdry then nv, ne0, ne1 must use spline's cps created
01598         * by add_knot*/
01599         ControlPoint cp0,cp1,cp2;
01600         double splineu, v0u = 0.0, v2u = 0.0;
01601 
01602         /* get u values of vertexs along this boundary edge*/
01603         v0u = v0->get_u(bdry,v2);
01604         v2u = v2->get_u(bdry,v0);
01605         //assert(!Tumble::are_equal(v0u, v2u));
01606 
01607         if (ev[0] == v0) {
01608           /*  u*v2u + (1-u)*v0u  */
01609           splineu = v0u + u*(v2u - v0u);
01610         } else {
01611           /* if the edge is backwards from the spline, then u' = 1 - u */
01612           assert(ev[1] == v0);
01613           assert(ev[0] == v2);
01614 
01615           /* u'*v2u + (1-u')*v0u == u*v02 + (1-u)*v2u */
01616           splineu = v2u + u*(v0u - v2u);
01617         }
01618 
01619         /*insert new knot in spline*/
01620         bdry->get_spline()->add_knot( splineu,cp0,cp1,cp2 );
01621 
01622         /* add vertex */
01623         nv = add_bezier_vertex( cp1, t0_newd );
01624         nv->set_bdry( bdry, splineu );
01625 
01626         /*add edges */
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     /* otherwise if not on the bdry then nv, ne0, ne1 will create their own cps */
01639     else {
01640         /* add vertex */
01641         nv = add_bezier_vertex( t0_newp, t0_newd );
01642 
01643         /*add edges */
01644         ne0 = add_bezier_edge( t0pc[ ne0index ], t0dc[ ne0index ], nv, v0 );
01645         ne1 = add_bezier_edge( t0pc[ ne1index ], t0dc[ ne1index ], nv, v2 );
01646     }
01647      //assert(are_equal(nv->get_cp().x(), insertpt.x()));
01648      //assert(are_equal(nv->get_cp().y(), insertpt.y()));
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     /* add triangles */
01654     nt0 = add_bezier_triangle( t0face, ne0, e0, ne2 ); //ccw: tp517 4-16-07
01655     nt1 = add_bezier_triangle( t0face, ne2, e1, ne1 ); //ccw: tp517 4-16-07
01656     if ( !one_sided ) {
01657       nt2 = add_bezier_triangle( t1face, ne1, e2, ne3 ); //ccw: tp517 4-16-07
01658       nt3 = add_bezier_triangle( t1face, ne3, e3, ne0 ); //ccw: tp517 4-16-07
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     /* initial cavity is simply edges of t */
01726     lower( t, cavity );
01727 
01728     /* check for encroachment on initial cavity */
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     /* if no encroachment then do the insertion and flip out cavity */
01743     new_vertex = insert_point( t, u, v );
01744     flip_out_cavity( cavity, new_cavity, new_vertex );
01745 
01746     if (!force) {
01747     /* now, if e encroaches on any edge in the new cavity we need to back up
01748      * and do an insert_midpoint  this is inefficient, but hopefully most
01749      * cases are caught by the first encroachment cases
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     /* If this isn't a forced point but it is on a bdry, we should be adding the midpoint of the
01781      *  boundary edge instead
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     /* collect all edges around faces of e.  remove e from cavity vector.*/
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     //insert and flip out
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())  // If we've inserted a boundary midpoint, don't yield
01811       {
01812     /* now, if e encroaches on any edge in the new cavity we need to back up
01813      * and do an insert_midpoint  this is inefficient, but hopefully most
01814      * cases are caught by the first encroachment cases
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); // over_bdry makes no sense without a start_tri
01860     assert (over_bdry || !force); // If we can't walk over boundaries, then we can't force this point in
01861     double u,v;
01862     int cd; /* containment dimension */
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         /* Illegal to insert points that already exist. */
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         /* Split the edge we found (either we landed on it, or we're trying
01883            to cross through it). */
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           /* assert that (u,v) lands at p -- unless we hit a boundary */
01894 
01895       /*
01896 
01897       TODO: This needs to be replaced with floating point tolerance
01898 
01899           Point2D ev = cellfound.e->eval(u);
01900           //assert(are_equal(p.x(), ev.x()));
01901           //assert(are_equal(p.y(), ev.y()));
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           /* assert that (u,v) lands at p */
01913           Point2D ev = cellfound.f->eval(u,v);
01914           //assert(are_equal(p.x(), ev.x()));
01915           //assert(are_equal(p.y(), ev.y()));
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     /* grab initial vertex */
01958     v0 = Switch( 0, tup ).v;
01959     link.push_back( v0 );
01960 
01961     /* Switch around vertex (so that tup.v == start_tup.v, always),
01962      * then at each iter, switch0 out to the link and grab the vertex.
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     /* If we hit the bdry, then we must start adding vertexs in the other direction.
01976      * thus reverse current list and add to the end until bdry reached again.
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     /* is it possible to do this without reversing? */
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     /* If CONVEX then no problems, simply stop at 1 non-bdry edge adjacent*/
02025     if ( concave < 0 )
02026         return 1;
02027 
02028     /* Otherwise we are concave */
02029 
02030     /* if link has no non-bdry edge we must return 0*/
02031     if ( link.size() == 2 )
02032         return 0;
02033 
02034     /* If any vertex in the link is in the convex hull of the bdry_edges
02035      * adjacent to v, then we cannot remove successfully, so return -1
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     /* if link is very close to linear (very slightly concave) then we will return 1 to avoid poor triangles*/
02046     if ( concave < 0.0001 )
02047         return 1;
02048 
02049     /* Otherwise this is a valid concave case and we will require 0 non-bdry edges */
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     /* p[0]-p[2] are ear control points p[3] is center cp*/
02071     Point2D p[ 4 ];
02072     int i;
02073     list<BezierVertex*>::iterator temp;
02074 
02075     /* Get prev vertex, wrap prev pointer around to back if we are at begin*/
02076     temp = ear;
02077     if ( temp == link.begin() ) p[ 0 ] = link.back()->get_cp();
02078     else p[ 0 ] = (*( --temp ))->get_cp();
02079 
02080     /* record center vertex */
02081     p[ 1 ] = (*ear)->get_cp();
02082 
02083     /* Get next vertex, wrap next pointer around to front if we are at end */
02084     temp = ear;
02085     if ( ++temp == link.end() ) p[ 2 ] = link.front()->get_cp();
02086     else p[ 2 ] = (*temp)->get_cp();
02087 
02088     /* Check for a concave or almost-flat ear. */
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     /* Check the other side of the flip is also convex: this test should
02098        be of the opposite sign. */
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     /* create priority queue only insert beg and end-1 if not on the bdry*/
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         /* Remove best flip (top) from queue and add to the edges to flip */
02166         double topval = queue.front->p;
02167         queue.pop(top);
02168         assert( find_common_edge( v, *top) != NULL);
02169 
02170         /* break if we're down to flipping edges to flat. */
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         /*  If there is a next ear, find it */
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         /* If there is a prev ear, find it */
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         /* remove top from link, so that ears prev and next will now be correct */
02216         link.erase( top );
02217 
02218         /* remove, and reinsert prev and next */
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     /* do flips in order*/
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     /* Check if d0 vertex, in this case we cannot remove */
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         /* If spline is too small to have a knot removed then fail */
02311         if((spline->closed && spline->get_num_deboor() < 6) || (spline->get_num_deboor() < 4)) return tup;
02312 
02313         /* Mesh before coarsening in double sided case
02314          *         ------][<<____________
02315          *        /      o top           \
02316          *       /       \\e      /       \
02317          *      /         \\t    /         |l
02318          *     /           \\o  /          |i
02319          *    l|stop_deg2=0 \\p/           |n
02320          *    i|    ---------v----------   |k
02321          *    n|            //\stop_deg1=1 |
02322          *    k| face2     //e \           /
02323          *    2|          //b   \    face1/
02324          *     |         //o     \       /
02325          *      \       //t       \     /
02326          *       \      o bot          /
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         /* new data for edge is average. possible error here? */
02339         newd = (etop->get_dp(1) + ebot->get_dp(1))*0.5;
02340 
02341         /* Stop degree is number of non-bdry edges adjacent to link after devillers
02342            if negative then vertex cannot be removed */
02343         stop_degree1 = check_bdry_vertex_removal_degeneracies(link, v);
02344         if( stop_degree1 < 0) return tup;
02345 
02346         /* Determine if there is mesh on other side of bdry */
02347         one_sided = ebot->num_faces() < 2;
02348 
02349         if(!one_sided){
02350             /* get tuple on other side of bdry */
02351             /* I _KNOW_ that using get_tuple(v,e) is safe thanks to earlier checks for 2-sidedness*/
02352             tup2 = Switch(2, get_tuple(v, ebot));
02353             face2 = tup2.f->get_bdry_face_or_null();
02354             get_link(tup2,link2);
02355 
02356             /* Make sure links sync up correctly*/
02357             assert(link2.back() == link.front());
02358             assert(link2.front() == link.back());
02359 
02360             /* stop_degree2 is number for other side, again cannot remove is stop_degree2 is negative */
02361             stop_degree2 = check_bdry_vertex_removal_degeneracies(link2, v);
02362             if( stop_degree2 < 0) return tup;
02363 
02364             /* cannot both be concave */
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         /* This is a diagram of the mesh after devillers for a two sided
02377          *  bdry where the left side had stop_degree2=0 and right stop_degree1=1
02378          *
02379          *              top
02380          *               O \            x=tup
02381          *              /|\\  \         y=tup2
02382          *             / | \\e  \
02383          *            /  |  \\t   \
02384          *           /  e|   \\o    \
02385          *   face2  /   s|    \\p     \     face1
02386          *         /    p|     \\       \
02387          *        /     a|     y\\        \
02388          *  left o      n|       v---------o right
02389          *       \       |      //x       /
02390          *        \      |    e//       /
02391          *         \     |   b//      /
02392          *          \    |  o//     /
02393          *           \   | t//    /
02394          *            \  | //   /
02395          *             \ |//  /
02396          *               O /
02397          *              bot
02398          * now find left, right and espan
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         /* All data is acquired, so remove v and espan(if it exists) */
02417         if(espan) delete_edge(espan);
02418         delete_vertex(v);
02419 
02420         /* Remove the knot, this function will return the new center CP for the
02421          * new edges, it will also return the u0 and u1 values for the edge
02422          * We can't rely on top and bot for these u values, because if they are
02423          * D0 points then they don't have a u value
02424          */
02425         spline->remove_knot(knot_to_remove, nedge_center_cp, u0, u1 );
02426 
02427         /* Create new edges and triangles, and set bdry info for edge */
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); // CW: tp517 4/16/07
02432         if(!one_sided) nt_left = add_bezier_triangle(face2, nedge, find_common_edge(bot, left), find_common_edge(top, left)); // CCW: tp517 4/16/07
02433 
02434         return get_tuple(top, nt_right);
02435         }
02436 
02437       case 2:
02438         {
02439 
02440           /* Otherwise we are Containment dimension 2 (not on bdry)
02441              Normally we'd set stop_degree to 3, but we want to deal
02442              with the case of removing a vertex that is exactly on
02443              an edge that will be created (i.e. if we back out of
02444              insert_edge_midpoint).  So we set it to 4, triangulate
02445              that, and flip if necessary. */
02446 
02447           /* get link and flip out */
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           /* Collect the new cavity of size stop_degree:
02454            *  v0  -- e3 -- v3             v0
02455            *  |             |            /  \
02456            *  e0           e2   or     e0    e2
02457            *  |             |         /        \
02458            *  v1  -- e1 -- v2       v1 -- e1 -- v2
02459            * In the case of stop_degree 4, we need to retriangulate.
02460            * Remember that we got into the case of degree 4 because
02461            * a triangle was almost flat; be careful not to create that
02462            * triangle.
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           /* Remove vertex */
02477           delete_vertex(v);
02478 
02479       /* Now create 1-2 new triangles in void */
02480 
02481       // a little examination to get the orientation of canonical edge elink[0]
02482       bool e0_is_cw = (elink[0]->get_canon_vertex() != vlink[0]);
02483 
02484           /*
02485            * Just create the new triangle and be done.
02486            */
02487           if (stop_degree == 3) {
02488 
02489         BezierTriangle *t = add_bezier_triangle(face, elink[0], elink[1], elink[2], e0_is_cw); 
02490         //calculated: tp517 4/16/07     
02491             return get_tuple(t);
02492           }
02493 
02494       //cout << "Stitching in four new triangles after deletion" << endl;
02495 
02496           /*
02497            * If the degree was 4, we need to retriangulate the cavity.
02498            * Create a new cross edge, choosing v0-v2 or v1-v3 depending on
02499            * which is Delaunay.
02500            * Remember that the whole point is to avoid creating a flat
02501            * triangle, so we can't just create a triangle and flip the edge if
02502            * we created the wrong one.
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             /* 123 is a bad triangle, so the cross edge must be 02 */
02508             BezierEdge *cross = add_straight_bezier_edge(vlink[0], vlink[2]);
02509             add_bezier_triangle(face, elink[0], elink[1], cross, e0_is_cw); //calculated:tp517 4/16/07
02510             add_bezier_triangle(face, cross, elink[2], elink[3]); // ccw: tp517 4/16/07
02511 
02512         //      cout << "grabbing a souvenir" << endl;
02513 
02514             tup = get_tuple(cross);
02515           } else {
02516             /* 123 is a good triangle, so the cross edge must be 13 */
02517             BezierEdge *cross = add_straight_bezier_edge(vlink[3], vlink[1]);
02518             add_bezier_triangle(face, elink[0], cross, elink[3], e0_is_cw); //calculated:tp517 4/16/07
02519             add_bezier_triangle(face, cross, elink[1], elink[2]); //ccw: tp517 4/16/07
02520 
02521             tup = get_tuple(cross);
02522           }
02523           return tup;
02524         }
02525     }
02526 
02527     /* shouldn't fall through, nor have containment dimension != 0,1,2 */
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     /* compute n^(1/3) */
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     /* Find a random subset; keep track of the changes we've made and
02574        undo them after. */
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     /* Zero out return values*/
02640     u=0.0;
02641     v=0.0;
02642 
02643     /* Locate the point in the underlying linear mesh */
02644     switch (locate_point_in_linear_mesh(pt, start, over_bdry, cellfound)) {
02645       case -1:
02646         /* The point is outside the mesh, or across a boundary. */
02647         u = 0.5; /* ?!? */
02648         return -1;
02649 
02650       case 0:
02651         /* Vertex: we actually hit the vertex exactly, so don't
02652          * bother searching the quadratic mesh. */
02653         return 0;
02654 
02655       case 1:
02656       case 2:
02657         /* All is good; time to search the quadratic mesh. */
02658         break;
02659 
02660       default:
02661         /* No other case in 2-d */
02662     assert(0);
02663         return 0;
02664     }
02665 
02666     /*  
02667      * by tp517: Forget about exact point location
02668      * if the point is not in the linear triangle it is supposed to be,
02669      * then just return the midpoint of the edge in the proper direction
02670      * rather than a proper bfs to find the real quadratic triangle
02671      *
02672      */
02673 
02674 #ifdef DEBUG_LOCATOR
02675         cout << "[BezierMesh]: considering triangle "<< *cellfound.f;
02676 #endif
02677         /* Look to see if the point is in this triangle */
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     /*zero the return values */
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); // check we converged
02718         cellfound = get_tuple(t->get_edge(edge_num));
02719       } else {
02720         assert(niter < 0); // should only happen if we diverged
02721         cellfound = get_tuple(t);
02722       }
02723       return -1;
02724     } else {
02725       assert(niter >= 0); // check we converged
02726 
02727       double w[3]; /* these are in CCW order, whereas alpha/beta are CW */
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) { // TODO: newton_zero_tolerance
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           /* Two zeroes => we found a vertex. */
02746           {
02747             /* w[0] is for cp[0], w[1] for cp[2], w[2] for cp[5];
02748                find the vertex to go along with it.  There is no
02749                parameter to set. */
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); // not found?!?
02764               }
02765             }
02766             assert(0); // no non-zero?!?
02767             return 0;
02768           }
02769 
02770         case 1:
02771           /* One zero => we found an edge. */
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           /* Make sure we really got u right. */
02779           {
02780             double a, b;
02781             edge_param_to_tri_param(cellfound.e, cellfound.f, u, a, b);
02782             /*if (!are_equal(a, alpha) || !are_equal(b, beta))*/ {
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             //assert(are_equal(a, alpha));
02797             //assert(are_equal(b, beta));
02798             Point2D p2 = cellfound.f->eval(alpha, beta);
02799             //assert(are_equal(pt.x(), p2.x()));
02800             //assert(are_equal(pt.y(), p2.y()));
02801             p2 = cellfound.e->eval(u);
02802             //assert(are_equal(pt.x(), p2.x()));
02803             //assert(are_equal(pt.y(), p2.y()));
02804           }
02805 #endif
02806           return 1;
02807 
02808         case 0:
02809           /* No zeroes => Inside.  Set both parameters. */
02810           u = alpha;
02811           v = beta;
02812           cellfound = get_tuple(t);
02813           return 2;
02814 
02815         default:
02816           /* This is dead code because of the asserts before the switch */
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     /* For each triangle, loop around the edges and find one for
02858      * which the point is on the other side.  If there is none,
02859      * then the point is inside the triangle, or on it.
02860      * We'll either have found the edge or vertex that matches the
02861      * point, or we'll have established that the point is inside the
02862      * triangle. */
02863     tup = get_tuple( start );
02864     first_e=tup.e;
02865     while(1) {
02866       hits++;
02867       assert(hits <= 3 * get_num_faces()); // each edge of every face
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         /* The point is *on* the line of the edge.  So we know exists alpha:
02886          *   alpha a + (1 - alpha) b = c
02887          *   alpha = (c - b) / (a - b)
02888          * (alpha is a scalar; the relation holds for both x and y)
02889          * We're on the edge if 0<alpha<1.
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())) { /* avoid divide-by-zero */
02896           assert(!is_zero(ab.y())); /* that would mean a == b */
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         /* otherwise, fall through to the else of the next if (yuck) */
02909       }
02910       if(test < 0.0) {
02911         /* Then our point is to the right of this edge, hence must be
02912            outside the triangle. */
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           /* We're about to exit the mesh. */
02920           cellfound = get_tuple(e);
02921           return -1;
02922         }
02923 
02924         if (e->is_boundary() && !over_bdry) {
02925           /* We're about to cross a boundary, but we're not allowed. */
02926           cellfound = get_tuple(e);
02927           return -1;
02928         }
02929 
02930         /* Otherwise we move to the next triangle, keeping track
02931          * of this edge so we don't consider it again. */
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         /* We are inside the triangle, move to next edge */
02939         tup = Switch(1, Switch(0, tup));
02940 
02941         /* If we have verified each edge around the triangle then the point
02942          * is inside it */
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     /*Point was not located */
02953     assert(0);
02954     return 0;
02955 }
02956 
02957 
02958 #ifdef false
02959 /* Set all the internal degrees of freedom in new_triangles
02960  * in order to best interpolate the function defined on old_triangles
02961  * old_triangles must geometrically contain new_triangles
02962  * size of new_triangles and old_triangles are assumed to be relatively small
02963  * Should run in roughly O(|new_triangles| * |old_triangles|)
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     /* Determine which edges of the new_triangles are free */
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     // This section can be ignored if there are no internal vertices in the cavity
02992 
02993     list<BezierVertex*> free_vertices;
02994 // Determine which vertices of the new_triangles are free
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         //foreach triangle ot around vertex
03006         //BezierTriangle *ot = t.f;
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 // zero out all the data points that we plan to set
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     /* Now find the triangle's orientation with respect to the edge, e
03036      * the tri_orientation vector is booleans used by BezierMesh::phi_evaluate to
03037      * choose two of the factors (alpha, beta, gamma) in order to form the correct
03038      * basis function, phi, on that edge, given the orientation
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     /* Integrate using 7 point Gaussian quadrature, ALPHA, BETA and WEIGHT are
03051      * stored as global constants
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); /* temporary */
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             /* Only use contribution of Gauss point if 't' is not inverted at this point */
03075             /* Sometimes an inverted triangle 't' is created by a flip in order to do a vertex
03076              * removal, so we ignore the contribution at this point
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         /* Incase one of the Gauss points was ignored, correct the weighting to reflect the total
03089          * weight of all used points */
03090         TotalErrInt += ErrInt * final_weight;
03091         TotalPhiInt += PhiInt * final_weight;
03092     }
03093 
03094     /* Set edge data point */
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     /* retrieve edges data point and zero it out */
03121     data = &e->access_dp(1);
03122     data->zero();
03123 
03124     /* if no data, then no need to integrate */
03125     if(data->length==0) return;
03126 
03127 
03128     /* Now find the triangle's orientation with respect to the edge, e
03129      * the tri_orientation vector is booleans used by BezierMesh::phi_evaluate to
03130      * choose two of the factors (alpha, beta, gamma) in order to form the correct
03131      * basis function, phi, on that edge, given the orientation
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     /* Integrate using 7 point Gaussian quadrature, ALPHA, BETA and WEIGHT are
03144      * stored as global constants
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); /* temporary */
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             /* Only use contribution of Gauss point if 't' is not inverted at this point */
03168             /* Sometimes an inverted triangle 't' is created by a flip in order to do a vertex
03169              * removal, so we ignore the contribution at this point
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         /* Incase one of the Gauss points was ignored, correct the weighting to reflect the total
03182          * weight of all used points */
03183         TotalErrInt += ErrInt * final_weight;
03184         TotalPhiInt += PhiInt * final_weight;
03185     }
03186 
03187     /* Set edge data point */
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     /* Return olddata - newdata */
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       /* no function angles defined on boundaries */
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     /* plane0 is normal plane on t0 at parameter u along e
03268      * it is defined by p0, p1, p2
03269      *
03270      * plane1 is normal plane on t1 at parameter u along e
03271      * it is defined by p1, p2, p3
03272      *
03273      * p1 and p2 are on edge
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                 /* smooth all of t's edges (except boundaries) */
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   /* insert all edges into dequeue */
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 /* !\brief Make the mesh delaunay, assuming that the only non-delaunay edges
03379  * are those in \a flip_list
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     //    unsigned num_failures=0;
03389 
03390     /* variables for a new delaunay alg */
03391     list<BezierEdge*> local_edges;
03392     vector<BezierEdge*> new_edges;
03393     list<BezierEdge*>::iterator i;
03394     vector<BezierEdge*>::iterator j;
03395     //    unsigned num_splits=0;
03396     //    bool check_func_angles = (angle_const > 0.0);
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         /* don't flip edges with a big function angle, as we will loose data */
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     /* If we couldn't flip this edge for geometric reasons */
03419         if(!success){
03420       num_failures++;
03421       num_splits++;
03422       split_edge_near_unflippable(e, new_edges);
03423     } else { // successful flip
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         /* Check opposite vertex of first tri for encroachment */
03463         tup = Switch(0, Switch(1, get_tuple(e)));
03464         if( tup.e->is_boundary() || Switch(1, tup).e->is_boundary())
03465           continue; /* no encroachment on neighboring boundaries */
03466         p0 = tup.v->get_cp();
03467 
03468         /* Check opposite vertex of second tri for encroachment */
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; /* no encroachment on neighboring boundaries*/
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     /* Initialize refine list with all triangles and randomize it */
03505     copy(get_faces_begin(), get_faces_end(), back_inserter( refine_queue ));
03506 
03507     //    random_shuffle(refine_queue.begin(), refine_queue.end());
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         /*insert cirucmcenter */
03517         num_refines++;
03518         vert = clean_insert_circumcenter(t);
03519     assert(vert != NULL);
03520         /* Add faces surrounding new vertex into the queue */
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     /* Initialize refine list with all triangles and randomize it */
03543     copy(get_faces_begin(), get_faces_end(), back_inserter( refine_queue ));
03544     //    random_shuffle(refine_queue.begin(), refine_queue.end());
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         /* check for large triangle, correct by factor of 2 * PI to keep this from
03553          * thrashing with a constant sizing cleaner which interprets the size constant
03554          * as a ball packing
03555          */
03556         if( t->area() < 2.0 * PI * size_const ) continue;
03557 
03558         /*insert cirucmcenter */
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     /* calculate all edge lengths */
03714     /* This is O( |E| ) = O( |V| ) */
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     /* keep all d0 vertexs (boundary vertexs) */
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     /* keep all d1 vertexs that douglas puecker says are needed */
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     /* this will keep points adjacent to edges with steep function angles */
03771 
03772     /* This is a multiplier for the angle_const used by the algorithm
03773      * I lower the angle const so as to keep edges with a moderate amount of
03774      * curvature around, as they are likley carying important data
03775      */
03776     double angle_adj=0.50;
03777 
03778     /* Area needs slack for exactly the same reason
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         /* If this edge would normally be refined, then keep each vertex of
03793          * this edge */
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     /* Create initial approximation to radius function, as the minimum of the coarsening function,
03821      * and the nearest neighbor function, also ensure that keep nodes have small enough radii, so that
03822      * they will always be in the final ball packing
03823      *
03824      * This is O( |V| )
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         /* if this is a keeper then make ball half of the dist to nearest neighbor */
03831         if(keep.find(v) != keep.end()){
03832             /* find min dist to neighbor */
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         /* Otherwise this is not a keep node*/
03844         /* Let N(v) be the set of neighbors of v
03845          * Set the function to min{ c(v), min{ |v-v0|*nnc : v0 in N(v) } }
03846          * in this case c(v) = radius_const
03847          */
03848         else {
03849             double min = radius_const; /* replace radius const with coarsening function if not using constant coarsening */
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     /* find maximal non-overlapping set of vertexs, including all original keep points
03911     * This is O( |V| )
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     /* remove all vertexs to kill */
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         /* find if we are in the tokill list*/
03972         for(i=tokill.begin(); i!=tokill.end(); ++i){
03973             if(*i == v){
03974                 killset.insert(v);
03975                 break;
03976             }
03977         }
03978     }
03979 
03980     /* Draw yellow for the keepers and grey for the kills, otherwise don;t draw point */
03981     /* draw radii for non-kills */
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     /* redraw */
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     /* Find triangles that need refined */
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       /* If we should refine then add the faces to the todo queue */
04026       todo.insert(todo.end(), e->begin_faces(), e->end_faces());
04027     }
04028 
04029     /* Refine triangles by adding thier circumcenter.
04030      * Check to make sure the triangles are still around before working with
04031      * them as they my have been removed by earlier inserts
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; /* don't worry about boundaries */
04060     if(e->num_faces() != 2) return false; /* must have two faces to have an angle */
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     /* if function angle is less than the cut-off, then these triangles are ok to coarsen, so skip them and move on */
04068     if((xangle < angle_const) && (yangle < angle_const)) return false;
04069 
04070     /* if these triangles are very small, then they are OK to coarsen, so skip them and move on */
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     /* At this point we have an edge with a large angle, who is not part of small triangles*/
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     // make conservative since new adaptive time: tp517 4/26/10
04101     // (t->is_linear_inverted() || t->is_definitely_inverted())
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     /* assert the cp and dp pointers all match up */
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     /* assert the sampling array is accurate */
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     /* assert switch sizes make sense */
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     /* bfs through the mesh; assert that we find all the elements */
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     /* check cp's */
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     /* check dp's */
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 

Generated on Mon May 24 09:53:30 2010 for TUMBLE by  doxygen 1.5.2