
#include <rd_spikingchannel.h>


rdSpikingChannel::rdSpikingChannel(double stepp) : BaseSpikingChannel(stepp)
{
  diameter=1;
  sizeX=&diameter; sizeY=&diameter;
  foveaDensity=1;
  nb_circles=0;
  noisePos=0;
  randomAngularOffset=true;
}


void rdSpikingChannel::xml_ize()
{
  BaseSpikingChannel::xml_ize();
  xmlClass::add_param(diameter,"diameter");
  xmlClass::add_param(foveaDensity,"fovea-density");
}


rdSpikingChannel::~rdSpikingChannel(void)
{
  if(done)
  {
    delete[] summed_units;
    delete[] angular_offset;
  }
}

void rdSpikingChannel::allocateValues()
{

  BaseSpikingChannel::allocateValues();

  //FIRST STEP : counting circles, units in each circle, and total number of units, i.e. initializing index functions.
  double r=0;
  int Nb=0, n=0;
  while(r<=diameter/2.0)
  {
    Nb+=get_nb_units(r);
    n++;
    r=get_r(n);
  }
  nb_circles=n;

  summed_units=new int[nb_circles+1];
  summed_units[0]=0;
  for (int n=0;n<nb_circles;++n)
    summed_units[n+1]=summed_units[n]+get_nb_units(get_r(n));


  //SECOND STEP : getting all angular offsets and creating the VisUnit array (with noise n_pos and n_tau) (
  if (!units.size())	//meaning that units have not been loaded yet from an xml file
  {
    int ind=0;
    angular_offset=new double[nb_circles];
    for(int n=0;n<nb_circles;++n)
    {
      double radius=get_r(n);
      double angular_step=2*Pi/(double)get_nb_units(radius);
      if (randomAngularOffset)                  //a detail, really...
        angular_offset[n]=ranf()*angular_step;
      else angular_offset[n]=0;

      for(int k=0;k<get_nb_units(radius);k++)
      {

        double rnoise=noisePos*ranf()/cellDensity(radius);
        double thetanoise=2*Pi*ranf();
        double xnoise=rnoise*cos(thetanoise);
        double ynoise=rnoise*sin(thetanoise);


        BaseSpikingChannel::create_new_unit(
          radius*cos(angular_offset[n]+angular_step*k)+xnoise ,
          radius*sin(angular_offset[n]+angular_step*k)+ynoise );
        ind++;
      }
    }
  }
  done=true;
}


void rdSpikingChannel::set_diameter(int d)
{
  checkStatus();
  diameter=d;
}

void rdSpikingChannel::set_foveaDensity(double f)
{
  checkStatus();
  foveaDensity=f;
}

void rdSpikingChannel::set_channel(int diam, double d_fov)
{
  checkStatus();
  diameter=diam;
  foveaDensity=d_fov;
}

void rdSpikingChannel::set_noisePos(double f)
{
  checkStatus();
  noisePos=f;
}

