/**
* @file LFonHSG.cpp
* @brief Implementation of the LocalFeatureHSG.h. See description there.
* @author Eric Bach
* @date 26.10.2011
*/

/* LocalFeatureHSG Include */
#include "vislearning/features/localfeatures/LFonHSG.h"

using namespace std;
using namespace NICE;
using namespace OBJREC;

#ifdef NICE_USELIB_BOOST
using namespace boost;
#endif

LFonHSG::LFonHSG (const Config *conf, const string section)
{
  /** initialization **/
  this->lf = NULL;

  /** get parameters for the grid **/
  this->sampleScaling = conf->gI (section, "sample_scaling", 50);
  this->scales = conf->gS (section, "scales"        , "1");
  // the scales are seperated by '+', like in the Van de Sande implementation
  char separator = '+';

  /** get debuginformation **/
  this->debug = conf->gB ("debug", "show_log_HSG", false);

  /** generate the descriptor-instanz **/
  lf = GenericLocalFeatureSelection::selectLocalFeature (conf, section);

  /** parse scales string **/
  if ( this->debug )
  {
    clog << "[log] LocalFeatureHSG::LocalFeatureHSG" << std::endl;
    clog << "[log] try to parse the 'scales-string': " << this->scales << " -> ";
  }

#ifdef NICE_USELIB_BOOST
  typedef tokenizer<boost::char_separator<char> > tokenizer;
  char_separator<char> sep (separator);
  tokenizer tokens (scales, sep);		// parse the string into tokens
  for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter)
  {
    if ( this->debug )
      clog << *tok_iter << " ";
    
    scalesV.push_back(StringTools::convert<float>(*tok_iter));
  }
#else // standard
  std::vector<std::string> temp;
  StringTools::split (scales, separator, temp);
  for ( std::vector<std::string>::const_iterator it = temp.begin(); it != temp.end(); ++it)
  {
    if ( this->debug )
      clog << *it << " ";
    
    scalesV.push_back(StringTools::convert<float>(*it));
  }
#endif
  if ( this->debug )
    clog << std::endl;
}

LFonHSG::~LFonHSG()
{
  /** free memory of descriptors **/
  
  // don't waste memory
  if ( this->lf != NULL )
  {
    delete this->lf;
    this->lf = NULL;
  }
}

int LFonHSG::getDescSize() const
{
  return lf->getDescSize();
}

void LFonHSG::getPositionsOnHSG (const unsigned int imageWidth, const unsigned int imageHeight, VVector& positions) const
{
  if (sampleScaling < 1)
  {
    std::cerr << "[err] sample-scaling (" << sampleScaling << ") musst be larger the 0!" << std::endl;
    return;
  }

  if ( this->debug )
    clog << "[log] LocalFeatureHSG::getPositionsOnHSG calculate ";

  bool oddRow = true;
  NICE::Vector pos (4);

  /** we have to calculate the koo. for every different scale **/
  for ( std::vector<float>::const_iterator it = this->scalesV.begin(); it != this->scalesV.end(); ++it)
  {
    oddRow = true;

    for (unsigned int j = sampleScaling; j <= (imageHeight - sampleScaling); j += sampleScaling)
    {
      for ( unsigned int i = (oddRow ? sampleScaling + sampleScaling / 2 : sampleScaling);
            i <= (imageWidth - sampleScaling);
            i += sampleScaling
          )
      {
        pos[ 0 ] = i;
        pos[ 1 ] = j;
        pos[ 2 ] = *it;
        pos[ 3 ] = 0;
        positions.push_back (pos);
      }
      oddRow = !oddRow;
    }
  }
}

int LFonHSG::extractFeatures (const NICE::ColorImage & cimg, VVector & features, VVector & positions) const
{
  /** To get the keypoint descriptor, we need the positions of the keypoints. **/
  this->getPositionsOnHSG (cimg.width(), cimg.height(), positions);

  /** calulate the descriptor-values **/
  return lf->getDescriptors (cimg, positions, features);
}


int LFonHSG::extractFeatures (const NICE::Image & img, VVector & features, VVector & positions) const
{
  /** To get the keypoint descriptor, we need the positions of the keypoints. **/
  this->getPositionsOnHSG (img.width(), img.height(), positions);

  /** calculate the descriptor-values **/
  return lf->getDescriptors (img, positions, features);
}

void LFonHSG::visualizeFeatures (NICE::Image & mark, const VVector & positions, size_t color) const
{
  // TODO: Implementierung des gewaehlten Descriptortyps aufrufen.
  throw NICE::Exception( "LFonHSG::visualizeFeatures currently not implemented." );
}














