示例#1
0
void
ZcrossPath::build(CBface_list& list )
{
   Bface_list::size_type k;
   for (k = 0 ; k < list.size(); k++)
      if ( has_sil(list[k]))
         start_sil(list[k]);
}
示例#2
0
void
ZcrossPath::build(CBface_list& list )
{
   int k;
   for (k = 0 ; k < list.num(); k++)
      if ( has_sil(list[k]))
         start_sil(list[k]);
}
示例#3
0
void
ZcrossPath::start_sil(Bface *f )
{

   /*
    *
    *  the face class accessor to vertices, edges, etc 
    *  f->v() , f->e(), etc. all take a point from 1 to 3
    *  this is a huge pain when you are trying to move around
    *  the triangle, so i store my values , - g , ex1, ex2, 
    *  in the 0 to 2 range 
    *
    */



   /* the call to has_sil returns if mesh has been looked at
    * and ALWAYS marks it as such. be careful..
    *
    *  this should really be called sil_marked(); or something
    */
   if (!has_sil(f))
      return; //f has been zx_checked this frame


   double g[3]; //
   int ex1, ex2 , nex1, nex2; //indices of cross edges, in 0-2;
   //ex1  is vertex 1 of edge 1 ( and index to edge )
   //nex1 is vertex 2 of edge 1
   bool bgrad;

   get_g(f, g, ex1, ex2 ); //calculates g values, and where

   Bface *f1;
   Bface *f2;

   Bface *iter_f; //iterator for mesh traversal;
   nex1 = (ex1+1)%3;
   nex2 = (ex2+1)%3;

   // new iterators for mesh traversal
   Bvert * svrt[3];
   double sg[3];

   //never check across a crease boundary ()
   //it's a discontinuity in the isosurface

   f1 = ( f->e(ex1+1)->is_crease()) ? nullptr : f->nbr(ex1+1);
   f2 = ( f->e(ex2+1)->is_crease()) ? nullptr : f->nbr(ex2+1);


   //case 1 - we search and close the loop
   //case 2 - we do not close loop -> so search backward, fix

   double alph1 = -g[ex1] / (g[nex1] - g[ex1]);
   Wpt pt1 = interp ( f->v(ex1+1)->loc(), f->v(nex1+1)->loc(), alph1);

   double alph2 = -g[ex2] / (g[nex2] - g[ex2]);
   Wpt pt2 = interp ( f->v(ex2+1)->loc(), f->v(nex2+1)->loc(), alph2);


   // gradient test;
   int gmax = ( g[0] > g[1] ) ? 0 : 1;
   gmax = ( g[2] > g[gmax] ) ? 2 : gmax;

   Wvec v_iso = pt1 - pt2;
   Wvec v_max = f->v(gmax+1)->loc() - pt2;
   Wvec v_grad = v_max.orthogonalized(v_iso);
   bgrad = ( ( _eye - pt2 ) * v_grad  > 0 ) ;

   //we always move clockwise
   // more specifically, if gradient is up, we always
   // check in the same direction

   // you only have to check once

   if ( cross( v_grad , f->norm()) * v_iso > 0 ) {
      swap ( pt1, pt2);
      swap ( alph1, alph2);
      swap ( f1, f2);
      swap ( ex1, ex2 );
      swap ( nex1, nex2);
   }

   //if everything switches, so does bgrad!

   //vert is the front ( according to gradient ) vertex on the list
   //we were going to use it for visibility, but at the moment it's
   //useless.

   // store our own barycentric coordinate

   Wvec bc;
   bc[ex2] = 1.0-alph2;
   bc[nex2] = alph2;


   //start search on f1



   int cstart = num(); // index start of this chain (for case 2 );

   iter_f = f;
   add_seg ( f , pt2, f->v(ex2+1), bgrad, f);

   if (f1) {

      svrt  [0]   = f->v(ex2+1) ;     //initialize cache values
      sg    [0]   = g[ex2];        //for sil_search
      svrt  [1]   = f->v(nex2+1);     //skee-daddle
      sg    [1]   = g[nex2];

      //we start at f, having already added the previous point
      while ( iter_f ) {

         iter_f = sil_walk_search(iter_f, svrt, sg);

         if ( iter_f == f ) {  //closed loop

            if ( !( _segs[cstart].p()  == _segs.back().p() ) ) {
               //cerr << "XXX ZcrossPath::start_sil():: points are not equal" << endl;
               //                 Wpt a = _segs[cstart].p();
               //                 Wpt b = _segs.last().p();
               //cerr << "diff:" << (a-b).length() << endl;
               _segs.back().p() = _segs[cstart].p() ;
            }
            _segs.back().setf( nullptr );
            _segs.back().set_end();
            _segs.back().set_bary(f2);

            return;
         }

      }
   } else {
      add_seg ( nullptr , pt1, f->v(ex1+1), bgrad, f);
   }

   //if we are this far, we have a section of
   //silhouette in the forward direction, ( it may only cross one triangle tho )
   //which ran across a discontinuity

   //now check for the stretch in the opposite direction

   int chain2start = num(); // index of start of next chain

   if ( !f2 )
      return; // first face in reverse direction is nullptr, we are done.

   //find second chain, which needs to be reversed
   //starts at pt2;


   iter_f  = f2;
   add_seg ( f2 , pt2, f->v(ex2+1), bgrad, f2);

   svrt[0] = f->v(ex2+1) ;     //initialize cached values
   sg[0]  = g[ex2];  //for sil_search
   svrt[1] = f->v(nex2+1);
   sg[1]  = g[nex2];

   while ( iter_f ) {
      iter_f = sil_walk_search ( iter_f, svrt, sg );
   }
   int chain2end = num();
   // second chain is found in wrong order, so we flip it


   // reversal code


   int chain2num = (chain2end - chain2start) -1 ;
   if ( chain2num < 0 )
      return;

   _segs.insert(_segs.begin() + cstart, chain2num, ZXseg());
   int last_ind = num()-1;

   int j=0;
   for ( ; j < chain2num ; j++ ) {
      _segs[last_ind-j].setf( _segs[last_ind-(j+1)].f() );      //shift the faces over by one
      //AND any per-face values
      _segs[last_ind-j].setg(_segs[last_ind-(j+1)].g());        //grad associates with face
      _segs[last_ind-j].set_bary(_segs[last_ind-j].f());        //recalc barycentric
   }
   for ( j=0; j < chain2num ; j++) {
      _segs[cstart+j] = _segs.back();
      _segs.pop_back();
   }

   _segs.pop_back(); //last point was the duplicate

   return;
}