#include <cassert>
#include <iostream>
#include <vector>
using namespace std;

#include <aclock.h>
#include <commandline.h>
#include <halfspaceD3.h>
#include <halfspaceD3indexed.h>
#include <halfspaceD3indexedfull.h>
#include <halfspaceD3test.h>
#include <point.h>
#include <random.h>


void halfspaceD3test::test01()
{
  typedef point3<double> pt3;

  pt3 p0(0.0,0.0,0.0);
  pt3 p1(0.0,0.0,1.0);
  pt3 p2(1.0,0.0,0.0);


  halfspaceD3<pt3,double> h1(p0,p1,p2);

  cout << endl;
  cout << "Half space (plane) from the ordered points." << endl;
  cout << SHOW(p0) << endl;
  cout << SHOW(p1) << endl;
  cout << SHOW(p2) << endl;
  cout << SHOW(h1.normal) << endl;

  cout << "Enter a point: ";
  
  pt3 p;
  cin >> p;

  cout << SHOW(h1.isInside(p)) << endl;
  cout << SHOW(h1.isInsideOrOnBoundary(p)) << endl;

}

void halfspaceD3test::test02()
{
  typedef point3<double> pt3;

  pt3 p0(0.0,0.0,0.0);
  pt3 p1(0.0,0.0,1.0);
  pt3 p2(1.0,0.0,0.0);
  halfspaceD3<pt3,double> h1(p0,p1,p2);

  cout << endl;
  cout << "Half space (plane) from the ordered points." << endl;
  cout << SHOW(p0) << endl;
  cout << SHOW(p1) << endl;
  cout << SHOW(p2) << endl;

  cout << SHOW(h1.normal) << endl;

  cout << "Enter a point: ";
  
  pt3 p;
  cin >> p;

  cout << SHOW(h1.distancefromhalfspace(p)) << endl;


}

void halfspaceD3test::test03(int argc, char** argv)
{
  typedef point3<double> pt3;

  random11<> r;

  pt3 pts0[3] = 
  { 
    pt3(r(),r(),r()),
    pt3(r(),r(),r()),
    pt3(r(),r(),r())
//    pt3(0.0,0.0,0.0), 
//    pt3(0.0,0.0,1.0),
//    pt3(1.0,0.0,0.0)
  };

  halfspaceD3<pt3,double> h1(pts0,0,1,2);
  cout << SHOW(sizeof(h1)) << endl;

  halfspaceD3indexed<pt3,double,uint> h2(pts0,0,1,2);
  cout << SHOW(sizeof(h2)) << endl;

  halfspaceD3indexedfull<pt3,double,uint> h3(pts0,0,1,2);
  cout << SHOW(sizeof(h3)) << endl;


  commandline cmd(argc,argv);

  uint N(1000);
  cmd.mapvar(N,"N");

  vector< pt3 > pts(N);
  for (uint i=0; i<N; ++i)
    pts[i] = pt3(r(),r(),r());

  uint count[3];

  partitionspace<pt3>* part[3];
  part[0] = & h1;
  part[1] = & h2;
  part[2] = & h3;

  for (uint k=0; k<3; ++k)
  {
    count[k]=0;

    aclock ac;
    ac.measure();

    for (uint i=0; i<N; ++i)
    {
      if ( part[k]->isInside( pts[i] ) )
        ++count[k];
    }

    ac.measure();
    cout << "The event took " << ac.diff_ms() << "ms" << endl;
  }

  cout << SHOW(count[0]) << endl;

  assert(count[0]==count[1]);
}




