#ifndef REGIOND2TESSDISPLAY_H
#define REGIOND2TESSDISPLAY_H

#include <pointsdisplay.h>
#include <gobj.h>
#include <pnlink.h>
#include <random.h>
#include <typedefs.h>


/*!
\brief Display the outside polygon mesh as a dotted line.
*/
template< typename TS, typename Indx > 
class regionD2tessdisplaymesh : public gobj
{
public:

  /** Unprocessed graphics. */
  gobjContainer & gr;
  /** The tesselation. */ 
  TS & tess;

  /** Randomly color the mesh. */
  bool multicolored;

  /** The graphics output, first link and coloring option set. */
  regionD2tessdisplaymesh
  (
    gobjContainer & gr_,
    TS & tess_,
    boolc _multicolored=true
  )
    : gr(gr_), tess(tess_), multicolored(_multicolored) {}

  /** Write the graphics as gobj objects. */
  void draw();
};


/*!
\brief Display the point and region indexes.
*/
template< typename TS, typename Indx > 
class regionD2tessdisplaypoints : public gobj
{
public:

  /** Unprocessed graphics. */
  gobjContainer & gr;
  /** The tesselation. */ 
  TS & tess;

  /** The color of the displayed points index. */
  point3<float> pointcolor;
  /** The color of the polytopes index. */
  point3<float> regioncolor;

  /** Turn on or off the points index display. */
  bool displaypoints;

  /** Turn on or off the regions index display. */
  bool displayregions;

  /** The graphics output and first link. */
  regionD2tessdisplaypoints
  (
    gobjContainer & gr_,
    TS & tess_
  );

  /** Write the graphics as gobj objects. */
  void draw();
};


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

template< typename TS, typename Indx >
regionD2tessdisplaypoints<TS,Indx>::regionD2tessdisplaypoints
(
  gobjContainer & gr_,
  TS & tess_
)
  : gr(gr_), tess(tess_) 
{ 
  pointcolor=point3<float>(0.0,1.0,0.0);
  regioncolor=point3<float>(1.0,0.0,0.0);
  displaypoints=true;
  displayregions=true;
}

template< typename TS, typename Indx >
void regionD2tessdisplaypoints<TS,Indx>::draw()
{
  if (displaypoints)
  {
    gr.push( new gobjglColor3f(pointcolor) );
    gr.push( new pointsdisplay2D< point2<double> >(gr,tess.pts,false,true));
  }

  if (displayregions)
  {
    vector< point2<float> > vicenter;
    for (Indx i=0; i<tess.vi.size(); ++i)
    {
      if (tess.vi[i].isnull())
      {
        vicenter.push_back( point2<float>() );
        continue;
      }

      uint count=0;
      point2<float> c(0.0,0.0);
      pnlinkiter<Indx> iter(tess.vi[i].start);
      iter.reset();
      do
      {
        c.x += tess.pts[iter->plink].x;
        c.y += tess.pts[iter->plink].y;
        ++count;
        ++iter;
      } while (!iter);

      assert(count!=0);
      c /= (double)count;
      vicenter.push_back(c);
    }

    gr.push( new gobjglColor3f(regioncolor) );
    gr.push( new pointsdisplay2D< point2<float> >(gr,vicenter,false,true));
  }
}

template< typename TS, typename Indx >
void regionD2tessdisplaymesh<TS,Indx>::draw()
{
//cout << "regionD2tessdisplaymesh<TS,Indx>::draw()" << endl;
  gr.push( new gobjglEnable(GL_LINE_STIPPLE) );
  gr.push( new gobjglLineStipple(1,0x1C47) );

  gr.push( new gobjglBegin(GL_LINES) );

  Indx imax = tess.vi.size();
  for (Indx i=0; i<imax; ++i)
  {
    if ( tess.vi[i].isnull())
      continue;

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

    if (multicolored)
    {
        random11<double> r;
        gr.push(new gobjglColor3f(r(),r(),r()));
    }

    pnlinkiterconst<Indx> k(tess.vi[i].start);
    k.reset();
    do
    {
//cout << SHOW(k->plink) << " " << SHOW(k->next->plink) << endl;
      gr.push( new gobjglVertex2f(tess.pts[k->plink]) );
      gr.push( new gobjglVertex2f(tess.pts[k->next->plink]) );
      ++k;
    } while (!k);
  }

  gr.push( new gobjglEnd() );
  gr.push(new gobjglDisable(GL_LINE_STIPPLE));
}




#endif



