#ifndef BSPTREED2DISPREGIONS01_H
#define BSPTREED2DISPREGIONS01_H

#include <bsptreeD2.h>
#include <gobj.h>
#include <graphmisc.h>
#include <pointsdisplay.h>
#include <treeindexedD2iter.h>

/*!
\brief Display a bsp tree's partition regions with numbers.
*/
template< typename PT, typename PD, typename INDX >
class bsptreeD2dispregions01 : public gobjContainer
{
public:

  /** Adjusts the region numbers away from the half-space
      intersection. */
  PD delta;

  /** The bsp tree being displayed. */
  bsptreeD2<PT,PD,INDX> & bsp;
  /** Constructor initializes but does not realize. */
  bsptreeD2dispregions01( bsptreeD2<PT,PD,INDX> & bsp_ )
    : gobjContainer(true), delta(0.2), bsp(bsp_) {}

  /** Call update to write the graphics to itself. */
  void update();

};

//---------------------------------------------------------
//  Implementation

template< typename PT, typename PD, typename INDX >
void bsptreeD2dispregions01<PT,PD,INDX>::update()
{
  nuke();

  if (bsp.empty())
    return;

  uint sz;

  INDX region;

  INDX hpindex;
  INDX hindex;


//  gobjQuadric * q2 = new gobjQuadric();
//  q2->radius = 0.05;
//  q2->slices=30;
//  q2->loops=7;

  PT parentnormal;
  PT hnormal;

  vector<PT> ptlist;
  vector<string> ptlabels;

  for ( treeindexedD2iterleaf<INDX> i1(bsp.tree); !i1; ++i1)
  {

    region = i1()->index;

//cout << SHOW(region) << endl;

    sz = i1.path.size();
    if (sz<3)
    {
      if (sz!=2)
        continue;

      hindex = i1.path[0]->index;
//cout << SHOW(hindex) << endl;
//cout << SHOW(bsp.vi.size()) << endl;

assert(hindex<bsp.vi.size());
      halfspaceD2<PT,PD> & h( bsp.vi[ hindex ] );

      PT p0 = (h.p0 + h.p1)*0.5;
      parentnormal=h.normal;
//cout << SHOW(parentnormal) << endl;
      parentnormal.normalize();
      parentnormal *= delta;
//cout << SHOW(parentnormal) << endl;
      if (i1.path[0]->isright(region))
        parentnormal *= -1;

//cout << SHOW(p0) << endl;
      p0 += parentnormal;
//cout << SHOW(p0) << endl;

      ptlist.push_back(p0);

      {
        stringstream ss;
        ss << region;
        ptlabels.push_back(ss.str());
      }

      continue;
    }

    hpindex = i1.path[sz-3]->index;
    hindex = i1.path[sz-2]->index;
    // h2 is the parent half-space of h1.
    halfspaceD2<PT,PD> & hp( bsp.vi[ hpindex ] );
    halfspaceD2<PT,PD> & h( bsp.vi[ hindex ] );

//cout << SHOW(region) << "  " << SHOW(hpindex) << "  " << SHOW(hindex) << endl;
//cout << "hp:  " << hp.print() << endl;
//cout << "h:   " << h.print() << endl;

    PT p0;
    h.intersection(p0,hp.p0,hp.p1);

    parentnormal=hp.normal;
    parentnormal.normalize();
    parentnormal *= delta;
//cout << SHOW(parentnormal) << endl;
//cout << SHOW(i1.path[sz-3]->isrightinternal(hindex)) << endl;

    if (i1.path[sz-3]->isrightinternal(hindex))
      parentnormal *= -1;
//cout << SHOW(parentnormal) << endl;

    p0 += parentnormal;
//cout << SHOW(p0) << endl;

    hnormal = h.normal;
    hnormal.normalize();
    hnormal *= delta;

    if (i1.path[sz-2]->isright(region))
      hnormal *= -1;

//cout << SHOW(hnormal) << endl;

    p0 += hnormal;

//cout << SHOW(p0) << endl;
//cout << endl;
  
    ptlist.push_back(p0);

    {
      stringstream ss;
      ss << region;
      ptlabels.push_back(ss.str());
    }
      
//    push(new gobjMySphereDraw(p0,q2));

  }

  push(new gobjglPushAttrib(GL_LIGHTING));
  push(new gobjglPushAttrib(GL_CURRENT_BIT));

  push(new gobjglDisable(GL_LIGHTING));

  push(new gobjglColor3f(1.0,0.0,0.0));

  pointsdisplay2D< PT > pd( *this, ptlist, ptlabels );
  
  push(new gobjglPopAttrib());
  push(new gobjglPopAttrib());
}


#endif


