<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbDSFuzzyModelEstimation.h"

#include <iostream>
#include "otbCommandLineArgumentParser.h"

#include "otbVectorImage.h"
#include "otbImageFileReader.h"

#include "otbVectorData.h"
#include "otbVectorDataFileReader.h"
#include "otbImageToEnvelopeVectorDataFilter.h"
#include "otbVectorDataToRandomLineGenerator.h"

#include "otbVectorDataProjectionFilter.h"  //Envelope TO WGS84 (OSM friendly)
#include "otbVectorDataIntoImageProjectionFilter.h" //WGS84 to index

#include "otbVectorDataToRoadDescriptionFilter.h"
#include "otbVectorDataToDSValidatedVectorDataFilter.h"

#include "itkAmoebaOptimizer.h"
#include "otbStandardDSCostFunction.h"

#include "otbFuzzyDescriptorsModelManager.h"

//  The following piece of code implements an observer
//  that will monitor the evolution of the registration process.
#include "itkCommand.h"
class CommandIterationUpdate : public itk::Command
{
public:
  typedef  CommandIterationUpdate   Self;
  typedef  itk::Command             Superclass;
  typedef itk::SmartPointer<Self>   Pointer;
  itkNewMacro( Self );
protected:
  CommandIterationUpdate() {};
public:
  typedef itk::AmoebaOptimizer         OptimizerType;
  typedef   const OptimizerType   *    OptimizerPointer;

  void Execute(itk::Object *caller, const itk::EventObject & event)
    {
    Execute( (const itk::Object *)caller, event);
    }

  void Execute(const itk::Object * object, const itk::EventObject & event)
    {
    OptimizerPointer optimizer =
                      dynamic_cast< OptimizerPointer >( object );
    if( ! itk::IterationEvent().CheckEvent( &event ) )
      {
      return;
      }
    std::cout << optimizer->GetCachedValue() << "   ";
    std::cout << optimizer->GetCachedCurrentPosition() << std::endl;
    }
};

//TESTING
#include "otbVectorDataFileWriter.h"

//namespace otb
//{

int otb::DSFuzzyModelEstimation::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("DSFuzzyModelEstimation");
  descriptor->SetDescription("Estimate feature fuzzy model parameters using an image and an VectorData");
  descriptor->AddOption("InputImage", "Support to estimate the models on",
                        "in", 1, true, ApplicationDescriptor::InputImage);
  descriptor->AddOption("InputVectorData", "Ground Truth Vector Data",
                        "vdin", 1, true, ApplicationDescriptor::FileName);
  descriptor->AddOption("Hypothesis", "Dempster Shafer study hypothesis",
                        "hyp", 2, false, ApplicationDescriptor::StringList);
  //descriptor->AddOption("Criterion", "Dempster Shafer Criterion (by default (Belief+Plausibility)/2 >= 0.5))",
  //                      "cri", 1, false, ApplicationDescriptor::String);
  descriptor->AddOption("weighting", "Coefficient between 0 and 1 to promote false detections or undetection (default 0.5)",
                        "wgt", 1, false, ApplicationDescriptor::Real);
  descriptor->AddOption("MaximumNumberOfIterations", "Maximum Number os Optimizer Iteration",
                        "MaxNbIt", 1, false, ApplicationDescriptor::Integer);
  descriptor->AddOption("DEMDirectory", "DEM directory",
                        "dem", 1, false, ApplicationDescriptor::DirectoryName);
  descriptor->AddOption("OptimizerObserver", "Activate or not the optimizer observer",
                        "OptObs", 1, true, ApplicationDescriptor::Integer);

  //TESTING PURPOSE
  descriptor->AddOption("Output", "Output Model File Name",
                        "out", 1, true, ApplicationDescriptor::FileName);
  return EXIT_SUCCESS;
}

int otb::DSFuzzyModelEstimation::Execute(otb::ApplicationOptionsResult* parseResult)
{
  typedef otb::VectorData<double>                     VectorDataType;
  typedef VectorDataType::ValuePrecisionType          PrecisionType;
  typedef VectorDataType::PrecisionType               CoordRepType;
  typedef otb::VectorDataFileReader<VectorDataType>   VectorDataReaderType;
  typedef otb::VectorDataToRandomLineGenerator<VectorDataType>
                                                      RandomGeneratorType;

  typedef otb::VectorImage<PrecisionType , 2>         ImageType;
  typedef otb::ImageFileReader<ImageType>             ImageReaderType;

  typedef otb::ImageToEnvelopeVectorDataFilter<ImageType, VectorDataType>
                                                      EnvelopeFilterType;

  typedef otb::VectorDataProjectionFilter<VectorDataType, ImageType>
                                                      VectorDataProjFilter;

  typedef otb::VectorDataIntoImageProjectionFilter<VectorDataType, ImageType>
                                                      VectorDataReProjFilter;

  typedef otb::VectorDataToRoadDescriptionFilter<VectorDataType, ImageType>
                                                      DescriptionFilterType;

  typedef otb::VectorDataToDSValidatedVectorDataFilter<VectorDataType, PrecisionType>
                                                      ValidationFilterType;

  typedef otb::StandardDSCostFunction<ValidationFilterType>
                                                      CostFunctionType;
  typedef CostFunctionType::LabelSetType              LabelSetType;

  typedef itk::AmoebaOptimizer                        OptimizerType;

  typedef otb::VectorDataFileWriter<VectorDataType>   VectorDataWriterType;

  //Instantiate
  ImageReaderType::Pointer                   imgReader = ImageReaderType::New();
  VectorDataReaderType::Pointer               vdReader = VectorDataReaderType::New();
  EnvelopeFilterType::Pointer           envelopeFilter = EnvelopeFilterType::New();
  RandomGeneratorType::Pointer       vdRandomGenerator = RandomGeneratorType::New();
  VectorDataReProjFilter::Pointer     vdReProjFilterGT = VectorDataReProjFilter::New();
  VectorDataReProjFilter::Pointer     vdReProjFilterRL = VectorDataReProjFilter::New();
  DescriptionFilterType::Pointer   descriptionFilterGT = DescriptionFilterType::New();
  DescriptionFilterType::Pointer   descriptionFilterNS = DescriptionFilterType::New();
  CostFunctionType::Pointer               costFunction = CostFunctionType::New();
  OptimizerType::Pointer                     optimizer = OptimizerType::New();

  VectorDataWriterType::Pointer               vdWriter = VectorDataWriterType::New();

  //Read the image
  imgReader->SetFileName(parseResult->GetParameterString("InputImage"));
  imgReader->UpdateOutputInformation();

  imgReader->SetGlobalWarningDisplay(0);

  //Read the vector data
  vdReader->SetFileName(parseResult->GetParameterString("InputVectorData"));
  vdReader->Update();

  //Generate the envelope
  envelopeFilter->SetInput(imgReader->GetOutput()); //->Output in WGS84
  envelopeFilter->Update();

  //Generate Random lines
  vdRandomGenerator->SetInput(envelopeFilter->GetOutput());
  vdRandomGenerator->SetNumberOfOutputLine(vdReader->GetOutput()->Size());
  vdRandomGenerator->SetMinLineSize(4);
  vdRandomGenerator->SetMaxLineSize(20);

  //Reproject into image index coordinates
  vdReProjFilterGT->SetInputImage(imgReader->GetOutput());
  vdReProjFilterGT->SetInputVectorData(vdReader->GetOutput());
  vdReProjFilterGT->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory"));
  vdReProjFilterGT->SetUseOutputSpacingAndOriginFromImage(true);
  vdReProjFilterGT->Update();

  vdReProjFilterRL->SetInputImage(imgReader->GetOutput());
  vdReProjFilterRL->SetInputVectorData(vdRandomGenerator->GetOutput());
  vdReProjFilterRL->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory"));
  vdReProjFilterRL->SetUseOutputSpacingAndOriginFromImage(true);
  vdReProjFilterRL->Update();

  //Add Description to VectorDatas
  descriptionFilterGT->SetInput(vdReProjFilterGT->GetOutput());
  descriptionFilterGT->AddOpticalImage(imgReader->GetOutput());
  descriptionFilterGT->Update();
  descriptionFilterNS->SetInput(vdReProjFilterRL->GetOutput());
  descriptionFilterNS->AddOpticalImage(imgReader->GetOutput());
  descriptionFilterNS->Update();

  //Cost Function
  //Format Hypothesis
  LabelSetType hyp;
  if (parseResult->IsOptionPresent("Hypothesis"))
    {
    int NumberOfChannel = parseResult->GetNumberOfParameters("Hypothesis");
    for (int i = 0; i < NumberOfChannel; i++)
       {
        std::string str = parseResult->GetParameterString("Hypothesis", i);
        hyp.insert(str);
       }
    costFunction->SetHypothesis(hyp);
    }
  if (parseResult->IsOptionPresent("Weighting"))
    {
    costFunction->SetWeight(parseResult->GetParameterDouble("Weighting"));
    }
  costFunction->SetGTVectorData(descriptionFilterGT->GetOutput());
  costFunction->SetNSVectorData(descriptionFilterNS->GetOutput());

  //Optimizer
  optimizer->SetCostFunction(costFunction);
  if (parseResult->IsOptionPresent("MaximumNumberOfIterations"))
    {
    optimizer->SetMaximumNumberOfIterations(parseResult->GetParameterInt("MaximumNumberOfIterations"));
    }
  else
    {
    optimizer->SetMaximumNumberOfIterations(200);
    }
/*
  optimizer->SetParametersConvergenceTolerance( 0.01 );
  optimizer->SetFunctionConvergenceTolerance(0.001);
*/
  OptimizerType::ParametersType
      simplexDelta( costFunction->GetNumberOfParameters() );
  simplexDelta.Fill(.25);
  /*
  simplexDelta.SetElement(0, 0.25);
  simplexDelta.SetElement(1, 0.25);
  simplexDelta.SetElement(2, 0.25);
  simplexDelta.SetElement(3, 0.20);
  simplexDelta.SetElement(4, 0.25);
  simplexDelta.SetElement(5, 0.25);
  simplexDelta.SetElement(6, 0.25);
  simplexDelta.SetElement(7, 0.20);
  */
  optimizer->AutomaticInitialSimplexOff();
  optimizer->SetInitialSimplexDelta( simplexDelta );

  //optimizer->SetScales()

  OptimizerType::ParametersType
        initialPosition( costFunction->GetNumberOfParameters() );
  //initialPosition.Fill(0.25);
  initialPosition.SetElement(0, 0.25);
  initialPosition.SetElement(1, 0.50);
  initialPosition.SetElement(2, 0.75);
  initialPosition.SetElement(3, 0.99);
  initialPosition.SetElement(4, 0.25);
  initialPosition.SetElement(5, 0.50);
  initialPosition.SetElement(6, 0.75);
  initialPosition.SetElement(7, 0.99);

  //initialPosition.SetElement();
  optimizer->SetInitialPosition(initialPosition);

  // Create the Command observer and register it with the optimizer.
  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
  if (parseResult->GetParameterInt("OptimizerObserver"))
    {
    optimizer->AddObserver( itk::IterationEvent(), observer );
    }

  try
      {
      // do the optimization
      optimizer->StartOptimization();
      }
  catch( itk::ExceptionObject& err )
      {
      // An error has occurred in the optimization.
      // Update the parameters
      std::cout << "ERROR: Exception Catched!" << std::endl;
      std::cout << err.GetDescription() << std::endl;
      const unsigned int numberOfIterations
        = optimizer->GetOptimizer()->get_num_evaluations();
      std::cout << "numberOfIterations : " << numberOfIterations << std::endl;
      std::cout << "Results : " << optimizer->GetCurrentPosition() << std::endl;
      }
  // get the results
  const unsigned int numberOfIterations
    = optimizer->GetOptimizer()->get_num_evaluations();
  std::cout << "numberOfIterations : " << numberOfIterations << std::endl;
  std::cout << "Results : " << optimizer->GetCurrentPosition() << std::endl;

  otb::FuzzyDescriptorsModelManager::DescriptorsModelType model;
  otb::FuzzyDescriptorsModelManager::ParameterType        ndvi, radiom;

  for (unsigned int i = 0; i<4; i++)
    {
    ndvi.push_back(optimizer->GetCurrentPosition()[i]);
    }
  for (unsigned int i = 0; i<4; i++)
    {
    radiom.push_back(optimizer->GetCurrentPosition()[i+4]);
    }
  otb::FuzzyDescriptorsModelManager::AddDescriptor("NDVI", ndvi, model);
  otb::FuzzyDescriptorsModelManager::AddDescriptor("RADIOM", radiom, model);
  otb::FuzzyDescriptorsModelManager::Save(parseResult->GetParameterString("Output"),
                                          model);

  return EXIT_SUCCESS;
}

//}

<commit_msg>REFAC: clean some comments<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbDSFuzzyModelEstimation.h"

#include <iostream>
#include "otbCommandLineArgumentParser.h"

#include "otbVectorImage.h"
#include "otbImageFileReader.h"

#include "otbVectorData.h"
#include "otbVectorDataFileReader.h"
#include "otbImageToEnvelopeVectorDataFilter.h"
#include "otbVectorDataToRandomLineGenerator.h"

#include "otbVectorDataProjectionFilter.h"  //Envelope TO WGS84 (OSM friendly)
#include "otbVectorDataIntoImageProjectionFilter.h" //WGS84 to index

#include "otbVectorDataToRoadDescriptionFilter.h"
#include "otbVectorDataToDSValidatedVectorDataFilter.h"

#include "itkAmoebaOptimizer.h"
#include "otbStandardDSCostFunction.h"

#include "otbFuzzyDescriptorsModelManager.h"

//  The following piece of code implements an observer
//  that will monitor the evolution of the registration process.
#include "itkCommand.h"
class CommandIterationUpdate : public itk::Command
{
public:
  typedef  CommandIterationUpdate   Self;
  typedef  itk::Command             Superclass;
  typedef itk::SmartPointer<Self>   Pointer;
  itkNewMacro( Self );
protected:
  CommandIterationUpdate() {};
public:
  typedef itk::AmoebaOptimizer         OptimizerType;
  typedef   const OptimizerType   *    OptimizerPointer;

  void Execute(itk::Object *caller, const itk::EventObject & event)
    {
    Execute( (const itk::Object *)caller, event);
    }

  void Execute(const itk::Object * object, const itk::EventObject & event)
    {
    OptimizerPointer optimizer =
                      dynamic_cast< OptimizerPointer >( object );
    if( ! itk::IterationEvent().CheckEvent( &event ) )
      {
      return;
      }
    std::cout << optimizer->GetCachedValue() << "   ";
    std::cout << optimizer->GetCachedCurrentPosition() << std::endl;
    }
};

//TESTING
#include "otbVectorDataFileWriter.h"

//namespace otb
//{

int otb::DSFuzzyModelEstimation::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("DSFuzzyModelEstimation");
  descriptor->SetDescription("Estimate feature fuzzy model parameters using an image and an VectorData");
  descriptor->AddOption("InputImage", "Support to estimate the models on",
                        "in", 1, true, ApplicationDescriptor::InputImage);
  descriptor->AddOption("InputVectorData", "Ground Truth Vector Data",
                        "vdin", 1, true, ApplicationDescriptor::FileName);
  descriptor->AddOption("Hypothesis", "Dempster Shafer study hypothesis",
                        "hyp", 2, false, ApplicationDescriptor::StringList);
  //descriptor->AddOption("Criterion", "Dempster Shafer Criterion (by default (Belief+Plausibility)/2 >= 0.5))",
  //                      "cri", 1, false, ApplicationDescriptor::String);
  descriptor->AddOption("weighting", "Coefficient between 0 and 1 to promote false detections or undetection (default 0.5)",
                        "wgt", 1, false, ApplicationDescriptor::Real);
  descriptor->AddOption("MaximumNumberOfIterations", "Maximum Number os Optimizer Iteration",
                        "MaxNbIt", 1, false, ApplicationDescriptor::Integer);
  descriptor->AddOption("DEMDirectory", "DEM directory",
                        "dem", 1, false, ApplicationDescriptor::DirectoryName);
  descriptor->AddOption("OptimizerObserver", "Activate or not the optimizer observer",
                        "OptObs", 1, true, ApplicationDescriptor::Integer);

  //TESTING PURPOSE
  descriptor->AddOption("Output", "Output Model File Name",
                        "out", 1, true, ApplicationDescriptor::FileName);
  return EXIT_SUCCESS;
}

int otb::DSFuzzyModelEstimation::Execute(otb::ApplicationOptionsResult* parseResult)
{
  typedef otb::VectorData<double>                     VectorDataType;
  typedef VectorDataType::ValuePrecisionType          PrecisionType;
  typedef VectorDataType::PrecisionType               CoordRepType;
  typedef otb::VectorDataFileReader<VectorDataType>   VectorDataReaderType;
  typedef otb::VectorDataToRandomLineGenerator<VectorDataType>
                                                      RandomGeneratorType;

  typedef otb::VectorImage<PrecisionType , 2>         ImageType;
  typedef otb::ImageFileReader<ImageType>             ImageReaderType;

  typedef otb::ImageToEnvelopeVectorDataFilter<ImageType, VectorDataType>
                                                      EnvelopeFilterType;

  typedef otb::VectorDataProjectionFilter<VectorDataType, ImageType>
                                                      VectorDataProjFilter;

  typedef otb::VectorDataIntoImageProjectionFilter<VectorDataType, ImageType>
                                                      VectorDataReProjFilter;

  typedef otb::VectorDataToRoadDescriptionFilter<VectorDataType, ImageType>
                                                      DescriptionFilterType;

  typedef otb::VectorDataToDSValidatedVectorDataFilter<VectorDataType, PrecisionType>
                                                      ValidationFilterType;

  typedef otb::StandardDSCostFunction<ValidationFilterType>
                                                      CostFunctionType;
  typedef CostFunctionType::LabelSetType              LabelSetType;

  typedef itk::AmoebaOptimizer                        OptimizerType;

  typedef otb::VectorDataFileWriter<VectorDataType>   VectorDataWriterType;

  //Instantiate
  ImageReaderType::Pointer                   imgReader = ImageReaderType::New();
  VectorDataReaderType::Pointer               vdReader = VectorDataReaderType::New();
  EnvelopeFilterType::Pointer           envelopeFilter = EnvelopeFilterType::New();
  RandomGeneratorType::Pointer       vdRandomGenerator = RandomGeneratorType::New();
  VectorDataReProjFilter::Pointer     vdReProjFilterGT = VectorDataReProjFilter::New();
  VectorDataReProjFilter::Pointer     vdReProjFilterRL = VectorDataReProjFilter::New();
  DescriptionFilterType::Pointer   descriptionFilterGT = DescriptionFilterType::New();
  DescriptionFilterType::Pointer   descriptionFilterNS = DescriptionFilterType::New();
  CostFunctionType::Pointer               costFunction = CostFunctionType::New();
  OptimizerType::Pointer                     optimizer = OptimizerType::New();

  VectorDataWriterType::Pointer               vdWriter = VectorDataWriterType::New();

  //Read the image
  imgReader->SetFileName(parseResult->GetParameterString("InputImage"));
  imgReader->UpdateOutputInformation();

  imgReader->SetGlobalWarningDisplay(0);

  //Read the vector data
  vdReader->SetFileName(parseResult->GetParameterString("InputVectorData"));
  vdReader->Update();

  //Generate the envelope
  envelopeFilter->SetInput(imgReader->GetOutput()); //->Output in WGS84
  envelopeFilter->Update();

  //Generate Random lines
  vdRandomGenerator->SetInput(envelopeFilter->GetOutput());
  vdRandomGenerator->SetNumberOfOutputLine(vdReader->GetOutput()->Size());
  vdRandomGenerator->SetMinLineSize(4);
  vdRandomGenerator->SetMaxLineSize(20);

  //Reproject into image index coordinates
  vdReProjFilterGT->SetInputImage(imgReader->GetOutput());
  vdReProjFilterGT->SetInputVectorData(vdReader->GetOutput());
  vdReProjFilterGT->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory"));
  vdReProjFilterGT->SetUseOutputSpacingAndOriginFromImage(true);
  vdReProjFilterGT->Update();

  vdReProjFilterRL->SetInputImage(imgReader->GetOutput());
  vdReProjFilterRL->SetInputVectorData(vdRandomGenerator->GetOutput());
  vdReProjFilterRL->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory"));
  vdReProjFilterRL->SetUseOutputSpacingAndOriginFromImage(true);
  vdReProjFilterRL->Update();

  //Add Description to VectorDatas
  descriptionFilterGT->SetInput(vdReProjFilterGT->GetOutput());
  descriptionFilterGT->AddOpticalImage(imgReader->GetOutput());
  descriptionFilterGT->Update();
  descriptionFilterNS->SetInput(vdReProjFilterRL->GetOutput());
  descriptionFilterNS->AddOpticalImage(imgReader->GetOutput());
  descriptionFilterNS->Update();

  //Cost Function
  //Format Hypothesis
  LabelSetType hyp;
  if (parseResult->IsOptionPresent("Hypothesis"))
    {
    int NumberOfChannel = parseResult->GetNumberOfParameters("Hypothesis");
    for (int i = 0; i < NumberOfChannel; i++)
       {
        std::string str = parseResult->GetParameterString("Hypothesis", i);
        hyp.insert(str);
       }
    costFunction->SetHypothesis(hyp);
    }
  if (parseResult->IsOptionPresent("Weighting"))
    {
    costFunction->SetWeight(parseResult->GetParameterDouble("Weighting"));
    }
  costFunction->SetGTVectorData(descriptionFilterGT->GetOutput());
  costFunction->SetNSVectorData(descriptionFilterNS->GetOutput());

  //Optimizer
  optimizer->SetCostFunction(costFunction);
  if (parseResult->IsOptionPresent("MaximumNumberOfIterations"))
    {
    optimizer->SetMaximumNumberOfIterations(parseResult->GetParameterInt("MaximumNumberOfIterations"));
    }
  else
    {
    optimizer->SetMaximumNumberOfIterations(200);
    }
/*
  optimizer->SetParametersConvergenceTolerance( 0.01 );
  optimizer->SetFunctionConvergenceTolerance(0.001);
*/
  OptimizerType::ParametersType
      simplexDelta( costFunction->GetNumberOfParameters() );
  simplexDelta.Fill(.25);

  optimizer->AutomaticInitialSimplexOff();
  optimizer->SetInitialSimplexDelta( simplexDelta );

  OptimizerType::ParametersType
        initialPosition( costFunction->GetNumberOfParameters() );
  initialPosition.Fill(0.25);

  for (unsigned int i=0; i<(double)(costFunction->GetNumberOfParameters())/4.0; i++)
    {
     initialPosition.SetElement(4*i+1, 0.50);
     initialPosition.SetElement(4*i+2, 0.75);
     initialPosition.SetElement(4*i+3, 0.99);
    }

  optimizer->SetInitialPosition(initialPosition);

  // Create the Command observer and register it with the optimizer.
  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
  if (parseResult->GetParameterInt("OptimizerObserver"))
    {
    optimizer->AddObserver( itk::IterationEvent(), observer );
    }

  try
      {
      // do the optimization
      optimizer->StartOptimization();
      }
  catch( itk::ExceptionObject& err )
      {
      // An error has occurred in the optimization.
      // Update the parameters
      std::cout << "ERROR: Exception Catched!" << std::endl;
      std::cout << err.GetDescription() << std::endl;
      const unsigned int numberOfIterations
        = optimizer->GetOptimizer()->get_num_evaluations();
      std::cout << "numberOfIterations : " << numberOfIterations << std::endl;
      std::cout << "Results : " << optimizer->GetCurrentPosition() << std::endl;
      }
  // get the results
  const unsigned int numberOfIterations
    = optimizer->GetOptimizer()->get_num_evaluations();
  std::cout << "numberOfIterations : " << numberOfIterations << std::endl;
  std::cout << "Results : " << optimizer->GetCurrentPosition() << std::endl;

  otb::FuzzyDescriptorsModelManager::DescriptorsModelType model;
  otb::FuzzyDescriptorsModelManager::ParameterType        ndvi, radiom;

  for (unsigned int i = 0; i<4; i++)
    {
    ndvi.push_back(optimizer->GetCurrentPosition()[i]);
    }
  for (unsigned int i = 0; i<4; i++)
    {
    radiom.push_back(optimizer->GetCurrentPosition()[i+4]);
    }

  otb::FuzzyDescriptorsModelManager::AddDescriptor("NDVI", ndvi, model);
  otb::FuzzyDescriptorsModelManager::AddDescriptor("RADIOM", radiom, model);
  otb::FuzzyDescriptorsModelManager::Save(parseResult->GetParameterString("Output"),
                                          model);

  return EXIT_SUCCESS;
}

//}

<|endoftext|>


<commit_before>#include <cassert>
#include <cstdio>

#include <memory>

#include <SDL.h>
#include <SDL_ttf.h>

#include "config.h"
#include "input.h"
#include "game.h"
#include "draw.h"

/////////////////////////////
//
// TODO: Logger class from gurka/gameserver
//
/////////////////////////////

using Window = std::unique_ptr<SDL_Window,  decltype(&SDL_DestroyWindow)>;

Window initSDL()
{
  // Init SDL
  if (SDL_Init(SDL_INIT_VIDEO) < 0)
  {
    fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError());
    return Window(nullptr, SDL_DestroyWindow);
  }

  // Init SDL_ttf
  if (TTF_Init() < 0)
  {
    fprintf(stderr, "Could not initialize TTF: %s\n", TTF_GetError());
    return Window(nullptr, SDL_DestroyWindow);
  }

  atexit(SDL_Quit);

  return Window(SDL_CreateWindow("OpenCrystalCaves",
                                 0,
                                 0,
                                 config::CAMERA_WIDTH * config::SCREEN_SCALE,
                                 config::CAMERA_HEIGHT * config::SCREEN_SCALE,
                                 SDL_WINDOW_SHOWN),
                SDL_DestroyWindow);
}

void readInput(Input* input)
{
  assert(input != nullptr);

  // Set any input that is pressed as repeated here
  input->up.repeated    = input->up.pressed;
  input->down.repeated  = input->down.pressed;
  input->left.repeated  = input->left.pressed;
  input->right.repeated = input->right.pressed;
  input->space.repeated = input->space.pressed;
  input->num_1.repeated = input->num_1.pressed;
  input->num_2.repeated = input->num_2.pressed;
  input->num_3.repeated = input->num_3.pressed;
  input->num_4.repeated = input->num_4.pressed;

  // Read events
  SDL_Event event;
  while (SDL_PollEvent(&event) != 0)
  {
    if (event.type == SDL_QUIT)
    {
      input->quit = true;
      return;  // Quit asap
    }

    else if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
    {
      switch (event.key.keysym.sym)
      {
        case SDLK_UP:
          if (event.type == SDL_KEYDOWN)
          {
            input->up.pressed  = true;
          }
          else
          {
            input->up.pressed = false;
            input->up.repeated = false;
          }
          break;

        case SDLK_DOWN:
          if (event.type == SDL_KEYDOWN)
          {
            input->down.pressed  = true;
          }
          else
          {
            input->down.pressed = false;
            input->down.repeated = false;
          }
          break;

        case SDLK_LEFT:
          if (event.type == SDL_KEYDOWN)
          {
            input->left.pressed  = true;
          }
          else
          {
            input->left.pressed = false;
            input->left.repeated = false;
          }
          break;

        case SDLK_RIGHT:
          if (event.type == SDL_KEYDOWN)
          {
            input->right.pressed  = true;
          }
          else
          {
            input->right.pressed = false;
            input->right.repeated = false;
          }
          break;

        case SDLK_SPACE:
          if (event.type == SDL_KEYDOWN)
          {
            input->space.pressed  = true;
          }
          else
          {
            input->space.pressed = false;
            input->space.repeated = false;
          }
          break;

        case SDLK_1:
          if (event.type == SDL_KEYDOWN)
          {
            input->num_1.pressed  = true;
          }
          else
          {
            input->num_1.pressed = false;
            input->num_1.repeated = false;
          }
          break;

        case SDLK_2:
          if (event.type == SDL_KEYDOWN)
          {
            input->num_2.pressed  = true;
          }
          else
          {
            input->num_2.pressed = false;
            input->num_2.repeated = false;
          }
          break;

        case SDLK_3:
          if (event.type == SDL_KEYDOWN)
          {
            input->num_3.pressed  = true;
          }
          else
          {
            input->num_3.pressed = false;
            input->num_3.repeated = false;
          }
          break;

        case SDLK_4:
          if (event.type == SDL_KEYDOWN)
          {
            input->num_4.pressed  = true;
          }
          else
          {
            input->num_4.pressed = false;
            input->num_4.repeated = false;
          }
          break;

        case SDLK_ESCAPE:
          input->quit = true;
          return;

        default:
          break;
      }
    }
  }
}

int main(int argc, char* argv[])
{
  // Unused for now
  (void)argc;
  (void)argv;

  Window window = initSDL();
  if (!window)
  {
    return 1;
  }
  auto* window_surface = SDL_GetWindowSurface(window.get());

  Game game;
  if (!game.init(window_surface))
  {
    fprintf(stderr, "Could not initialize Game\n");
    return 1;
  }

  // Game loop
  {
    Input input;

    const auto current_tick = SDL_GetTicks();

    // Game loop logic
    const auto ms_per_update = 57;  // 17.5~ ticks per second
    auto tick_last_update = current_tick;
    auto lag = 0u;

    // FPS logic
    auto fps_num_renders = 0u;
    auto fps_last_calc = current_tick;
    auto fps_start_time = current_tick;
    auto fps = 0u;

    while (true)
    {
      /////////////////////////////////////////////////////////////////////////
      ///
      ///  Logic
      ///
      /////////////////////////////////////////////////////////////////////////
      auto current_tick = SDL_GetTicks();
      auto elapsed_ticks = current_tick - tick_last_update;
      tick_last_update = current_tick;
      lag += elapsed_ticks;
      while (lag >= ms_per_update)
      {
        readInput(&input);
        game.update(input);
        lag -= ms_per_update;
      }
      if (input.quit)
      {
        break;
      }

      /////////////////////////////////////////////////////////////////////////
      ///
      ///  Render
      ///
      /////////////////////////////////////////////////////////////////////////
      // Render game
      game.render(window_surface);

      // Render FPS
      auto fps_str = "fps: " + std::to_string(fps);
      draw::text(5, 5, fps_str, { 255u, 255u, 255u, 0u }, window_surface);

      // Update screen
      SDL_UpdateWindowSurface(window.get());

      fps_num_renders++;

      // Calculate FPS each second
      if (current_tick >= (fps_last_calc + 1000))
      {
        const auto total_time = current_tick - fps_start_time;
        fps = fps_num_renders / (total_time / 1000);
        fps_last_calc = current_tick;

        // Reset
        fps_num_renders = 0;
        fps_start_time = current_tick;
      }
    }
  }

  return 0;
}
<commit_msg>Use main() instead of ignoring argc and argv<commit_after>#include <cassert>
#include <cstdio>

#include <memory>

#include <SDL.h>
#include <SDL_ttf.h>

#include "config.h"
#include "input.h"
#include "game.h"
#include "draw.h"

/////////////////////////////
//
// TODO: Logger class from gurka/gameserver
//
/////////////////////////////

using Window = std::unique_ptr<SDL_Window,  decltype(&SDL_DestroyWindow)>;

Window initSDL()
{
  // Init SDL
  if (SDL_Init(SDL_INIT_VIDEO) < 0)
  {
    fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError());
    return Window(nullptr, SDL_DestroyWindow);
  }

  // Init SDL_ttf
  if (TTF_Init() < 0)
  {
    fprintf(stderr, "Could not initialize TTF: %s\n", TTF_GetError());
    return Window(nullptr, SDL_DestroyWindow);
  }

  atexit(SDL_Quit);

  return Window(SDL_CreateWindow("OpenCrystalCaves",
                                 0,
                                 0,
                                 config::CAMERA_WIDTH * config::SCREEN_SCALE,
                                 config::CAMERA_HEIGHT * config::SCREEN_SCALE,
                                 SDL_WINDOW_SHOWN),
                SDL_DestroyWindow);
}

void readInput(Input* input)
{
  assert(input != nullptr);

  // Set any input that is pressed as repeated here
  input->up.repeated    = input->up.pressed;
  input->down.repeated  = input->down.pressed;
  input->left.repeated  = input->left.pressed;
  input->right.repeated = input->right.pressed;
  input->space.repeated = input->space.pressed;
  input->num_1.repeated = input->num_1.pressed;
  input->num_2.repeated = input->num_2.pressed;
  input->num_3.repeated = input->num_3.pressed;
  input->num_4.repeated = input->num_4.pressed;

  // Read events
  SDL_Event event;
  while (SDL_PollEvent(&event) != 0)
  {
    if (event.type == SDL_QUIT)
    {
      input->quit = true;
      return;  // Quit asap
    }

    else if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
    {
      switch (event.key.keysym.sym)
      {
        case SDLK_UP:
          if (event.type == SDL_KEYDOWN)
          {
            input->up.pressed  = true;
          }
          else
          {
            input->up.pressed = false;
            input->up.repeated = false;
          }
          break;

        case SDLK_DOWN:
          if (event.type == SDL_KEYDOWN)
          {
            input->down.pressed  = true;
          }
          else
          {
            input->down.pressed = false;
            input->down.repeated = false;
          }
          break;

        case SDLK_LEFT:
          if (event.type == SDL_KEYDOWN)
          {
            input->left.pressed  = true;
          }
          else
          {
            input->left.pressed = false;
            input->left.repeated = false;
          }
          break;

        case SDLK_RIGHT:
          if (event.type == SDL_KEYDOWN)
          {
            input->right.pressed  = true;
          }
          else
          {
            input->right.pressed = false;
            input->right.repeated = false;
          }
          break;

        case SDLK_SPACE:
          if (event.type == SDL_KEYDOWN)
          {
            input->space.pressed  = true;
          }
          else
          {
            input->space.pressed = false;
            input->space.repeated = false;
          }
          break;

        case SDLK_1:
          if (event.type == SDL_KEYDOWN)
          {
            input->num_1.pressed  = true;
          }
          else
          {
            input->num_1.pressed = false;
            input->num_1.repeated = false;
          }
          break;

        case SDLK_2:
          if (event.type == SDL_KEYDOWN)
          {
            input->num_2.pressed  = true;
          }
          else
          {
            input->num_2.pressed = false;
            input->num_2.repeated = false;
          }
          break;

        case SDLK_3:
          if (event.type == SDL_KEYDOWN)
          {
            input->num_3.pressed  = true;
          }
          else
          {
            input->num_3.pressed = false;
            input->num_3.repeated = false;
          }
          break;

        case SDLK_4:
          if (event.type == SDL_KEYDOWN)
          {
            input->num_4.pressed  = true;
          }
          else
          {
            input->num_4.pressed = false;
            input->num_4.repeated = false;
          }
          break;

        case SDLK_ESCAPE:
          input->quit = true;
          return;

        default:
          break;
      }
    }
  }
}

int main()
{
  Window window = initSDL();
  if (!window)
  {
    return 1;
  }
  auto* window_surface = SDL_GetWindowSurface(window.get());

  Game game;
  if (!game.init(window_surface))
  {
    fprintf(stderr, "Could not initialize Game\n");
    return 1;
  }

  // Game loop
  {
    Input input;

    const auto current_tick = SDL_GetTicks();

    // Game loop logic
    const auto ms_per_update = 57;  // 17.5~ ticks per second
    auto tick_last_update = current_tick;
    auto lag = 0u;

    // FPS logic
    auto fps_num_renders = 0u;
    auto fps_last_calc = current_tick;
    auto fps_start_time = current_tick;
    auto fps = 0u;

    while (true)
    {
      /////////////////////////////////////////////////////////////////////////
      ///
      ///  Logic
      ///
      /////////////////////////////////////////////////////////////////////////
      auto current_tick = SDL_GetTicks();
      auto elapsed_ticks = current_tick - tick_last_update;
      tick_last_update = current_tick;
      lag += elapsed_ticks;
      while (lag >= ms_per_update)
      {
        readInput(&input);
        game.update(input);
        lag -= ms_per_update;
      }
      if (input.quit)
      {
        break;
      }

      /////////////////////////////////////////////////////////////////////////
      ///
      ///  Render
      ///
      /////////////////////////////////////////////////////////////////////////
      // Render game
      game.render(window_surface);

      // Render FPS
      auto fps_str = "fps: " + std::to_string(fps);
      draw::text(5, 5, fps_str, { 255u, 255u, 255u, 0u }, window_surface);

      // Update screen
      SDL_UpdateWindowSurface(window.get());

      fps_num_renders++;

      // Calculate FPS each second
      if (current_tick >= (fps_last_calc + 1000))
      {
        const auto total_time = current_tick - fps_start_time;
        fps = fps_num_renders / (total_time / 1000);
        fps_last_calc = current_tick;

        // Reset
        fps_num_renders = 0;
        fps_start_time = current_tick;
      }
    }
  }

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: inspectorhelpwindow.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2006-12-15 02:13:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"

#ifndef INSPECTORHELPWINDOW_HXX
#include "inspectorhelpwindow.hxx"
#endif
#ifndef EXTENSIONS_PROPCTRLR_MODULEPRC_HXX
#include "modulepcr.hxx"
#endif
#ifndef EXTENSIONS_PROPRESID_HRC
#include "propresid.hrc"
#endif

/** === begin UNO includes === **/
/** === end UNO includes === **/

//........................................................................
namespace pcr
{
//........................................................................

    /** === begin UNO using === **/
    /** === end UNO using === **/

    //====================================================================
    //= InspectorHelpWindow
    //====================================================================
    //--------------------------------------------------------------------
    InspectorHelpWindow::InspectorHelpWindow( Window* _pParent )
        :Window( _pParent, WB_DIALOGCONTROL )
        ,m_aSeparator( this )
        ,m_aHelpText( this, WB_LEFT | WB_READONLY | WB_AUTOVSCROLL )
        ,m_nMinLines( 3 )
        ,m_nMaxLines( 8 )
    {
        m_aSeparator.SetText( String( PcrRes( RID_STR_HELP_SECTION_LABEL ) ) );
        m_aSeparator.Show();

        m_aHelpText.SetControlBackground( m_aSeparator.GetBackground().GetColor() );
        m_aHelpText.Show();
    }

    //--------------------------------------------------------------------
    void InspectorHelpWindow::SetText( const XubString& _rStr )
    {
        m_aHelpText.SetText( _rStr );
    }

    //--------------------------------------------------------------------
    void InspectorHelpWindow::SetLimits( sal_Int32 _nMinLines, sal_Int32 _nMaxLines )
    {
        m_nMinLines = _nMinLines;
        m_nMaxLines = _nMaxLines;
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::impl_getHelpTextBorderHeight()
    {
        sal_Int32 nTop(0), nBottom(0), nDummy(0);
        m_aHelpText.GetBorder( nDummy, nTop, nDummy, nBottom );
        return nTop + nBottom;
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::impl_getSpaceAboveTextWindow()
    {
        Size aSeparatorSize( LogicToPixel( Size( 0, 8 ), MAP_APPFONT ) );
        Size a3AppFontSize( LogicToPixel( Size( 3, 3 ), MAP_APPFONT ) );
        return aSeparatorSize.Height() + a3AppFontSize.Height();
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::GetMinimalHeightPixel()
    {
        return impl_getMinimalTextWindowHeight() + impl_getSpaceAboveTextWindow();
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::GetMaximalHeightPixel()
    {
        return impl_getMaximalTextWindowHeight() + impl_getSpaceAboveTextWindow();
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::impl_getMinimalTextWindowHeight()
    {
        return impl_getHelpTextBorderHeight() + m_aHelpText.GetTextHeight() * m_nMinLines;
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::impl_getMaximalTextWindowHeight()
    {
        return impl_getHelpTextBorderHeight() + m_aHelpText.GetTextHeight() * m_nMaxLines;
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::GetOptimalHeightPixel()
    {
        // --- calc the height as needed for the mere text window
        long nMinTextWindowHeight = impl_getMinimalTextWindowHeight();
        long nMaxTextWindowHeight = impl_getMaximalTextWindowHeight();

        Rectangle aTextRect( Point( 0, 0 ), m_aHelpText.GetOutputSizePixel() );
        aTextRect = m_aHelpText.GetTextRect( aTextRect, m_aHelpText.GetText(),
            TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
        long nActTextWindowHeight = impl_getHelpTextBorderHeight() + aTextRect.GetHeight();

        long nOptTextWindowHeight = ::std::max( nMinTextWindowHeight, ::std::min( nMaxTextWindowHeight, nActTextWindowHeight ) );

        // --- then add the space above the text window
        return nOptTextWindowHeight + impl_getSpaceAboveTextWindow();
    }

    //--------------------------------------------------------------------
    void InspectorHelpWindow::Resize()
    {
        Size a3AppFont( LogicToPixel( Size( 3, 3 ), MAP_APPFONT ) );

        Rectangle aPlayground( Point( 0, 0 ), GetOutputSizePixel() );

        Rectangle aSeparatorArea( aPlayground );
        aSeparatorArea.Bottom() = aSeparatorArea.Top() + LogicToPixel( Size( 0, 8 ), MAP_APPFONT ).Height();
        m_aSeparator.SetPosSizePixel( aSeparatorArea.TopLeft(), aSeparatorArea.GetSize() );

        Rectangle aTextArea( aPlayground );
        aTextArea.Top() = aSeparatorArea.Bottom() + a3AppFont.Height();
        m_aHelpText.SetPosSizePixel( aTextArea.TopLeft(), aTextArea.GetSize() );
    }

//........................................................................
} // namespace pcr
//........................................................................

<commit_msg>INTEGRATION: CWS oj14 (1.3.10); FILE MERGED 2007/02/20 12:02:41 oj 1.3.10.1: set PaintTransparent to true<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: inspectorhelpwindow.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-06 08:50:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"

#ifndef INSPECTORHELPWINDOW_HXX
#include "inspectorhelpwindow.hxx"
#endif
#ifndef EXTENSIONS_PROPCTRLR_MODULEPRC_HXX
#include "modulepcr.hxx"
#endif
#ifndef EXTENSIONS_PROPRESID_HRC
#include "propresid.hrc"
#endif

/** === begin UNO includes === **/
/** === end UNO includes === **/

//........................................................................
namespace pcr
{
//........................................................................

    /** === begin UNO using === **/
    /** === end UNO using === **/

    //====================================================================
    //= InspectorHelpWindow
    //====================================================================
    //--------------------------------------------------------------------
    InspectorHelpWindow::InspectorHelpWindow( Window* _pParent )
        :Window( _pParent, WB_DIALOGCONTROL )
        ,m_aSeparator( this )
        ,m_aHelpText( this, WB_LEFT | WB_READONLY | WB_AUTOVSCROLL )
        ,m_nMinLines( 3 )
        ,m_nMaxLines( 8 )
    {
        SetBackground();
        SetPaintTransparent(TRUE);
        m_aSeparator.SetText( String( PcrRes( RID_STR_HELP_SECTION_LABEL ) ) );
        m_aSeparator.SetBackground();
        m_aSeparator.Show();

        m_aHelpText.SetControlBackground( /*m_aSeparator.GetBackground().GetColor() */);
        m_aHelpText.SetBackground();
        m_aHelpText.SetPaintTransparent(TRUE);
        m_aHelpText.Show();
    }

    //--------------------------------------------------------------------
    void InspectorHelpWindow::SetText( const XubString& _rStr )
    {
        m_aHelpText.SetText( _rStr );
    }

    //--------------------------------------------------------------------
    void InspectorHelpWindow::SetLimits( sal_Int32 _nMinLines, sal_Int32 _nMaxLines )
    {
        m_nMinLines = _nMinLines;
        m_nMaxLines = _nMaxLines;
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::impl_getHelpTextBorderHeight()
    {
        sal_Int32 nTop(0), nBottom(0), nDummy(0);
        m_aHelpText.GetBorder( nDummy, nTop, nDummy, nBottom );
        return nTop + nBottom;
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::impl_getSpaceAboveTextWindow()
    {
        Size aSeparatorSize( LogicToPixel( Size( 0, 8 ), MAP_APPFONT ) );
        Size a3AppFontSize( LogicToPixel( Size( 3, 3 ), MAP_APPFONT ) );
        return aSeparatorSize.Height() + a3AppFontSize.Height();
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::GetMinimalHeightPixel()
    {
        return impl_getMinimalTextWindowHeight() + impl_getSpaceAboveTextWindow();
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::GetMaximalHeightPixel()
    {
        return impl_getMaximalTextWindowHeight() + impl_getSpaceAboveTextWindow();
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::impl_getMinimalTextWindowHeight()
    {
        return impl_getHelpTextBorderHeight() + m_aHelpText.GetTextHeight() * m_nMinLines;
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::impl_getMaximalTextWindowHeight()
    {
        return impl_getHelpTextBorderHeight() + m_aHelpText.GetTextHeight() * m_nMaxLines;
    }

    //--------------------------------------------------------------------
    long InspectorHelpWindow::GetOptimalHeightPixel()
    {
        // --- calc the height as needed for the mere text window
        long nMinTextWindowHeight = impl_getMinimalTextWindowHeight();
        long nMaxTextWindowHeight = impl_getMaximalTextWindowHeight();

        Rectangle aTextRect( Point( 0, 0 ), m_aHelpText.GetOutputSizePixel() );
        aTextRect = m_aHelpText.GetTextRect( aTextRect, m_aHelpText.GetText(),
            TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
        long nActTextWindowHeight = impl_getHelpTextBorderHeight() + aTextRect.GetHeight();

        long nOptTextWindowHeight = ::std::max( nMinTextWindowHeight, ::std::min( nMaxTextWindowHeight, nActTextWindowHeight ) );

        // --- then add the space above the text window
        return nOptTextWindowHeight + impl_getSpaceAboveTextWindow();
    }

    //--------------------------------------------------------------------
    void InspectorHelpWindow::Resize()
    {
        Size a3AppFont( LogicToPixel( Size( 3, 3 ), MAP_APPFONT ) );

        Rectangle aPlayground( Point( 0, 0 ), GetOutputSizePixel() );

        Rectangle aSeparatorArea( aPlayground );
        aSeparatorArea.Bottom() = aSeparatorArea.Top() + LogicToPixel( Size( 0, 8 ), MAP_APPFONT ).Height();
        m_aSeparator.SetPosSizePixel( aSeparatorArea.TopLeft(), aSeparatorArea.GetSize() );

        Rectangle aTextArea( aPlayground );
        aTextArea.Top() = aSeparatorArea.Bottom() + a3AppFont.Height();
        m_aHelpText.SetPosSizePixel( aTextArea.TopLeft(), aTextArea.GetSize() );
    }

//........................................................................
} // namespace pcr
//........................................................................

<|endoftext|>


<commit_before>
#ifndef __BUFFER_CACHE_WRITEBACK_IMPL_HPP__
#define __BUFFER_CACHE_WRITEBACK_IMPL_HPP__

template <class config_t>
writeback_tmpl_t<config_t>::writeback_tmpl_t(cache_t *cache,
        bool wait_for_flush, unsigned int flush_interval_ms)
    : wait_for_flush(wait_for_flush),
      interval_ms(flush_interval_ms),
      cache(cache),
      num_txns(0),
      shutdown_callback(NULL),
      final_sync(NULL),
      state(state_none),
      transaction(NULL) {
}

template <class config_t>
writeback_tmpl_t<config_t>::~writeback_tmpl_t() {
    delete flush_lock;
}

template <class config_t>
void writeback_tmpl_t<config_t>::start() {
    flush_lock =
        new rwi_lock_t(&get_cpu_context()->event_queue->message_hub,
                       get_cpu_context()->event_queue->queue_id);
    start_flush_timer();
}

template <class config_t>
void writeback_tmpl_t<config_t>::shutdown(sync_callback<config_t> *callback) {
    assert(shutdown_callback == NULL);
    shutdown_callback = callback;
    if (!num_txns && state == state_none) // If num_txns, commit() will do this
        sync(callback);
}

template <class config_t>
void writeback_tmpl_t<config_t>::sync(sync_callback<config_t> *callback) {
    sync_callbacks.push_back(callback);
    // Start a new writeback process if one isn't in progress.
    if (state == state_none)
        writeback(NULL);
}

template <class config_t>
bool writeback_tmpl_t<config_t>::begin_transaction(transaction_t *txn) {
    assert(txn->get_access() == rwi_read || txn->get_access() == rwi_write);
    // TODO(NNW): If there's ever any asynchrony between socket reads and
    // begin_transaction, we'll need a better check here.
    assert(shutdown_callback == NULL || final_sync);
    num_txns++;
    if (txn->get_access() == rwi_read)
        return true;
    bool locked = flush_lock->lock(rwi_read, txn);
    return locked;
}

template <class config_t>
bool writeback_tmpl_t<config_t>::commit(transaction_t *txn,
        transaction_commit_callback_t *callback) {
    if (!--num_txns && shutdown_callback != NULL) {
        sync(shutdown_callback); // All txns shut down, start final sync.
    }
    if (txn->get_access() == rwi_read)
        return true;
    flush_lock->unlock();
    if (!wait_for_flush)
        return true;
    txns.insert(txn_state_t(txn, callback));
    return false;
}

template <class config_t>
void writeback_tmpl_t<config_t>::aio_complete(buf_t *buf, bool written) {
    if (written)
        writeback(buf);
}

template <class config_t>
void writeback_tmpl_t<config_t>::local_buf_t::set_dirty(buf_t *super) {
	// 'super' is actually 'this', but as a buf_t* instead of a local_buf_t*
    dirty = true;
    // Maybe we should store a pointer to the block itself, instead of its ID; it shouldn't get
    // swapped out because it's dirty.
    writeback->dirty_blocks.insert(super->get_block_id());
}

template <class config_t>
void writeback_tmpl_t<config_t>::start_flush_timer() {
	if (interval_ms != NEVER_FLUSH && interval_ms != 0) {
		timespec ts;
		ts.tv_sec = interval_ms / 1000;
		ts.tv_nsec = (interval_ms % 1000) * 1000 * 1000;
		get_cpu_context()->event_queue->timer_once(&ts, timer_callback, this);
	}
}

template <class config_t>
void writeback_tmpl_t<config_t>::timer_callback(void *ctx) {
    // TODO(NNW): We can't start writeback when it's already started, but we
    // may want a more thorough way of dealing with this case.
    if (static_cast<writeback_tmpl_t *>(ctx)->state == state_none)
        static_cast<writeback_tmpl_t *>(ctx)->writeback(NULL);
}

template <class config_t>
void writeback_tmpl_t<config_t>::on_lock_available() {
    assert(state == state_locking);
    if (state == state_locking) {
        state = state_locked;
        writeback(NULL);
    }
}

template <class config_t>
void writeback_tmpl_t<config_t>::writeback(buf_t *buf) {
    //printf("Writeback being called, state %d\n", state);

    if (state == state_none) {
        assert(buf == NULL);

        /* Start a read transaction so we can request bufs. */
        assert(transaction == NULL);
        if (shutdown_callback) // Backdoor around "no new transactions" assert.
            final_sync = true;
        transaction = cache->begin_transaction(rwi_read, NULL);
        final_sync = false;
        assert(transaction != NULL); // Read txns always start immediately.

        /* Request exclusive flush_lock, forcing all write txns to complete. */
        state = state_locking;
        bool locked = flush_lock->lock(rwi_write, this);
        if (locked)
            state = state_locked;
    }
    if (state == state_locked) {
        assert(buf == NULL);
        assert(flush_bufs.empty());
        assert(flush_txns.empty());

        flush_txns = txns;
        txns.clear();

        /* Request read locks on all of the blocks we need to flush. */
        for (typename std::set<block_id_t>::iterator it = dirty_blocks.begin();
            it != dirty_blocks.end(); ++it) {
            buf_t *buf = transaction->acquire(*it, rwi_read, NULL);
            assert(buf); // Acquire must succeed since we hold the flush_lock.
            flush_bufs.insert(buf);
        }

        dirty_blocks.clear();
        flush_lock->unlock(); // Write transactions can now proceed again.

        /* Start writing all the dirty bufs down, as a transaction. */
        typename serializer_t::write *writes =
            (typename serializer_t::write *)calloc(flush_bufs.size(),
                                                   sizeof *writes);
        int i = 0;
        for (typename std::set<buf_t *>::iterator it = flush_bufs.begin();
             it != flush_bufs.end(); ++it, i++) {
            writes[i].block_id = (*it)->get_block_id();
            writes[i].buf = (*it)->ptr();
            writes[i].callback = (*it);
        }
        // TODO(NNW): Now that the serializer/aio-system breaks writes up into
        // chunks, we may want to worry about submitting more heavily contended
        // bufs earlier in the process so more write FSMs can proceed sooner.
        if (flush_bufs.size())
            cache->do_write(get_cpu_context()->event_queue, writes,
                flush_bufs.size());
        free(writes);
        state = state_write_bufs;
    }
    if (state == state_write_bufs) {
        if (buf) {
            assert(flush_bufs.find(buf) != flush_bufs.end());
            flush_bufs.erase(buf);
            buf->set_clean();
            buf->release();
        }
        if (flush_bufs.empty()) {
            /* Notify all waiting transactions of completion. */
            for (typename std::set<txn_state_t>::iterator it =
                flush_txns.begin(); it != flush_txns.end(); ++it) {
                it->first->committed(it->second);
            }
            flush_txns.clear();

            for (typename std::vector<sync_callback_t *>::iterator it =
                 sync_callbacks.begin(); it != sync_callbacks.end(); ++it)
                (*it)->on_sync();
            sync_callbacks.clear();

            /* Reset all of our state. */
            bool committed = transaction->commit(NULL);
            assert(committed); // Read-only transactions commit immediately.
            transaction = NULL;
            state = state_none;

            // The timer for the next flush is not started until the current flush is complete. This
            // is a bit dangerous because if anything causes the current flush to abort prematurely,
            // the flush timer will never get restarted. As of 2010-06-28 this should never happen,
            // but keep it in mind when changing the behavior of the writeback.
            start_flush_timer();

            //printf("Writeback complete\n");
        } else {
            //printf("Flush bufs, waiting for %ld more\n", flush_bufs.size());
        }
    }
}

#endif  // __BUFFER_CACHE_WRITEBACK_IMPL_HPP__
<commit_msg>Fixing writeback to allocate rwi lock with gnew<commit_after>
#ifndef __BUFFER_CACHE_WRITEBACK_IMPL_HPP__
#define __BUFFER_CACHE_WRITEBACK_IMPL_HPP__

template <class config_t>
writeback_tmpl_t<config_t>::writeback_tmpl_t(cache_t *cache,
        bool wait_for_flush, unsigned int flush_interval_ms)
    : wait_for_flush(wait_for_flush),
      interval_ms(flush_interval_ms),
      cache(cache),
      num_txns(0),
      shutdown_callback(NULL),
      final_sync(NULL),
      state(state_none),
      transaction(NULL) {
}

template <class config_t>
writeback_tmpl_t<config_t>::~writeback_tmpl_t() {
    gdelete(flush_lock);
}

template <class config_t>
void writeback_tmpl_t<config_t>::start() {
    flush_lock =
        gnew<rwi_lock_t>(&get_cpu_context()->event_queue->message_hub,
                         get_cpu_context()->event_queue->queue_id);
    start_flush_timer();
}

template <class config_t>
void writeback_tmpl_t<config_t>::shutdown(sync_callback<config_t> *callback) {
    assert(shutdown_callback == NULL);
    shutdown_callback = callback;
    if (!num_txns && state == state_none) // If num_txns, commit() will do this
        sync(callback);
}

template <class config_t>
void writeback_tmpl_t<config_t>::sync(sync_callback<config_t> *callback) {
    sync_callbacks.push_back(callback);
    // Start a new writeback process if one isn't in progress.
    if (state == state_none)
        writeback(NULL);
}

template <class config_t>
bool writeback_tmpl_t<config_t>::begin_transaction(transaction_t *txn) {
    assert(txn->get_access() == rwi_read || txn->get_access() == rwi_write);
    // TODO(NNW): If there's ever any asynchrony between socket reads and
    // begin_transaction, we'll need a better check here.
    assert(shutdown_callback == NULL || final_sync);
    num_txns++;
    if (txn->get_access() == rwi_read)
        return true;
    bool locked = flush_lock->lock(rwi_read, txn);
    return locked;
}

template <class config_t>
bool writeback_tmpl_t<config_t>::commit(transaction_t *txn,
        transaction_commit_callback_t *callback) {
    if (!--num_txns && shutdown_callback != NULL) {
        sync(shutdown_callback); // All txns shut down, start final sync.
    }
    if (txn->get_access() == rwi_read)
        return true;
    flush_lock->unlock();
    if (!wait_for_flush)
        return true;
    txns.insert(txn_state_t(txn, callback));
    return false;
}

template <class config_t>
void writeback_tmpl_t<config_t>::aio_complete(buf_t *buf, bool written) {
    if (written)
        writeback(buf);
}

template <class config_t>
void writeback_tmpl_t<config_t>::local_buf_t::set_dirty(buf_t *super) {
	// 'super' is actually 'this', but as a buf_t* instead of a local_buf_t*
    dirty = true;
    // Maybe we should store a pointer to the block itself, instead of its ID; it shouldn't get
    // swapped out because it's dirty.
    writeback->dirty_blocks.insert(super->get_block_id());
}

template <class config_t>
void writeback_tmpl_t<config_t>::start_flush_timer() {
	if (interval_ms != NEVER_FLUSH && interval_ms != 0) {
		timespec ts;
		ts.tv_sec = interval_ms / 1000;
		ts.tv_nsec = (interval_ms % 1000) * 1000 * 1000;
		get_cpu_context()->event_queue->timer_once(&ts, timer_callback, this);
	}
}

template <class config_t>
void writeback_tmpl_t<config_t>::timer_callback(void *ctx) {
    // TODO(NNW): We can't start writeback when it's already started, but we
    // may want a more thorough way of dealing with this case.
    if (static_cast<writeback_tmpl_t *>(ctx)->state == state_none)
        static_cast<writeback_tmpl_t *>(ctx)->writeback(NULL);
}

template <class config_t>
void writeback_tmpl_t<config_t>::on_lock_available() {
    assert(state == state_locking);
    if (state == state_locking) {
        state = state_locked;
        writeback(NULL);
    }
}

template <class config_t>
void writeback_tmpl_t<config_t>::writeback(buf_t *buf) {
    //printf("Writeback being called, state %d\n", state);

    if (state == state_none) {
        assert(buf == NULL);

        /* Start a read transaction so we can request bufs. */
        assert(transaction == NULL);
        if (shutdown_callback) // Backdoor around "no new transactions" assert.
            final_sync = true;
        transaction = cache->begin_transaction(rwi_read, NULL);
        final_sync = false;
        assert(transaction != NULL); // Read txns always start immediately.

        /* Request exclusive flush_lock, forcing all write txns to complete. */
        state = state_locking;
        bool locked = flush_lock->lock(rwi_write, this);
        if (locked)
            state = state_locked;
    }
    if (state == state_locked) {
        assert(buf == NULL);
        assert(flush_bufs.empty());
        assert(flush_txns.empty());

        flush_txns = txns;
        txns.clear();

        /* Request read locks on all of the blocks we need to flush. */
        for (typename std::set<block_id_t>::iterator it = dirty_blocks.begin();
            it != dirty_blocks.end(); ++it) {
            buf_t *buf = transaction->acquire(*it, rwi_read, NULL);
            assert(buf); // Acquire must succeed since we hold the flush_lock.
            flush_bufs.insert(buf);
        }

        dirty_blocks.clear();
        flush_lock->unlock(); // Write transactions can now proceed again.

        /* Start writing all the dirty bufs down, as a transaction. */
        typename serializer_t::write *writes =
            (typename serializer_t::write *)calloc(flush_bufs.size(),
                                                   sizeof *writes);
        int i = 0;
        for (typename std::set<buf_t *>::iterator it = flush_bufs.begin();
             it != flush_bufs.end(); ++it, i++) {
            writes[i].block_id = (*it)->get_block_id();
            writes[i].buf = (*it)->ptr();
            writes[i].callback = (*it);
        }
        // TODO(NNW): Now that the serializer/aio-system breaks writes up into
        // chunks, we may want to worry about submitting more heavily contended
        // bufs earlier in the process so more write FSMs can proceed sooner.
        if (flush_bufs.size())
            cache->do_write(get_cpu_context()->event_queue, writes,
                flush_bufs.size());
        free(writes);
        state = state_write_bufs;
    }
    if (state == state_write_bufs) {
        if (buf) {
            assert(flush_bufs.find(buf) != flush_bufs.end());
            flush_bufs.erase(buf);
            buf->set_clean();
            buf->release();
        }
        if (flush_bufs.empty()) {
            /* Notify all waiting transactions of completion. */
            for (typename std::set<txn_state_t>::iterator it =
                flush_txns.begin(); it != flush_txns.end(); ++it) {
                it->first->committed(it->second);
            }
            flush_txns.clear();

            for (typename std::vector<sync_callback_t *>::iterator it =
                 sync_callbacks.begin(); it != sync_callbacks.end(); ++it)
                (*it)->on_sync();
            sync_callbacks.clear();

            /* Reset all of our state. */
            bool committed = transaction->commit(NULL);
            assert(committed); // Read-only transactions commit immediately.
            transaction = NULL;
            state = state_none;

            // The timer for the next flush is not started until the current flush is complete. This
            // is a bit dangerous because if anything causes the current flush to abort prematurely,
            // the flush timer will never get restarted. As of 2010-06-28 this should never happen,
            // but keep it in mind when changing the behavior of the writeback.
            start_flush_timer();

            //printf("Writeback complete\n");
        } else {
            //printf("Flush bufs, waiting for %ld more\n", flush_bufs.size());
        }
    }
}

#endif  // __BUFFER_CACHE_WRITEBACK_IMPL_HPP__
<|endoftext|>


<commit_before>/*
 * Satisfier.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  January 2009
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atoms/pattern/PatternLink.h>

#include "BindLinkAPI.h"
#include "Satisfier.h"

using namespace opencog;

bool Satisfier::grounding(const HandleMap &var_soln,
                          const HandleMap &term_soln)
{
	// PatternMatchEngine::print_solution(var_soln, term_soln);
	_result = TruthValue::TRUE_TV();

	// Record the grounding; we cache this later.
	if (1 == _varseq.size())
	{
		_ground = var_soln.at(_varseq[0]);
	}
	else
	{
		// If more than one variable, encapsulate in sequential order,
		// in a ListLink.
		HandleSeq vargnds;
		for (const Handle& hv : _varseq)
		{
			vargnds.push_back(var_soln.at(hv));
		}
		_ground = createLink(vargnds, LIST_LINK);
	}

	// No need to look for more groundings as _result isn't going to change
	// and opencog::satisfaction_link only needs the value of _result.
	return true;
}

/// This method handles the case of SequentialAnd, SequentialOr with
/// embedded AbsentLinks, NotLink-PresentLink and some weird
/// combinations of NotLink-ChoiceLink, and so-on.  The idea here is
/// that, if the pattern matcher ran to exhaustion, and NO groundings
/// at all were found, then pattern evaluation may still need to
/// trigger evaluatable clauses that evaluate only when exhaustive
/// search fails.  So, indeed, we do that here.
///
/// Of course, if the pattern had no variables (e.g. a SequenceLink or
/// FallbackLink with only evaluatables), then there cannot be a
/// grounding failure, by definition.  And if there was a grounding,
/// there can be no grounding failure, either. So we only process the
/// case where there are variables, and grounding failed.
bool Satisfier::search_finished(bool done)
{
	if (done) return done;

	// If there were no variables to be grounded, we have nothing to do.
	if (not _have_variables) return done;

	// If there was a grounding, then don't re-run; we're here
	// only to handle the no-groundings case.
	if (TruthValue::TRUE_TV() == _result) return done;

	// _optionals_present will be set to true if some optional clause
	// was grounded. Ergo, its not the no-grounding case.
	if (_optionals_present) return done;

	// Multi-component patterns will not have distinct bodies.
	// A failure to match one of the components is benign, and is
	// treated appropriately upstream. Just return.
	if (nullptr == _pattern_body) return done;

	// Evaluating the pattern body only makes sense if it is sequential
	// (ordered) -- if the body is an unordered AndLink, or if its a
	// ChoiceLink, etc, this makes no sense.
	Type btype = _pattern_body->getType();
	if (SEQUENTIAL_AND_LINK != btype and SEQUENTIAL_OR_LINK != btype)
		return done;

	HandleMap empty;
	bool rc = eval_sentence(_pattern_body, empty);
	if (rc)
		_result = TruthValue::TRUE_TV();

	return rc;
}

// ===========================================================

bool SatisfyingSet::grounding(const HandleMap &var_soln,
                              const HandleMap &term_soln)
{
	// PatternMatchEngine::log_solution(var_soln, term_soln);

	// Do not accept new solution if maximum number has been already reached
	if (_satisfying_set.size() >= max_results)
		return true;

	if (1 == _varseq.size())
	{
		_satisfying_set.emplace(var_soln.at(_varseq[0]));

		// If we found as many as we want, then stop looking for more.
		return (_satisfying_set.size() >= max_results);
	}

	// If more than one variable, encapsulate in sequential order,
	// in a ListLink.
	HandleSeq vargnds;
	for (const Handle& hv : _varseq)
	{
		vargnds.push_back(var_soln.at(hv));
	}
	_satisfying_set.emplace(Handle(createLink(vargnds, LIST_LINK)));

	// If we found as many as we want, then stop looking for more.
	return (_satisfying_set.size() >= max_results);
}

TruthValuePtr opencog::satisfaction_link(AtomSpace* as, const Handle& hlink)
{
	PatternLinkPtr plp(PatternLinkCast(hlink));
	if (NULL == plp)
	{
		// If it is a BindLink (for example), we want to use that ctor
		// instead of the default ctor.
		if (classserver().isA(hlink->getType(), SATISFACTION_LINK))
			plp = createPatternLink(*LinkCast(hlink));
		else
			plp = createPatternLink(hlink);
	}

	Satisfier sater(as);
	plp->satisfy(sater);

	// Cache the variable groundings. OpenPsi wants this.
	plp->set_groundings(sater._ground);
	return sater._result;
}

Handle opencog::satisfying_set(AtomSpace* as, const Handle& hlink, size_t max_results)
{
	// Special case the BindLink. We probably shouldn't have to, and
	// the C++ code for handling this case could maybe be refactored
	// to handle BindLink as well as GetLink in one place... but right
	// now, it doesn't.
	Type blt = hlink->getType();
	if (BIND_LINK == blt)
	{
		return bindlink(as, hlink, max_results);
	}
	if (DUAL_LINK == blt)
	{
		return recognize(as, hlink);
	}

	// If we are here, then we are a GET_LINK, right?
	if (GET_LINK != blt)
		throw RuntimeException(TRACE_INFO,
			"Unexpected SatisfyingLink type!");

	PatternLinkPtr bl(PatternLinkCast(hlink));
	if (NULL == bl)
	{
		bl = createPatternLink(*LinkCast(hlink));
	}

	SatisfyingSet sater(as);
	sater.max_results = max_results;
	bl->satisfy(sater);

	// Ugh. We used an std::set to avoid duplicates. But now, we need a
	// vector.  Which means copying. Got a better idea?
	HandleSeq satvec;
	for (const Handle& h : sater._satisfying_set)
		satvec.push_back(h);

	// Create the satisfying set, and cache it.
	Handle satset(createLink(satvec, SET_LINK));

#define PLACE_RESULTS_IN_ATOMSPACE
#ifdef PLACE_RESULTS_IN_ATOMSPACE
	// Shoot. XXX FIXME. Most of the unit tests require that the atom
	// that we return is in the atomspace. But it would be nice if we
	// could defer this indefinitely, until its really needed.
	satset = as->add_atom(satset);
#endif /* PLACE_RESULTS_IN_ATOMSPACE */
	bl->set_groundings(satset);

	return satset;
}

/* ===================== END OF FILE ===================== */
<commit_msg>Place results in atomspace<commit_after>/*
 * Satisfier.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  January 2009
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atoms/pattern/PatternLink.h>

#include "BindLinkAPI.h"
#include "Satisfier.h"

using namespace opencog;

bool Satisfier::grounding(const HandleMap &var_soln,
                          const HandleMap &term_soln)
{
	// PatternMatchEngine::print_solution(var_soln, term_soln);
	_result = TruthValue::TRUE_TV();

	// Record the grounding; we cache this later.
	if (1 == _varseq.size())
	{
		_ground = var_soln.at(_varseq[0]);
	}
	else
	{
		// If more than one variable, encapsulate in sequential order,
		// in a ListLink.
		HandleSeq vargnds;
		for (const Handle& hv : _varseq)
		{
			vargnds.push_back(var_soln.at(hv));
		}
		_ground = createLink(vargnds, LIST_LINK);
	}

	// No need to look for more groundings as _result isn't going to change
	// and opencog::satisfaction_link only needs the value of _result.
	return true;
}

/// This method handles the case of SequentialAnd, SequentialOr with
/// embedded AbsentLinks, NotLink-PresentLink and some weird
/// combinations of NotLink-ChoiceLink, and so-on.  The idea here is
/// that, if the pattern matcher ran to exhaustion, and NO groundings
/// at all were found, then pattern evaluation may still need to
/// trigger evaluatable clauses that evaluate only when exhaustive
/// search fails.  So, indeed, we do that here.
///
/// Of course, if the pattern had no variables (e.g. a SequenceLink or
/// FallbackLink with only evaluatables), then there cannot be a
/// grounding failure, by definition.  And if there was a grounding,
/// there can be no grounding failure, either. So we only process the
/// case where there are variables, and grounding failed.
bool Satisfier::search_finished(bool done)
{
	if (done) return done;

	// If there were no variables to be grounded, we have nothing to do.
	if (not _have_variables) return done;

	// If there was a grounding, then don't re-run; we're here
	// only to handle the no-groundings case.
	if (TruthValue::TRUE_TV() == _result) return done;

	// _optionals_present will be set to true if some optional clause
	// was grounded. Ergo, its not the no-grounding case.
	if (_optionals_present) return done;

	// Multi-component patterns will not have distinct bodies.
	// A failure to match one of the components is benign, and is
	// treated appropriately upstream. Just return.
	if (nullptr == _pattern_body) return done;

	// Evaluating the pattern body only makes sense if it is sequential
	// (ordered) -- if the body is an unordered AndLink, or if its a
	// ChoiceLink, etc, this makes no sense.
	Type btype = _pattern_body->getType();
	if (SEQUENTIAL_AND_LINK != btype and SEQUENTIAL_OR_LINK != btype)
		return done;

	HandleMap empty;
	bool rc = eval_sentence(_pattern_body, empty);
	if (rc)
		_result = TruthValue::TRUE_TV();

	return rc;
}

// ===========================================================

bool SatisfyingSet::grounding(const HandleMap &var_soln,
                              const HandleMap &term_soln)
{
	// PatternMatchEngine::log_solution(var_soln, term_soln);

	// Do not accept new solution if maximum number has been already reached
	if (_satisfying_set.size() >= max_results)
		return true;

	if (1 == _varseq.size())
	{
		_satisfying_set.emplace(var_soln.at(_varseq[0]));

		// If we found as many as we want, then stop looking for more.
		return (_satisfying_set.size() >= max_results);
	}

	// If more than one variable, encapsulate in sequential order,
	// in a ListLink.
	HandleSeq vargnds;
	for (const Handle& hv : _varseq)
	{
		vargnds.push_back(var_soln.at(hv));
	}
	_satisfying_set.emplace(Handle(createLink(vargnds, LIST_LINK)));

	// If we found as many as we want, then stop looking for more.
	return (_satisfying_set.size() >= max_results);
}

TruthValuePtr opencog::satisfaction_link(AtomSpace* as, const Handle& hlink)
{
	PatternLinkPtr plp(PatternLinkCast(hlink));
	if (NULL == plp)
	{
		// If it is a BindLink (for example), we want to use that ctor
		// instead of the default ctor.
		if (classserver().isA(hlink->getType(), SATISFACTION_LINK))
			plp = createPatternLink(*LinkCast(hlink));
		else
			plp = createPatternLink(hlink);
	}

	Satisfier sater(as);
	plp->satisfy(sater);

#define PLACE_RESULTS_IN_ATOMSPACE
#ifdef PLACE_RESULTS_IN_ATOMSPACE
	// Shoot. XXX FIXME. Most of the unit tests require that the atom
	// that we return is in the atomspace. But it would be nice if we
	// could defer this indefinitely, until its really needed.
	Handle satgrd = as->add_atom(sater._ground);
#endif /* PLACE_RESULTS_IN_ATOMSPACE */

	// Cache the variable groundings. OpenPsi wants this.
	plp->set_groundings(satgrd);

	return sater._result;
}

Handle opencog::satisfying_set(AtomSpace* as, const Handle& hlink, size_t max_results)
{
	// Special case the BindLink. We probably shouldn't have to, and
	// the C++ code for handling this case could maybe be refactored
	// to handle BindLink as well as GetLink in one place... but right
	// now, it doesn't.
	Type blt = hlink->getType();
	if (BIND_LINK == blt)
	{
		return bindlink(as, hlink, max_results);
	}
	if (DUAL_LINK == blt)
	{
		return recognize(as, hlink);
	}

	// If we are here, then we are a GET_LINK, right?
	if (GET_LINK != blt)
		throw RuntimeException(TRACE_INFO,
			"Unexpected SatisfyingLink type!");

	PatternLinkPtr bl(PatternLinkCast(hlink));
	if (NULL == bl)
	{
		bl = createPatternLink(*LinkCast(hlink));
	}

	SatisfyingSet sater(as);
	sater.max_results = max_results;
	bl->satisfy(sater);

	// Ugh. We used an std::set to avoid duplicates. But now, we need a
	// vector.  Which means copying. Got a better idea?
	HandleSeq satvec;
	for (const Handle& h : sater._satisfying_set)
		satvec.push_back(h);

	// Create the satisfying set, and cache it.
	Handle satset(createLink(satvec, SET_LINK));

#define PLACE_RESULTS_IN_ATOMSPACE
#ifdef PLACE_RESULTS_IN_ATOMSPACE
	// Shoot. XXX FIXME. Most of the unit tests require that the atom
	// that we return is in the atomspace. But it would be nice if we
	// could defer this indefinitely, until its really needed.
	satset = as->add_atom(satset);
#endif /* PLACE_RESULTS_IN_ATOMSPACE */
	bl->set_groundings(satset);

	return satset;
}

/* ===================== END OF FILE ===================== */
<|endoftext|>


<commit_before><commit_msg>Revert of Remove unneeded DocumentLoader null check in WindowProxy. (patchset #1 id:1 of https://codereview.chromium.org/797483003/)<commit_after><|endoftext|>


<commit_before>#include "BarcodeFormat.h"

// Reader
#include "DecodeHints.h"
#include "GenericLuminanceSource.h"
#include "HybridBinarizer.h"
#include "MultiFormatReader.h"
#include "Result.h"

// Writer
#include "BitMatrix.h"
#include "MultiFormatWriter.h"
#include "TextUtfEncoding.h"

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <memory>
#include <vector>

using namespace ZXing;
namespace py = pybind11;

// Numpy array wrapper class for images (either BGR or GRAYSCALE)
using Image = py::array_t<uint8_t, py::array::c_style>;

Result read_barcode(const Image& image, BarcodeFormats formats, bool fastMode, bool tryRotate, bool hybridBinarizer)
{
	DecodeHints hints;
	hints.setTryHarder(!fastMode);
	hints.setTryRotate(tryRotate);
	hints.setPossibleFormats(formats);
	MultiFormatReader reader(hints);
	const auto height = static_cast<int>(image.shape(0));
	const auto width = static_cast<int>(image.shape(1));
	const auto bytes = image.data();
	std::shared_ptr<LuminanceSource> source;

	if (image.ndim() == 2) {
		// Grayscale image
		source = std::make_shared<GenericLuminanceSource>(width, height, bytes, width);
	} else {
		// BGR image
		const auto channels = image.shape(2);
		source = std::make_shared<GenericLuminanceSource>(width, height, bytes, width * channels, channels, 2, 1, 0);
	}

	if (hybridBinarizer) {
		return reader.read(HybridBinarizer(source));
	} else {
		return reader.read(GlobalHistogramBinarizer(source));
	}
}

Image write_barcode(BarcodeFormat format, std::string text, int width, int height, int margin, int eccLevel)
{
	auto writer = MultiFormatWriter(format).setMargin(margin).setEccLevel(eccLevel);
	auto bitmap = writer.encode(TextUtfEncoding::FromUtf8(text), width, height);

	auto result = Image({bitmap.width(), bitmap.height()});
	auto r = result.mutable_unchecked<2>();
	for (ssize_t y = 0; y < r.shape(0); y++)
		for (ssize_t x = 0; x < r.shape(1); x++)
			r(y, x) = bitmap.get(x, y) ? 0 : 255;
	return result;
}

PYBIND11_MODULE(zxing, m)
{
	m.doc() = "python bindings for zxing-cpp";
	py::enum_<BarcodeFormat>(m, "BarcodeFormat")
		.value("AZTEC", BarcodeFormat::AZTEC)
		.value("CODABAR", BarcodeFormat::CODABAR)
		.value("CODE_39", BarcodeFormat::CODE_39)
		.value("CODE_93", BarcodeFormat::CODE_93)
		.value("CODE_128", BarcodeFormat::CODE_128)
		.value("DATA_MATRIX", BarcodeFormat::DATA_MATRIX)
		.value("EAN_8", BarcodeFormat::EAN_8)
		.value("EAN_13", BarcodeFormat::EAN_13)
		.value("ITF", BarcodeFormat::ITF)
		.value("MAXICODE", BarcodeFormat::MAXICODE)
		.value("PDF_417", BarcodeFormat::PDF_417)
		.value("QR_CODE", BarcodeFormat::QR_CODE)
		.value("RSS_14", BarcodeFormat::RSS_14)
		.value("RSS_EXPANDED", BarcodeFormat::RSS_EXPANDED)
		.value("UPC_A", BarcodeFormat::UPC_A)
		.value("UPC_E", BarcodeFormat::UPC_E)
		.value("UPC_EAN_EXTENSION", BarcodeFormat::UPC_EAN_EXTENSION)
		.value("FORMAT_COUNT", BarcodeFormat::FORMAT_COUNT)
		.value("INVALID", BarcodeFormat::INVALID)
		.export_values();
	py::class_<ResultPoint>(m, "ResultPoint")
		.def_property_readonly("x", &ResultPoint::x)
		.def_property_readonly("y", &ResultPoint::y);
	py::class_<Result>(m, "Result")
		.def_property_readonly("valid", &Result::isValid)
		.def_property_readonly("text", &Result::text)
		.def_property_readonly("format", &Result::format)
		.def_property_readonly("points", &Result::resultPoints);
	m.def("barcode_format_from_str", &BarcodeFormatFromString, "Convert string to BarcodeFormat", py::arg("str"));
	m.def("barcode_formats_from_str", &BarcodeFormatsFromString, "Convert string to BarcodeFormats", py::arg("str"));
	m.def("read_barcode", &read_barcode, "Read (decode) a barcode from a numpy BGR or grayscale image array",
		py::arg("image"),
		py::arg("formats") = BarcodeFormats{},
		py::arg("fastMode") = false,
		py::arg("tryRotate") = true,
		py::arg("hybridBinarizer") = true
	);
	m.def("write_barcode", &write_barcode, "Write (encode) a text into a barcode and return numpy image array",
		py::arg("format"),
		py::arg("text"),
		py::arg("width") = 0,
		py::arg("height") = 0,
		py::arg("margin") = -1,
		py::arg("eccLevel") = -1
	);
}
<commit_msg>python: fix more VS warnings (introduced with write_barcode function)<commit_after>#include "BarcodeFormat.h"

// Reader
#include "DecodeHints.h"
#include "GenericLuminanceSource.h"
#include "HybridBinarizer.h"
#include "MultiFormatReader.h"
#include "Result.h"

// Writer
#include "BitMatrix.h"
#include "MultiFormatWriter.h"
#include "TextUtfEncoding.h"

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <memory>
#include <vector>

using namespace ZXing;
namespace py = pybind11;

// Numpy array wrapper class for images (either BGR or GRAYSCALE)
using Image = py::array_t<uint8_t, py::array::c_style>;

template<typename OUT, typename IN>
OUT narrow(IN in)
{
	return static_cast<OUT>(in);
}

Result read_barcode(const Image& image, BarcodeFormats formats, bool fastMode, bool tryRotate, bool hybridBinarizer)
{
	DecodeHints hints;
	hints.setTryHarder(!fastMode);
	hints.setTryRotate(tryRotate);
	hints.setPossibleFormats(formats);
	MultiFormatReader reader(hints);
	const auto height = narrow<int>(image.shape(0));
	const auto width = narrow<int>(image.shape(1));
	const auto bytes = image.data();
	std::shared_ptr<LuminanceSource> source;

	if (image.ndim() == 2) {
		// Grayscale image
		source = std::make_shared<GenericLuminanceSource>(width, height, bytes, width);
	} else {
		// BGR image
		const auto channels = image.shape(2);
		source = std::make_shared<GenericLuminanceSource>(width, height, bytes, width * channels, channels, 2, 1, 0);
	}

	if (hybridBinarizer) {
		return reader.read(HybridBinarizer(source));
	} else {
		return reader.read(GlobalHistogramBinarizer(source));
	}
}

Image write_barcode(BarcodeFormat format, std::string text, int width, int height, int margin, int eccLevel)
{
	auto writer = MultiFormatWriter(format).setMargin(margin).setEccLevel(eccLevel);
	auto bitmap = writer.encode(TextUtfEncoding::FromUtf8(text), width, height);

	auto result = Image({bitmap.width(), bitmap.height()});
	auto r = result.mutable_unchecked<2>();
	for (ssize_t y = 0; y < r.shape(0); y++)
		for (ssize_t x = 0; x < r.shape(1); x++)
			r(y, x) = bitmap.get(narrow<int>(x), narrow<int>(y)) ? 0 : 255;
	return result;
}

PYBIND11_MODULE(zxing, m)
{
	m.doc() = "python bindings for zxing-cpp";
	py::enum_<BarcodeFormat>(m, "BarcodeFormat")
		.value("AZTEC", BarcodeFormat::AZTEC)
		.value("CODABAR", BarcodeFormat::CODABAR)
		.value("CODE_39", BarcodeFormat::CODE_39)
		.value("CODE_93", BarcodeFormat::CODE_93)
		.value("CODE_128", BarcodeFormat::CODE_128)
		.value("DATA_MATRIX", BarcodeFormat::DATA_MATRIX)
		.value("EAN_8", BarcodeFormat::EAN_8)
		.value("EAN_13", BarcodeFormat::EAN_13)
		.value("ITF", BarcodeFormat::ITF)
		.value("MAXICODE", BarcodeFormat::MAXICODE)
		.value("PDF_417", BarcodeFormat::PDF_417)
		.value("QR_CODE", BarcodeFormat::QR_CODE)
		.value("RSS_14", BarcodeFormat::RSS_14)
		.value("RSS_EXPANDED", BarcodeFormat::RSS_EXPANDED)
		.value("UPC_A", BarcodeFormat::UPC_A)
		.value("UPC_E", BarcodeFormat::UPC_E)
		.value("UPC_EAN_EXTENSION", BarcodeFormat::UPC_EAN_EXTENSION)
		.value("FORMAT_COUNT", BarcodeFormat::FORMAT_COUNT)
		.value("INVALID", BarcodeFormat::INVALID)
		.export_values();
	py::class_<ResultPoint>(m, "ResultPoint")
		.def_property_readonly("x", &ResultPoint::x)
		.def_property_readonly("y", &ResultPoint::y);
	py::class_<Result>(m, "Result")
		.def_property_readonly("valid", &Result::isValid)
		.def_property_readonly("text", &Result::text)
		.def_property_readonly("format", &Result::format)
		.def_property_readonly("points", &Result::resultPoints);
	m.def("barcode_format_from_str", &BarcodeFormatFromString, "Convert string to BarcodeFormat", py::arg("str"));
	m.def("barcode_formats_from_str", &BarcodeFormatsFromString, "Convert string to BarcodeFormats", py::arg("str"));
	m.def("read_barcode", &read_barcode, "Read (decode) a barcode from a numpy BGR or grayscale image array",
		py::arg("image"),
		py::arg("formats") = BarcodeFormats{},
		py::arg("fastMode") = false,
		py::arg("tryRotate") = true,
		py::arg("hybridBinarizer") = true
	);
	m.def("write_barcode", &write_barcode, "Write (encode) a text into a barcode and return numpy image array",
		py::arg("format"),
		py::arg("text"),
		py::arg("width") = 0,
		py::arg("height") = 0,
		py::arg("margin") = -1,
		py::arg("eccLevel") = -1
	);
}
<|endoftext|>