#include <print.h>

#include <simplexface.h>
#include <d3fan.h>



d3fan::d3fan( d3tess & tess_ )
  : tess(tess_), vs(tess_.vs), vi(tess_.vi), cp(tess.cp)
{
}


void d3fan::addspike()
{
  uintc index = vi.size();
  vi.push_back( simplexD2linked() );
  simplexD2linked & ti(vi[index]);
  simplexD2linked const & x(vi[cp]);

  cpf = tess.cpsimplexfaceget();

  ti.pi[0] = x.pi[ vs.v[1] ];
  ti.pi[1] = x.pi[ vs.v[0] ];
  ti.pi[2] = w;
  ti.ni[2] = cpf.id;

  stot[cpf] = index;

  // This cp must be processed at a later date.
  process.push_back(cpf);
}


bool const d3fan::link(uintc from, uintc fromni, uintc vslocalpi)
{
  cpf = tess.cpsimplexfaceget();

  // Is the cp on the boundary or already processed?
  if (dead.find(cpf)!=dead.end())
    return false;

  // Does the triangle already exist?
  if (stot.find(cpf)==stot.end())
  {
    // This is a new surface triangle.
 
    if (tess.surfaceviewable(w)==false)
    {
      dead.insert(cpf);
      return false;
    }

    addspike();
  }

  // Get the point on the surface base opposite the central triangle.
  uint p2 = vi[cpf.id].pi[ vs.v[vslocalpi] ];

  uintc z = stot[cpf];
  vi[from].ni[fromni] = z;

  simplexD2linked & x(vi[z]);
  x.ni[ x.piInverse(p2) ] = from;
     
  return true;
}


void d3fan::eval(uintc w_ )
{
  w = w_;
  dead.clear();
  stot.clear();
  process.clear();

  tess.debugcheck();

  assert(tess.surfaceviewable(w));

  addspike();

  // k is the current surface face being processed.
  simplexface k;
  // kt is an index into the central triangle K.
  uint kt;
  // The points of vs at cp on the boundary.
  uint p[2];

  uint sz = process.size();
  for ( ; sz!=0; sz = process.size() )
  {
    k = process[ sz-1 ];   
assert(k.face<3);
    process.pop_back();
    dead.insert(k);

    // The current triangle  must have vs's base viewable to w.
    tess.cpsimplexfaceset(k);
    assert(tess.surfaceviewable(w));

    for (uint i=0; i<2; ++i)
      p[i] = vi[cp].pi[ vs.v[i] ];

    kt = stot[k];

    tess.surfaceleft();
    link(kt,vi[kt].piInverse(p[1]),0);

    tess.surfaceright();
    tess.surfaceright();
    link(kt,vi[kt].piInverse(p[0]),1);

  }

  // Iterate over surface connecting the surface with
  //   the fan.

  for (map<simplexface,uint>::iterator i=stot.begin();
    i!=stot.end(); ++i)
  {
    tess.cpsimplexfaceset(i->first);
    vi[ cp ].ni[ vs.v[2] ] = i->second;
  }

  tess.debugcheck();

  // Apply minimization to each new triangle with
  //   an already existing triangle on the old surface.
  for (map<simplexface,uint>::iterator i=stot.begin();
    i!=stot.end(); ++i)
    tess.minimizer->eval( (i->first).id, i->second );

}


ostream & operator << (ostream & os, d3fan const & x)
{
  return x.print(os);
}


ostream & d3fan::print(ostream & os) const
{
  os << "w=" << w << endl;
//  os << "surf" << endl << " ";
//  for( set<simplexface>::const_iterator i = surf.begin();
//    i!=surf.end(); ++i)
//    os << *i << ":" << vi[(*i).id] << endl;
//  os << endl;

//  os << "dead" << endl << " ";
//  for( set<simplexface>::const_iterator i = dead.begin();
//    i!=dead.end(); ++i)
//    os << *i << " ";
//  os << endl;

  os << "stot" << endl << " ";
  for( map<simplexface,uint>::const_iterator i = stot.begin();
    i!=stot.end(); ++i)
    os << i->first << "->" << i->second << ": " << vi[i->second] << endl;
  os << endl;

  os << "process" << endl << " ";
  for ( uint i=0; i<process.size(); ++i)
    os << process[i] << " ";
  os << endl;

  return os;
} 







