<commit_before>#include "dwi/gradient.h"

namespace MR
{
  namespace DWI
  {

    using namespace App;

    OptionGroup GradImportOptions (bool include_bvalue_scaling)
    {
      OptionGroup group ("DW gradient table import options");

      group
        + Option ("grad",
            "specify the diffusion-weighted gradient scheme used in the acquisition. "
            "The program will normally attempt to use the encoding stored in the image "
            "header. This should be supplied as a 4xN text file with each line is in "
            "the format [ X Y Z b ], where [ X Y Z ] describe the direction of the "
            "applied gradient, and b gives the b-value in units of s/mm^2.")
        +   Argument ("encoding").type_file_in()

        + Option ("fslgrad",
            "specify the diffusion-weighted gradient scheme used in the acquisition in FSL bvecs/bvals format.")
        +   Argument ("bvecs").type_file_in()
        +   Argument ("bvals").type_file_in();

      if (include_bvalue_scaling)
        group
          + Option ("bvalue_scaling",
              "specifies whether the b-values should be scaled by the square of "
              "the corresponding DW gradient norm, as often required for "
              "multi-shell or DSI DW acquisition schemes. The default action can "
              "also be set in the MRtrix config file, under the BValueScaling entry. "
              "Valid choices are yes/no, true/false, 0/1.")
          +   Argument ("mode").type_bool (true);

      return group;
    }

    OptionGroup GradExportOptions()
    {
      return OptionGroup ("DW gradient table export options")

        + Option ("export_grad_mrtrix", "export the diffusion-weighted gradient table to file in MRtrix format")
        +   Argument ("path").type_file_out()

        + Option ("export_grad_fsl", "export the diffusion-weighted gradient table to files in FSL (bvecs / bvals) format")
        +   Argument ("bvecs_path").type_file_out()
        +   Argument ("bvals_path").type_file_out();
    }

    void save_bvecs_bvals (const Image::Header& header, const std::string& bvecs_path, const std::string& bvals_path)
    {

      const Math::Matrix<float>& grad (header.DW_scheme());
      Math::Matrix<float> G (grad.rows(), 3);

      // rotate vectors from scanner space to image space
      Math::Matrix<float> grad_G = grad.sub (0, grad.rows(), 0, 3);
      Math::Matrix<float> rotation = header.transform().sub (0,3,0,3);
      Math::mult (G, 0.0f, 1.0f, CblasNoTrans, grad_G, CblasNoTrans, rotation);

      // deal with FSL requiring gradient directions to coincide with data strides
      // also transpose matrices in preparation for file output
      std::vector<size_t> order = Image::Stride::order (header, 0, 3);
      Math::Matrix<float> bvecs (3, grad.rows());
      Math::Matrix<float> bvals (1, grad.rows());
      for (size_t n = 0; n < G.rows(); ++n) {
        bvecs(0,n) = header.stride(order[0]) > 0 ? G(n,order[0]) : -G(n,order[0]);
        bvecs(1,n) = header.stride(order[1]) > 0 ? G(n,order[1]) : -G(n,order[1]);
        bvecs(2,n) = header.stride(order[2]) > 0 ? G(n,order[2]) : -G(n,order[2]);
        bvals(0,n) = grad(n,3);
      }

      bvecs.save (bvecs_path);
      bvals.save (bvals_path);

    }

    void export_grad_commandline (const Image::Header& header)
    {
      auto check = [](const Image::Header& h) -> const Image::Header& {
        if (!h.DW_scheme().is_set())
          throw Exception ("no gradient information found within image \"" + h.name() + "\"");
        if (h.DW_scheme().rows() == 0 || h.DW_scheme().columns() < 4)
          throw Exception ("DW scheme in header \"" + h.name() + "\" has unexpected dimensions");
        return h;
      };

      App::Options opt = get_options ("export_grad_mrtrix");
      if (opt.size())
        check (header).DW_scheme().save (opt[0][0]);

      opt = get_options ("export_grad_fsl");
      if (opt.size())
        save_bvecs_bvals (check (header), opt[0][0], opt[0][1]);
    }

  }
}

<commit_msg>state default value of -bvalue_scaling option in doc string<commit_after>#include "dwi/gradient.h"

namespace MR
{
  namespace DWI
  {

    using namespace App;

    OptionGroup GradImportOptions (bool include_bvalue_scaling)
    {
      OptionGroup group ("DW gradient table import options");

      group
        + Option ("grad",
            "specify the diffusion-weighted gradient scheme used in the acquisition. "
            "The program will normally attempt to use the encoding stored in the image "
            "header. This should be supplied as a 4xN text file with each line is in "
            "the format [ X Y Z b ], where [ X Y Z ] describe the direction of the "
            "applied gradient, and b gives the b-value in units of s/mm^2.")
        +   Argument ("encoding").type_file_in()

        + Option ("fslgrad",
            "specify the diffusion-weighted gradient scheme used in the acquisition in FSL bvecs/bvals format.")
        +   Argument ("bvecs").type_file_in()
        +   Argument ("bvals").type_file_in();

      if (include_bvalue_scaling)
        group
          + Option ("bvalue_scaling",
              "specifies whether the b-values should be scaled by the square of "
              "the corresponding DW gradient norm, as often required for "
              "multi-shell or DSI DW acquisition schemes. The default action can "
              "also be set in the MRtrix config file, under the BValueScaling entry. "
              "Valid choices are yes/no, true/false, 0/1 (default: true).")
          +   Argument ("mode").type_bool (true);

      return group;
    }

    OptionGroup GradExportOptions()
    {
      return OptionGroup ("DW gradient table export options")

        + Option ("export_grad_mrtrix", "export the diffusion-weighted gradient table to file in MRtrix format")
        +   Argument ("path").type_file_out()

        + Option ("export_grad_fsl", "export the diffusion-weighted gradient table to files in FSL (bvecs / bvals) format")
        +   Argument ("bvecs_path").type_file_out()
        +   Argument ("bvals_path").type_file_out();
    }

    void save_bvecs_bvals (const Image::Header& header, const std::string& bvecs_path, const std::string& bvals_path)
    {

      const Math::Matrix<float>& grad (header.DW_scheme());
      Math::Matrix<float> G (grad.rows(), 3);

      // rotate vectors from scanner space to image space
      Math::Matrix<float> grad_G = grad.sub (0, grad.rows(), 0, 3);
      Math::Matrix<float> rotation = header.transform().sub (0,3,0,3);
      Math::mult (G, 0.0f, 1.0f, CblasNoTrans, grad_G, CblasNoTrans, rotation);

      // deal with FSL requiring gradient directions to coincide with data strides
      // also transpose matrices in preparation for file output
      std::vector<size_t> order = Image::Stride::order (header, 0, 3);
      Math::Matrix<float> bvecs (3, grad.rows());
      Math::Matrix<float> bvals (1, grad.rows());
      for (size_t n = 0; n < G.rows(); ++n) {
        bvecs(0,n) = header.stride(order[0]) > 0 ? G(n,order[0]) : -G(n,order[0]);
        bvecs(1,n) = header.stride(order[1]) > 0 ? G(n,order[1]) : -G(n,order[1]);
        bvecs(2,n) = header.stride(order[2]) > 0 ? G(n,order[2]) : -G(n,order[2]);
        bvals(0,n) = grad(n,3);
      }

      bvecs.save (bvecs_path);
      bvals.save (bvals_path);

    }

    void export_grad_commandline (const Image::Header& header)
    {
      auto check = [](const Image::Header& h) -> const Image::Header& {
        if (!h.DW_scheme().is_set())
          throw Exception ("no gradient information found within image \"" + h.name() + "\"");
        if (h.DW_scheme().rows() == 0 || h.DW_scheme().columns() < 4)
          throw Exception ("DW scheme in header \"" + h.name() + "\" has unexpected dimensions");
        return h;
      };

      App::Options opt = get_options ("export_grad_mrtrix");
      if (opt.size())
        check (header).DW_scheme().save (opt[0][0]);

      opt = get_options ("export_grad_fsl");
      if (opt.size())
        save_bvecs_bvals (check (header), opt[0][0], opt[0][1]);
    }

  }
}

<|endoftext|>


<commit_before>
#include <iostream>
#include <memory>
#include <ctime>
#include <cmath>

#include "dynamicmodel.h"
#include "history.h"
#include "modelstate.h"
#include "config.h"
#include "constants.h"
#include "logging.h"
#include "meteo.h"
#include "surfacedensity.h"
#include "metamorphism.h"
#include "compaction.h"
#include "heatsolver.h"
#include "utils.h"

namespace DSM{

DynamicModel::DynamicModel() : _nt(0) { }

void DynamicModel::run(){
   /* MAIN DRIVER ROUTINE
      initializes submodels, runs timeloop and writes output */
   const char * option_name;

   /* read time step */
   option_name = "general:dt";
   _dt = (long) config.getInt(option_name, true, 1, (int)1e9, -1);
   const long dt_per_year = sec_in_year / _dt;
   logger << "INFO: dt_per_year = " << dt_per_year << std::endl;

   /* read stopping criteria */
   option_name = "stopping_criteria:which_spinup";
   const int which_spinup = config.getInt(option_name, false, 0, 1, 0);
   bool spinup_stop_year = false;
   bool spinup_stop_dens = false;
   switch (which_spinup) {
      case 0   :  spinup_stop_year = true; break;
      case 1   :  spinup_stop_dens = true; break;
//      case 2   :  stop_depth = true; break;
//      case 3   :  stop_year = true; stop_dens = true; break;
//      case 4   :  stop_year = true; stop_depth = true; break;
//      case 5   :  stop_year = true; stop_dens = true; stop_depth = true; break;
      default  :
         logger << "ERROR: unknown value: " << which_spinup << " for config option " << option_name << std::endl;
         std::abort();
   }
   int spinup_nyear;
   double spinup_dens;
   if (spinup_stop_year) {
      option_name = "stopping_criteria:spinup_nyear";
      logger << "INFO: spinup is done based on number of years" << std::endl;
      spinup_nyear = config.getInt(option_name, true, 0, (int)1e9, -1);
   }
   if (spinup_stop_dens) {
      option_name = "stopping_criteria:spinup_dens";
      logger << "INFO: spinup is done based on target density" << std::endl;
      spinup_dens = config.getDouble(option_name, true, 1., 900., -1.);
   }
  option_name = "stopping_criteria:nyear";
  const int nyear = config.getInt(option_name, true, 1, (int)1e9, -1);

   /* setup submodels */
   std::unique_ptr<Meteo> meteo           = instantiate_meteo(*this);
   std::unique_ptr<SurfaceDensity> surf   = instantiate_surfacedensity(*meteo);
   ModelState mstate(*meteo, *surf, *this);
   std::unique_ptr<Metamorphism> mm       = instantiate_metamorphism(mstate, *this);
   std::unique_ptr<Compaction> comp       = instantiate_compaction(mstate, *this);
   std::unique_ptr<HeatSolver> heat       = instantiate_heatsolver(mstate, *this);
   History history(mstate);

   /* print some meteo statistics */
   logger << "INFO: initial surface temperature is: " << meteo->surfaceTemperature() << std::endl;
   logger << "INFO: initial surface wind is: " << meteo->surfaceWind() << std::endl;
   logger << "INFO: initial accumulation rate is: " << meteo->accumulationRate() << std::endl;

   /* start of the spinup time loop */
   std::clock_t start;
   int kYear = 0;
   while(
         (spinup_stop_year ? kYear < spinup_nyear : true)
      && (spinup_stop_dens ? !mstate.hasReachedDensity(spinup_dens) : true)) {

      start = clock();
      for(int tstep = 0; tstep < dt_per_year; tstep++) {
         runTimeStep(mstate, *mm, *comp, *heat);
      }
      double elapsed = ((double)(clock() - start)) / CLOCKS_PER_SEC;

      logger  << "spinup year=" << kYear
            << ", Tmin=" << mstate.minTemp()
            << ", Tmax=" << mstate.maxTemp()
            << ", rho_max=" << mstate.maxDens()
            << ", sec/year=" << elapsed
            << ", year/hour=" << 3600./elapsed << std::endl;
      kYear++;
   }

   /* start of the main time loop */
   kYear = 0;
   while( kYear < nyear ) {
      start = clock();
      for(int tstep = 0; tstep < dt_per_year; tstep++) {
         runTimeStep(mstate, *mm, *comp, *heat);
         history.update(startOfDay(tstep * _dt));
      }
      double elapsed = ((double)(clock() - start)) / CLOCKS_PER_SEC;

      logger  << "model year=" << kYear
            << ", Tmin=" << mstate.minTemp()
            << ", Tmax=" << mstate.maxTemp()
            << ", rho_max=" << mstate.maxDens()
            << ", sec/year=" << elapsed
            << ", year/hour=" << 3600./elapsed << std::endl;
      kYear++;
   }
   mstate.printSummary();
   mstate.writeModelState();
   history.writeHistory();
}

void DynamicModel::runTimeStep(ModelState& mstate, Metamorphism& mm, Compaction& comp, HeatSolver& heat) {
   accumulate(mstate);
   mm.metamorphism();
   comp.compaction();
   doGridChecks(mstate);
   heat.heatdiffusion();
   _nt++;
}

void DynamicModel::doGridChecks(ModelState& mstate){
   /* PERFORMS A NUMBER OF CHECKS ON THE CONSISTENCY AND EFFICIENCY OF THE GRID */

   Grid& grid = mstate.getGrid();
   int i;

   /* check minimum thickness (top layer, index N-1) */
   i = grid.size()-1;
   if (grid[i].dz < dzmin_top && mstate.gridsize() > 1){
      // Layer is too thin, combine with neighbor
      mstate.combineLayers(grid[i-1], grid[i]);
      grid.pop_back();
   }

   /* check minimum thickness, start with second layer (index N-2) */
   i = grid.size()-2;
   while (i >= 0 ) { // Use while instead of for-loop as size may change during loop
      if (grid[i].dz < dzmin && mstate.gridsize() > 1){
         // Layer is too thin, combine with neighbor
         if (i == 0  || grid[i-1].dz > grid[i+1].dz  ) {
            /* CASE 1: Bottom layer can only be combined with the one above */
            /* CASE 2: Determine smallest neighbour */
            mstate.combineLayers(grid[i+1], grid[i]);
         } else {
            mstate.combineLayers(grid[i-1], grid[i]);
         }
         grid.erase(grid.begin() + i); // NOTE: this is very inefficient
      }
      i--;
   }

   /* check maximum layer thickness */
   Layer& top = grid.back();
   while (grid.back().dz > dzmax ) {
      /* Split in unequal parts 4:1
         all vars are identical except thickness */
      top = grid.back();
      Layer layer = top;
      layer.dz    = top.dz/5.;
      top.dz      = top.dz * 4./5;
      grid.push_back(layer);
   }

   /* remove bottom layers that have attained ice density */
   while(!grid.empty() && grid.front().dens > 900.)
      grid.erase(grid.begin());

   if (grid.empty()) {
      logger << "ERROR: all layers turned to ice and were removed! This probably means that something is wrong with the compaction routine or the accumulation flux" << std::endl;
      std::abort();
   }
}

void DynamicModel::accumulate(ModelState& mstate) {
   const double acc = mstate.getMeteo().accumulationRate();
   if ( doubles_equal(acc, 0.0)) {return;}
   if ( acc < 0.) {
      accumulateNegative(mstate);
   } else {
      accumulatePositive(mstate);
   }
}

void DynamicModel::accumulateNegative(ModelState& mstate) {
   Grid& grid = mstate.getGrid();
   const double evap = std::abs(mstate.getMeteo().accumulationRate() * 1e-3 * _dt);
   while (grid.back().dz * grid.back().dens / rho_w < evap) {
      if (grid.size() < 2) {
         logger << "WARNING: not enough mass present for sublimation / evaporation" << std::endl;
         return;
      }
      logger << "grid size = " << grid.size() << std::endl;
      logger << "DEBUG combining [ " << (grid.end()[-2]).dz * (grid.end()[-2]).dens / rho_w << ", "
             << grid.back().dz * grid.back().dens / rho_w << " ] mm W.E. to meet " << evap << " mm W.E. of subl." << std::endl;
      mstate.combineLayers(grid.end()[-2], grid.back());
      grid.pop_back();
   }
   grid.back().dz -= evap * (rho_w/grid.back().dens);
//   logger << "DEBUG removing " << evap * (rho_w/grid.back().dens) << " m from top layer" << std::endl;
   if (grid.back().dz <= 0.) {
      logger << "ERROR: negative layer thickness after evaporation (programmer error)" << std::endl;
      std::abort();
   }
   return;
}

void DynamicModel::accumulatePositive(ModelState& mstate) {
   Grid& grid = mstate.getGrid();
   const double dens = mstate.getSurf().density();
   const double acc = mstate.getMeteo().accumulationRate() * 1e-3 * _dt; // convert from [mm/s] to [m]
   const double dz = (rho_w/dens) * acc;
   Layer& top = grid.back();

   // grain parameters are mass weighted
   const double U = mstate.getMeteo().surfaceWind();
   const double dfall = std::min(std::max(1.29-0.17*U, 0.20), 1.);
   const double sfall = std::min(std::max(0.08*U + 0.38, 0.5), 0.9);
   const double new_snow = dz*dens;
   const double old_snow = top.dz*top.dz;

#ifdef DEBUG
   const double dold = top.dnd;
   const double sold = top.sph;
#endif

   top.dnd    = (top.dnd*old_snow + dfall*new_snow)/(new_snow+old_snow);
   top.sph    = (top.sph*old_snow + sfall*new_snow)/(new_snow+old_snow);
   top.gs   = (top.gs*old_snow + fs_gs*new_snow)/(new_snow+old_snow);

#ifdef DEBUG
   if (top.dnd > 1. || top.dnd < 0) {
      logger << "DEBUG top.dnd = " << top.dnd << ", U = " << U << std::endl;
      logger << "DEBUG dfall = " << dfall << ", sfall = " << sfall << std::endl;
      logger << "DEBUG dold = " << dold << ", sold = " << sold << std::endl;
      logger << "DEBUG new_snow = " << new_snow << ", old_snow = " << old_snow << std::endl;
      std::abort();
   }
#endif

   top.dens = top.dz/(top.dz+dz)*top.dens + dz/(top.dz+dz)*dens;
   top.dz = top.dz + dz;

}

bool DynamicModel::startOfDay(long curr_sec){
   /*
      Some History updates are only performed at the beginning of a new day.
      This is a somewhat crude approach and won't work if a day does not
      nicely divide by the model timestep!

      TODO: replace with class Time, that stores the current timestep and
      has a function at_beginning_of_day()
   */
   return (curr_sec % 86400 == 0 ? true : false);
}

} // namespace
<commit_msg>bugfix in mass weighing of grain parameters<commit_after>
#include <iostream>
#include <memory>
#include <ctime>
#include <cmath>

#include "dynamicmodel.h"
#include "history.h"
#include "modelstate.h"
#include "config.h"
#include "constants.h"
#include "logging.h"
#include "meteo.h"
#include "surfacedensity.h"
#include "metamorphism.h"
#include "compaction.h"
#include "heatsolver.h"
#include "utils.h"

namespace DSM{

DynamicModel::DynamicModel() : _nt(0) { }

void DynamicModel::run(){
   /* MAIN DRIVER ROUTINE
      initializes submodels, runs timeloop and writes output */
   const char * option_name;

   /* read time step */
   option_name = "general:dt";
   _dt = (long) config.getInt(option_name, true, 1, (int)1e9, -1);
   const long dt_per_year = sec_in_year / _dt;
   logger << "INFO: dt_per_year = " << dt_per_year << std::endl;

   /* read stopping criteria */
   option_name = "stopping_criteria:which_spinup";
   const int which_spinup = config.getInt(option_name, false, 0, 1, 0);
   bool spinup_stop_year = false;
   bool spinup_stop_dens = false;
   switch (which_spinup) {
      case 0   :  spinup_stop_year = true; break;
      case 1   :  spinup_stop_dens = true; break;
//      case 2   :  stop_depth = true; break;
//      case 3   :  stop_year = true; stop_dens = true; break;
//      case 4   :  stop_year = true; stop_depth = true; break;
//      case 5   :  stop_year = true; stop_dens = true; stop_depth = true; break;
      default  :
         logger << "ERROR: unknown value: " << which_spinup << " for config option " << option_name << std::endl;
         std::abort();
   }
   int spinup_nyear;
   double spinup_dens;
   if (spinup_stop_year) {
      option_name = "stopping_criteria:spinup_nyear";
      logger << "INFO: spinup is done based on number of years" << std::endl;
      spinup_nyear = config.getInt(option_name, true, 0, (int)1e9, -1);
   }
   if (spinup_stop_dens) {
      option_name = "stopping_criteria:spinup_dens";
      logger << "INFO: spinup is done based on target density" << std::endl;
      spinup_dens = config.getDouble(option_name, true, 1., 900., -1.);
   }
  option_name = "stopping_criteria:nyear";
  const int nyear = config.getInt(option_name, true, 1, (int)1e9, -1);

   /* setup submodels */
   std::unique_ptr<Meteo> meteo           = instantiate_meteo(*this);
   std::unique_ptr<SurfaceDensity> surf   = instantiate_surfacedensity(*meteo);
   ModelState mstate(*meteo, *surf, *this);
   std::unique_ptr<Metamorphism> mm       = instantiate_metamorphism(mstate, *this);
   std::unique_ptr<Compaction> comp       = instantiate_compaction(mstate, *this);
   std::unique_ptr<HeatSolver> heat       = instantiate_heatsolver(mstate, *this);
   History history(mstate);

   /* print some meteo statistics */
   logger << "INFO: initial surface temperature is: " << meteo->surfaceTemperature() << std::endl;
   logger << "INFO: initial surface wind is: " << meteo->surfaceWind() << std::endl;
   logger << "INFO: initial accumulation rate is: " << meteo->accumulationRate() << std::endl;

   /* start of the spinup time loop */
   std::clock_t start;
   int kYear = 0;
   while(
         (spinup_stop_year ? kYear < spinup_nyear : true)
      && (spinup_stop_dens ? !mstate.hasReachedDensity(spinup_dens) : true)) {

      start = clock();
      for(int tstep = 0; tstep < dt_per_year; tstep++) {
         runTimeStep(mstate, *mm, *comp, *heat);
      }
      double elapsed = ((double)(clock() - start)) / CLOCKS_PER_SEC;

      logger  << "spinup year=" << kYear
            << ", Tmin=" << mstate.minTemp()
            << ", Tmax=" << mstate.maxTemp()
            << ", rho_max=" << mstate.maxDens()
            << ", tdepth=" << mstate.totalDepth()
            << ", sec/year=" << elapsed
            << ", year/hour=" << 3600./elapsed << std::endl;
      kYear++;
   }

   /* start of the main time loop */
   kYear = 0;
   while( kYear < nyear ) {
      start = clock();
      for(int tstep = 0; tstep < dt_per_year; tstep++) {
         runTimeStep(mstate, *mm, *comp, *heat);
         history.update(startOfDay(tstep * _dt));
      }
      double elapsed = ((double)(clock() - start)) / CLOCKS_PER_SEC;

      logger  << "model year=" << kYear
            << ", Tmin=" << mstate.minTemp()
            << ", Tmax=" << mstate.maxTemp()
            << ", rho_max=" << mstate.maxDens()
            << ", sec/year=" << elapsed
            << ", year/hour=" << 3600./elapsed << std::endl;
      kYear++;
   }
   mstate.printSummary();
   mstate.writeModelState();
   history.writeHistory();
}

void DynamicModel::runTimeStep(ModelState& mstate, Metamorphism& mm, Compaction& comp, HeatSolver& heat) {
   accumulate(mstate);
   mm.metamorphism();
   comp.compaction();
   doGridChecks(mstate);
   heat.heatdiffusion();
   _nt++;
}

void DynamicModel::doGridChecks(ModelState& mstate){
   /* PERFORMS A NUMBER OF CHECKS ON THE CONSISTENCY AND EFFICIENCY OF THE GRID */

   Grid& grid = mstate.getGrid();
   int i;

   /* check minimum thickness (top layer, index N-1) */
   i = grid.size()-1;
   if (grid[i].dz < dzmin_top && mstate.gridsize() > 1){
      // Layer is too thin, combine with neighbor
      mstate.combineLayers(grid[i-1], grid[i]);
      grid.pop_back();
   }

   /* check minimum thickness, start with second layer (index N-2) */
   i = grid.size()-2;
   while (i >= 0 ) { // Use while instead of for-loop as size may change during loop
      if (grid[i].dz < dzmin && mstate.gridsize() > 1){
         // Layer is too thin, combine with neighbor
         if (i == 0  || grid[i-1].dz > grid[i+1].dz  ) {
            /* CASE 1: Bottom layer can only be combined with the one above */
            /* CASE 2: Determine smallest neighbour */
            mstate.combineLayers(grid[i+1], grid[i]);
         } else {
            mstate.combineLayers(grid[i-1], grid[i]);
         }
         grid.erase(grid.begin() + i); // NOTE: this is very inefficient
      }
      i--;
   }

   /* check maximum layer thickness */
   Layer& top = grid.back();
   while (grid.back().dz > dzmax ) {
      /* Split in unequal parts 4:1
         all vars are identical except thickness */
      top = grid.back();
      Layer layer = top;
      layer.dz    = top.dz/5.;
      top.dz      = top.dz * 4./5;
      grid.push_back(layer);
   }

   /* remove bottom layers that have attained ice density */
   while(!grid.empty() && grid.front().dens > 900.)
      grid.erase(grid.begin());

   if (grid.empty()) {
      logger << "ERROR: all layers turned to ice and were removed! This probably means that something is wrong with the compaction routine or the accumulation flux" << std::endl;
      std::abort();
   }
}

void DynamicModel::accumulate(ModelState& mstate) {
   const double acc = mstate.getMeteo().accumulationRate();
   if ( doubles_equal(acc, 0.0)) {return;}
   if ( acc < 0.) {
      accumulateNegative(mstate);
   } else {
      accumulatePositive(mstate);
   }
}

void DynamicModel::accumulateNegative(ModelState& mstate) {
   Grid& grid = mstate.getGrid();
   const double evap = std::abs(mstate.getMeteo().accumulationRate() * 1e-3 * _dt);
   while (grid.back().dz * grid.back().dens / rho_w < evap) {
      if (grid.size() < 2) {
         logger << "WARNING: not enough mass present for sublimation / evaporation" << std::endl;
         return;
      }
      logger << "grid size = " << grid.size() << std::endl;
      logger << "DEBUG combining [ " << (grid.end()[-2]).dz * (grid.end()[-2]).dens / rho_w << ", "
             << grid.back().dz * grid.back().dens / rho_w << " ] mm W.E. to meet " << evap << " mm W.E. of subl." << std::endl;
      mstate.combineLayers(grid.end()[-2], grid.back());
      grid.pop_back();
   }
   grid.back().dz -= evap * (rho_w/grid.back().dens);
//   logger << "DEBUG removing " << evap * (rho_w/grid.back().dens) << " m from top layer" << std::endl;
   if (grid.back().dz <= 0.) {
      logger << "ERROR: negative layer thickness after evaporation (programmer error)" << std::endl;
      std::abort();
   }
   return;
}

void DynamicModel::accumulatePositive(ModelState& mstate) {
   Grid& grid = mstate.getGrid();
   const double dens = mstate.getSurf().density();
   const double acc = mstate.getMeteo().accumulationRate() * 1e-3 * _dt; // convert from [mm/s] to [m]
   const double dz = (rho_w/dens) * acc;
   Layer& top = grid.back();

   // grain parameters are mass weighted
   const double U = mstate.getMeteo().surfaceWind();
   const double dfall = std::min(std::max(1.29-0.17*U, 0.20), 1.);
   const double sfall = std::min(std::max(0.08*U + 0.38, 0.5), 0.9);
   const double new_snow = dz*dens; // mass of new snow [kg/m2]
   const double old_snow = top.dz*top.dens; // mass of existing snow [kg/m2]

#ifdef DEBUG
   const double dold = top.dnd;
   const double sold = top.sph;
#endif

   top.dnd    = (top.dnd*old_snow + dfall*new_snow)/(new_snow+old_snow);
   top.sph    = (top.sph*old_snow + sfall*new_snow)/(new_snow+old_snow);
   top.gs   = (top.gs*old_snow + fs_gs*new_snow)/(new_snow+old_snow);

#ifdef DEBUG
   if (top.dnd > 1. || top.dnd < 0) {
      logger << "DEBUG top.dnd = " << top.dnd << ", U = " << U << std::endl;
      logger << "DEBUG dfall = " << dfall << ", sfall = " << sfall << std::endl;
      logger << "DEBUG dold = " << dold << ", sold = " << sold << std::endl;
      logger << "DEBUG new_snow = " << new_snow << ", old_snow = " << old_snow << std::endl;
      std::abort();
   }
#endif

   top.dens = top.dz/(top.dz+dz)*top.dens + dz/(top.dz+dz)*dens;
   top.dz = top.dz + dz;
}

bool DynamicModel::startOfDay(long curr_sec){
   /*
      Some History updates are only performed at the beginning of a new day.
      This is a somewhat crude approach and won't work if a day does not
      nicely divide by the model timestep!

      TODO: replace with class Time, that stores the current timestep and
      has a function at_beginning_of_day()
   */
   return (curr_sec % 86400 == 0 ? true : false);
}

} // namespace
<|endoftext|>


<commit_before>#include <fstream>

#include "glsl++.h"

namespace glsl {

	float eps = 0.0001;
	float pi = 3.1415926;
	float pi2 = pi/2.0;
	float time;
	uniform vec4 params[2];

	mat3 rm(float angle, vec3 n)
	{
		float c = cos(angle), s = sin(angle);
		n = normalize(n);
		return mat3(c,n.z*s,-n.y*s,
	            	    -n.z*s,c,n.x*s,
	            	    n.y*s,-n.x*s,c) +  outerProduct(n * vec3(1.0f-c), n);
	}

	vec3 phong(vec3 D, vec3 P, vec3 N, vec3 L, vec3 d, vec3 s, float e)
	{
		L = normalize(L - P);
		//    return d * max(dot(N, L), 0.0) + s * pow(max(dot(N, normalize(L - D)), 0.0), e); // Blinn-Phong
		return d * max(dot(N, L), 0.0f) + s * pow(max(dot(reflect(L, N), D), 0.0f), e);
	}

	float sphere(vec3 pos, vec3 origin, float radius)
	{
		return distance(pos, origin) - radius;
	}

	float cube(vec3 pos, vec3 origin, float size)
	{
		vec3 c = abs(pos - origin) - size;
		return max(max(c.x, c.y), c.z);
	}

	float torus(vec3 pos, vec3 origin, float radius1, float radius2)
	{
		return length(vec2(length((pos - origin).xz) - radius1, pos.y - origin.y)) - radius2;
	}

	vec3 eval(mat3 pos)
	{
		vec3 dist;
		vec3 p2 = pos[0] * rm((pos[0].y+pos[0].z)*(cos(time*0.73)*params[0].x + params[0].y /*0.3*/ /*+1.0*/), vec3(0.0, 0.0, 1.0) * rm(time*0.43, vec3(0.0, 1.0, 0.0)));
		p2 += cos(p2*params[0].z /* + cos(time*0.87)*params[0].w + 1.5 */);
	//	p2 += cos(p2*params[0].z /*2.0*/ + cos(time*0.87)*params[0].w /*0.5*/ + 1.5);
		dist.x = min(-sphere(pos[0], vec3(0.0, 0.0, 0.0), 20.0), torus(p2, vec3(0.0, 0.0, 0.0), 1.0, 0.30+cos(time*0.37)*params[1].x /*0.1*/) - params[1].y /*0.15*/ * sphere(p2 * rm(time*0.57, vec3(0.0, 1.0, 0.0)) * (vec3(0.1, 1.0, 1.0)), vec3(0.0, 0.0, 0.0), 1.0));
	//	dist.x = min(-sphere(pos[0], vec3(0.0, 0.0, 0.0), 20.0), torus(pos[0], vec3(0.0, 0.0, 0.0), 1.0, 0.25));
		dist.y = -sphere(pos[1], vec3(0.0, 0.0, 0.0), 10.0);
		dist.z = -cube(pos[2] * rm((pos[2].x+pos[2].y)*cos(time*0.37)*params[1].z /*0.05*/, vec3(1.0, 1.0, 0.0)), vec3(0.0, 0.0, 0.0), 7.0);
		return dist;
	}

	vec3 cast(inout vec3& dir, inout vec3& origin)
	{
		float i = 0.0;
		vec3 dist, tdist = vec3(0.0, 0.0, 0.0);
		mat3 m_origin = mat3(origin, origin, origin);
		do
		{
			dist = eval(m_origin) * vec3(0.1, 1.0, 0.5);
			tdist += max(dist, vec3(eps));
	/*		m_origin[0] += dir * max(dist.x, eps);
			m_origin[1] += dir * max(dist.y, eps);
			m_origin[2] += dir * max(dist.z, eps);
			m_origin[3] += dir * max(dist.w, eps);*/
			m_origin += outerProduct(dir, max(dist, vec3(eps)));
			i += 1.0;
	//	} while (i < 400.0 && greaterThan(dist, vec3(eps)) != bvec3(false, false, false));
		} while (i < 300.0 && (dist.x > eps || dist.y > eps || dist.z > eps)); // greaterThan(dist, vec3(eps)) != bvec3(false, false, false));

	/*	if (i >= 400.0)
			return vec3(1.0, 1.0, 1.0);*/

		mat3 e1 = mat3(eps, 0.0, 0.0,
				eps, 0.0, 0.0,
				eps, 0.0, 0.0);
		mat3 e2 = mat3(0.0, eps, 0.0,
				0.0, eps, 0.0,
				0.0, eps, 0.0);
		mat3 e3 = mat3(0.0, 0.0, eps,
				0.0, 0.0, eps,
				0.0, 0.0, eps);
		mat3 N = transpose(mat3(
		                  	  eval(m_origin + e1) - eval(m_origin - e1),
		                  	  eval(m_origin + e2) - eval(m_origin - e2),
		                  	  eval(m_origin + e3) - eval(m_origin - e3)
		                 	 ));
		N[0] = normalize(N[0]);
		N[1] = normalize(N[1]);
		N[2] = normalize(N[2]);
		vec3 color = 0;
		if ((tdist.x < tdist.y) && (tdist.x < tdist.z)) {
			color = phong(dir, m_origin[0], N[0], vec3(0.0, 4.0, 4.0), vec3(1.0, 0.5, 0.2), vec3(1.0, 0.7, 0.0), 50.0)
		       	       + phong(dir, m_origin[0], N[0], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, 1.0), 50.0);
			dir = reflect(dir, N[0]);
		}
		else if ((tdist.y < tdist.z)) {
			color = phong(dir, m_origin[1], N[1], vec3(0.0, 4.0, 4.0), vec3(1.0, 0.7, 0.2), vec3(0.0, 0.0, 1.0), 50.0)
		       	       + phong(dir, m_origin[1], N[1], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 0.0), 50.0);
			dir = reflect(dir, N[1]);
		}
		else {
			color = phong(dir, m_origin[2], N[2], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.1, 0.0), vec3(0.0, 0.0, 0.7), 100.0)
		       	       + phong(dir, m_origin[2], N[2], vec3(-4.0, -4.0, 0.0), vec3(0.2, 0.1, 0.5), vec3(0.0, 0.0, 0.7), 100.0);
			dir = reflect(dir, N[2]);
		}
	/*	if ((tdist.x < tdist.y) && (tdist.x < tdist.z)) {
			color = 0;
			color = phong(dir, m_origin[0], N[0], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.4, 0.2), vec3(0.4, 0.0, 0.0), 50.0)
		       	       + phong(dir, m_origin[0], N[0], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.5, 0.0), vec3(0.0, 0.0, 0.4), 50.0);
			dir = reflect(dir, N[0]);
		}
		else if ((tdist.y < tdist.z)) {
			color = 0;
			color = phong(dir, m_origin[1], N[1], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.2, 0.0), vec3(1.0, 1.0, 1.0), 50.0)
		       	       + phong(dir, m_origin[1], N[1], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 0.2), vec3(1.0, 1.0, 1.0), 50.0);
			dir = reflect(dir, N[1]);
		}
		else {
			color = 0;
			color = phong(dir, m_origin[2], N[2], vec3(0.0, 4.0, 4.0), vec3(0.4, 0.4, 0.1), vec3(0.4, 0.1, 0.3), 50.0)
		       	       + phong(dir, m_origin[2], N[2], vec3(-4.0, -4.0, 0.0), vec3(0.4, 0.1, 0.1), vec3(0.1, 0.4, 0.1), 50.0);
			dir = reflect(dir, N[2]);
		}*/
		return color;
	}

	void glslmain( void )
	{
		vec2 p = vec2(gl_FragCoord.x + (gl_TexCoord[0].y - gl_TexCoord[0].x)/2.0, gl_FragCoord.y) / gl_TexCoord[0].yy * 2.0 - 1.0;
		mat3 m = mat3(1.0);
		vec3 tr = vec3(0.0);
		time = gl_TexCoord[0].z;

		m *= rm(time*0.1, vec3(1.0, 1.0, 0.0));

		vec3 dir = normalize(vec3(p, -1.0) * m);
		vec3 origin = vec3(0.0, 0.0, 3.5 - (cos(time*0.43)*0.75+cos(time*1.04)*0.25+1.0)*params[1].w) * m + tr;

		vec3 c1 = cast(dir, origin);
		vec3 c2 = cast(dir, origin);
		vec3 c = c1 * 0.75 + c2 * 0.25;
	/*	float exposure = 3.0, maxbright = 1.0;
		c = c * exposure * (exposure / (maxbright + 1.0)) / (exposure + 1.0);*/
		c *= 1.125;
		gl_FragColor = vec4(pow(c, vec3(1.0 / 1.0)), 1.0);
	}

	int main()
	{
		std::ofstream out("out.raw");
		int xres = 1920, yres = 1080;

		gl_TexCoord[0] = vec4(xres, yres, 20.0f, 0.0f);
		params[0] = vec4(0.8f, 0.8f, 1.0f, 1.0f);
		params[1] = vec4(0.2f, 0.4f, 0.01f, 3.0f);
		#pragma omp parallel for schedule(dynamic, 4)
		for (int y = yres-1; y >= 0; --y) {
			for (int x = 0; x < xres; ++x) {
				gl_FragCoord = vec4(x, y, 0.0f, 0.0f);
				glslmain();
				out << (unsigned char) clamp(gl_FragColor.r * 255, 0, 255) << (unsigned char) clamp(gl_FragColor.g * 255, 0, 255) << (unsigned char) clamp(gl_FragColor.b * 255, 0, 255);
			}
		}
		return 0;
	}
}

int main()
{
	return glsl::main();
}
<commit_msg>Fix OpenMP support<commit_after>#include <fstream>

#include "glsl++.h"

namespace glsl {

	float eps = 0.0001;
	float pi = 3.1415926;
	float pi2 = pi/2.0;
	float time;
	uniform vec4 params[2];

	mat3 rm(float angle, vec3 n)
	{
		float c = cos(angle), s = sin(angle);
		n = normalize(n);
		return mat3(c,n.z*s,-n.y*s,
	            	    -n.z*s,c,n.x*s,
	            	    n.y*s,-n.x*s,c) +  outerProduct(n * vec3(1.0f-c), n);
	}

	vec3 phong(vec3 D, vec3 P, vec3 N, vec3 L, vec3 d, vec3 s, float e)
	{
		L = normalize(L - P);
		//    return d * max(dot(N, L), 0.0) + s * pow(max(dot(N, normalize(L - D)), 0.0), e); // Blinn-Phong
		return d * max(dot(N, L), 0.0f) + s * pow(max(dot(reflect(L, N), D), 0.0f), e);
	}

	float sphere(vec3 pos, vec3 origin, float radius)
	{
		return distance(pos, origin) - radius;
	}

	float cube(vec3 pos, vec3 origin, float size)
	{
		vec3 c = abs(pos - origin) - size;
		return max(max(c.x, c.y), c.z);
	}

	float torus(vec3 pos, vec3 origin, float radius1, float radius2)
	{
		return length(vec2(length((pos - origin).xz) - radius1, pos.y - origin.y)) - radius2;
	}

	vec3 eval(mat3 pos)
	{
		vec3 dist;
		vec3 p2 = pos[0] * rm((pos[0].y+pos[0].z)*(cos(time*0.73)*params[0].x + params[0].y /*0.3*/ /*+1.0*/), vec3(0.0, 0.0, 1.0) * rm(time*0.43, vec3(0.0, 1.0, 0.0)));
		p2 += cos(p2*params[0].z /* + cos(time*0.87)*params[0].w + 1.5 */);
	//	p2 += cos(p2*params[0].z /*2.0*/ + cos(time*0.87)*params[0].w /*0.5*/ + 1.5);
		dist.x = min(-sphere(pos[0], vec3(0.0, 0.0, 0.0), 20.0), torus(p2, vec3(0.0, 0.0, 0.0), 1.0, 0.30+cos(time*0.37)*params[1].x /*0.1*/) - params[1].y /*0.15*/ * sphere(p2 * rm(time*0.57, vec3(0.0, 1.0, 0.0)) * (vec3(0.1, 1.0, 1.0)), vec3(0.0, 0.0, 0.0), 1.0));
	//	dist.x = min(-sphere(pos[0], vec3(0.0, 0.0, 0.0), 20.0), torus(pos[0], vec3(0.0, 0.0, 0.0), 1.0, 0.25));
		dist.y = -sphere(pos[1], vec3(0.0, 0.0, 0.0), 10.0);
		dist.z = -cube(pos[2] * rm((pos[2].x+pos[2].y)*cos(time*0.37)*params[1].z /*0.05*/, vec3(1.0, 1.0, 0.0)), vec3(0.0, 0.0, 0.0), 7.0);
		return dist;
	}

	vec3 cast(inout vec3& dir, inout vec3& origin)
	{
		float i = 0.0;
		vec3 dist, tdist = vec3(0.0, 0.0, 0.0);
		mat3 m_origin = mat3(origin, origin, origin);
		do
		{
			dist = eval(m_origin) * vec3(0.1, 1.0, 0.5);
			tdist += max(dist, vec3(eps));
	/*		m_origin[0] += dir * max(dist.x, eps);
			m_origin[1] += dir * max(dist.y, eps);
			m_origin[2] += dir * max(dist.z, eps);
			m_origin[3] += dir * max(dist.w, eps);*/
			m_origin += outerProduct(dir, max(dist, vec3(eps)));
			i += 1.0;
	//	} while (i < 400.0 && greaterThan(dist, vec3(eps)) != bvec3(false, false, false));
		} while (i < 300.0 && (dist.x > eps || dist.y > eps || dist.z > eps)); // greaterThan(dist, vec3(eps)) != bvec3(false, false, false));

	/*	if (i >= 400.0)
			return vec3(1.0, 1.0, 1.0);*/

		mat3 e1 = mat3(eps, 0.0, 0.0,
				eps, 0.0, 0.0,
				eps, 0.0, 0.0);
		mat3 e2 = mat3(0.0, eps, 0.0,
				0.0, eps, 0.0,
				0.0, eps, 0.0);
		mat3 e3 = mat3(0.0, 0.0, eps,
				0.0, 0.0, eps,
				0.0, 0.0, eps);
		mat3 N = transpose(mat3(
		                  	  eval(m_origin + e1) - eval(m_origin - e1),
		                  	  eval(m_origin + e2) - eval(m_origin - e2),
		                  	  eval(m_origin + e3) - eval(m_origin - e3)
		                 	 ));
		N[0] = normalize(N[0]);
		N[1] = normalize(N[1]);
		N[2] = normalize(N[2]);
		vec3 color = 0;
		if ((tdist.x < tdist.y) && (tdist.x < tdist.z)) {
			color = phong(dir, m_origin[0], N[0], vec3(0.0, 4.0, 4.0), vec3(1.0, 0.5, 0.2), vec3(1.0, 0.7, 0.0), 50.0)
		       	       + phong(dir, m_origin[0], N[0], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, 1.0), 50.0);
			dir = reflect(dir, N[0]);
		}
		else if ((tdist.y < tdist.z)) {
			color = phong(dir, m_origin[1], N[1], vec3(0.0, 4.0, 4.0), vec3(1.0, 0.7, 0.2), vec3(0.0, 0.0, 1.0), 50.0)
		       	       + phong(dir, m_origin[1], N[1], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 0.0), 50.0);
			dir = reflect(dir, N[1]);
		}
		else {
			color = phong(dir, m_origin[2], N[2], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.1, 0.0), vec3(0.0, 0.0, 0.7), 100.0)
		       	       + phong(dir, m_origin[2], N[2], vec3(-4.0, -4.0, 0.0), vec3(0.2, 0.1, 0.5), vec3(0.0, 0.0, 0.7), 100.0);
			dir = reflect(dir, N[2]);
		}
	/*	if ((tdist.x < tdist.y) && (tdist.x < tdist.z)) {
			color = 0;
			color = phong(dir, m_origin[0], N[0], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.4, 0.2), vec3(0.4, 0.0, 0.0), 50.0)
		       	       + phong(dir, m_origin[0], N[0], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.5, 0.0), vec3(0.0, 0.0, 0.4), 50.0);
			dir = reflect(dir, N[0]);
		}
		else if ((tdist.y < tdist.z)) {
			color = 0;
			color = phong(dir, m_origin[1], N[1], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.2, 0.0), vec3(1.0, 1.0, 1.0), 50.0)
		       	       + phong(dir, m_origin[1], N[1], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 0.2), vec3(1.0, 1.0, 1.0), 50.0);
			dir = reflect(dir, N[1]);
		}
		else {
			color = 0;
			color = phong(dir, m_origin[2], N[2], vec3(0.0, 4.0, 4.0), vec3(0.4, 0.4, 0.1), vec3(0.4, 0.1, 0.3), 50.0)
		       	       + phong(dir, m_origin[2], N[2], vec3(-4.0, -4.0, 0.0), vec3(0.4, 0.1, 0.1), vec3(0.1, 0.4, 0.1), 50.0);
			dir = reflect(dir, N[2]);
		}*/
		return color;
	}

	void glslmain( void )
	{
		vec2 p = vec2(gl_FragCoord.x + (gl_TexCoord[0].y - gl_TexCoord[0].x)/2.0, gl_FragCoord.y) / gl_TexCoord[0].yy * 2.0 - 1.0;
		mat3 m = mat3(1.0);
		vec3 tr = vec3(0.0);
		time = gl_TexCoord[0].z;

		m *= rm(time*0.1, vec3(1.0, 1.0, 0.0));

		vec3 dir = normalize(vec3(p, -1.0) * m);
		vec3 origin = vec3(0.0, 0.0, 3.5 - (cos(time*0.43)*0.75+cos(time*1.04)*0.25+1.0)*params[1].w) * m + tr;

		vec3 c1 = cast(dir, origin);
		vec3 c2 = cast(dir, origin);
		vec3 c = c1 * 0.75 + c2 * 0.25;
	/*	float exposure = 3.0, maxbright = 1.0;
		c = c * exposure * (exposure / (maxbright + 1.0)) / (exposure + 1.0);*/
		c *= 1.125;
		gl_FragColor = vec4(pow(c, vec3(1.0 / 1.0)), 1.0);
	}

	int main()
	{
		std::ofstream out("out.raw");
		int xres = 720, yres = 480;
		unsigned char *data = (unsigned char*) malloc(yres*xres*3);

		gl_TexCoord[0] = vec4(xres, yres, 20.0f, 0.0f);
		params[0] = vec4(0.8f, 0.8f, 1.0f, 1.0f);
		params[1] = vec4(0.2f, 0.4f, 0.01f, 3.0f);
		#pragma omp parallel for schedule(dynamic, 4)
		for (int y = 0; y < yres; ++y) {
			for (int x = 0; x < xres; ++x) {
				gl_FragCoord = vec4(x, y, 0.0f, 0.0f);
				glslmain();
				data[((yres-y-1)*xres+x)*3] = clamp(gl_FragColor.r * 255, 0, 255);
				data[((yres-y-1)*xres+x)*3+1] = clamp(gl_FragColor.g * 255, 0, 255);
				data[((yres-y-1)*xres+x)*3+2] = clamp(gl_FragColor.b * 255, 0, 255);
			}
		}
		// There's probably a better way to do this, something akin to fwrite(), in C++
		for (long long i = 0; i < yres*xres*3; ++i) {
			out << data[i];
		}
		free(data);
		return 0;
	}
}

int main()
{
	return glsl::main();
}
<|endoftext|>


<commit_before><commit_msg>minor cleanup of AnnEngine constructor<commit_after><|endoftext|>


<commit_before>#include <fstream>

#include "glsl++.h"

namespace glsl {

	float eps = 0.0001;
	float pi = 3.1415926;
	float pi2 = pi/2.0;
	float time;
	uniform vec4 params[2];

	mat3 rm(float angle, vec3 n)
	{
		float c = cos(angle), s = sin(angle);
		n = normalize(n);
		return mat3(c,n.z*s,-n.y*s,
	            	    -n.z*s,c,n.x*s,
	            	    n.y*s,-n.x*s,c) +  outerProduct(n * vec3(1.0f-c), n);
	}

	vec3 phong(vec3 D, vec3 P, vec3 N, vec3 L, vec3 d, vec3 s, float e)
	{
		L = normalize(L - P);
		//    return d * max(dot(N, L), 0.0) + s * pow(max(dot(N, normalize(L - D)), 0.0), e); // Blinn-Phong
		return d * max(dot(N, L), 0.0f) + s * pow(max(dot(reflect(L, N), D), 0.0f), e);
	}

	float sphere(vec3 pos, vec3 origin, float radius)
	{
		return distance(pos, origin) - radius;
	}

	float cube(vec3 pos, vec3 origin, float size)
	{
		vec3 c = abs(pos - origin) - size;
		return max(max(c.x, c.y), c.z);
	}

	float torus(vec3 pos, vec3 origin, float radius1, float radius2)
	{
		return length(vec2(length((pos - origin).xz) - radius1, pos.y - origin.y)) - radius2;
	}

	vec3 eval(mat3 pos)
	{
		vec3 dist;
		vec3 p2 = pos[0] * rm((pos[0].y+pos[0].z)*(cos(time*0.73)*params[0].x + params[0].y /*0.3*/ /*+1.0*/), vec3(0.0, 0.0, 1.0) * rm(time*0.43, vec3(0.0, 1.0, 0.0)));
		p2 += cos(p2*params[0].z /* + cos(time*0.87)*params[0].w + 1.5 */);
	//	p2 += cos(p2*params[0].z /*2.0*/ + cos(time*0.87)*params[0].w /*0.5*/ + 1.5);
		dist.x = min(-sphere(pos[0], vec3(0.0, 0.0, 0.0), 20.0), torus(p2, vec3(0.0, 0.0, 0.0), 1.0, 0.30+cos(time*0.37)*params[1].x /*0.1*/) - params[1].y /*0.15*/ * sphere(p2 * rm(time*0.57, vec3(0.0, 1.0, 0.0)) * (vec3(0.1, 1.0, 1.0)), vec3(0.0, 0.0, 0.0), 1.0));
	//	dist.x = min(-sphere(pos[0], vec3(0.0, 0.0, 0.0), 20.0), torus(pos[0], vec3(0.0, 0.0, 0.0), 1.0, 0.25));
		dist.y = -sphere(pos[1], vec3(0.0, 0.0, 0.0), 10.0);
		dist.z = -cube(pos[2] * rm((pos[2].x+pos[2].y)*cos(time*0.37)*params[1].z /*0.05*/, vec3(1.0, 1.0, 0.0)), vec3(0.0, 0.0, 0.0), 7.0);
		return dist;
	}

	vec3 cast(inout vec3& dir, inout vec3& origin)
	{
		float i = 0.0;
		vec3 dist, tdist = vec3(0.0, 0.0, 0.0);
		mat3 m_origin = mat3(origin, origin, origin);
		do
		{
			dist = eval(m_origin) * vec3(0.1, 1.0, 0.5);
			tdist += max(dist, vec3(eps));
	/*		m_origin[0] += dir * max(dist.x, eps);
			m_origin[1] += dir * max(dist.y, eps);
			m_origin[2] += dir * max(dist.z, eps);
			m_origin[3] += dir * max(dist.w, eps);*/
			m_origin += outerProduct(dir, max(dist, vec3(eps)));
			i += 1.0;
	//	} while (i < 400.0 && greaterThan(dist, vec3(eps)) != bvec3(false, false, false));
		} while (i < 300.0 && (dist.x > eps || dist.y > eps || dist.z > eps)); // greaterThan(dist, vec3(eps)) != bvec3(false, false, false));

	/*	if (i >= 400.0)
			return vec3(1.0, 1.0, 1.0);*/

		mat3 e1 = mat3(eps, 0.0, 0.0,
				eps, 0.0, 0.0,
				eps, 0.0, 0.0);
		mat3 e2 = mat3(0.0, eps, 0.0,
				0.0, eps, 0.0,
				0.0, eps, 0.0);
		mat3 e3 = mat3(0.0, 0.0, eps,
				0.0, 0.0, eps,
				0.0, 0.0, eps);
		mat3 N = transpose(mat3(
		                  	  eval(m_origin + e1) - eval(m_origin - e1),
		                  	  eval(m_origin + e2) - eval(m_origin - e2),
		                  	  eval(m_origin + e3) - eval(m_origin - e3)
		                 	 ));
		N[0] = normalize(N[0]);
		N[1] = normalize(N[1]);
		N[2] = normalize(N[2]);
		vec3 color = 0;
		if ((tdist.x < tdist.y) && (tdist.x < tdist.z)) {
			color = phong(dir, m_origin[0], N[0], vec3(0.0, 4.0, 4.0), vec3(1.0, 0.5, 0.2), vec3(1.0, 0.7, 0.0), 50.0)
		       	       + phong(dir, m_origin[0], N[0], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, 1.0), 50.0);
			dir = reflect(dir, N[0]);
		}
		else if ((tdist.y < tdist.z)) {
			color = phong(dir, m_origin[1], N[1], vec3(0.0, 4.0, 4.0), vec3(1.0, 0.7, 0.2), vec3(0.0, 0.0, 1.0), 50.0)
		       	       + phong(dir, m_origin[1], N[1], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 0.0), 50.0);
			dir = reflect(dir, N[1]);
		}
		else {
			color = phong(dir, m_origin[2], N[2], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.1, 0.0), vec3(0.0, 0.0, 0.7), 100.0)
		       	       + phong(dir, m_origin[2], N[2], vec3(-4.0, -4.0, 0.0), vec3(0.2, 0.1, 0.5), vec3(0.0, 0.0, 0.7), 100.0);
			dir = reflect(dir, N[2]);
		}
	/*	if ((tdist.x < tdist.y) && (tdist.x < tdist.z)) {
			color = 0;
			color = phong(dir, m_origin[0], N[0], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.4, 0.2), vec3(0.4, 0.0, 0.0), 50.0)
		       	       + phong(dir, m_origin[0], N[0], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.5, 0.0), vec3(0.0, 0.0, 0.4), 50.0);
			dir = reflect(dir, N[0]);
		}
		else if ((tdist.y < tdist.z)) {
			color = 0;
			color = phong(dir, m_origin[1], N[1], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.2, 0.0), vec3(1.0, 1.0, 1.0), 50.0)
		       	       + phong(dir, m_origin[1], N[1], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 0.2), vec3(1.0, 1.0, 1.0), 50.0);
			dir = reflect(dir, N[1]);
		}
		else {
			color = 0;
			color = phong(dir, m_origin[2], N[2], vec3(0.0, 4.0, 4.0), vec3(0.4, 0.4, 0.1), vec3(0.4, 0.1, 0.3), 50.0)
		       	       + phong(dir, m_origin[2], N[2], vec3(-4.0, -4.0, 0.0), vec3(0.4, 0.1, 0.1), vec3(0.1, 0.4, 0.1), 50.0);
			dir = reflect(dir, N[2]);
		}*/
		return color;
	}

	void glslmain( void )
	{
		vec2 p = vec2(gl_FragCoord.x + (gl_TexCoord[0].y - gl_TexCoord[0].x)/2.0, gl_FragCoord.y) / gl_TexCoord[0].yy * 2.0 - 1.0;
		mat3 m = mat3(1.0);
		vec3 tr = vec3(0.0);
		time = gl_TexCoord[0].z;

		m *= rm(time*0.1, vec3(1.0, 1.0, 0.0));

		vec3 dir = normalize(vec3(p, -1.0) * m);
		vec3 origin = vec3(0.0, 0.0, 3.5 - (cos(time*0.43)*0.75+cos(time*1.04)*0.25+1.0)*params[1].w) * m + tr;

		vec3 c1 = cast(dir, origin);
		vec3 c2 = cast(dir, origin);
		vec3 c = c1 * 0.75 + c2 * 0.25;
	/*	float exposure = 3.0, maxbright = 1.0;
		c = c * exposure * (exposure / (maxbright + 1.0)) / (exposure + 1.0);*/
		c *= 1.125;
		gl_FragColor = vec4(pow(c, vec3(1.0 / 1.0)), 1.0);
	}

	int main()
	{
		std::ofstream out("out.raw");

		gl_TexCoord[0] = vec4(720, 480, 0.0f, 0.0f);
		params[0] = vec4(0.0f, 0.0f, 0.0f, 0.0f);
		params[1] = vec4(0.0f, 0.0f, 0.0f, 0.0f);
		for (int y = 479; y >= 0; --y) {
			for (int x = 0; x < 720; ++x) {
				gl_FragCoord = vec4(x, y, 0.0f, 0.0f);
				glslmain();
				out << (char) clamp(gl_FragColor.r * 255, 0, 255) << (char) clamp(gl_FragColor.g * 255, 0, 255) << (char) clamp(gl_FragColor.b * 255, 0, 255);
			}
		}
		return 0;
	}
}

int main()
{
	return glsl::main();
}
<commit_msg>Fix output to file in example<commit_after>#include <fstream>

#include "glsl++.h"

namespace glsl {

	float eps = 0.0001;
	float pi = 3.1415926;
	float pi2 = pi/2.0;
	float time;
	uniform vec4 params[2];

	mat3 rm(float angle, vec3 n)
	{
		float c = cos(angle), s = sin(angle);
		n = normalize(n);
		return mat3(c,n.z*s,-n.y*s,
	            	    -n.z*s,c,n.x*s,
	            	    n.y*s,-n.x*s,c) +  outerProduct(n * vec3(1.0f-c), n);
	}

	vec3 phong(vec3 D, vec3 P, vec3 N, vec3 L, vec3 d, vec3 s, float e)
	{
		L = normalize(L - P);
		//    return d * max(dot(N, L), 0.0) + s * pow(max(dot(N, normalize(L - D)), 0.0), e); // Blinn-Phong
		return d * max(dot(N, L), 0.0f) + s * pow(max(dot(reflect(L, N), D), 0.0f), e);
	}

	float sphere(vec3 pos, vec3 origin, float radius)
	{
		return distance(pos, origin) - radius;
	}

	float cube(vec3 pos, vec3 origin, float size)
	{
		vec3 c = abs(pos - origin) - size;
		return max(max(c.x, c.y), c.z);
	}

	float torus(vec3 pos, vec3 origin, float radius1, float radius2)
	{
		return length(vec2(length((pos - origin).xz) - radius1, pos.y - origin.y)) - radius2;
	}

	vec3 eval(mat3 pos)
	{
		vec3 dist;
		vec3 p2 = pos[0] * rm((pos[0].y+pos[0].z)*(cos(time*0.73)*params[0].x + params[0].y /*0.3*/ /*+1.0*/), vec3(0.0, 0.0, 1.0) * rm(time*0.43, vec3(0.0, 1.0, 0.0)));
		p2 += cos(p2*params[0].z /* + cos(time*0.87)*params[0].w + 1.5 */);
	//	p2 += cos(p2*params[0].z /*2.0*/ + cos(time*0.87)*params[0].w /*0.5*/ + 1.5);
		dist.x = min(-sphere(pos[0], vec3(0.0, 0.0, 0.0), 20.0), torus(p2, vec3(0.0, 0.0, 0.0), 1.0, 0.30+cos(time*0.37)*params[1].x /*0.1*/) - params[1].y /*0.15*/ * sphere(p2 * rm(time*0.57, vec3(0.0, 1.0, 0.0)) * (vec3(0.1, 1.0, 1.0)), vec3(0.0, 0.0, 0.0), 1.0));
	//	dist.x = min(-sphere(pos[0], vec3(0.0, 0.0, 0.0), 20.0), torus(pos[0], vec3(0.0, 0.0, 0.0), 1.0, 0.25));
		dist.y = -sphere(pos[1], vec3(0.0, 0.0, 0.0), 10.0);
		dist.z = -cube(pos[2] * rm((pos[2].x+pos[2].y)*cos(time*0.37)*params[1].z /*0.05*/, vec3(1.0, 1.0, 0.0)), vec3(0.0, 0.0, 0.0), 7.0);
		return dist;
	}

	vec3 cast(inout vec3& dir, inout vec3& origin)
	{
		float i = 0.0;
		vec3 dist, tdist = vec3(0.0, 0.0, 0.0);
		mat3 m_origin = mat3(origin, origin, origin);
		do
		{
			dist = eval(m_origin) * vec3(0.1, 1.0, 0.5);
			tdist += max(dist, vec3(eps));
	/*		m_origin[0] += dir * max(dist.x, eps);
			m_origin[1] += dir * max(dist.y, eps);
			m_origin[2] += dir * max(dist.z, eps);
			m_origin[3] += dir * max(dist.w, eps);*/
			m_origin += outerProduct(dir, max(dist, vec3(eps)));
			i += 1.0;
	//	} while (i < 400.0 && greaterThan(dist, vec3(eps)) != bvec3(false, false, false));
		} while (i < 300.0 && (dist.x > eps || dist.y > eps || dist.z > eps)); // greaterThan(dist, vec3(eps)) != bvec3(false, false, false));

	/*	if (i >= 400.0)
			return vec3(1.0, 1.0, 1.0);*/

		mat3 e1 = mat3(eps, 0.0, 0.0,
				eps, 0.0, 0.0,
				eps, 0.0, 0.0);
		mat3 e2 = mat3(0.0, eps, 0.0,
				0.0, eps, 0.0,
				0.0, eps, 0.0);
		mat3 e3 = mat3(0.0, 0.0, eps,
				0.0, 0.0, eps,
				0.0, 0.0, eps);
		mat3 N = transpose(mat3(
		                  	  eval(m_origin + e1) - eval(m_origin - e1),
		                  	  eval(m_origin + e2) - eval(m_origin - e2),
		                  	  eval(m_origin + e3) - eval(m_origin - e3)
		                 	 ));
		N[0] = normalize(N[0]);
		N[1] = normalize(N[1]);
		N[2] = normalize(N[2]);
		vec3 color = 0;
		if ((tdist.x < tdist.y) && (tdist.x < tdist.z)) {
			color = phong(dir, m_origin[0], N[0], vec3(0.0, 4.0, 4.0), vec3(1.0, 0.5, 0.2), vec3(1.0, 0.7, 0.0), 50.0)
		       	       + phong(dir, m_origin[0], N[0], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, 1.0), 50.0);
			dir = reflect(dir, N[0]);
		}
		else if ((tdist.y < tdist.z)) {
			color = phong(dir, m_origin[1], N[1], vec3(0.0, 4.0, 4.0), vec3(1.0, 0.7, 0.2), vec3(0.0, 0.0, 1.0), 50.0)
		       	       + phong(dir, m_origin[1], N[1], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 0.0), 50.0);
			dir = reflect(dir, N[1]);
		}
		else {
			color = phong(dir, m_origin[2], N[2], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.1, 0.0), vec3(0.0, 0.0, 0.7), 100.0)
		       	       + phong(dir, m_origin[2], N[2], vec3(-4.0, -4.0, 0.0), vec3(0.2, 0.1, 0.5), vec3(0.0, 0.0, 0.7), 100.0);
			dir = reflect(dir, N[2]);
		}
	/*	if ((tdist.x < tdist.y) && (tdist.x < tdist.z)) {
			color = 0;
			color = phong(dir, m_origin[0], N[0], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.4, 0.2), vec3(0.4, 0.0, 0.0), 50.0)
		       	       + phong(dir, m_origin[0], N[0], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.5, 0.0), vec3(0.0, 0.0, 0.4), 50.0);
			dir = reflect(dir, N[0]);
		}
		else if ((tdist.y < tdist.z)) {
			color = 0;
			color = phong(dir, m_origin[1], N[1], vec3(0.0, 4.0, 4.0), vec3(0.2, 0.2, 0.0), vec3(1.0, 1.0, 1.0), 50.0)
		       	       + phong(dir, m_origin[1], N[1], vec3(-4.0, -4.0, 0.0), vec3(0.0, 0.0, 0.2), vec3(1.0, 1.0, 1.0), 50.0);
			dir = reflect(dir, N[1]);
		}
		else {
			color = 0;
			color = phong(dir, m_origin[2], N[2], vec3(0.0, 4.0, 4.0), vec3(0.4, 0.4, 0.1), vec3(0.4, 0.1, 0.3), 50.0)
		       	       + phong(dir, m_origin[2], N[2], vec3(-4.0, -4.0, 0.0), vec3(0.4, 0.1, 0.1), vec3(0.1, 0.4, 0.1), 50.0);
			dir = reflect(dir, N[2]);
		}*/
		return color;
	}

	void glslmain( void )
	{
		vec2 p = vec2(gl_FragCoord.x + (gl_TexCoord[0].y - gl_TexCoord[0].x)/2.0, gl_FragCoord.y) / gl_TexCoord[0].yy * 2.0 - 1.0;
		mat3 m = mat3(1.0);
		vec3 tr = vec3(0.0);
		time = gl_TexCoord[0].z;

		m *= rm(time*0.1, vec3(1.0, 1.0, 0.0));

		vec3 dir = normalize(vec3(p, -1.0) * m);
		vec3 origin = vec3(0.0, 0.0, 3.5 - (cos(time*0.43)*0.75+cos(time*1.04)*0.25+1.0)*params[1].w) * m + tr;

		vec3 c1 = cast(dir, origin);
		vec3 c2 = cast(dir, origin);
		vec3 c = c1 * 0.75 + c2 * 0.25;
	/*	float exposure = 3.0, maxbright = 1.0;
		c = c * exposure * (exposure / (maxbright + 1.0)) / (exposure + 1.0);*/
		c *= 1.125;
		gl_FragColor = vec4(pow(c, vec3(1.0 / 1.0)), 1.0);
	}

	int main()
	{
		std::ofstream out("out.raw");

		gl_TexCoord[0] = vec4(720, 480, 0.0f, 0.0f);
		params[0] = vec4(0.0f, 0.0f, 0.0f, 0.0f);
		params[1] = vec4(0.0f, 0.0f, 0.0f, 0.0f);
		for (int y = 479; y >= 0; --y) {
			for (int x = 0; x < 720; ++x) {
				gl_FragCoord = vec4(x, y, 0.0f, 0.0f);
				glslmain();
				out << (unsigned char) clamp(gl_FragColor.r * 255, 0, 255) << (unsigned char) clamp(gl_FragColor.g * 255, 0, 255) << (unsigned char) clamp(gl_FragColor.b * 255, 0, 255);
			}
		}
		return 0;
	}
}

int main()
{
	return glsl::main();
}
<|endoftext|>


<commit_before><commit_msg>Change the way to evaluate vx and vy from phi<commit_after><|endoftext|>


<commit_before>#include "PacketRenderer.h"

#include <QFile>
#include <QGraphicsRectItem>
#include <QPen>
#include <QStringList>

#include <QDebug>

#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <net/ethernet.h>

// ---------------------------------------------------------------------

PacketRenderer::PacketRenderer( const QString& colourFile,
                                bool useLogScaling,
                                QObject* parent )
  : QObject( parent ),
    _useLogScaling( useLogScaling ),
    _packetWidth( 0.f ),
    _packetHeight( 0.f )
{
  QFile input( colourFile );
  input.open( QFile::ReadOnly );

  QString glob      = input.readAll();
  QStringList lines = glob.split( "\n" );

  foreach( QString line, lines )
  {
    QStringList tokens = line.split( "," );

    // Sanity check
    if( tokens.size() != 3 )
      break;

    float r     = tokens[0].toInt();
    float g     = tokens[1].toInt();
    float b     = tokens[2].toInt();

    _colours.append( QColor::fromRgb( r,
                                      g,
                                      b ) );
  }
}

// ---------------------------------------------------------------------

PacketRenderer::~PacketRenderer()
{
}

// ---------------------------------------------------------------------

void PacketRenderer::setPacketWidth( float width )
{
  _packetWidth = width;
}

// ---------------------------------------------------------------------

void PacketRenderer::setPacketHeight( float height )
{
  _packetHeight = height;
}

// ---------------------------------------------------------------------

void PacketRenderer::setMTU( int mtu )
{
  _mtu = mtu;
}

// ---------------------------------------------------------------------

QGraphicsItem* PacketRenderer::render( qreal x, qreal y,
                                       const pcap_pkthdr* packetHeader,
                                       const uchar* packetData ) const
{
  const ether_header* ethernetHeader = reinterpret_cast<const ether_header*>( packetData );
  if( ntohs( ethernetHeader->ether_type ) != ETHERTYPE_IP )
    return( 0 );

  QColor packetColour;

  const iphdr* ipHeader = reinterpret_cast<const iphdr*>( packetData + sizeof( ether_header ) );
  switch( ipHeader->protocol )
  {
  case IPPROTO_TCP:
    packetColour = _colours[0];
    break;
  case IPPROTO_UDP:
    packetColour = _colours[1];
    break;
  case IPPROTO_ICMP:
    packetColour = _colours[2];
    break;
  default:
    packetColour = _colours[3];
    break;
  }

  float relativeLength = 0.f;

  if( _useLogScaling )
    relativeLength = std::log( packetHeader->len ) / std::log( _mtu );
  else
    relativeLength = packetHeader->len / static_cast<float>( _mtu );

  // Clamp to [0,1]. Else the packets will overlap in the graphics scene.
  relativeLength = relativeLength > 1.0f  ? 1.0f  : relativeLength;

  float width  = _packetWidth  * relativeLength;
  float height = _packetHeight * relativeLength;

  // Ensure that at least one pixel is draw. Else, the graphics items will
  // become too small for the scene view.
  if( width < 1.f )
    width = 1.f;

  if( height < 1.f )
    height = 1.f;

  QGraphicsRectItem* renderedPacket = new QGraphicsRectItem( x + 0.5f * ( _packetWidth - width ),
                                                             y + 0.5f * ( _packetHeight - height ),
                                                             width,
                                                             height );

  renderedPacket->setPen( QPen( Qt::NoPen ) );
  renderedPacket->setBrush( packetColour );

  return( renderedPacket );
}

// ---------------------------------------------------------------------
<commit_msg>Simple error handling for colour files<commit_after>#include "PacketRenderer.h"

#include <QFile>
#include <QGraphicsRectItem>
#include <QPen>
#include <QStringList>

#include <QDebug>

#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <net/ethernet.h>

// ---------------------------------------------------------------------

PacketRenderer::PacketRenderer( const QString& colourFile,
                                bool useLogScaling,
                                QObject* parent )
  : QObject( parent ),
    _useLogScaling( useLogScaling ),
    _packetWidth( 0.f ),
    _packetHeight( 0.f )
{
  QFile input( colourFile );
  input.open( QFile::ReadOnly );

  if( !input.isReadable() )
    qFatal( "Colour file is required" );

  QString glob      = input.readAll();
  QStringList lines = glob.split( "\n" );

  foreach( QString line, lines )
  {
    QStringList tokens = line.split( "," );

    // Sanity check
    if( tokens.size() != 3 )
    {
      qFatal( "Invalid colour file format" );
      break;
    }

    float r     = tokens[0].toInt();
    float g     = tokens[1].toInt();
    float b     = tokens[2].toInt();

    _colours.append( QColor::fromRgb( r,
                                      g,
                                      b ) );
  }
}

// ---------------------------------------------------------------------

PacketRenderer::~PacketRenderer()
{
}

// ---------------------------------------------------------------------

void PacketRenderer::setPacketWidth( float width )
{
  _packetWidth = width;
}

// ---------------------------------------------------------------------

void PacketRenderer::setPacketHeight( float height )
{
  _packetHeight = height;
}

// ---------------------------------------------------------------------

void PacketRenderer::setMTU( int mtu )
{
  _mtu = mtu;
}

// ---------------------------------------------------------------------

QGraphicsItem* PacketRenderer::render( qreal x, qreal y,
                                       const pcap_pkthdr* packetHeader,
                                       const uchar* packetData ) const
{
  const ether_header* ethernetHeader = reinterpret_cast<const ether_header*>( packetData );
  if( ntohs( ethernetHeader->ether_type ) != ETHERTYPE_IP )
    return( 0 );

  QColor packetColour;

  const iphdr* ipHeader = reinterpret_cast<const iphdr*>( packetData + sizeof( ether_header ) );
  switch( ipHeader->protocol )
  {
  case IPPROTO_TCP:
    packetColour = _colours[0];
    break;
  case IPPROTO_UDP:
    packetColour = _colours[1];
    break;
  case IPPROTO_ICMP:
    packetColour = _colours[2];
    break;
  default:
    packetColour = _colours[3];
    break;
  }

  float relativeLength = 0.f;

  if( _useLogScaling )
    relativeLength = std::log( packetHeader->len ) / std::log( _mtu );
  else
    relativeLength = packetHeader->len / static_cast<float>( _mtu );

  // Clamp to [0,1]. Else the packets will overlap in the graphics scene.
  relativeLength = relativeLength > 1.0f  ? 1.0f  : relativeLength;

  float width  = _packetWidth  * relativeLength;
  float height = _packetHeight * relativeLength;

  // Ensure that at least one pixel is draw. Else, the graphics items will
  // become too small for the scene view.
  if( width < 1.f )
    width = 1.f;

  if( height < 1.f )
    height = 1.f;

  QGraphicsRectItem* renderedPacket = new QGraphicsRectItem( x + 0.5f * ( _packetWidth - width ),
                                                             y + 0.5f * ( _packetHeight - height ),
                                                             width,
                                                             height );

  renderedPacket->setPen( QPen( Qt::NoPen ) );
  renderedPacket->setBrush( packetColour );

  return( renderedPacket );
}

// ---------------------------------------------------------------------
<|endoftext|>


<commit_before>/*     Copyright 2015-2018 Egor Yusov
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
*
*  In no event and under no legal theory, whether in tort (including negligence),
*  contract, or otherwise, unless required by applicable law (such as deliberate
*  and grossly negligent acts) or agreed to in writing, shall any Contributor be
*  liable for any damages, including any direct, indirect, special, incidental,
*  or consequential damages of any character arising as a result of this License or
*  out of the use or inability to use the software (including but not limited to damages
*  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
*  all other commercial damages or losses), even if such Contributor has been advised
*  of the possibility of such damages.
*/

#include "AndroidFileSystem.hpp"
#include "EngineFactoryOpenGL.h"
#include "SampleApp.hpp"
#include "RenderDeviceGLES.h"
#include "ImGuiImplAndroid.hpp"

namespace Diligent
{

class SampleAppAndroid final : public SampleApp
{
public:
    SampleAppAndroid()
    {
        m_DeviceType = RENDER_DEVICE_TYPE_GLES;
    }

    virtual void Initialize() override final
    {
        GetEngineFactoryOpenGL()->InitAndroidFileSystem(app_->activity, native_activity_class_name_.c_str());
        AndroidFileSystem::Init(app_->activity, native_activity_class_name_.c_str());
        SampleApp::Initialize();
        AndroidNativeWindow Window;
        Window.pAWindow = app_->window;
        InitializeDiligentEngine(&Window);
        const auto& SCDesc = m_pSwapChain->GetDesc();
        m_pImGui.reset(new ImGuiImplAndroid(m_pDevice, SCDesc.ColorBufferFormat, SCDesc.DepthBufferFormat, SCDesc.Width, SCDesc.Height));
        m_RenderDeviceGLES = RefCntAutoPtr<IRenderDeviceGLES>(m_pDevice, IID_RenderDeviceGLES);
        InitializeSample();
    }

    virtual int Resume(ANativeWindow* window) override final
    {
        return m_RenderDeviceGLES->Resume(window);
    }

    virtual void TermDisplay() override final
    {
        // Tear down the EGL context currently associated with the display.
        m_RenderDeviceGLES->Suspend();
    }

    virtual void TrimMemory() override final
    {
        LOGI("Trimming memory");
        m_RenderDeviceGLES->Invalidate();
    }

    virtual int32_t HandleInput(AInputEvent* event) override final
    {
        if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
        {
            ndk_helper::GESTURE_STATE doubleTapState = doubletap_detector_.Detect(event);
            ndk_helper::GESTURE_STATE dragState      = drag_detector_.Detect(event);
            ndk_helper::GESTURE_STATE pinchState     = pinch_detector_.Detect(event);

            //Double tap detector has a priority over other detectors
            if (doubleTapState == ndk_helper::GESTURE_STATE_ACTION)
            {
                //Detect double tap
                //tap_camera_.Reset( true );
            }
            else
            {
                //Handle drag state
                if (dragState & ndk_helper::GESTURE_STATE_START)
                {
                    //Otherwise, start dragging
                    ndk_helper::Vec2 v;
                    drag_detector_.GetPointer(v);
                    float fX = 0, fY = 0;
                    v.Value(fX, fY);
                    auto Handled = static_cast<ImGuiImplAndroid*>(m_pImGui.get())->BeginDrag(fX, fY);
                    if (!Handled)
                    {
                        m_TheSample->GetInputController().BeginDrag(fX, fY);
                    }
                }
                else if (dragState & ndk_helper::GESTURE_STATE_MOVE)
                {
                    ndk_helper::Vec2 v;
                    drag_detector_.GetPointer(v);
                    float fX = 0, fY = 0;
                    v.Value(fX, fY);
                    auto Handled = static_cast<ImGuiImplAndroid*>(m_pImGui.get())->DragMove(fX, fY);
                    if (!Handled)
                    {
                        m_TheSample->GetInputController().DragMove(fX, fY);
                    }
                }
                else if (dragState & ndk_helper::GESTURE_STATE_END)
                {
                    static_cast<ImGuiImplAndroid*>(m_pImGui.get())->EndDrag();
                    m_TheSample->GetInputController().EndDrag();
                }

                //Handle pinch state
                if (pinchState & ndk_helper::GESTURE_STATE_START)
                {
                    //Start new pinch
                    ndk_helper::Vec2 v1;
                    ndk_helper::Vec2 v2;
                    pinch_detector_.GetPointers(v1, v2);
                    float fX1 = 0, fY1 = 0, fX2 = 0, fY2 = 0;
                    v1.Value(fX1, fY1);
                    v2.Value(fX2, fY2);
                    m_TheSample->GetInputController().StartPinch(fX1, fY1, fX2, fY2);
                    //tap_camera_.BeginPinch( v1, v2 );
                }
                else if (pinchState & ndk_helper::GESTURE_STATE_MOVE)
                {
                    //Multi touch
                    //Start new pinch
                    ndk_helper::Vec2 v1;
                    ndk_helper::Vec2 v2;
                    pinch_detector_.GetPointers(v1, v2);
                    float fX1 = 0, fY1 = 0, fX2 = 0, fY2 = 0;
                    v1.Value(fX1, fY1);
                    v2.Value(fX2, fY2);
                    m_TheSample->GetInputController().PinchMove(fX1, fY1, fX2, fY2);
                    //tap_camera_.Pinch( v1, v2 );
                }
                else if (pinchState & ndk_helper::GESTURE_STATE_END)
                {
                    m_TheSample->GetInputController().EndPinch();
                }
            }
            return 1;
        }
        return 0;
    }

private:
    RefCntAutoPtr<IRenderDeviceGLES> m_RenderDeviceGLES;
};

NativeAppBase* CreateApplication()
{
    return new SampleAppAndroid;
}

} // namespace Diligent
<commit_msg>Initial support of Vulkan on Android<commit_after>/*     Copyright 2015-2018 Egor Yusov
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
*
*  In no event and under no legal theory, whether in tort (including negligence),
*  contract, or otherwise, unless required by applicable law (such as deliberate
*  and grossly negligent acts) or agreed to in writing, shall any Contributor be
*  liable for any damages, including any direct, indirect, special, incidental,
*  or consequential damages of any character arising as a result of this License or
*  out of the use or inability to use the software (including but not limited to damages
*  for loss of goodwill, work stoppage, computer failure or malfunction, or any and
*  all other commercial damages or losses), even if such Contributor has been advised
*  of the possibility of such damages.
*/

#include "AndroidFileSystem.hpp"
#include "EngineFactoryOpenGL.h"
#if VULKAN_SUPPORTED
#    include "EngineFactoryVk.h"
#endif

#include "SampleApp.hpp"
#include "RenderDeviceGLES.h"
#include "ImGuiImplAndroid.hpp"

namespace Diligent
{

class SampleAppAndroid final : public SampleApp
{
public:
    SampleAppAndroid()
    {
        m_DeviceType = RENDER_DEVICE_TYPE_GLES;
#if VULKAN_SUPPORTED
        m_DeviceType = RENDER_DEVICE_TYPE_VULKAN;
#endif
    }

    virtual void Initialize() override final
    {
        switch (m_DeviceType)
        {
#if VULKAN_SUPPORTED
            case RENDER_DEVICE_TYPE_VULKAN:
                GetEngineFactoryVk()->InitAndroidFileSystem(app_->activity, native_activity_class_name_.c_str());
                break;
#endif

            case RENDER_DEVICE_TYPE_GLES:
                GetEngineFactoryOpenGL()->InitAndroidFileSystem(app_->activity, native_activity_class_name_.c_str());
                break;

            default:
                UNEXPECTED("Unexpected device type");
        }

        AndroidFileSystem::Init(app_->activity, native_activity_class_name_.c_str());

        SampleApp::Initialize();

        AndroidNativeWindow Window;
        Window.pAWindow = app_->window;
        InitializeDiligentEngine(&Window);
        const auto& SCDesc = m_pSwapChain->GetDesc();
        m_pImGui.reset(new ImGuiImplAndroid(m_pDevice, SCDesc.ColorBufferFormat, SCDesc.DepthBufferFormat, SCDesc.Width, SCDesc.Height));

        switch (m_DeviceType)
        {
#if VULKAN_SUPPORTED
            case RENDER_DEVICE_TYPE_VULKAN:
                break;
#endif

            case RENDER_DEVICE_TYPE_GLES:
                m_RenderDeviceGLES = RefCntAutoPtr<IRenderDeviceGLES>(m_pDevice, IID_RenderDeviceGLES);
                break;

            default:
                UNEXPECTED("Unexpected device type");
        }

        InitializeSample();
    }

    virtual int Resume(ANativeWindow* window) override final
    {
        switch (m_DeviceType)
        {
#if VULKAN_SUPPORTED
            case RENDER_DEVICE_TYPE_VULKAN:
                break;
#endif

            case RENDER_DEVICE_TYPE_GLES:
                return m_RenderDeviceGLES->Resume(window);

            default:
                UNEXPECTED("Unexpected device type");
        }

        return EGL_NOT_INITIALIZED;
    }

    virtual void TermDisplay() override final
    {
        switch (m_DeviceType)
        {
#if VULKAN_SUPPORTED
            case RENDER_DEVICE_TYPE_VULKAN:
                break;
#endif

            case RENDER_DEVICE_TYPE_GLES:
                // Tear down the EGL context currently associated with the display.
                m_RenderDeviceGLES->Suspend();
                break;

            default:
                UNEXPECTED("Unexpected device type");
        }
    }

    virtual void TrimMemory() override final
    {
        LOGI("Trimming memory");
        switch (m_DeviceType)
        {
#if VULKAN_SUPPORTED
            case RENDER_DEVICE_TYPE_VULKAN:
                break;
#endif

            case RENDER_DEVICE_TYPE_GLES:
                m_RenderDeviceGLES->Invalidate();
                break;

            default:
                UNEXPECTED("Unexpected device type");
        }
    }

    virtual int32_t HandleInput(AInputEvent* event) override final
    {
        if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
        {
            ndk_helper::GESTURE_STATE doubleTapState = doubletap_detector_.Detect(event);
            ndk_helper::GESTURE_STATE dragState      = drag_detector_.Detect(event);
            ndk_helper::GESTURE_STATE pinchState     = pinch_detector_.Detect(event);

            //Double tap detector has a priority over other detectors
            if (doubleTapState == ndk_helper::GESTURE_STATE_ACTION)
            {
                //Detect double tap
                //tap_camera_.Reset( true );
            }
            else
            {
                //Handle drag state
                if (dragState & ndk_helper::GESTURE_STATE_START)
                {
                    //Otherwise, start dragging
                    ndk_helper::Vec2 v;
                    drag_detector_.GetPointer(v);
                    float fX = 0, fY = 0;
                    v.Value(fX, fY);
                    auto Handled = static_cast<ImGuiImplAndroid*>(m_pImGui.get())->BeginDrag(fX, fY);
                    if (!Handled)
                    {
                        m_TheSample->GetInputController().BeginDrag(fX, fY);
                    }
                }
                else if (dragState & ndk_helper::GESTURE_STATE_MOVE)
                {
                    ndk_helper::Vec2 v;
                    drag_detector_.GetPointer(v);
                    float fX = 0, fY = 0;
                    v.Value(fX, fY);
                    auto Handled = static_cast<ImGuiImplAndroid*>(m_pImGui.get())->DragMove(fX, fY);
                    if (!Handled)
                    {
                        m_TheSample->GetInputController().DragMove(fX, fY);
                    }
                }
                else if (dragState & ndk_helper::GESTURE_STATE_END)
                {
                    static_cast<ImGuiImplAndroid*>(m_pImGui.get())->EndDrag();
                    m_TheSample->GetInputController().EndDrag();
                }

                //Handle pinch state
                if (pinchState & ndk_helper::GESTURE_STATE_START)
                {
                    //Start new pinch
                    ndk_helper::Vec2 v1;
                    ndk_helper::Vec2 v2;
                    pinch_detector_.GetPointers(v1, v2);
                    float fX1 = 0, fY1 = 0, fX2 = 0, fY2 = 0;
                    v1.Value(fX1, fY1);
                    v2.Value(fX2, fY2);
                    m_TheSample->GetInputController().StartPinch(fX1, fY1, fX2, fY2);
                    //tap_camera_.BeginPinch( v1, v2 );
                }
                else if (pinchState & ndk_helper::GESTURE_STATE_MOVE)
                {
                    //Multi touch
                    //Start new pinch
                    ndk_helper::Vec2 v1;
                    ndk_helper::Vec2 v2;
                    pinch_detector_.GetPointers(v1, v2);
                    float fX1 = 0, fY1 = 0, fX2 = 0, fY2 = 0;
                    v1.Value(fX1, fY1);
                    v2.Value(fX2, fY2);
                    m_TheSample->GetInputController().PinchMove(fX1, fY1, fX2, fY2);
                    //tap_camera_.Pinch( v1, v2 );
                }
                else if (pinchState & ndk_helper::GESTURE_STATE_END)
                {
                    m_TheSample->GetInputController().EndPinch();
                }
            }
            return 1;
        }
        return 0;
    }

private:
    RefCntAutoPtr<IRenderDeviceGLES> m_RenderDeviceGLES;
};

NativeAppBase* CreateApplication()
{
    return new SampleAppAndroid;
}

} // namespace Diligent
<|endoftext|>


<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 "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbSarRadiometricCalibrationToImageFilter.h"

namespace otb
{
namespace Wrapper
{

class SarRadiometricCalibration : public Application
{
public:
  /** Standard class typedefs. */
  typedef SarRadiometricCalibration     Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(SarRadiometricCalibration, otb::Application);

  typedef otb::SarRadiometricCalibrationToImageFilter<ComplexFloatImageType,
                                                      ComplexFloatImageType>     CalibrationFilterType;

private:
  SarRadiometricCalibration()
  {
    SetName("SarRadiometricCalibration");
    SetDescription("Perform SAR calibration on input complex images");
  }

  virtual ~SarRadiometricCalibration()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_ComplexInputImage,  "cin", "Input Complex Image");
    AddParameter(ParameterType_ComplexOutputImage,  "out", "Output Image");
    AddParameter(ParameterType_Empty, "noise", "Disable Noise");
    MandatoryOff("noise");
  }

  void DoUpdateParameters()
  { }

  void DoExecute()
  {
    // Get the input complex image
    ComplexFloatImageType*  floatComplexImage = GetParameterComplexFloatImage("cin");

    // Set the filer input
    m_CalibrationFilter = CalibrationFilterType::New();
    m_CalibrationFilter->SetInput(floatComplexImage);

    if (IsParameterEnabled("noise"))
      {
      m_CalibrationFilter->SetEnableNoise(false);
      }

    // Set the output image
    SetParameterComplexOutputImage("out", m_CalibrationFilter->GetOutput());
  }

  CalibrationFilterType::Pointer   m_CalibrationFilter;
};
}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::SarRadiometricCalibration)
<commit_msg>DOC: SAR Radiometric calibration application doc update.<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 "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbSarRadiometricCalibrationToImageFilter.h"

namespace otb
{
namespace Wrapper
{

class SarRadiometricCalibration : public Application
{
public:
  /** Standard class typedefs. */
  typedef SarRadiometricCalibration     Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(SarRadiometricCalibration, otb::Application);

  typedef otb::SarRadiometricCalibrationToImageFilter<ComplexFloatImageType,
                                                      ComplexFloatImageType>     CalibrationFilterType;

private:
  SarRadiometricCalibration()
  {
    SetName("SarRadiometricCalibration");
    SetDescription("Perform SAR calibration on input complex images");

    // Documentation
    SetDocName("SAR Radiometric calibration application");
    SetDocLongDescription("This application performs SAR calibration on input complex images.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");
    SetDocCLExample("otbApplicationLauncherCommandLine sarRadiometricCalibration ${OTB-BIN}/bin "
      "--cin ${OTB-DATA}/Input/scene.png --out calibratedImage.tif");
    AddDocTag("Calibration");
    AddDocTag("SAR");
  }

  virtual ~SarRadiometricCalibration()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_ComplexInputImage,  "cin", "Input Complex Image");
    AddParameter(ParameterType_ComplexOutputImage,  "out", "Output Image");
    AddParameter(ParameterType_Empty, "noise", "Disable Noise");
    MandatoryOff("noise");
  }

  void DoUpdateParameters()
  { }

  void DoExecute()
  {
    // Get the input complex image
    ComplexFloatImageType*  floatComplexImage = GetParameterComplexFloatImage("cin");

    // Set the filer input
    m_CalibrationFilter = CalibrationFilterType::New();
    m_CalibrationFilter->SetInput(floatComplexImage);

    if (IsParameterEnabled("noise"))
      {
      m_CalibrationFilter->SetEnableNoise(false);
      }

    // Set the output image
    SetParameterComplexOutputImage("out", m_CalibrationFilter->GetOutput());
  }

  CalibrationFilterType::Pointer   m_CalibrationFilter;
};
}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::SarRadiometricCalibration)
<|endoftext|>


<commit_before>#include "Utility/String.h"

#include <string>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cctype>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <cmath>

namespace String
{
    namespace
    {
        const auto whitespace = " \t\n";
    }
}

std::vector<std::string> String::split(std::string s, std::string delim, size_t count) noexcept
{
    if(delim.empty())
    {
        s = remove_extra_whitespace(s);
        delim = " ";
    }

    if(s.empty())
    {
        return {};
    }

    std::vector<std::string> result;
    size_t start_index = 0;
    size_t end_index = 0;
    size_t split_count = 0;
    while(end_index < s.size() && split_count < count)
    {
        end_index = s.find(delim, start_index);
        result.push_back(s.substr(start_index, end_index - start_index));
        start_index = std::min(end_index, s.size()) + delim.size();
        ++split_count;
    }

    if(start_index <= s.size())
    {
        result.push_back(s.substr(start_index));
    }

    return result;
}

bool String::starts_with(const std::string& s, const std::string& beginning) noexcept
{
    return (beginning.size() <= s.size()) && std::equal(beginning.begin(), beginning.end(), s.begin());
}

bool String::ends_with(const std::string& s, const std::string& ending) noexcept
{
    return (ending.size() <= s.size()) && std::equal(ending.rbegin(), ending.rend(), s.rbegin());
}

std::string String::trim_outer_whitespace(const std::string& s) noexcept
{
    auto text_start = s.find_first_not_of(whitespace);
    if(text_start == std::string::npos)
    {
        return {};
    }

    auto text_end = s.find_last_not_of(whitespace);
    return s.substr(text_start, text_end - text_start + 1);
}

std::string String::remove_extra_whitespace(const std::string& s) noexcept
{
    std::string s2 = trim_outer_whitespace(s);
    std::replace_if(s2.begin(), s2.end(), [](auto c) { return String::contains(whitespace, c); }, ' ');
    std::string result;
    std::copy_if(s2.begin(), s2.end(), std::back_inserter(result),
                 [&result](auto c)
                 {
                     return  c != ' ' || result.back() != ' ';
                 });

    return result;
}

std::string String::strip_comments(const std::string& str, const std::string& comment) noexcept
{
    return trim_outer_whitespace(str.substr(0, str.find(comment)));
}

std::string String::strip_block_comment(const std::string& str, const std::string& start, const std::string& end)
{
    auto start_comment_index = str.find(start);
    auto end_comment_index = str.find(end);

    if(start_comment_index == std::string::npos && end_comment_index == std::string::npos)
    {
        return trim_outer_whitespace(str);
    }

    if(start_comment_index == std::string::npos || end_comment_index == std::string::npos)
    {
        throw std::invalid_argument("\"" + str + "\" is missing a comment delimiter: " + start + end);
    }

    if(start_comment_index >= end_comment_index)
    {
        throw std::invalid_argument("\"" + str + "\" contains bad comment delimiters: " + start + end);
    }

    auto first_part = str.substr(0, start_comment_index);
    auto last_part = str.substr(end_comment_index + end.size());
    try
    {
        return strip_block_comment(trim_outer_whitespace(first_part) + " " + trim_outer_whitespace(last_part), start, end);
    }
    catch(const std::invalid_argument& e)
    {
        throw std::invalid_argument(e.what() + std::string("\nOriginal line: ") + str);
    }
}

std::string String::extract_delimited_text(const std::string& str, const std::string& start, const std::string& end)
{
    auto start_split = split(str, start, 1);
    if(start_split.size() != 2)
    {
        throw std::invalid_argument("Starting delimiter not found in \"" + str + "\": " + start + " " + end);
    }
    auto start_of_inside = start_split[1];
    auto inside_split = split(start_of_inside, end, 1);
    if(inside_split.size() != 2)
    {
        throw std::invalid_argument("Ending delimiter not found in \"" + str + "\": " + start + " " + end);
    }
    return inside_split[0];
}

std::string String::lowercase(std::string s) noexcept
{
    for(auto& c : s){ c = std::tolower(c); }
    return s;
}

std::string String::round_to_precision(double x, double precision) noexcept
{
    auto result = std::to_string(std::round(x/precision)*precision);
    auto last_significant_index = result.find_last_not_of('0');
    if(last_significant_index == std::string::npos)
    {
        return result;
    }
    else
    {
        if(result[last_significant_index] == '.')
        {
            if(precision < 1.0)
            {
                // Include ".0"
                return result.substr(0, last_significant_index + 2);
            }
            else
            {
                // Precision is greater than one, so delete fractional part
                return result.substr(0, last_significant_index);
            }
        }
        else
        {
            // Include first non-significant digit
            return result.substr(0, last_significant_index + 1);
        }
    }
}

size_t String::string_to_size_t(const std::string& s)
{
    size_t result;
    std::string remainder;
    std::istringstream(s) >> result >> remainder;
    if( ! String::trim_outer_whitespace(remainder).empty())
    {
        throw std::invalid_argument("Non-numeric characters in string: " + s);
    }
    return result;
}

std::string String::date_and_time_format(const std::chrono::system_clock::time_point& point_in_time,
                                         const std::string& format) noexcept
{
    auto time_c = std::chrono::system_clock::to_time_t(point_in_time);
    std::tm time_out;
#ifdef _WIN32
    localtime_s(&time_out, &time_c);
#elif defined(__linux__)
    localtime_r(&time_c, &time_out);
#endif
    auto ss = std::ostringstream{};
    ss << std::put_time(&time_out, format.c_str());
    return ss.str();
}
<commit_msg>Delete unneeded namespace<commit_after>#include "Utility/String.h"

#include <string>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cctype>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <cmath>

namespace
{
    const auto whitespace = " \t\n";
}

std::vector<std::string> String::split(std::string s, std::string delim, size_t count) noexcept
{
    if(delim.empty())
    {
        s = remove_extra_whitespace(s);
        delim = " ";
    }

    if(s.empty())
    {
        return {};
    }

    std::vector<std::string> result;
    size_t start_index = 0;
    size_t end_index = 0;
    size_t split_count = 0;
    while(end_index < s.size() && split_count < count)
    {
        end_index = s.find(delim, start_index);
        result.push_back(s.substr(start_index, end_index - start_index));
        start_index = std::min(end_index, s.size()) + delim.size();
        ++split_count;
    }

    if(start_index <= s.size())
    {
        result.push_back(s.substr(start_index));
    }

    return result;
}

bool String::starts_with(const std::string& s, const std::string& beginning) noexcept
{
    return (beginning.size() <= s.size()) && std::equal(beginning.begin(), beginning.end(), s.begin());
}

bool String::ends_with(const std::string& s, const std::string& ending) noexcept
{
    return (ending.size() <= s.size()) && std::equal(ending.rbegin(), ending.rend(), s.rbegin());
}

std::string String::trim_outer_whitespace(const std::string& s) noexcept
{
    auto text_start = s.find_first_not_of(whitespace);
    if(text_start == std::string::npos)
    {
        return {};
    }

    auto text_end = s.find_last_not_of(whitespace);
    return s.substr(text_start, text_end - text_start + 1);
}

std::string String::remove_extra_whitespace(const std::string& s) noexcept
{
    std::string s2 = trim_outer_whitespace(s);
    std::replace_if(s2.begin(), s2.end(), [](auto c) { return String::contains(whitespace, c); }, ' ');
    std::string result;
    std::copy_if(s2.begin(), s2.end(), std::back_inserter(result),
                 [&result](auto c)
                 {
                     return  c != ' ' || result.back() != ' ';
                 });

    return result;
}

std::string String::strip_comments(const std::string& str, const std::string& comment) noexcept
{
    return trim_outer_whitespace(str.substr(0, str.find(comment)));
}

std::string String::strip_block_comment(const std::string& str, const std::string& start, const std::string& end)
{
    auto start_comment_index = str.find(start);
    auto end_comment_index = str.find(end);

    if(start_comment_index == std::string::npos && end_comment_index == std::string::npos)
    {
        return trim_outer_whitespace(str);
    }

    if(start_comment_index == std::string::npos || end_comment_index == std::string::npos)
    {
        throw std::invalid_argument("\"" + str + "\" is missing a comment delimiter: " + start + end);
    }

    if(start_comment_index >= end_comment_index)
    {
        throw std::invalid_argument("\"" + str + "\" contains bad comment delimiters: " + start + end);
    }

    auto first_part = str.substr(0, start_comment_index);
    auto last_part = str.substr(end_comment_index + end.size());
    try
    {
        return strip_block_comment(trim_outer_whitespace(first_part) + " " + trim_outer_whitespace(last_part), start, end);
    }
    catch(const std::invalid_argument& e)
    {
        throw std::invalid_argument(e.what() + std::string("\nOriginal line: ") + str);
    }
}

std::string String::extract_delimited_text(const std::string& str, const std::string& start, const std::string& end)
{
    auto start_split = split(str, start, 1);
    if(start_split.size() != 2)
    {
        throw std::invalid_argument("Starting delimiter not found in \"" + str + "\": " + start + " " + end);
    }
    auto start_of_inside = start_split[1];
    auto inside_split = split(start_of_inside, end, 1);
    if(inside_split.size() != 2)
    {
        throw std::invalid_argument("Ending delimiter not found in \"" + str + "\": " + start + " " + end);
    }
    return inside_split[0];
}

std::string String::lowercase(std::string s) noexcept
{
    for(auto& c : s){ c = std::tolower(c); }
    return s;
}

std::string String::round_to_precision(double x, double precision) noexcept
{
    auto result = std::to_string(std::round(x/precision)*precision);
    auto last_significant_index = result.find_last_not_of('0');
    if(last_significant_index == std::string::npos)
    {
        return result;
    }
    else
    {
        if(result[last_significant_index] == '.')
        {
            if(precision < 1.0)
            {
                // Include ".0"
                return result.substr(0, last_significant_index + 2);
            }
            else
            {
                // Precision is greater than one, so delete fractional part
                return result.substr(0, last_significant_index);
            }
        }
        else
        {
            // Include first non-significant digit
            return result.substr(0, last_significant_index + 1);
        }
    }
}

size_t String::string_to_size_t(const std::string& s)
{
    size_t result;
    std::string remainder;
    std::istringstream(s) >> result >> remainder;
    if( ! String::trim_outer_whitespace(remainder).empty())
    {
        throw std::invalid_argument("Non-numeric characters in string: " + s);
    }
    return result;
}

std::string String::date_and_time_format(const std::chrono::system_clock::time_point& point_in_time,
                                         const std::string& format) noexcept
{
    auto time_c = std::chrono::system_clock::to_time_t(point_in_time);
    std::tm time_out;
#ifdef _WIN32
    localtime_s(&time_out, &time_c);
#elif defined(__linux__)
    localtime_r(&time_c, &time_out);
#endif
    auto ss = std::ostringstream{};
    ss << std::put_time(&time_out, format.c_str());
    return ss.str();
}
<|endoftext|>