<commit_before>// $Id: fe_hermite_shape_3D.C,v 1.4 2006-02-22 22:30:53 roystgnr Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ inlcludes

// Local includes
#include "fe.h"
#include "elem.h"

// Anonymous namespace for persistant variables.
// This allows us to cache the global-to-local mapping transformation
// FIXME: This should also screw up multithreading royally
namespace
{
  static unsigned int old_elem_id = libMesh::invalid_uint;
  static std::vector<std::vector<Real> > dxdxi(3, std::vector<Real>(2, 0));
#ifdef DEBUG
  static std::vector<Real> dydxi(2), dzdeta(2), dxdzeta(2);
  static std::vector<Real> dzdxi(2), dxdeta(2), dydzeta(2);
#endif

// Compute the static coefficients for an element
void hermite_compute_coefs(const Elem* elem)
{
  // Coefficients are cached from old elements
  if (elem->id() == old_elem_id)
    return;

  old_elem_id = elem->id();

  const Order mapping_order        (elem->default_order());
  const ElemType mapping_elem_type (elem->type());
  const int n_mapping_shape_functions =
    FE<3,LAGRANGE>::n_shape_functions(mapping_elem_type,
				      mapping_order);

  std::vector<Point> dofpt;
  dofpt.push_back(Point(-1,-1,-1));
  dofpt.push_back(Point(1,1,1));

  for (int p = 0; p != 2; ++p)
    {
      dxdxi[0][p] = 0;
      dxdxi[1][p] = 0;
      dxdxi[2][p] = 0;
#ifdef DEBUG
      dydxi[p] = 0;
      dzdeta[p] = 0;
      dxdzeta[p] = 0;
      dzdxi[p] = 0;
      dxdeta[p] = 0;
      dydzeta[p] = 0;
#endif
      for (int i = 0; i != n_mapping_shape_functions; ++i)
        {
          const Real ddxi = FE<3,LAGRANGE>::shape_deriv
            (mapping_elem_type, mapping_order, i, 0, dofpt[p]);
          const Real ddeta = FE<3,LAGRANGE>::shape_deriv
            (mapping_elem_type, mapping_order, i, 1, dofpt[p]);
          const Real ddzeta = FE<3,LAGRANGE>::shape_deriv
            (mapping_elem_type, mapping_order, i, 2, dofpt[p]);

	  // dxdeta, dxdzeta, dydxi, dydzeta, dzdxi, dzdeta should all
          // be 0!
          dxdxi[0][p] += elem->point(i)(0) * ddxi;
          dxdxi[1][p] += elem->point(i)(1) * ddeta;
          dxdxi[2][p] += elem->point(i)(2) * ddzeta;
#ifdef DEBUG
          dydxi[p] += elem->point(i)(1) * ddxi;
          dzdeta[p] += elem->point(i)(2) * ddeta;
          dxdzeta[p] += elem->point(i)(0) * ddzeta;
          dzdxi[p] += elem->point(i)(2) * ddxi;
          dxdeta[p] += elem->point(i)(0) * ddeta;
          dydzeta[p] += elem->point(i)(1) * ddzeta;
#endif
        }
      // No singular elements!
      assert(dxdxi[0][p]);
      assert(dxdxi[1][p]);
      assert(dxdxi[2][p]);
      // No non-rectilinear or non-axis-aligned elements!
#ifdef DEBUG
      assert(std::abs(dydxi[p]) < 1e-9);
      assert(std::abs(dzdeta[p]) < 1e-9);
      assert(std::abs(dxdzeta[p]) < 1e-9);
      assert(std::abs(dzdxi[p]) < 1e-9);
      assert(std::abs(dxdeta[p]) < 1e-9);
      assert(std::abs(dydzeta[p]) < 1e-9);
#endif
    }
}

} // end anonymous namespace

template <>
Real FE<3,HERMITE>::shape(const ElemType,
			  const Order,
			  const unsigned int,
			  const Point&)
{
  std::cerr << "Hermite elements require the real element\n"
	    << "to construct gradient-based degrees of freedom."
	    << std::endl;

  error();
  return 0.;
}

template <>
Real FE<3,HERMITE>::shape(const Elem* elem,
			  const Order order,
			  const unsigned int i,
			  const Point& p)
{
  assert (elem != NULL);

  hermite_compute_coefs(elem);

  const ElemType type = elem->type();

  switch (order)
    {
      // 3rd-order tricubic Hermite functions
    case THIRD:
      {
	switch (type)
	  {
	  case HEX8:
	  case HEX20:
	  case HEX27:
	    {
	      assert (i<64);

              std::vector<unsigned int> bases1D;

              Real coef = FEHermite<1>::hermite_bases(bases1D, dxdxi, i, 3);

	      return coef *
                     FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                     FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                     FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
	    }
	  default:
            std::cerr << "ERROR: Unsupported element type!" << std::endl;
	    error();
	  }
      }
      // by default throw an error
    default:
      std::cerr << "ERROR: Unsupported polynomial order!" << std::endl;
      error();
    }

  error();
  return 0.;
}

template <>
Real FE<3,HERMITE>::shape_deriv(const ElemType,
				const Order,
				const unsigned int,
				const unsigned int,
				const Point&)
{
  std::cerr << "Hermite elements require the real element\n"
	    << "to construct gradient-based degrees of freedom."
	    << std::endl;

  error();
  return 0.;
}

template <>
Real FE<3,HERMITE>::shape_deriv(const Elem* elem,
				const Order order,
				const unsigned int i,
				const unsigned int j,
				const Point& p)
{
  assert (elem != NULL);
  assert (j == 0 || j == 1 || j == 2);

  hermite_compute_coefs(elem);

  const ElemType type = elem->type();

  switch (order)
    {
      // 3rd-order tricubic Hermite functions
    case THIRD:
      {
	switch (type)
	  {
	  case HEX8:
	  case HEX20:
	  case HEX27:
	    {
	      assert (i<64);

              std::vector<unsigned int> bases1D;

              Real coef = FEHermite<1>::hermite_bases(bases1D, dxdxi, i, 3);

              switch (j) // Derivative type
		{
		case 0:
                  return coef *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 1:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 2:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[2],p(2));
                  break;
                }

	    }
	  default:
            std::cerr << "ERROR: Unsupported element type!" << std::endl;
	    error();
	  }
      }
      // by default throw an error
    default:
      std::cerr << "ERROR: Unsupported polynomial order!" << std::endl;
      error();
    }

  error();
  return 0.;
}

template <>
Real FE<3,HERMITE>::shape_second_deriv(const Elem* elem,
                                      const Order order,
                                      const unsigned int i,
                                      const unsigned int j,
                                      const Point& p)
{
  assert (elem != NULL);

  hermite_compute_coefs(elem);

  const ElemType type = elem->type();

  switch (order)
    {
      // 3rd-order tricubic Hermite functions
    case THIRD:
      {
	switch (type)
	  {
	  case HEX8:
	  case HEX20:
	  case HEX27:
	    {
	      assert (i<64);

              std::vector<unsigned int> bases1D;

              Real coef = FEHermite<1>::hermite_bases(bases1D, dxdxi, i, 3);

              switch (j) // Derivative type
		{
		case 0:
                  return coef *
                    FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 1:
                  return coef *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 2:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 3:
                  return coef *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[2],p(2));
                  break;
		case 4:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[2],p(2));
                  break;
		case 5:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[2],p(2));
                  break;
                }

	    }
	  default:
            std::cerr << "ERROR: Unsupported element type!" << std::endl;
	    error();
	  }
      }
      // by default throw an error
    default:
      std::cerr << "ERROR: Unsupported polynomial order!" << std::endl;
      error();
    }

  error();
  return 0.;
}
<commit_msg>Make rectilinearity assertions less sensitive and tolerance-dependent<commit_after>// $Id: fe_hermite_shape_3D.C,v 1.5 2006-03-01 22:48:28 roystgnr Exp $

// The libMesh Finite Element Library.
// Copyright (C) 2002-2005  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ inlcludes

// Local includes
#include "fe.h"
#include "elem.h"

// Anonymous namespace for persistant variables.
// This allows us to cache the global-to-local mapping transformation
// FIXME: This should also screw up multithreading royally
namespace
{
  static unsigned int old_elem_id = libMesh::invalid_uint;
  static std::vector<std::vector<Real> > dxdxi(3, std::vector<Real>(2, 0));
#ifdef DEBUG
  static std::vector<Real> dydxi(2), dzdeta(2), dxdzeta(2);
  static std::vector<Real> dzdxi(2), dxdeta(2), dydzeta(2);
#endif

// Compute the static coefficients for an element
void hermite_compute_coefs(const Elem* elem)
{
  // Coefficients are cached from old elements
  if (elem->id() == old_elem_id)
    return;

  old_elem_id = elem->id();

  const Order mapping_order        (elem->default_order());
  const ElemType mapping_elem_type (elem->type());
  const int n_mapping_shape_functions =
    FE<3,LAGRANGE>::n_shape_functions(mapping_elem_type,
				      mapping_order);

  std::vector<Point> dofpt;
  dofpt.push_back(Point(-1,-1,-1));
  dofpt.push_back(Point(1,1,1));

  for (int p = 0; p != 2; ++p)
    {
      dxdxi[0][p] = 0;
      dxdxi[1][p] = 0;
      dxdxi[2][p] = 0;
#ifdef DEBUG
      dydxi[p] = 0;
      dzdeta[p] = 0;
      dxdzeta[p] = 0;
      dzdxi[p] = 0;
      dxdeta[p] = 0;
      dydzeta[p] = 0;
#endif
      for (int i = 0; i != n_mapping_shape_functions; ++i)
        {
          const Real ddxi = FE<3,LAGRANGE>::shape_deriv
            (mapping_elem_type, mapping_order, i, 0, dofpt[p]);
          const Real ddeta = FE<3,LAGRANGE>::shape_deriv
            (mapping_elem_type, mapping_order, i, 1, dofpt[p]);
          const Real ddzeta = FE<3,LAGRANGE>::shape_deriv
            (mapping_elem_type, mapping_order, i, 2, dofpt[p]);

	  // dxdeta, dxdzeta, dydxi, dydzeta, dzdxi, dzdeta should all
          // be 0!
          dxdxi[0][p] += elem->point(i)(0) * ddxi;
          dxdxi[1][p] += elem->point(i)(1) * ddeta;
          dxdxi[2][p] += elem->point(i)(2) * ddzeta;
#ifdef DEBUG
          dydxi[p] += elem->point(i)(1) * ddxi;
          dzdeta[p] += elem->point(i)(2) * ddeta;
          dxdzeta[p] += elem->point(i)(0) * ddzeta;
          dzdxi[p] += elem->point(i)(2) * ddxi;
          dxdeta[p] += elem->point(i)(0) * ddeta;
          dydzeta[p] += elem->point(i)(1) * ddzeta;
#endif
        }

      // No singular elements!
      assert(dxdxi[0][p]);
      assert(dxdxi[1][p]);
      assert(dxdxi[2][p]);
      // No non-rectilinear or non-axis-aligned elements!
#ifdef DEBUG
      assert(std::abs(dydxi[p]) < TOLERANCE);
      assert(std::abs(dzdeta[p]) < TOLERANCE);
      assert(std::abs(dxdzeta[p]) < TOLERANCE);
      assert(std::abs(dzdxi[p]) < TOLERANCE);
      assert(std::abs(dxdeta[p]) < TOLERANCE);
      assert(std::abs(dydzeta[p]) < TOLERANCE);
#endif
    }
}

} // end anonymous namespace

template <>
Real FE<3,HERMITE>::shape(const ElemType,
			  const Order,
			  const unsigned int,
			  const Point&)
{
  std::cerr << "Hermite elements require the real element\n"
	    << "to construct gradient-based degrees of freedom."
	    << std::endl;

  error();
  return 0.;
}

template <>
Real FE<3,HERMITE>::shape(const Elem* elem,
			  const Order order,
			  const unsigned int i,
			  const Point& p)
{
  assert (elem != NULL);

  hermite_compute_coefs(elem);

  const ElemType type = elem->type();

  switch (order)
    {
      // 3rd-order tricubic Hermite functions
    case THIRD:
      {
	switch (type)
	  {
	  case HEX8:
	  case HEX20:
	  case HEX27:
	    {
	      assert (i<64);

              std::vector<unsigned int> bases1D;

              Real coef = FEHermite<1>::hermite_bases(bases1D, dxdxi, i, 3);

	      return coef *
                     FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                     FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                     FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
	    }
	  default:
            std::cerr << "ERROR: Unsupported element type!" << std::endl;
	    error();
	  }
      }
      // by default throw an error
    default:
      std::cerr << "ERROR: Unsupported polynomial order!" << std::endl;
      error();
    }

  error();
  return 0.;
}

template <>
Real FE<3,HERMITE>::shape_deriv(const ElemType,
				const Order,
				const unsigned int,
				const unsigned int,
				const Point&)
{
  std::cerr << "Hermite elements require the real element\n"
	    << "to construct gradient-based degrees of freedom."
	    << std::endl;

  error();
  return 0.;
}

template <>
Real FE<3,HERMITE>::shape_deriv(const Elem* elem,
				const Order order,
				const unsigned int i,
				const unsigned int j,
				const Point& p)
{
  assert (elem != NULL);
  assert (j == 0 || j == 1 || j == 2);

  hermite_compute_coefs(elem);

  const ElemType type = elem->type();

  switch (order)
    {
      // 3rd-order tricubic Hermite functions
    case THIRD:
      {
	switch (type)
	  {
	  case HEX8:
	  case HEX20:
	  case HEX27:
	    {
	      assert (i<64);

              std::vector<unsigned int> bases1D;

              Real coef = FEHermite<1>::hermite_bases(bases1D, dxdxi, i, 3);

              switch (j) // Derivative type
		{
		case 0:
                  return coef *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 1:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 2:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[2],p(2));
                  break;
                }

	    }
	  default:
            std::cerr << "ERROR: Unsupported element type!" << std::endl;
	    error();
	  }
      }
      // by default throw an error
    default:
      std::cerr << "ERROR: Unsupported polynomial order!" << std::endl;
      error();
    }

  error();
  return 0.;
}

template <>
Real FE<3,HERMITE>::shape_second_deriv(const Elem* elem,
                                      const Order order,
                                      const unsigned int i,
                                      const unsigned int j,
                                      const Point& p)
{
  assert (elem != NULL);

  hermite_compute_coefs(elem);

  const ElemType type = elem->type();

  switch (order)
    {
      // 3rd-order tricubic Hermite functions
    case THIRD:
      {
	switch (type)
	  {
	  case HEX8:
	  case HEX20:
	  case HEX27:
	    {
	      assert (i<64);

              std::vector<unsigned int> bases1D;

              Real coef = FEHermite<1>::hermite_bases(bases1D, dxdxi, i, 3);

              switch (j) // Derivative type
		{
		case 0:
                  return coef *
                    FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 1:
                  return coef *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 2:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[2],p(2));
                  break;
		case 3:
                  return coef *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[2],p(2));
                  break;
		case 4:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape_deriv(bases1D[2],p(2));
                  break;
		case 5:
                  return coef *
                    FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
                    FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)) *
                    FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[2],p(2));
                  break;
                }

	    }
	  default:
            std::cerr << "ERROR: Unsupported element type!" << std::endl;
	    error();
	  }
      }
      // by default throw an error
    default:
      std::cerr << "ERROR: Unsupported polynomial order!" << std::endl;
      error();
    }

  error();
  return 0.;
}
<|endoftext|>


<commit_before>// $Id: NMRSpectrum.C,v 1.7 2000/09/22 14:14:59 amoll Exp $

#include<BALL/NMR/NMRSpectrum.h>
#include<BALL/FORMAT/PDBFile.h>
#include<BALL/KERNEL/PTE.h>
#include<BALL/COMMON/limits.h>

///////////////////////////////////////////////////////////////////////////

/* shift Module sind alle von Prozessoren abgeleitet
   NMRSpectrum verwaltet eine Liste mit Prozessoren
   verbesserung : eine von Prozessor abgeleitete gemeinsame Basisklasse
   		  der shift Module entwerfen und die Liste darauf definieren
   		  stellt sicher das nur shift module in der Liste abgelegt
   		  werden koennen.

   Shift Module koennen ueber Strings definiert werden.
   neue Module erforden eine neue Zeile in insert_shift_module(CBallString)
   und dementsprechung eine neu compilierung. besser waere es die Neucompilierung
   auf das neue Modulzu beschraenken.

   !!! korrigieren : Fehler wenn nur ein peak vorhanden : stepSize = 0 und
	Schleife terminiert nicht  bei Ausgabe in file
*/

///////////////////////////////////////////////////////////////////////////

using namespace std;

namespace BALL
{

	typedef struct
	{
		String name;
		float shift;
	}
	name_shift;

	NMRSpectrum::NMRSpectrum()
		:	system_(0),
			density_(100),
			is_sorted_(false)
	{
	}

	NMRSpectrum::~NMRSpectrum()
	{
	}

	void NMRSpectrum::setSystem(System* s)
	{
		system_ = s;
	}

	const System* NMRSpectrum::getSystem() const
	{
		return system_;
	}

	void NMRSpectrum::calculateShifts()
	{
		system_->apply(shift_model_);
	}

	void NMRSpectrum::createSpectrum()
	{
		system_->apply(create_spectrum_);
		spectrum_ = create_spectrum_.getPeakList();
		spectrum_.sort();
	}

	const list<Peak1D>& NMRSpectrum::getPeakList() const
	{
		return spectrum_;
	}

	void NMRSpectrum::setPeakList(const list<Peak1D>& peak_list)
	{
		spectrum_ = peak_list;
		is_sorted_ = false;
	}

	float NMRSpectrum::getSpectrumMin() const
	{
		if (is_sorted_)
		{
			return spectrum_.begin()->getValue();
		}

		float min = Limits<float>::max();
		list<Peak1D>::const_iterator it = spectrum_.begin();
		while (it != spectrum_.end())
		{
			if (it->getValue() < min)
			{
				min = it->getValue();
			}
			it++;
		}

		return min;
	}

	float NMRSpectrum::getSpectrumMax() const
	{
		if (is_sorted_)
		{
			return spectrum_.rbegin()->getValue();
		}

		float max = Limits<float>::min();
		list<Peak1D>::const_iterator it = spectrum_.begin();
		while (it != spectrum_.end())
		{
			if (it->getValue() > max)
			{
				max = it->getValue();
			}
			it++;
		}

		return max;
	}

	void NMRSpectrum::sortSpectrum()
	{
		spectrum_.sort();
		is_sorted_ = true;
	}

	void NMRSpectrum::setDensity(Size density)
	{
		density_ = density;
	}

	Size NMRSpectrum::getDensity() const
	{
		return density_;
	}

	void NMRSpectrum::plotPeaks(const String& filename) const
	{
		ofstream outfile(filename.c_str (), ios::out);

		list<Peak1D>::const_iterator peak_iter = spectrum_.begin();
		for (; peak_iter != spectrum_.end(); ++peak_iter)
		{
			outfile << peak_iter->getValue() << " " << peak_iter->getHeight() << endl;
		}
	}

	void NMRSpectrum::writePeaks(const String& filename) const
	{
		float shift;
		ofstream outfile (filename.c_str(), ios::out);

		AtomIterator atom_iter = system_->beginAtom();
		for (; atom_iter != system_->endAtom(); ++atom_iter)
		{
			shift = (*atom_iter).getProperty ("chemical_shift").getFloat();
			if (shift != 0 && shift < 100)
			{
				outfile << (*atom_iter).getFullName() << " " << shift << endl;
			}
		}
		outfile << "END" << " " << 0.0 << endl;
	}

	void NMRSpectrum::plotSpectrum(const String& filename) const
	{
		// berechnet die peak Daten und schreibt sie in das file : filename

	  list<Peak1D>::const_iterator peak_iter1;
	  list<Peak1D>::const_iterator peak_iter2;

		ofstream outfile(filename.c_str(), ios::out);

		// Berechnung der Dichteverteilung:

		float omega, ts, gs;

	  const float& min = getSpectrumMin();
	  const float& max = getSpectrumMax();

	  const float stepSize = max - min / density_;
	  float y = stepSize;
	  float value = peak_iter1->getValue();
	  float value_old = value;
	  peak_iter1 = spectrum_.begin();

		for (float x = min; x <= max; x += y)
		{
			if (x < value)
			{
				omega = x;
			}
			else
			{
				omega = value;
				++peak_iter1;
				value_old = value;
				value = (*peak_iter1).getValue();
				x -= y;
			}

			gs = 0;
			for (peak_iter2 = spectrum_.begin(); peak_iter2 != spectrum_.end(); ++peak_iter2)
			{
				const float number = peak_iter2->getValue() * 2 * Constants::PI * 1e6 - omega * 2 * Constants::PI * 1e6;

				ts =	peak_iter2->getHeight() / (1 +  (number * number * 4 / peak_iter2->getWidth()));
				gs += ts;
			}
			outfile << omega << " " << gs << endl;
			if (((x - value)     < stepSize && (x - value)     > -stepSize) ||
					((x - value_old) < stepSize && (x - value_old) > -stepSize)    )
			{
				y = stepSize / 10;
			}
			else
			{
				y = stepSize;
			}
		}
	}

	void makeDifference(const float& diff, const String &a, const String& b, const String& out)
	{
		std::list<name_shift>						liste_b;
		std::list<name_shift>::iterator iter;

		String atom_name;
		float shift;
		name_shift *eintrag;

		ifstream infile_b (b.c_str(), ios::in);

		while (atom_name != "END");
		{
			infile_b >> atom_name;
			infile_b >> shift;
			eintrag = new name_shift;
			eintrag->name = atom_name;
			eintrag->shift = shift;
			liste_b.push_back (*eintrag);
		}

		ifstream infile_a (a.c_str(), ios::in);
		ofstream outfile (out.c_str(), ios::out);

		bool found;

		do
		{
			found = false;
			infile_a >> atom_name;
			infile_a >> shift;
			for (iter = liste_b.begin(); iter != liste_b.end(); ++iter)
			{
				if ((atom_name == (*iter).name) && ((shift - (*iter).shift < diff) && (shift - (*iter).shift > -diff)))
				{
					found = true;
					break;
				}
			}
			if (!found)
			{
				outfile << atom_name << " " << shift << endl;
			}
		}
		while (atom_name != "END");

		outfile << "END" << " " << 0.0 << endl;
	}

	void setDifference(NMRSpectrum* a, NMRSpectrum* b, const String& outpdb, const String& out)
	{
		const System& system_a = *a->getSystem();
		const System& system_b = *b->getSystem();

	  StringHashMap<Atom*> table_b;

		AtomIterator atom_iter = system_b.beginAtom();
		for (; +atom_iter; ++atom_iter)
		{
			if ((*atom_iter).getElement() == PTE[Element::H])
			{
				table_b[(*atom_iter).getFullName()] = &(*atom_iter);
			}
		}

		PDBAtom*	patom_a;
		Atom*			atom_b;

		ofstream dfile(out.c_str(), ios::out);

		float shift_a, shift_b, difference;

		atom_iter = system_a.beginAtom();
		for (; +atom_iter; ++atom_iter)
		{
			patom_a = RTTI::castTo<PDBAtom>((*atom_iter));
			patom_a->setOccupancy(0.5);
			if ((*atom_iter).getElement() == PTE[Element::H] &&
					 table_b.has((*atom_iter).getFullName()))
			{
				atom_b = table_b[(*atom_iter).getFullName()];
				shift_a = patom_a->getProperty ("chemical_shift").getFloat();
				shift_b = atom_b->getProperty ("chemical_shift").getFloat();

				difference = shift_a - shift_b;
				if (shift_a > 100)
				{
					difference = 0.5;
				}
				patom_a->setOccupancy(patom_a->getOccupancy() + difference);
				dfile << (*atom_iter).getFullName() << " " << shift_a << " " << difference << endl;
			}
		}

		PDBFile outfile(outpdb, ios::out);
		//outfile.open;
		outfile << system_a;
		outfile.close();
	}

}	// namespace Ball
<commit_msg>changed: rewrite of the plotSpectrum method<commit_after>// $Id: NMRSpectrum.C,v 1.8 2000/09/27 07:21:10 oliver Exp $

#include<BALL/NMR/NMRSpectrum.h>
#include<BALL/FORMAT/PDBFile.h>
#include<BALL/KERNEL/PTE.h>
#include<BALL/COMMON/limits.h>

///////////////////////////////////////////////////////////////////////////

/* shift Module sind alle von Prozessoren abgeleitet
   NMRSpectrum verwaltet eine Liste mit Prozessoren
   verbesserung : eine von Prozessor abgeleitete gemeinsame Basisklasse
   		  der shift Module entwerfen und die Liste darauf definieren
   		  stellt sicher das nur shift module in der Liste abgelegt
   		  werden koennen.

   Shift Module koennen ueber Strings definiert werden.
   neue Module erforden eine neue Zeile in insert_shift_module(CBallString)
   und dementsprechung eine neu compilierung. besser waere es die Neucompilierung
   auf das neue Modulzu beschraenken.

   !!! korrigieren : Fehler wenn nur ein peak vorhanden : stepSize = 0 und
	Schleife terminiert nicht  bei Ausgabe in file
*/

///////////////////////////////////////////////////////////////////////////

using namespace std;

namespace BALL
{

	typedef struct
	{
		String name;
		float shift;
	}
	name_shift;

	NMRSpectrum::NMRSpectrum()
		:	system_(0),
			density_(100),
			is_sorted_(false)
	{
	}

	NMRSpectrum::~NMRSpectrum()
	{
	}

	void NMRSpectrum::setSystem(System* s)
	{
		system_ = s;
	}

	const System* NMRSpectrum::getSystem() const
	{
		return system_;
	}

	void NMRSpectrum::calculateShifts()
	{
		system_->apply(shift_model_);
	}

	void NMRSpectrum::createSpectrum()
	{
		create_spectrum_.init();
		system_->apply(create_spectrum_);
		spectrum_ = create_spectrum_.getPeakList();
		spectrum_.sort();
	}

	const ShiftModel& NMRSpectrum::getShiftModel() const
	{
		return shift_model_;
	}

	void NMRSpectrum::setShiftModel(const ShiftModel& model)
	{
		shift_model_ = model;
	}

	const list<Peak1D>& NMRSpectrum::getPeakList() const
	{
		return spectrum_;
	}

	void NMRSpectrum::setPeakList(const list<Peak1D>& peak_list)
	{
		spectrum_ = peak_list;
		is_sorted_ = false;
	}

	float NMRSpectrum::getSpectrumMin() const
	{
		if (is_sorted_)
		{
			return spectrum_.begin()->getValue();
		}

		float min = Limits<float>::max();
		list<Peak1D>::const_iterator it = spectrum_.begin();
		while (it != spectrum_.end())
		{
			if (it->getValue() < min)
			{
				min = it->getValue();
			}
			it++;
		}

		return min;
	}

	float NMRSpectrum::getSpectrumMax() const
	{
		if (is_sorted_)
		{
			return spectrum_.rbegin()->getValue();
		}

		float max = Limits<float>::min();
		list<Peak1D>::const_iterator it = spectrum_.begin();
		while (it != spectrum_.end())
		{
			if (it->getValue() > max)
			{
				max = it->getValue();
			}
			it++;
		}

		return max;
	}

	void NMRSpectrum::sortSpectrum()
	{
		spectrum_.sort();
		is_sorted_ = true;
	}

	void NMRSpectrum::setDensity(Size density)
	{
		density_ = density;
	}

	Size NMRSpectrum::getDensity() const
	{
		return density_;
	}

	void NMRSpectrum::plotPeaks(const String& filename) const
	{
		ofstream outfile(filename.c_str (), ios::out);

		list<Peak1D>::const_iterator peak_it = spectrum_.begin();
		for (; peak_it != spectrum_.end(); ++peak_it)
		{
			outfile << peak_it->getValue() << " " << peak_it->getHeight() << " " << peak_it->getAtom()->getFullName()<< endl;
		}
	}

	void NMRSpectrum::writePeaks(const String& filename) const
	{
		float shift;
		ofstream outfile (filename.c_str(), ios::out);

		AtomIterator atom_iter = system_->beginAtom();
		for (; atom_iter != system_->endAtom(); ++atom_iter)
		{
			shift = (*atom_iter).getProperty(ShiftModule::PROPERTY__SHIFT).getFloat();
			if (shift != 0.0)
			{
				outfile << (*atom_iter).getFullName() << " " << shift << endl;
			}
		}
		outfile << "END" << " " << 0.0 << endl;
	}

	void NMRSpectrum::plotSpectrum(const String& filename) const
	{
		// berechnet die peak Daten und schreibt sie in das file : filename

		ofstream outfile(filename.c_str(), ios::out);

		// Berechnung der Dichteverteilung:

	  float min = getSpectrumMin();
	  float max = getSpectrumMax();
	  float step_size = (max - min) / density_;

		if (step_size <= 0.0)
		{
			Log.error() << "NMRSpectrum:plotSpectrum: spectrum has empty range. Aborted." << endl;
		}
		else
		{

			Log.info() << " min = " << min << "   max = " << max << "   density_ = " << density_ << "   step_size = " << step_size << endl;

			List<Peak1D>::const_iterator peak_it;
			for (float x = min; x <= max; x += step_size)
			{
				float y = 0;
				for (peak_it = spectrum_.begin(); peak_it != spectrum_.end(); ++peak_it)
				{
					float number = peak_it->getValue() * 2 * Constants::PI  - x * 2 * Constants::PI;

					y +=	peak_it->getHeight() / (1 +  (number * number * 4 / (peak_it->getWidth() / 10.0)));
				}
				outfile << x << " " << y << endl;
			}
		}
		outfile.close();
	}

	void makeDifference(const float& diff, const String &a, const String& b, const String& out)
	{
		std::list<name_shift>						liste_b;
		std::list<name_shift>::iterator iter;

		String atom_name;
		float shift;
		name_shift *eintrag;

		ifstream infile_b (b.c_str(), ios::in);

		while (atom_name != "END");
		{
			infile_b >> atom_name;
			infile_b >> shift;
			eintrag = new name_shift;
			eintrag->name = atom_name;
			eintrag->shift = shift;
			liste_b.push_back (*eintrag);
		}

		ifstream infile_a (a.c_str(), ios::in);
		ofstream outfile (out.c_str(), ios::out);

		bool found;

		do
		{
			found = false;
			infile_a >> atom_name;
			infile_a >> shift;
			for (iter = liste_b.begin(); iter != liste_b.end(); ++iter)
			{
				if ((atom_name == (*iter).name) && ((shift - (*iter).shift < diff) && (shift - (*iter).shift > -diff)))
				{
					found = true;
					break;
				}
			}
			if (!found)
			{
				outfile << atom_name << " " << shift << endl;
			}
		}
		while (atom_name != "END");

		outfile << "END" << " " << 0.0 << endl;
	}

}	// namespace Ball
<|endoftext|>


<commit_before>#include "ScriptWrapper.h"
#include "MagnetiteCore.h"
#include "World.h"
#include "BaseBlock.h"
#include "BlockFactory.h"
#include <fstream>
using namespace v8;

std::string strize( Handle<Value> s )
{
	String::Utf8Value v(s);
	return *v ? *v : "";
}

void report( TryCatch* handler )
{
	HandleScope scope;

	if(handler->Message().IsEmpty())
	{
		// No message
		Util::log( strize( handler->Exception() ) );
	}
	else
	{
		Handle<Message> message = handler->Message();
		std::string file = strize( message->GetScriptResourceName() );
		int lnnum = message->GetLineNumber();
		Util::log( file + ":" + Util::toString(lnnum) + " " + strize( handler->Exception() ) );
	}
}

typedef std::map<BaseBlock*,PersistentObject> WrappedBlocks;
WrappedBlocks gWrappedBlocks;
Persistent<ObjectTemplate> blockTemplate;
ValueHandle wrapBlock( BaseBlock* block )
{
	if( !block ) return Undefined();
	WrappedBlocks::iterator it = gWrappedBlocks.find( block );
	if( it != gWrappedBlocks.end() )
	{
		return it->second;
	}

	if( blockTemplate.IsEmpty() )
	{
		blockTemplate = Persistent<ObjectTemplate>::New(ObjectTemplate::New());
		blockTemplate->Set( String::New( "type" ), String::New( block->getType().c_str() ) );
	}

	PersistentObject obj = Persistent<Object>::New(blockTemplate->NewInstance());
	gWrappedBlocks.insert( WrappedBlocks::value_type( block, obj) );

	return obj;
}

ValueHandle runFile( std::string filename )
{
	std::ifstream is(filename.c_str(), std::ios_base::in);

	if(is.is_open())
	{
		std::string source;
		std::string line;

		while( !is.eof() )
		{
			std::getline(is, line);
			source.append(line);
		}

		HandleScope scope;
		TryCatch try_catch;

		Handle<Script> script = Script::Compile( String::New(source.c_str()), String::New(filename.c_str()) );
		if( script.IsEmpty() )
		{
			if(try_catch.HasCaught())
			{
				report(&try_catch);
				return Undefined();
			}
		}

		ValueHandle result = script->Run();
		if(try_catch.HasCaught())
		{
			report(&try_catch);
			return Undefined();
		}
		return scope.Close(result);
	}
	else
	{
		Util::log("Unable to open: " + filename);
	}

	return Undefined();
}

ValueHandle log(const Arguments& args)
{
	for( size_t i = 0; i < args.Length(); i++ )
	{
		Util::log( strize(args[i]->ToString() ));
	}
}

ValueHandle import(const Arguments& args)
{
	if( args.Length() >= 1 )
	{
		return runFile( strize( args[0]->ToString() ) );
	}
	return Undefined();
}

/*=========== World Object functions ===========*/
ValueHandle world_getBlock(const Arguments& args)
{
	if( args.Length() >= 3 )
	{
		return wrapBlock(CoreSingleton->getWorld()->getBlockAt( args[0]->Int32Value(), args[1]->Int32Value(), args[2]->Int32Value() ));
	}
	return Undefined();
}

ValueHandle world_removeBlock(const Arguments& args)
{
	if( args.Length() >= 3 )
	{
		CoreSingleton->getWorld()->removeBlockAt( args[0]->Int32Value(), args[1]->Int32Value(), args[2]->Int32Value() );
	}
	return Undefined();
}

ValueHandle world_createBlock(const Arguments& args)
{
	if( args.Length() >= 1 )
	{
		BaseBlock* block = FactoryManager::getManager().createBlock( strize(args[0]) );
		if( block == NULL ) return Undefined();
		if( args.Length() >= 4 )
		{
			CoreSingleton->getWorld()->setBlockAt(block, args[1]->Int32Value(), args[2]->Int32Value(), args[3]->Int32Value() );
		}
		return wrapBlock(block);
	}
	return Undefined();
}

void ScriptWrapper::init()
{
	HandleScope scope;

	Handle<ObjectTemplate> global = ObjectTemplate::New();
	global->Set(String::New("import"), FunctionTemplate::New(import));

	Handle<ObjectTemplate> console = ObjectTemplate::New();
	console->Set(String::New("log"), FunctionTemplate::New(log));

	Handle<ObjectTemplate> world = ObjectTemplate::New();
	world->Set(String::New("getBlock"), FunctionTemplate::New(world_getBlock));
	world->Set(String::New("removeBlock"), FunctionTemplate::New(world_removeBlock));
	world->Set(String::New("createBlock"), FunctionTemplate::New(world_createBlock));

	global->Set(String::New("console"), console);
	global->Set(String::New("world"), world);

	mContext = Context::New(NULL, global);

	Context::Scope ctx_scope(mContext);

	runFile("../scripts/main.js");
}
<commit_msg>move scripts folder<commit_after>#include "ScriptWrapper.h"
#include "MagnetiteCore.h"
#include "World.h"
#include "BaseBlock.h"
#include "BlockFactory.h"
#include <fstream>
using namespace v8;

std::string strize( Handle<Value> s )
{
	String::Utf8Value v(s);
	return *v ? *v : "";
}

void report( TryCatch* handler )
{
	HandleScope scope;

	if(handler->Message().IsEmpty())
	{
		// No message
		Util::log( strize( handler->Exception() ) );
	}
	else
	{
		Handle<Message> message = handler->Message();
		std::string file = strize( message->GetScriptResourceName() );
		int lnnum = message->GetLineNumber();
		Util::log( file + ":" + Util::toString(lnnum) + " " + strize( handler->Exception() ) );
	}
}

typedef std::map<BaseBlock*,PersistentObject> WrappedBlocks;
WrappedBlocks gWrappedBlocks;
Persistent<ObjectTemplate> blockTemplate;
ValueHandle wrapBlock( BaseBlock* block )
{
	if( !block ) return Undefined();
	WrappedBlocks::iterator it = gWrappedBlocks.find( block );
	if( it != gWrappedBlocks.end() )
	{
		return it->second;
	}

	if( blockTemplate.IsEmpty() )
	{
		blockTemplate = Persistent<ObjectTemplate>::New(ObjectTemplate::New());
		blockTemplate->Set( String::New( "type" ), String::New( block->getType().c_str() ) );
	}

	PersistentObject obj = Persistent<Object>::New(blockTemplate->NewInstance());
	gWrappedBlocks.insert( WrappedBlocks::value_type( block, obj) );

	return obj;
}

ValueHandle runFile( std::string filename )
{
	std::ifstream is(filename.c_str(), std::ios_base::in);

	if(is.is_open())
	{
		std::string source;
		std::string line;

		while( !is.eof() )
		{
			std::getline(is, line);
			source.append(line);
		}

		HandleScope scope;
		TryCatch try_catch;

		Handle<Script> script = Script::Compile( String::New(source.c_str()), String::New(filename.c_str()) );
		if( script.IsEmpty() )
		{
			if(try_catch.HasCaught())
			{
				report(&try_catch);
				return Undefined();
			}
		}

		ValueHandle result = script->Run();
		if(try_catch.HasCaught())
		{
			report(&try_catch);
			return Undefined();
		}
		return scope.Close(result);
	}
	else
	{
		Util::log("Unable to open: " + filename);
	}

	return Undefined();
}

ValueHandle log(const Arguments& args)
{
	for( size_t i = 0; i < args.Length(); i++ )
	{
		Util::log( strize(args[i]->ToString() ));
	}
}

ValueHandle import(const Arguments& args)
{
	if( args.Length() >= 1 )
	{
		return runFile( strize( args[0]->ToString() ) );
	}
	return Undefined();
}

/*=========== World Object functions ===========*/
ValueHandle world_getBlock(const Arguments& args)
{
	if( args.Length() >= 3 )
	{
		return wrapBlock(CoreSingleton->getWorld()->getBlockAt( args[0]->Int32Value(), args[1]->Int32Value(), args[2]->Int32Value() ));
	}
	return Undefined();
}

ValueHandle world_removeBlock(const Arguments& args)
{
	if( args.Length() >= 3 )
	{
		CoreSingleton->getWorld()->removeBlockAt( args[0]->Int32Value(), args[1]->Int32Value(), args[2]->Int32Value() );
	}
	return Undefined();
}

ValueHandle world_createBlock(const Arguments& args)
{
	if( args.Length() >= 1 )
	{
		BaseBlock* block = FactoryManager::getManager().createBlock( strize(args[0]) );
		if( block == NULL ) return Undefined();
		if( args.Length() >= 4 )
		{
			CoreSingleton->getWorld()->setBlockAt(block, args[1]->Int32Value(), args[2]->Int32Value(), args[3]->Int32Value() );
		}
		return wrapBlock(block);
	}
	return Undefined();
}

void ScriptWrapper::init()
{
	HandleScope scope;

	Handle<ObjectTemplate> global = ObjectTemplate::New();
	global->Set(String::New("import"), FunctionTemplate::New(import));

	Handle<ObjectTemplate> console = ObjectTemplate::New();
	console->Set(String::New("log"), FunctionTemplate::New(log));

	Handle<ObjectTemplate> world = ObjectTemplate::New();
	world->Set(String::New("getBlock"), FunctionTemplate::New(world_getBlock));
	world->Set(String::New("removeBlock"), FunctionTemplate::New(world_removeBlock));
	world->Set(String::New("createBlock"), FunctionTemplate::New(world_createBlock));

	global->Set(String::New("console"), console);
	global->Set(String::New("world"), world);

	mContext = Context::New(NULL, global);

	Context::Scope ctx_scope(mContext);

	runFile("./scripts/main.js");
}
<|endoftext|>


<commit_before>#include "ValueProcessor.h"

#include <sstream>
#include <iostream>

template <class T>
inline std::string to_string (const T& t)
{
  std::stringstream ss;
  ss << t;
  return ss.str();
}

ValueProcessor::ValueProcessor() {
  pushScope();
}
ValueProcessor::~ValueProcessor() {
  popScope();
}

TokenList* ValueProcessor::processValue(TokenList* value) {
  TokenList newvalue;
  Value* v;
  TokenList* var;
  Token* token;
  TokenList* variable;

  while (value->size() > 0) {
    v = processStatement(value);

    if (v != NULL) {
      if (newvalue.size() > 0)
        newvalue.push(new Token(" ", Token::WHITESPACE));

      newvalue.push(v->getTokens());
      delete v;
    } else if (value->size() > 0) {
      if (newvalue.size() > 0)
        newvalue.push(new Token(" ", Token::WHITESPACE));

      if (value->front()->type == Token::ATKEYWORD &&
          (variable = getVariable(value->front()->str)) != NULL) {
        newvalue.push(variable);
        delete value->shift();
      } else if (value->front()->type == Token::STRING ||
                 value->front()->type == Token::URL) {
        processString(value->front());
        newvalue.push(value->shift());
      } else {
        if ((var = processDeepVariable(value)) != NULL) {
          newvalue.push(var);
          delete var;
          delete value->shift();
          delete value->shift();
        } else if ((token = processEscape(value)) != NULL)
            newvalue.push(token);
        else
          newvalue.push(value->shift());
      }
    }
  }
  value->push(&newvalue);
  return value;
}
void ValueProcessor::putVariable(string key, TokenList* value) {
  scopes.back()->insert(pair<string, TokenList*>(key, value));
}
TokenList* ValueProcessor::getVariable(string key) {
  list<map<string, TokenList*>*>::reverse_iterator it;
  map<string, TokenList*>::iterator mit;

  for (it = scopes.rbegin(); it != scopes.rend(); it++) {
    mit = (*it)->find(key);
    if (mit != (*it)->end())
      return mit->second;
  }

  return NULL;
}

void ValueProcessor::pushScope() {
  scopes.push_back(new map<string, TokenList*>());
}
void ValueProcessor::popScope() {
  // delete tokenlists in scope
  delete scopes.back();
  scopes.pop_back();
}

Value* ValueProcessor::processStatement(TokenList* value) {
  Value* op, *v = processConstant(value);

  if (v != NULL) {
    while ((op = processOperator(value, v)))
      v = op;
    return v;
  } else
    return NULL;
}

Value* ValueProcessor::processOperator(TokenList* value, Value* v1,
                                       Token* lastop) {
  Value* v2, *tmp;
  Token* op;
  string operators("+-*/");

  while (value->size() > 0 &&
         value->front()->type == Token::WHITESPACE) {
    delete value->shift();
  }
  if (value->size() == 0 ||
      operators.find(value->front()->str) == string::npos)
    return NULL;

  if (lastop != NULL &&
      operators.find(lastop->str) >
      operators.find(value->front()->str)) {
    return NULL;
  }
  op = value->shift();
  v2 = processConstant(value);
  if (v2 == NULL) {
    if (value->size() > 0)
      throw new ParseException(value->front()->str, "Constant or @-variable");
    else
      throw new ParseException("end of line", "Constant or @-variable");
  }
  while ((tmp = processOperator(value, v2, op)))
    v2 = tmp;

  if (v2->type == Value::COLOR && v1->type != Value::COLOR) {
    if (op->str == "-" || op->str == "/")
      throw new ValueException("Cannot substract or divide a color \
from a number");

    tmp = v1;
    v1 = v2;
    v2 = tmp;
  }

  if (op->str == "+")
    v1->add(v2);
  else if (op->str == "-")
    v1->substract(v2);
  else if (op->str == "*")
    v1->multiply(v2);
  else if (op->str == "/")
    v1->divide(v2);
  delete v2;
  return v1;
}
Value* ValueProcessor::processConstant(TokenList* value) {
  Token* token;
  Value* ret;
  vector<Value*> arguments;
  TokenList* variable;

  while (value->size() > 0 &&
         value->front()->type == Token::WHITESPACE) {
    delete value->shift();
  }

  if (value->size() == 0)
    return NULL;

  token = value->front();
  switch(token->type) {
  case Token::HASH:
    // generate color from hex value
    return new Color(value->shift());
  case Token::NUMBER:
  case Token::PERCENTAGE:
  case Token::DIMENSION:
    return new Value(value->shift());

  case Token::FUNCTION:
    value->shift();
    if (value->front()->type != Token::PAREN_CLOSED)
      arguments.push_back(processConstant(value));

    while (value->front()->str == ",") {
      delete value->shift();
      arguments.push_back(processConstant(value));
    }
    if (value->front()->type != Token::PAREN_CLOSED)
      throw new ParseException(value->front()->str, ")");

    delete value->shift();

    return processFunction(token, arguments);

  case Token::ATKEYWORD:
    if ((variable = getVariable(token->str)) != NULL) {
      TokenList* var = variable->clone();
      ret = processConstant(var);
      while(!var->empty() && var->front()->type == Token::WHITESPACE)
        delete var->shift();

      if (!var->empty()) {
        delete ret;
        ret = NULL;
      } else
        delete value->shift();

      delete var;
      return ret;
    } else
      return NULL;

  case Token::PAREN_OPEN:
    delete value->shift();

    ret = processStatement(value);

    if (value->front()->type == Token::PAREN_CLOSED)
      delete value->shift();
    return ret;

  default:
    TokenList* var = processDeepVariable(value);

    if (var != NULL) {
      ret = processConstant(var);
      if (ret != NULL) {
        delete value->shift();
        delete value->shift();
      }
      delete var;
      return ret;
    } else
      return NULL;
  }
}

TokenList* ValueProcessor::processDeepVariable (TokenList* value) {
  Token* first, *second;
  TokenList* var;
  string key = "@";

  if (value->size() < 2)
    return NULL;

  first = value->front();
  second = value->at(1);

  if (first->type != Token::OTHER ||
      first->str != "@" ||
      second->type != Token::ATKEYWORD ||
      (var = getVariable(second->str)) == NULL)
    return NULL;

  if (var->size() > 1 || var->front()->type != Token::STRING)
    return NULL;

  // generate key with '@' + var without quotes
  key.append(var->front()->
             str.substr(1, var->front()->str.size() - 2));

  var = getVariable(key);
  if (var == NULL)
    return NULL;

  return var->clone();
}

Value* ValueProcessor::processFunction(Token* function,
                                   vector<Value*> arguments) {
  Color* color;
  string percentage;

  if(function->str == "rgb(") {
    // Color rgb(@red: NUMBER, @green: NUMBER, @blue: NUMBER)
    if (arguments.size() == 3 &&
        arguments[0]->type == Value::NUMBER &&
        arguments[1]->type == Value::NUMBER &&
        arguments[2]->type == Value::NUMBER) {
      return new Color(arguments[0]->getValue(),
                       arguments[1]->getValue(),
                       arguments[2]->getValue());
    }
  } else if(function->str == "rgba(") {
    // Color rgba(@red: NUMBER, @green: NUMBER, @blue: NUMBER,
    //            @alpha: NUMBER)
    if (arguments.size() == 4 &&
        arguments[0]->type == Value::NUMBER &&
        arguments[1]->type == Value::NUMBER &&
        arguments[2]->type == Value::NUMBER) {
      if (arguments[3]->type == Value::NUMBER) {
        return new Color(arguments[0]->getValue(),
                         arguments[1]->getValue(),
                         arguments[2]->getValue(),
                         arguments[3]->getValue());
      } else if (arguments[3]->type == Value::PERCENTAGE) {
        return new Color(arguments[0]->getValue(),
                         arguments[1]->getValue(),
                         arguments[2]->getValue(),
                         arguments[3]->getValue() * .01);
      }
    }
  } else if (function->str == "lighten(") {
    // Color lighten(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->lighten(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "darken(") {
    // Color darken(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->darken(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "saturate(") {
    // Color saturate(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->saturate(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "desaturate(") {
    // Color desaturate(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->desaturate(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "fadein(") {
    // Color fadein(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->fadein(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "fadeout(") {
    // Color fadeout(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->fadeout(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "spin(") {
    // Color fadein(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::NUMBER) {
      static_cast<Color*>(arguments[0])->spin(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "hsl(") {
    // Color hsl(PERCENTAGE, PERCENTAGE, PERCENTAGE)
    if (arguments.size() == 3 &&
        arguments[0]->type == Value::NUMBER &&
        arguments[1]->type == Value::PERCENTAGE &&
        arguments[2]->type == Value::PERCENTAGE) {
      color = new Color(0,0,0);
      color->setHSL(arguments[0]->getValue(),
                    arguments[1]->getValue(),
                    arguments[2]->getValue());
      return color;
    }
  } else if (function->str == "hue(") {
    // NUMBER hue(Color)
    if (arguments.size() == 1 &&
        arguments[0]->type == Value::COLOR) {
      percentage.append(to_string(static_cast<Color*>(arguments[0])->getHue()));
      return new Value(new Token(percentage, Token::NUMBER));
    }

  } else if (function->str == "saturation(") {
    // PERCENTAGE saturation(Color)
    if (arguments.size() == 1 &&
        arguments[0]->type == Value::COLOR) {
      percentage.append(to_string(static_cast<Color*>(arguments[0])->getSaturation()));
      percentage.append("%");
      return new Value(new Token(percentage, Token::PERCENTAGE));
    }

  } else if (function->str == "lightness(") {
    // PERCENTAGE lightness(Color)
    if (arguments.size() == 1 &&
        arguments[0]->type == Value::COLOR) {
      percentage.append(to_string(static_cast<Color*>(arguments[0])->getLightness()));
      percentage.append("%");
      return new Value(new Token(percentage, Token::PERCENTAGE));
    }
  } else
    return NULL;
  return NULL;
}

void ValueProcessor::processString(Token* token) {
  size_t start, end;
  string key = "@", value;
  TokenList* var;

  if ((start = token->str.find("@{")) == string::npos ||
      (end = token->str.find("}", start)) == string::npos)
    return;

  key.append(token->str.substr(start + 2, end - (start + 2)));
  var = getVariable(key);
  if (var == NULL)
    return;

  value = *var->toString();

  // Remove quotes of strings.
  if (var->size() == 1 && var->front()->type == Token::STRING)
    value = value.substr(1, value.size() - 2);

  token->str.replace(start, (end + 1) - start, value);
}

Token* ValueProcessor::processEscape (TokenList* value) {
  Token* first, *second;

  if (value->size() < 2)
    return NULL;

  first = value->front();
  second = value->at(1);

  if (first->str != "~" ||
      second->type != Token::STRING)
    return NULL;

  delete value->shift();
  second->str = second->str.substr(1, second->str.size() - 2);
  return value->shift();
}
<commit_msg>Added more exceptions for invalid syntax.<commit_after>#include "ValueProcessor.h"

#include <sstream>
#include <iostream>

template <class T>
inline std::string to_string (const T& t)
{
  std::stringstream ss;
  ss << t;
  return ss.str();
}

ValueProcessor::ValueProcessor() {
  pushScope();
}
ValueProcessor::~ValueProcessor() {
  popScope();
}

TokenList* ValueProcessor::processValue(TokenList* value) {
  TokenList newvalue;
  Value* v;
  TokenList* var;
  Token* token;
  TokenList* variable;

  while (value->size() > 0) {
    v = processStatement(value);

    if (v != NULL) {
      if (newvalue.size() > 0)
        newvalue.push(new Token(" ", Token::WHITESPACE));

      newvalue.push(v->getTokens());
      delete v;
    } else if (value->size() > 0) {
      if (newvalue.size() > 0)
        newvalue.push(new Token(" ", Token::WHITESPACE));

      if (value->front()->type == Token::ATKEYWORD &&
          (variable = getVariable(value->front()->str)) != NULL) {
        newvalue.push(variable);
        delete value->shift();
      } else if (value->front()->type == Token::STRING ||
                 value->front()->type == Token::URL) {
        processString(value->front());
        newvalue.push(value->shift());
      } else {
        if ((var = processDeepVariable(value)) != NULL) {
          newvalue.push(var);
          delete var;
          delete value->shift();
          delete value->shift();
        } else if ((token = processEscape(value)) != NULL)
            newvalue.push(token);
        else
          newvalue.push(value->shift());
      }
    }
  }
  value->push(&newvalue);
  return value;
}
void ValueProcessor::putVariable(string key, TokenList* value) {
  scopes.back()->insert(pair<string, TokenList*>(key, value));
}
TokenList* ValueProcessor::getVariable(string key) {
  list<map<string, TokenList*>*>::reverse_iterator it;
  map<string, TokenList*>::iterator mit;

  for (it = scopes.rbegin(); it != scopes.rend(); it++) {
    mit = (*it)->find(key);
    if (mit != (*it)->end())
      return mit->second;
  }

  return NULL;
}

void ValueProcessor::pushScope() {
  scopes.push_back(new map<string, TokenList*>());
}
void ValueProcessor::popScope() {
  // delete tokenlists in scope
  delete scopes.back();
  scopes.pop_back();
}

Value* ValueProcessor::processStatement(TokenList* value) {
  Value* op, *v = processConstant(value);

  if (v != NULL) {
    while ((op = processOperator(value, v)))
      v = op;
    return v;
  } else
    return NULL;
}

Value* ValueProcessor::processOperator(TokenList* value, Value* v1,
                                       Token* lastop) {
  Value* v2, *tmp;
  Token* op;
  string operators("+-*/");

  while (value->size() > 0 &&
         value->front()->type == Token::WHITESPACE) {
    delete value->shift();
  }
  if (value->size() == 0 ||
      operators.find(value->front()->str) == string::npos)
    return NULL;

  if (lastop != NULL &&
      operators.find(lastop->str) >
      operators.find(value->front()->str)) {
    return NULL;
  }
  op = value->shift();
  v2 = processConstant(value);
  if (v2 == NULL) {
    if (value->size() > 0)
      throw new ParseException(value->front()->str, "Constant or @-variable");
    else
      throw new ParseException("end of line", "Constant or @-variable");
  }
  while ((tmp = processOperator(value, v2, op)))
    v2 = tmp;

  if (v2->type == Value::COLOR && v1->type != Value::COLOR) {
    if (op->str == "-" || op->str == "/")
      throw new ValueException("Cannot substract or divide a color \
from a number");

    tmp = v1;
    v1 = v2;
    v2 = tmp;
  }

  if (op->str == "+")
    v1->add(v2);
  else if (op->str == "-")
    v1->substract(v2);
  else if (op->str == "*")
    v1->multiply(v2);
  else if (op->str == "/")
    v1->divide(v2);
  delete v2;
  return v1;
}
Value* ValueProcessor::processConstant(TokenList* value) {
  Token* token;
  Value* ret;
  vector<Value*> arguments;
  TokenList* variable;

  while (value->size() > 0 &&
         value->front()->type == Token::WHITESPACE) {
    delete value->shift();
  }

  if (value->size() == 0)
    return NULL;

  token = value->front();
  switch(token->type) {
  case Token::HASH:
    // generate color from hex value
    return new Color(value->shift());
  case Token::NUMBER:
  case Token::PERCENTAGE:
  case Token::DIMENSION:
    return new Value(value->shift());

  case Token::FUNCTION:
    value->shift();
    // TODO: Check if the function can be processed before parsing
    // arguments. Right now the arguments are lost if the function
    // isn't reckognized.

    if (value->front()->type != Token::PAREN_CLOSED)
      arguments.push_back(processConstant(value));

    while (value->front()->str == ",") {
      delete value->shift();
      arguments.push_back(processConstant(value));
    }
    if (value->front()->type != Token::PAREN_CLOSED)
      throw new ParseException(value->front()->str, ")");

    delete value->shift();

    return processFunction(token, arguments);

  case Token::ATKEYWORD:
    if ((variable = getVariable(token->str)) != NULL) {
      TokenList* var = variable->clone();
      ret = processConstant(var);
      while(!var->empty() && var->front()->type == Token::WHITESPACE)
        delete var->shift();

      if (!var->empty()) {
        delete ret;
        ret = NULL;
      } else
        delete value->shift();

      delete var;
      return ret;
    } else
      return NULL;

  case Token::PAREN_OPEN:
    delete value->shift();

    ret = processStatement(value);

    if (ret == NULL)
      throw new ValueException("Expecting a valid expression in \
parentheses. Something like '(5 + @x)'. Alternatively, one of the \
variables in the expression may not contain a proper value like 5, \
5%, 5em or #555555.");

    if (value->size() == 0)
      throw new ParseException("end of line", ")");
    else if (value->front()->type == Token::PAREN_CLOSED)
      delete value->shift();
    else
      throw new ParseException(value->front()->str, ")");

    return ret;

  default:
    TokenList* var = processDeepVariable(value);

    if (var != NULL) {
      ret = processConstant(var);
      if (ret != NULL) {
        delete value->shift();
        delete value->shift();
      }
      delete var;
      return ret;
    } else
      return NULL;
  }
}

TokenList* ValueProcessor::processDeepVariable (TokenList* value) {
  Token* first, *second;
  TokenList* var;
  string key = "@";

  if (value->size() < 2)
    return NULL;

  first = value->front();
  second = value->at(1);

  if (first->type != Token::OTHER ||
      first->str != "@" ||
      second->type != Token::ATKEYWORD ||
      (var = getVariable(second->str)) == NULL)
    return NULL;

  if (var->size() > 1 || var->front()->type != Token::STRING)
    return NULL;

  // generate key with '@' + var without quotes
  key.append(var->front()->
             str.substr(1, var->front()->str.size() - 2));

  var = getVariable(key);
  if (var == NULL)
    return NULL;

  return var->clone();
}

Value* ValueProcessor::processFunction(Token* function,
                                   vector<Value*> arguments) {
  Color* color;
  string percentage;

  if(function->str == "rgb(") {
    // Color rgb(@red: NUMBER, @green: NUMBER, @blue: NUMBER)
    if (arguments.size() == 3 &&
        arguments[0]->type == Value::NUMBER &&
        arguments[1]->type == Value::NUMBER &&
        arguments[2]->type == Value::NUMBER) {
      return new Color(arguments[0]->getValue(),
                       arguments[1]->getValue(),
                       arguments[2]->getValue());
    }
  } else if(function->str == "rgba(") {
    // Color rgba(@red: NUMBER, @green: NUMBER, @blue: NUMBER,
    //            @alpha: NUMBER)
    if (arguments.size() == 4 &&
        arguments[0]->type == Value::NUMBER &&
        arguments[1]->type == Value::NUMBER &&
        arguments[2]->type == Value::NUMBER) {
      if (arguments[3]->type == Value::NUMBER) {
        return new Color(arguments[0]->getValue(),
                         arguments[1]->getValue(),
                         arguments[2]->getValue(),
                         arguments[3]->getValue());
      } else if (arguments[3]->type == Value::PERCENTAGE) {
        return new Color(arguments[0]->getValue(),
                         arguments[1]->getValue(),
                         arguments[2]->getValue(),
                         arguments[3]->getValue() * .01);
      }
    }
  } else if (function->str == "lighten(") {
    // Color lighten(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->lighten(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "darken(") {
    // Color darken(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->darken(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "saturate(") {
    // Color saturate(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->saturate(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "desaturate(") {
    // Color desaturate(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->desaturate(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "fadein(") {
    // Color fadein(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->fadein(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "fadeout(") {
    // Color fadeout(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::PERCENTAGE) {
      static_cast<Color*>(arguments[0])->fadeout(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "spin(") {
    // Color fadein(Color, PERCENTAGE)
    if (arguments.size() == 2 &&
        arguments[0]->type == Value::COLOR &&
        arguments[1]->type == Value::NUMBER) {
      static_cast<Color*>(arguments[0])->spin(arguments[1]->getValue());
      return arguments[0];
    }

  } else if (function->str == "hsl(") {
    // Color hsl(PERCENTAGE, PERCENTAGE, PERCENTAGE)
    if (arguments.size() == 3 &&
        arguments[0]->type == Value::NUMBER &&
        arguments[1]->type == Value::PERCENTAGE &&
        arguments[2]->type == Value::PERCENTAGE) {
      color = new Color(0,0,0);
      color->setHSL(arguments[0]->getValue(),
                    arguments[1]->getValue(),
                    arguments[2]->getValue());
      return color;
    }
  } else if (function->str == "hue(") {
    // NUMBER hue(Color)
    if (arguments.size() == 1 &&
        arguments[0]->type == Value::COLOR) {
      percentage.append(to_string(static_cast<Color*>(arguments[0])->getHue()));
      return new Value(new Token(percentage, Token::NUMBER));
    }

  } else if (function->str == "saturation(") {
    // PERCENTAGE saturation(Color)
    if (arguments.size() == 1 &&
        arguments[0]->type == Value::COLOR) {
      percentage.append(to_string(static_cast<Color*>(arguments[0])->getSaturation()));
      percentage.append("%");
      return new Value(new Token(percentage, Token::PERCENTAGE));
    }

  } else if (function->str == "lightness(") {
    // PERCENTAGE lightness(Color)
    if (arguments.size() == 1 &&
        arguments[0]->type == Value::COLOR) {
      percentage.append(to_string(static_cast<Color*>(arguments[0])->getLightness()));
      percentage.append("%");
      return new Value(new Token(percentage, Token::PERCENTAGE));
    }
  } else
    return NULL;
  return NULL;
}

void ValueProcessor::processString(Token* token) {
  size_t start, end;
  string key = "@", value;
  TokenList* var;

  if ((start = token->str.find("@{")) == string::npos ||
      (end = token->str.find("}", start)) == string::npos)
    return;

  key.append(token->str.substr(start + 2, end - (start + 2)));
  var = getVariable(key);
  if (var == NULL)
    return;

  value = *var->toString();

  // Remove quotes of strings.
  if (var->size() == 1 && var->front()->type == Token::STRING)
    value = value.substr(1, value.size() - 2);

  token->str.replace(start, (end + 1) - start, value);
}

Token* ValueProcessor::processEscape (TokenList* value) {
  Token* first, *second;

  if (value->size() < 2)
    return NULL;

  first = value->front();
  second = value->at(1);

  if (first->str != "~" ||
      second->type != Token::STRING)
    return NULL;

  delete value->shift();
  second->str = second->str.substr(1, second->str.size() - 2);
  return value->shift();
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// Reaper
///
/// Copyright (c) 2015-2017 Thibault Schueller
/// This file is distributed under the MIT License
////////////////////////////////////////////////////////////////////////////////

#include "Track.h"

#include "math/Constants.h"
#include "math/Spline.h"

#include "mesh/Mesh.h"

#include "splinesonic/Constants.h"

#include <glm/gtx/norm.hpp>
#include <glm/gtx/projection.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <random>

namespace SplineSonic { namespace TrackGen
{
    constexpr float ThetaMax = 0.8f * Reaper::Math::HalfPi;
    constexpr float PhiMax = 1.0f * Reaper::Math::Pi;
    constexpr float RollMax = 0.25f * Reaper::Math::Pi;
    constexpr float WidthMin = 20.0f * MeterInGameUnits;
    constexpr float WidthMax = 50.0f * MeterInGameUnits;
    constexpr float RadiusMin = 100.0f * MeterInGameUnits;
    constexpr float RadiusMax = 300.0f * MeterInGameUnits;

    constexpr u32 MinLength = 5;
    constexpr u32 MaxLength = 1000;
    constexpr u32 MaxTryCount = 10000;

    constexpr u32 SplineOrder = 3;

    constexpr float SplineInnerWeight = 0.5f;

    constexpr u32 BoneCountPerChunk = 4;

    using RNG = std::mt19937;

    using Reaper::Math::UnitXAxis;
    using Reaper::Math::UnitYAxis;
    using Reaper::Math::UnitZAxis;

    namespace
    {
        glm::quat GenerateChunkEndLocalSpace(const GenerationInfo& genInfo, RNG& rng)
        {
            const glm::vec2 thetaBounds = glm::vec2(0.0f, ThetaMax) * genInfo.chaos;
            const glm::vec2 phiBounds = glm::vec2(-PhiMax, PhiMax) * genInfo.chaos;
            const glm::vec2 rollBounds = glm::vec2(-RollMax, RollMax) * genInfo.chaos;

            std::uniform_real_distribution<float> thetaDistribution(thetaBounds.x, thetaBounds.y);
            std::uniform_real_distribution<float> phiDistribution(phiBounds.x, phiBounds.y);
            std::uniform_real_distribution<float> rollDistribution(rollBounds.x, rollBounds.y);

            const float theta = thetaDistribution(rng);
            const float phi = phiDistribution(rng);
            const float roll = rollDistribution(rng);

            glm::quat deviation = glm::angleAxis(phi, UnitXAxis) * glm::angleAxis(theta, UnitZAxis);
            glm::quat rollFixup = glm::angleAxis(-phi + roll, deviation * UnitXAxis);

            return rollFixup * deviation;
        }

        bool IsNodeSelfColliding(const std::vector<TrackSkeletonNode>& nodes, const TrackSkeletonNode& currentNode, u32& outputNodeIdx)
        {
            for (u32 i = 0; (i + 1) < nodes.size(); i++)
            {
                const float distanceSq = glm::distance2(currentNode.positionWS, nodes[i].positionWS);
                const float minRadius = currentNode.radius + nodes[i].radius;

                if (distanceSq < (minRadius * minRadius))
                {
                    outputNodeIdx = i;
                    return true;
                }
            }

            return false;
        }

        TrackSkeletonNode GenerateNode(const GenerationInfo& genInfo, const std::vector<TrackSkeletonNode>& skeletonNodes, RNG& rng)
        {
            std::uniform_real_distribution<float> widthDistribution(WidthMin, WidthMax);
            std::uniform_real_distribution<float> radiusDistribution(RadiusMin, RadiusMax);

            TrackSkeletonNode node;

            node.radius = radiusDistribution(rng);

            if (skeletonNodes.empty())
            {
                node.orientationWS = glm::quat();
                node.inWidth = widthDistribution(rng);
                node.positionWS = glm::vec3(0.f);
            }
            else
            {
                const TrackSkeletonNode& previousNode = skeletonNodes.back();

                node.orientationWS = previousNode.orientationWS * previousNode.rotationLS;
                node.inWidth = previousNode.outWidth;

                const glm::vec3 offsetMS = UnitXAxis * (previousNode.radius + node.radius);
                const glm::vec3 offsetWS = node.orientationWS * offsetMS;

                node.positionWS = previousNode.positionWS + offsetWS;
            }

            node.rotationLS = GenerateChunkEndLocalSpace(genInfo, rng);
            node.outWidth = widthDistribution(rng);

            return node;
        }
    }

    void GenerateTrackSkeleton(const GenerationInfo& genInfo, std::vector<TrackSkeletonNode>& skeletonNodes)
    {
        Assert(genInfo.length >= MinLength);
        Assert(genInfo.length <= MaxLength);

        skeletonNodes.resize(0);
        skeletonNodes.reserve(genInfo.length);

        std::random_device rd;
        RNG rng(rd());

        u32 tryCount = 0;

        while (skeletonNodes.size() < genInfo.length && tryCount < MaxTryCount)
        {
            const TrackSkeletonNode node = GenerateNode(genInfo, skeletonNodes, rng);

            u32 colliderIdx = 0;
            if (IsNodeSelfColliding(skeletonNodes, node, colliderIdx))
                skeletonNodes.resize(colliderIdx + 1); // Shrink the vector and generate from collider
            else
                skeletonNodes.push_back(node);

            ++tryCount;
        }

        Assert(tryCount < MaxTryCount, "something is majorly FUBAR");
    }

    void GenerateTrackSplines(const std::vector<TrackSkeletonNode>& skeletonNodes, std::vector<Reaper::Math::Spline>& splines)
    {
        std::vector<glm::vec4> controlPoints(4);
        const u32 trackChunkCount = static_cast<u32>(skeletonNodes.size());

        Assert(trackChunkCount > 0);
        Assert(trackChunkCount == skeletonNodes.size());

        splines.resize(trackChunkCount);

        for (u32 i = 0; i < trackChunkCount; i++)
        {
            const TrackSkeletonNode& node = skeletonNodes[i];

            // Laying down 1 control point at each end and 2 in the center of the sphere
            // seems to work pretty well.
            controlPoints[0] = glm::vec4(UnitXAxis * -node.radius, 1.0f);
            controlPoints[1] = glm::vec4(glm::vec3(0.0f), SplineInnerWeight);
            controlPoints[2] = glm::vec4(glm::vec3(0.0f), SplineInnerWeight);
            controlPoints[3] = glm::vec4(node.rotationLS * UnitXAxis * node.radius, 1.0f);

            splines[i] = Reaper::Math::ConstructSpline(SplineOrder, controlPoints);
        }
    }

    namespace
    {
        void GenerateTrackSkinningForChunk(const TrackSkeletonNode& node,
                                           const Reaper::Math::Spline& spline,
                                           TrackSkinning& skinningInfo)
        {
            skinningInfo.bones.resize(BoneCountPerChunk);

            // Fill bone positions
            skinningInfo.bones[0].root = EvalSpline(spline, 0.0f);
            skinningInfo.bones[BoneCountPerChunk - 1].end = EvalSpline(spline, 1.0f);

            // Compute bone start and end positions
            for (u32 i = 1; i < BoneCountPerChunk; i++)
            {
                const float param = static_cast<float>(i) / static_cast<float>(BoneCountPerChunk);
                const glm::vec3 anchorPos = EvalSpline(spline, param);

                skinningInfo.bones[i - 1].end = anchorPos;
                skinningInfo.bones[i].root = anchorPos;
            }

            skinningInfo.invBindTransforms.resize(BoneCountPerChunk);

            // Compute inverse bind pose matrix
            for (u32 i = 0; i < BoneCountPerChunk; i++)
            {
                const float t = static_cast<float>(i) / static_cast<float>(BoneCountPerChunk);
                const float param = t * 2.0f - 1.0f;
                const glm::vec3 offset = UnitXAxis * (param * node.radius);

                // Inverse of a translation is the translation by the opposite vector
                skinningInfo.invBindTransforms[i] = glm::translate(glm::mat4(1.0f), -offset);
            }

            skinningInfo.poseTransforms.resize(BoneCountPerChunk);

            // Compute current pose matrix by reconstructing an ortho-base
            // We only have roll information at chunk boundary, so we have to
            // use tricks to get the correct bone rotation
            for (u32 i = 0; i < BoneCountPerChunk; i++)
            {
                const float t = static_cast<float>(i) / static_cast<float>(BoneCountPerChunk);
                const glm::fquat interpolatedOrientation = glm::slerp(glm::quat(), node.rotationLS, t);

                const Bone& bone = skinningInfo.bones[i];
                const glm::fvec3 plusX = glm::normalize(bone.end - bone.root);
                const glm::fvec3 interpolatedPlusY = interpolatedOrientation * UnitYAxis;
                const glm::fvec3 plusY = glm::normalize(interpolatedPlusY - glm::proj(interpolatedPlusY, plusX)); // Trick to get a correct-ish roll along the spline
                const glm::fvec3 plusZ = glm::cross(plusX, plusY); // Should already be normalized at this point (write assert)

                // Convert to a matrix
                const glm::fmat4 rotation = glm::fmat3(plusX, plusY, plusZ);
                const glm::fmat4 translation = glm::translate(glm::fmat4(1.0f), bone.root);

                skinningInfo.poseTransforms[i] = translation * rotation;
            }
        }
    }

    void GenerateTrackSkinning(const std::vector<TrackSkeletonNode>& skeletonNodes,
                               const std::vector<Reaper::Math::Spline>& splines,
                               std::vector<TrackSkinning>& skinning)
    {
        const u32 trackChunkCount = static_cast<u32>(splines.size());

        Assert(trackChunkCount > 0);

        skinning.resize(trackChunkCount);

        for (u32 chunkIdx = 0; chunkIdx < splines.size(); chunkIdx++)
        {
            GenerateTrackSkinningForChunk(skeletonNodes[chunkIdx], splines[chunkIdx], skinning[chunkIdx]);
        }
    }

    namespace
    {
        glm::fvec4 ComputeBoneWeights(glm::vec3 position)
        {
            static_cast<void>(position);
            return glm::vec4(1.0f, 0.0f, 0.0f, 0.0f); // FIXME
        }
    }

    void SkinTrackChunkMesh(const TrackSkeletonNode& node,
                            const TrackSkinning& trackSkinning,
                            Mesh& mesh, float meshLength)
    {
        const u32 vertexCount = static_cast<u32>(mesh.vertices.size());
        const u32 boneCount = 4; // FIXME
        std::vector<glm::fvec3> skinnedVertices(vertexCount);

        Assert(vertexCount > 0);

        const float scaleX = node.radius / (meshLength * 0.5f);

        for (u32 i = 0; i < vertexCount; i++)
        {
            const glm::fvec3 vertex = mesh.vertices[i] * glm::fvec3(scaleX, 1.0f, 1.0f);
            const glm::fvec4 boneWeights = ComputeBoneWeights(vertex);

            skinnedVertices[i] = glm::fvec3(0.0f);

            for (u32 j = 0; j < boneCount; j++)
            {
                const glm::fmat4 boneTransform = trackSkinning.poseTransforms[j] * trackSkinning.invBindTransforms[j];
                const glm::fvec4 skinnedVertex = (boneTransform * glm::fvec4(vertex, 1.0f)) * boneWeights[j];

                Assert(skinnedVertex.w > 0.0f);
                skinnedVertices[i] += glm::fvec3(skinnedVertex) / skinnedVertex.w;
            }
        }
        mesh.vertices = skinnedVertices;
    }
}} // namespace SplineSonic::TrackGen
<commit_msg>skinning: fix division by zero<commit_after>////////////////////////////////////////////////////////////////////////////////
/// Reaper
///
/// Copyright (c) 2015-2017 Thibault Schueller
/// This file is distributed under the MIT License
////////////////////////////////////////////////////////////////////////////////

#include "Track.h"

#include "math/Constants.h"
#include "math/Spline.h"

#include "mesh/Mesh.h"

#include "splinesonic/Constants.h"

#include <glm/gtx/norm.hpp>
#include <glm/gtx/projection.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <random>

namespace SplineSonic { namespace TrackGen
{
    constexpr float ThetaMax = 0.8f * Reaper::Math::HalfPi;
    constexpr float PhiMax = 1.0f * Reaper::Math::Pi;
    constexpr float RollMax = 0.25f * Reaper::Math::Pi;
    constexpr float WidthMin = 20.0f * MeterInGameUnits;
    constexpr float WidthMax = 50.0f * MeterInGameUnits;
    constexpr float RadiusMin = 100.0f * MeterInGameUnits;
    constexpr float RadiusMax = 300.0f * MeterInGameUnits;

    constexpr u32 MinLength = 5;
    constexpr u32 MaxLength = 1000;
    constexpr u32 MaxTryCount = 10000;

    constexpr u32 SplineOrder = 3;

    constexpr float SplineInnerWeight = 0.5f;

    constexpr u32 BoneCountPerChunk = 4;

    using RNG = std::mt19937;

    using Reaper::Math::UnitXAxis;
    using Reaper::Math::UnitYAxis;
    using Reaper::Math::UnitZAxis;

    namespace
    {
        glm::quat GenerateChunkEndLocalSpace(const GenerationInfo& genInfo, RNG& rng)
        {
            const glm::vec2 thetaBounds = glm::vec2(0.0f, ThetaMax) * genInfo.chaos;
            const glm::vec2 phiBounds = glm::vec2(-PhiMax, PhiMax) * genInfo.chaos;
            const glm::vec2 rollBounds = glm::vec2(-RollMax, RollMax) * genInfo.chaos;

            std::uniform_real_distribution<float> thetaDistribution(thetaBounds.x, thetaBounds.y);
            std::uniform_real_distribution<float> phiDistribution(phiBounds.x, phiBounds.y);
            std::uniform_real_distribution<float> rollDistribution(rollBounds.x, rollBounds.y);

            const float theta = thetaDistribution(rng);
            const float phi = phiDistribution(rng);
            const float roll = rollDistribution(rng);

            glm::quat deviation = glm::angleAxis(phi, UnitXAxis) * glm::angleAxis(theta, UnitZAxis);
            glm::quat rollFixup = glm::angleAxis(-phi + roll, deviation * UnitXAxis);

            return rollFixup * deviation;
        }

        bool IsNodeSelfColliding(const std::vector<TrackSkeletonNode>& nodes, const TrackSkeletonNode& currentNode, u32& outputNodeIdx)
        {
            for (u32 i = 0; (i + 1) < nodes.size(); i++)
            {
                const float distanceSq = glm::distance2(currentNode.positionWS, nodes[i].positionWS);
                const float minRadius = currentNode.radius + nodes[i].radius;

                if (distanceSq < (minRadius * minRadius))
                {
                    outputNodeIdx = i;
                    return true;
                }
            }

            return false;
        }

        TrackSkeletonNode GenerateNode(const GenerationInfo& genInfo, const std::vector<TrackSkeletonNode>& skeletonNodes, RNG& rng)
        {
            std::uniform_real_distribution<float> widthDistribution(WidthMin, WidthMax);
            std::uniform_real_distribution<float> radiusDistribution(RadiusMin, RadiusMax);

            TrackSkeletonNode node;

            node.radius = radiusDistribution(rng);

            if (skeletonNodes.empty())
            {
                node.orientationWS = glm::quat();
                node.inWidth = widthDistribution(rng);
                node.positionWS = glm::vec3(0.f);
            }
            else
            {
                const TrackSkeletonNode& previousNode = skeletonNodes.back();

                node.orientationWS = previousNode.orientationWS * previousNode.rotationLS;
                node.inWidth = previousNode.outWidth;

                const glm::vec3 offsetMS = UnitXAxis * (previousNode.radius + node.radius);
                const glm::vec3 offsetWS = node.orientationWS * offsetMS;

                node.positionWS = previousNode.positionWS + offsetWS;
            }

            node.rotationLS = GenerateChunkEndLocalSpace(genInfo, rng);
            node.outWidth = widthDistribution(rng);

            return node;
        }
    }

    void GenerateTrackSkeleton(const GenerationInfo& genInfo, std::vector<TrackSkeletonNode>& skeletonNodes)
    {
        Assert(genInfo.length >= MinLength);
        Assert(genInfo.length <= MaxLength);

        skeletonNodes.resize(0);
        skeletonNodes.reserve(genInfo.length);

        std::random_device rd;
        RNG rng(rd());

        u32 tryCount = 0;

        while (skeletonNodes.size() < genInfo.length && tryCount < MaxTryCount)
        {
            const TrackSkeletonNode node = GenerateNode(genInfo, skeletonNodes, rng);

            u32 colliderIdx = 0;
            if (IsNodeSelfColliding(skeletonNodes, node, colliderIdx))
                skeletonNodes.resize(colliderIdx + 1); // Shrink the vector and generate from collider
            else
                skeletonNodes.push_back(node);

            ++tryCount;
        }

        Assert(tryCount < MaxTryCount, "something is majorly FUBAR");
    }

    void GenerateTrackSplines(const std::vector<TrackSkeletonNode>& skeletonNodes, std::vector<Reaper::Math::Spline>& splines)
    {
        std::vector<glm::vec4> controlPoints(4);
        const u32 trackChunkCount = static_cast<u32>(skeletonNodes.size());

        Assert(trackChunkCount > 0);
        Assert(trackChunkCount == skeletonNodes.size());

        splines.resize(trackChunkCount);

        for (u32 i = 0; i < trackChunkCount; i++)
        {
            const TrackSkeletonNode& node = skeletonNodes[i];

            // Laying down 1 control point at each end and 2 in the center of the sphere
            // seems to work pretty well.
            controlPoints[0] = glm::vec4(UnitXAxis * -node.radius, 1.0f);
            controlPoints[1] = glm::vec4(glm::vec3(0.0f), SplineInnerWeight);
            controlPoints[2] = glm::vec4(glm::vec3(0.0f), SplineInnerWeight);
            controlPoints[3] = glm::vec4(node.rotationLS * UnitXAxis * node.radius, 1.0f);

            splines[i] = Reaper::Math::ConstructSpline(SplineOrder, controlPoints);
        }
    }

    namespace
    {
        void GenerateTrackSkinningForChunk(const TrackSkeletonNode& node,
                                           const Reaper::Math::Spline& spline,
                                           TrackSkinning& skinningInfo)
        {
            skinningInfo.bones.resize(BoneCountPerChunk);

            // Fill bone positions
            skinningInfo.bones[0].root = EvalSpline(spline, 0.0f);
            skinningInfo.bones[BoneCountPerChunk - 1].end = EvalSpline(spline, 1.0f);

            // Compute bone start and end positions
            for (u32 i = 1; i < BoneCountPerChunk; i++)
            {
                const float param = static_cast<float>(i) / static_cast<float>(BoneCountPerChunk);
                const glm::vec3 anchorPos = EvalSpline(spline, param);

                skinningInfo.bones[i - 1].end = anchorPos;
                skinningInfo.bones[i].root = anchorPos;
            }

            skinningInfo.invBindTransforms.resize(BoneCountPerChunk);

            // Compute inverse bind pose matrix
            for (u32 i = 0; i < BoneCountPerChunk; i++)
            {
                const float t = static_cast<float>(i) / static_cast<float>(BoneCountPerChunk);
                const float param = t * 2.0f - 1.0f;
                const glm::vec3 offset = UnitXAxis * (param * node.radius);

                // Inverse of a translation is the translation by the opposite vector
                skinningInfo.invBindTransforms[i] = glm::translate(glm::mat4(1.0f), -offset);
            }

            skinningInfo.poseTransforms.resize(BoneCountPerChunk);

            // Compute current pose matrix by reconstructing an ortho-base
            // We only have roll information at chunk boundary, so we have to
            // use tricks to get the correct bone rotation
            for (u32 i = 0; i < BoneCountPerChunk; i++)
            {
                const float t = static_cast<float>(i) / static_cast<float>(BoneCountPerChunk);
                const glm::fquat interpolatedOrientation = glm::slerp(glm::quat(), node.rotationLS, t);

                const Bone& bone = skinningInfo.bones[i];
                const glm::fvec3 plusX = glm::normalize(bone.end - bone.root);
                const glm::fvec3 interpolatedPlusY = interpolatedOrientation * UnitYAxis;
                const glm::fvec3 plusY = glm::normalize(interpolatedPlusY - glm::proj(interpolatedPlusY, plusX)); // Trick to get a correct-ish roll along the spline
                const glm::fvec3 plusZ = glm::cross(plusX, plusY); // Should already be normalized at this point (write assert)

                // Convert to a matrix
                const glm::fmat4 rotation = glm::fmat3(plusX, plusY, plusZ);
                const glm::fmat4 translation = glm::translate(glm::fmat4(1.0f), bone.root);

                skinningInfo.poseTransforms[i] = translation * rotation;
            }
        }
    }

    void GenerateTrackSkinning(const std::vector<TrackSkeletonNode>& skeletonNodes,
                               const std::vector<Reaper::Math::Spline>& splines,
                               std::vector<TrackSkinning>& skinning)
    {
        const u32 trackChunkCount = static_cast<u32>(splines.size());

        Assert(trackChunkCount > 0);

        skinning.resize(trackChunkCount);

        for (u32 chunkIdx = 0; chunkIdx < splines.size(); chunkIdx++)
        {
            GenerateTrackSkinningForChunk(skeletonNodes[chunkIdx], splines[chunkIdx], skinning[chunkIdx]);
        }
    }

    namespace
    {
        glm::fvec4 ComputeBoneWeights(glm::vec3 position)
        {
            static_cast<void>(position);
            return glm::vec4(1.0f, 0.0f, 0.0f, 0.0f); // FIXME
        }
    }

    void SkinTrackChunkMesh(const TrackSkeletonNode& node,
                            const TrackSkinning& trackSkinning,
                            Mesh& mesh, float meshLength)
    {
        const u32 vertexCount = static_cast<u32>(mesh.vertices.size());
        const u32 boneCount = 4; // FIXME
        std::vector<glm::fvec3> skinnedVertices(vertexCount);

        Assert(vertexCount > 0);

        const float scaleX = node.radius / (meshLength * 0.5f);

        for (u32 i = 0; i < vertexCount; i++)
        {
            const glm::fvec3 vertex = mesh.vertices[i] * glm::fvec3(scaleX, 1.0f, 1.0f);
            const glm::fvec4 boneWeights = ComputeBoneWeights(vertex);

            skinnedVertices[i] = glm::fvec3(0.0f);

            for (u32 j = 0; j < boneCount; j++)
            {
                const glm::fmat4 boneTransform = trackSkinning.poseTransforms[j] * trackSkinning.invBindTransforms[j];
                const glm::fvec4 skinnedVertex = (boneTransform * glm::fvec4(vertex, 1.0f)) * boneWeights[j];

                if (glm::abs(skinnedVertex.w) > 0.0f)
                    skinnedVertices[i] += glm::fvec3(skinnedVertex) / skinnedVertex.w;
            }
        }
        mesh.vertices = skinnedVertices;
    }
}} // namespace SplineSonic::TrackGen
<|endoftext|>


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

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"

#pragma warning(push,1) // disable warnings within system headers
#include <windows.h>
#pragma warning(pop)

void dso_init(void);
void dso_exit(void);

extern "C" BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpvReserved)
{
    switch(dwReason) {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hModule);

        dso_init();
        break;

    case DLL_PROCESS_DETACH:
        if (!lpvReserved)
            dso_exit();
        break;
    }

    return TRUE;
}
<commit_msg>INTEGRATION: CWS changefileheader (1.2.48); FILE MERGED 2008/03/28 16:30:38 rt 1.2.48.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dllinit.cxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"

#pragma warning(push,1) // disable warnings within system headers
#include <windows.h>
#pragma warning(pop)

void dso_init(void);
void dso_exit(void);

extern "C" BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpvReserved)
{
    switch(dwReason) {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hModule);

        dso_init();
        break;

    case DLL_PROCESS_DETACH:
        if (!lpvReserved)
            dso_exit();
        break;
    }

    return TRUE;
}
<|endoftext|>


<commit_before>#include "photoeffects.hpp"
#include <math.h>

using namespace cv;

#define MAX_KERNELSIZE 15

int edgeBlur(InputArray src, OutputArray dst, int indentTop, int indentLeft)
{
    CV_Assert(src.type() == CV_8UC3);
    dst.create(src.size(), src.type());
    Mat image = src.getMat(), outputImage = dst.getMat();

    CV_Assert(indentTop >= 0 && indentTop <= (image.rows / 2 - 10));
    CV_Assert(indentLeft >= 0 && indentLeft <= (image.cols / 2 - 10));

    float halfWidth = (image.cols / 2.0f) * (image.cols / 2.0f);
    float halfHeight = (image.rows / 2.0f) * (image.rows / 2.0f);
    float a = (image.cols / 2.0f - indentLeft)
            * (image.cols / 2.0f - indentLeft);
    float b = (image.rows / 2.0f - indentTop)
            * (image.rows / 2.0f - indentTop);
    int kSizeEdges = halfWidth / a + halfHeight / b;

    kSizeEdges = MIN(kSizeEdges, MAX_KERNELSIZE);
    Mat bearingImage(image.rows + 2 * kSizeEdges,
                    image.cols + 2 * kSizeEdges,
                    CV_8UC3);
    copyMakeBorder(image, bearingImage, kSizeEdges, kSizeEdges,
        kSizeEdges, kSizeEdges, BORDER_REPLICATE);

    for (int i = kSizeEdges; i < bearingImage.rows - kSizeEdges; i++)
    {
        for (int j = kSizeEdges; j < bearingImage.cols - kSizeEdges; j++)
        {
            int size;
            Vec3f sumF;
            Vec3b Color;
            float sumC = 0.0f, coeff;
            float bearHalfWidth = bearingImage.cols / 2.0f;
            float bearHalfHeight = bearingImage.rows / 2.0f;
            float radius = (bearHalfHeight - i)
                    * (bearHalfHeight - i)
                    / b

                    + (bearHalfWidth - j)
                    * (bearHalfWidth - j)
                    / a;
            if (radius < 1.0f)
            {
                outputImage.at<Vec3b>(i - kSizeEdges, j - kSizeEdges) =
                    bearingImage.at<Vec3b>(i, j);
                continue;
            }
            size = radius;
            radius = 2.0f * (radius - 0.5f) * (radius - 0.5f);
            size = MIN(size, kSizeEdges);
            for (int x = -size; x <= size; x++)
            {
                for (int y = -size; y <= size; y++)
                {
                    coeff = 1.0f / (CV_PI * radius)
                            * exp(- (x * x + y * y) / radius);

                    Color = bearingImage.at<Vec3b>(x + i, y + j);
                    sumF += coeff * Color;
                    sumC += coeff;
                }
            }
            sumF *= (1.0f / sumC);
            outputImage.at<Vec3b>(i - kSizeEdges, j - kSizeEdges) = sumF;
        }
    }

    return 0;
}
<commit_msg>Corrected<commit_after>#include "photoeffects.hpp"
#include <math.h>

using namespace cv;

#define MAX_KERNELSIZE 15

int edgeBlur(InputArray src, OutputArray dst, int indentTop, int indentLeft)
{
    CV_Assert(src.type() == CV_8UC3);
    dst.create(src.size(), src.type());
    Mat image = src.getMat(), outputImage = dst.getMat();

    CV_Assert(indentTop >= 0 && indentTop <= (image.rows / 2 - 10));
    CV_Assert(indentLeft >= 0 && indentLeft <= (image.cols / 2 - 10));

    float halfWidth = image.cols / 2.0f;
    float halfHeight = image.rows / 2.0f;
    float a = (image.cols / 2.0f - indentLeft)
            * (image.cols / 2.0f - indentLeft);
    float b = (image.rows / 2.0f - indentTop)
            * (image.rows / 2.0f - indentTop);
    int kSizeEdges = halfWidth * halfWidth / a + halfHeight * halfHeight / b;

    kSizeEdges = MIN(kSizeEdges, MAX_KERNELSIZE);
    Mat bearingImage(image.rows + 2 * kSizeEdges,
                    image.cols + 2 * kSizeEdges,
                    CV_8UC3);
    copyMakeBorder(image, bearingImage, kSizeEdges, kSizeEdges,
        kSizeEdges, kSizeEdges, BORDER_REPLICATE);

    for (int i = kSizeEdges; i < bearingImage.rows - kSizeEdges; i++)
    {
        for (int j = kSizeEdges; j < bearingImage.cols - kSizeEdges; j++)
        {
            int size;
            Vec3f sumF;
            Vec3b Color;
            float sumC = 0.0f, coeff;
            float radius = (halfHeight - i)
                    * (halfHeight- i)
                    / b

                    + (halfWidth - j)
                    * (halfHeight - j)
                    / a;
            if (radius < 1.0f)
            {
                outputImage.at<Vec3b>(i - kSizeEdges, j - kSizeEdges) =
                    bearingImage.at<Vec3b>(i, j);
                continue;
            }
            size = radius;
            radius = 2.0f * (radius - 0.5f) * (radius - 0.5f);
            size = MIN(size, kSizeEdges);
            for (int x = -size; x <= size; x++)
            {
                for (int y = -size; y <= size; y++)
                {
                    coeff = 1.0f / (CV_PI * radius)
                            * exp(- (x * x + y * y) / radius);

                    Color = bearingImage.at<Vec3b>(x + i, y + j);
                    sumF += coeff * (Vec3f)Color;
                    sumC += coeff;
                }
            }
            sumF *= (1.0f / sumC);
            outputImage.at<Vec3b>(i - kSizeEdges, j - kSizeEdges) = sumF;
        }
    }

    return 0;
}
<|endoftext|>