#include <math.h>
#include "hitlist.h"
#include "scene.h"
#include "potential.h"

#include "Common.h"
#include "EmissionStrategy.h"



PatchEmissionStrategy::PatchEmissionStrategy(PatchProbabilityAssigner *nppa)
{
  // Save
  ppa = nppa;
}

PatchEmissionStrategy::~PatchEmissionStrategy()
{
  delete ppa;
}


void PatchEmissionStrategy::Update(PATCH *patch)
{
  // Update probabilities
  ppa->assignProbabilities(patch);
}


double PatchEmissionStrategy::SendRay(PATCH *patch,RAY &rout,HITREC &hout)
{
  DENSITY_ESTIMATION_DATA     *thisData;
  PATCH                       *thisPatch;
  double                      xi_1,xi_2;
  
  // Choose a patch according to probability array.
  thisPatch = ppa->choosePatch();

  // First select the initial position.
  thisData =  (DENSITY_ESTIMATION_DATA_PTR) patch->radiance_data;
  xi_1 = drand48();
  xi_2 = drand48();
  PatchUniformPoint(patch,xi_1,xi_2,&rout.pos);

  // Then select the initial direction
  thisData =  (DENSITY_ESTIMATION_DATA_PTR) thisPatch->radiance_data;
  xi_1 = drand48();
  xi_2 = drand48();
  PatchUniformPoint(thisPatch,xi_1,xi_2,&rout.dir);
  VECTORSUBTRACT(rout.dir,rout.pos,rout.dir);
  VECTORNORMALIZE(rout.dir);
      
  // Send ray
  RayCastingFunction(patch,&rout,hout); // !!! FRONT ONLY !!!

  // Eval ray
  return EvalRay(patch,rout,hout);
}


double PatchEmissionStrategy::EvalRay(PATCH *patch,RAY &rout,HITREC &)
{
  HITLIST  *hitlist;
  double   res = 0.0,act;

  // Evaluate probability
  PatchDontIntersect(1, patch);
  hitlist = AllGridIntersections((HITLIST *)NULL, WorldGrid, &rout, 0.0, HUGE, HIT_FRONT|HIT_BACK|HIT_PATCH);
  ForAllHits(hit,hitlist)
    {
      act = fabs(VECTORDOTPRODUCT(rout.dir,hit->patch->normal));
      if (act>EPSILON)
	res += (ppa->getProbability(hit->patch)*hit->t*hit->t)/(act*hit->patch->area);
    } EndForAll;

  DestroyHitlist(hitlist);
  return res;
}


