#ifndef BSPTREED2DISP03_H
#define BSPTREED2DISP03_H

#include <sstream>
using namespace std;

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


/*!
\brief Display a bsp tree's partitions with lines, direction and initial
 point p0.

The color indicates the direction. Blue is at the bottom
 of the line and red at the top for the half-space pointing 
 to the left.
*/
template< typename PT, typename PD, typename INDX >
class bsptreeD2disp03 : public gobjContainer
{
public:

  /** The bsp tree being displayed. */
  bsptreeD2<PT,PD,INDX> & bsp;

  /** The radius of the spheres at the initial points p0 and p1. */
  double radius;
  
  /** Constructor initializes but does not realize. */
  bsptreeD2disp03
  ( 
    bsptreeD2<PT,PD,INDX> & bsp_,
    doublec radius_=0.05
  )
    : gobjContainer(true), bsp(bsp_), radius(radius_) {}

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

};

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

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

  if ( bsp.empty() )
    return;
  
  PT La;
  PT Lm;
  PT Lb;

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

  PD t0;
  PD t1;

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

  push(q2);

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

  for ( treeindexedD2iterinternal<INDX> i1(bsp.tree); 
    !i1; ++i1 )
  {
    halfspaceD2<PT,PD> & h1(bsp.vi[i1()->index]);

    Lm = h1.p1-h1.p0;
    La = h1.p0;
    Lb = h1.p1;

    //t0 = tmin;
    //t1 = tmax;
    t0 = bsp.tmin;
    t1 = bsp.tmax;

    Lmid = (La+Lb)*0.5;
    ptlist.push_back(Lmid);
    { 
      stringstream ss; 
      INDX idx = i1()->index;
      ss << idx; 
      ptlabels.push_back(ss.str());
    }

    uint sz = i1.path.size();
    if (sz<=1)
    {
      if (sz==0)
        continue;

      push(new gobjglDisable(GL_LIGHTING));
      push(new gobjglBegin(GL_LINES));
      push(new gobjglColor3f(0.0,0.0,1.0));
      push(new gobjglVertex3d(La+Lm*t0));
      push(new gobjglColor3f(1.0,0.0,0.0));
      push(new gobjglVertex3d(La+Lm*t1));
      push(new gobjglEnd());      

      push(new gobjglEnable(GL_LIGHTING));
      push(new gobjglColor3f(0.0,0.0,1.0));
      push(new gobjMySphereDraw(La,q2));
      push(new gobjglColor3f(1.0,0.0,0.0));
      push(new gobjMySphereDraw(Lb,q2));

      continue;
    }

    bsp.clip(t0,t1,La,Lm,i1);

    push(new gobjglDisable(GL_LIGHTING));
    push(new gobjglBegin(GL_LINES));
    push(new gobjglColor3f(0.0,0.0,1.0));
    push(new gobjglVertex3d(La+Lm*t0));
    push(new gobjglColor3f(1.0,0.0,0.0));
    push(new gobjglVertex3d(La+Lm*t1));
    push(new gobjglEnd());

    push(new gobjglEnable(GL_LIGHTING));
    push(new gobjglColor3f(0.0,0.0,1.0));
    push(new gobjMySphereDraw(La,q2));
    push(new gobjglColor3f(1.0,0.0,0.0));
    push(new gobjMySphereDraw(Lb,q2));
  }

  push(new gobjglDisable(GL_LIGHTING));
  push(new gobjglColor3f(1.0,1.0,0.0));
  pointsdisplay2D< PT > pd( *this, ptlist, ptlabels );

  push(new gobjglPopAttrib());
  push(new gobjglPopAttrib());
}


#endif



