virtual bool accept(CBsimplex* s) const 
 { 
    if (!is_face(s)) return false;
    HatchingSimplexDataFixed *hsdf = HatchingSimplexDataFixed::find((Bface *)s);
    if ((hsdf) && (hsdf->exists(_hgf))) return true;
    return false;
 }
/////////////////////////////////////
// clear_visibility()
/////////////////////////////////////
void
HatchingGroupFixed::clear_visibility(void)
{
   vector<Bface*>::size_type k;
   int ctr=0, kctr=0;
        
   const vector<Bface*>& faces = _patch->cur_faces();

   for (k=0; k<faces.size(); k++) {
      HatchingSimplexDataFixed *hsdf = HatchingSimplexDataFixed::find(faces[k]);
      if (hsdf) {
         if(hsdf->exists(this)) {
            hsdf->remove(this);
            ctr++;
            if (hsdf->num()==0) {
               faces[k]->rem_simplex_data(hsdf);
               kctr++;
               delete hsdf;
            }
         }
      }
   }
   err_mesg(ERR_LEV_INFO, "HatchingGroupFixed:clear_visibility - Removed from %d faces.", ctr);     
   err_mesg_cond((kctr>0), ERR_LEV_INFO, "HatchingGroupFixed:clear_visibility - Removed %d empty HatchingSimplexDataFixed's.", kctr);     

   _complete = false;
   
   _group->patch()->changed();
}
/////////////////////////////////////
// query_pick()
/////////////////////////////////////
bool
HatchingGroupFixed::query_pick(CNDCpt &pt)
{
   Wpt foo;
   Bface *f;
   HatchingSimplexDataFixed *hsdf;

   if (!_complete) return false;

   f = find_face_vis(pt,foo);
   if (f)
      {
         hsdf = HatchingSimplexDataFixed::find(f);
         if (hsdf)
            {
               if (hsdf->exists(this))
                  {
                     return true;
                  }
            }
      }

   return false;

}
/////////////////////////////////////
// get_visibility()
/////////////////////////////////////
void
HatchingGroupFixed::get_visibility(TAGformat &d)
{
   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::get_visibility()"); 

   BMESHptr m = _patch->mesh();
   LMESHptr lm = dynamic_pointer_cast<LMESH>(m);
   if (lm)
      m = lm->cur_mesh();

   vector<int>::size_type k;
   int ctr=0;
   vector<int> indices;
   CBface_list& faces = m->faces();

   *d >> indices;

   for (k=0; k<indices.size(); k++) {
      HatchingSimplexDataFixed *hsdf =
         HatchingSimplexDataFixed::find(faces[indices[k]]);
      if (!hsdf) {
         hsdf = new HatchingSimplexDataFixed(faces[indices[k]]);
         ctr++;
      }
      hsdf->add(this);
   }

   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::get_visibility() - Flagged %d tris and added %d new simplex data.", indices.size(), ctr);
}
/////////////////////////////////////
// put_visibility()
/////////////////////////////////////
void
HatchingGroupFixed::put_visibility(TAGformat &d) const
{
   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::put_visibility()"); 

   BMESHptr m = _patch->mesh();
   LMESHptr lm = dynamic_pointer_cast<LMESH>(m);
   if (lm)
      m = lm->cur_mesh();

   Bface_list::size_type k;
   vector<int> indices;
   CBface_list& faces = m->faces();
        
   for (k=0; k< faces.size(); k++) {
      HatchingSimplexDataFixed *hsdf = HatchingSimplexDataFixed::find(faces[k]);
      if (hsdf) {
         if (hsdf->exists(this))
            indices.push_back(faces[k]->index());
      }
   }
   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::put_visibility() - Stored %d tri indices.", indices.size());

   d.id();
   *d << indices;
   d.end_id();
}
/////////////////////////////////////
// get_visibility()
/////////////////////////////////////
void
HatchingGroupFixed::get_visibility(TAGformat &d)
{
   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::get_visibility()"); 

   BMESH *m = _patch->mesh();
   if (LMESH::isa(m))
      m = ((LMESH*)m)->cur_mesh();

   int k, ctr=0;
   ARRAY<int> indices;
   CBface_list& faces = m->faces();

   *d >> indices;

   for (k=0; k<indices.num(); k++)
      {
         HatchingSimplexDataFixed *hsdf =
            HatchingSimplexDataFixed::find(faces[indices[k]]);
         if (!hsdf) 
            {
               hsdf = new HatchingSimplexDataFixed(faces[indices[k]]);
               ctr++;
            }
         hsdf->add(this);
      }

   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::get_visibility() - Flagged %d tris and added %d new simplex data.", indices.num(), ctr); 


}
/////////////////////////////////////
// put_visibility()
/////////////////////////////////////
void
HatchingGroupFixed::put_visibility(TAGformat &d) const
{
   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::put_visibility()"); 

   BMESH *m = _patch->mesh();
   if (LMESH::isa(m))
      m = ((LMESH*)m)->cur_mesh();

   int k;
   ARRAY<int> indices;
   CBface_list& faces = m->faces();
        
   for (k=0; k< faces.num(); k++)
      {
         HatchingSimplexDataFixed *hsdf = HatchingSimplexDataFixed::find(faces[k]);
         if (hsdf) 
            {
               if(hsdf->hack_exists(this))
                  indices += faces[k]->index();
            }
      }
   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::put_visibility() - Stored %d tri indices.", indices.num()); 

   d.id();
   *d << indices;
   d.end_id();
}
/////////////////////////////////////
// recurse_visibility()
/////////////////////////////////////
int             
HatchingGroupFixed::recurse_visibility(Bface *f, CNDCpt_list &poly)
{           
   //Stop if no face, or if already seen
   if (!f) return 0;
   if (f->is_set(1)) return 0;

   f->set_bit(1);

   size_t i;
   int ctr = 0, added = 0;

   bool visible = false;

   //If any vertex fits in polygon, we're visible and want to recurse neighbors
   if (f->front_facing())
   {
      NDCpt_list tri(3);
      tri.push_back(f->v1()->wloc());
      tri.push_back(f->v2()->wloc());
      tri.push_back(f->v3()->wloc());

      //See if any tri vertex lands in the hull
      for (i=0; i<tri.size() && !visible; i++)
         if (poly.contains(tri[i]))
            visible = true;

      if (!visible) {
         //See if any hull vertex lands in the tri
         for (i=0; i<poly.size() && !visible; i++)
            if (tri.contains(poly[i]))
               visible = true;

         if (!visible) {
            //See if any edges cross
            NDCpt_list::size_type num = poly.size();
            for (i=0; i<poly.size() && !visible; i++) {
               if      (isect(poly[i],poly[(i+1)%num], tri[0],tri[1])) visible = true;
               else if (isect(poly[i],poly[(i+1)%num], tri[1],tri[2])) visible = true;            
               else if (isect(poly[i],poly[(i+1)%num], tri[2],tri[0])) visible = true;            
            }
         }
      }
   }

   if (visible) {
      //Add group to face
      HatchingSimplexDataFixed *hsdf = HatchingSimplexDataFixed::find(f);

      if (!hsdf) hsdf = new HatchingSimplexDataFixed(f);

      hsdf->add(this);
      added = 1;
             
      //Now check the adjacent faces
      ctr += recurse_visibility(f->e1()->other_face(f),poly);
      ctr += recurse_visibility(f->e2()->other_face(f),poly);
      ctr += recurse_visibility(f->e3()->other_face(f),poly);
   }


/*
   //Even if not in the region, we add this face, 
   //since it neighbors vis face
   //This gives us a 1 polygon border which 
   //helps defeat vis glitches near the border
   HatchingSimplexDataFixed *hsdf = HatchingSimplexDataFixed::find(f);
   if (!hsdf) 
   {
      hsdf = new HatchingSimplexDataFixed(f);
   }

   hsdf->add(this);
   added = 1;

   //If any vertex fits in polygon, we're visible and want to recurse neighbors
   if ( f->front_facing() &&
        (poly.contains(_patch->xform() * f->v1()->loc()) ||
         poly.contains(_patch->xform() * f->v2()->loc()) ||
         poly.contains(_patch->xform() * f->v3()->loc()) )  )
   {
             
      //Now check the adjacent faces
      ctr += recurse_visibility(f->e1()->other_face(f),poly);
      ctr += recurse_visibility(f->e2()->other_face(f),poly);
      ctr += recurse_visibility(f->e3()->other_face(f),poly);
   }
*/

   return added+ctr;
}