<commit_before>#include "cone.hpp"
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
#include <string>
#include "color.hpp"
#include "ray.hpp"
#include "material.hpp"
#include <glm/vec3.hpp>
#include <glm/glm.hpp>
#include <glm/gtx/intersect.hpp>
#define PI 3.14159265

Cone::Cone(): Shape{}, center_{0.0f, 0.0f, 0.0f}, radius_{0.0f}, center2_{0.0f, 0.0f, 0.0f}{}
Cone::Cone(glm::vec3 const& center, float radius, glm::vec3 const& center2): Shape{}, center_{center}, radius_{radius}, center2_{center2}{}
Cone::Cone(std::string name, glm::vec3 const& center, float radius, glm::vec3 const& center2, std::string material) : Shape{name, material}, center_{center}, radius_{radius}, center2_{center2}{}

//Cone::Cone(glm::vec3 const& center, float radius, glm::vec3 const& center2, std::string name, Color const& color):Shape{name, color}, center_{center}, radius_{radius}, center2_{center2}{}
//Cone::~Cone(){std::cout << "Cone Destructor" << std::endl;}

/*Cone::Cone(glm::vec3 const& center, float radius, glm::vec3 const& center2, std::string name, Material const& mat): Shape{name, mat}, center_{center}, radius_{radius}, center2_{center2}{}
Cone::Cone(glm::vec3 const& center, float radius, glm::vec3 const& center2, std::string name, std::string name_mat, Color const& ka, Color const& kd, Color const& ks, float m): Shape{name, name_mat, ka, kd, ks, m}, center_{center}, radius_{radius}, center2_{center2}{}*/

glm::vec3 const& Cone::get_center() const {
	return center_;
}

float const& Cone::get_radius() const {
	return radius_;
}

glm::vec3 const& Cone::get_center2() const {
	return center2_;

}

bool Cone::intersect(Ray const& ray, float& distance, glm::vec3& intersection, glm::vec3& normal)const{
	//Gerade durch Mitte des Kegels: p_a + v_a * t, p_a = Stützvektor = center unten, v_a = Richtungsvektor = center oben-center unten
	glm::vec3 p_a = center_;
	glm::vec3 v_a = center2_ - center_;

	glm::vec3 p = ray.origin;
	glm::vec3 v = ray.direction;

	float height = glm::length(v_a);
	float beta = atan(height/radius) * PI/180; //Winkel an der Fläche
	float alpha = PI/2 - beta; //Winkel an der Spitze = zwischen Gerade und einer Seite

	float a = cos(alpha) * cos(alpha) * (v - glm::dot(v, v_a) * v_a) * (v - glm::dot(v, v_a) * v_a) - sin(alpha) * sin(alpha) * (glm::dot(v, v_a)) * (glm::dot(v, v_a));
	float b = 2 * cos(alpha) * cos(alpha) * (v - glm::dot(v, v_a) * (glm::dot(v_a,(p-p_a))) - (glm::dot((p-p_a), v_a)) * v_a) - 2 * sin(alpha) * sin(alpha) * glm::dot(v, v_a) * glm::dot((p-p_a), v_a);
	float c = cos(alpha) * cos(alpha) * ((p-p_a) - glm::dot((p-p_a), v_a) * v_a) * ((p-p_a) - glm::dot((p-p_a), v_a) * v_a) - sin(alpha) * sin(alpha) * glm::dot((p-p_a), v_a) * glm::dot((p-p_a), v_a);

	float possibleT[3];

	float x1;
	float x2;

	solveQuadratic(a, b, c, x1, x2);

	//schauen ob die intersection zwischen Spitze und Basis ist
	glm::vec3 q1 = p + v*x1
	if (x1 > 0 && (glm::dot(v_a, (q1 - center_))) > 0 && (glm::dot(v_a, (q1 - center2_))) < 0){
		possibleT[0] = x1;
	}

	glm::vec3 q2 = p + v*x2
	if (x2 > 0 && (glm::dot(v_a, (q2 - center_))) > 0 && (glm::dot(v_a, (q2 - center2_))){
		possibleT[1] = x2;
	}

	//unten
	v_a = glm::normalize(v_a);
	glm::vec3 c = glm::normalize(center_);
	glm::vec3 origin = glm::normalize(ray.origin);
	glm::vec3 direction = glm::normalize(ray.direction);

	float x3;
	intersectDisk(v_a, c, radius, origin, direction, x3);
	possibleT[2] = x3;

	float t = possibleT[0];
	for (int i = 1; i < 4; i++){
		if (t == 0 && possibleT[i] > 0){
			t = possibleT[i]
		}
		else if(possibleT[i] < t && possibleT[i] > 0){
			t = possibleT[i]
		}
	}

	if (t > 0){
		intersection = p + v*t;

		if(t == x1 || t == x2){
			glm::vec3 b = intersection - p_a;
			float r = (glm::dot(b, v_a))/glm::length(v_a);
			glm::vec3 f = p_a + (r/glm::length(v_a))*v_a;
			normal = intersection - f;
		}

		else if(t == x3){
		normal = v_a;
		}

		return true;
	}

	else {
		return false;

	}
}

std::ostream& Cone::print(std::ostream& os) const{
	Shape::print(os);
	//os << "Name: " << get_name() << ", Color: " << get_color().r << " " << get_color().g << " " << get_color().b << "\n";
	os << "Mittelpunkt Basis: " << center_.x << " " << center_.y << " ";
	os << center_.z << "," << "Radius: " << radius_; << "," << "Spitze: ";
	os << center2_.x << " " << center2_.y << " " << center2_.z;

	return os;
}
<commit_msg>verbesserung<commit_after>#include "cone.hpp"
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
#include <string>
#include "color.hpp"
#include "ray.hpp"
#include "material.hpp"
#include <glm/vec3.hpp>
#include <glm/glm.hpp>
#include <glm/gtx/intersect.hpp>
#define PI 3.14159265

Cone::Cone(): Shape{}, center_{0.0f, 0.0f, 0.0f}, radius_{0.0f}, center2_{0.0f, 0.0f, 0.0f}{}
Cone::Cone(glm::vec3 const& center, float radius, glm::vec3 const& center2): Shape{}, center_{center}, radius_{radius}, center2_{center2}{}
Cone::Cone(std::string name, glm::vec3 const& center, float radius, glm::vec3 const& center2, std::string material) : Shape{name, material}, center_{center}, radius_{radius}, center2_{center2}{}

//Cone::Cone(glm::vec3 const& center, float radius, glm::vec3 const& center2, std::string name, Color const& color):Shape{name, color}, center_{center}, radius_{radius}, center2_{center2}{}
//Cone::~Cone(){std::cout << "Cone Destructor" << std::endl;}

/*Cone::Cone(glm::vec3 const& center, float radius, glm::vec3 const& center2, std::string name, Material const& mat): Shape{name, mat}, center_{center}, radius_{radius}, center2_{center2}{}
Cone::Cone(glm::vec3 const& center, float radius, glm::vec3 const& center2, std::string name, std::string name_mat, Color const& ka, Color const& kd, Color const& ks, float m): Shape{name, name_mat, ka, kd, ks, m}, center_{center}, radius_{radius}, center2_{center2}{}*/

glm::vec3 const& Cone::get_center() const {
	return center_;
}

float const& Cone::get_radius() const {
	return radius_;
}

glm::vec3 const& Cone::get_center2() const {
	return center2_;

}

bool Cone::intersect(Ray const& ray, float& distance, glm::vec3& intersection, glm::vec3& normal)const{
	//Gerade durch Mitte des Kegels: p_a + v_a * t, p_a = Stützvektor = center unten, v_a = Richtungsvektor = center oben-center unten
	glm::vec3 p_a = center_;
	glm::vec3 v_a = center2_ - center_;

	glm::vec3 p = ray.origin;
	glm::vec3 v = ray.direction;

	float height = glm::length(v_a);
	float beta = atan(height/radius); //Winkel an der Fläche
	float alpha = PI/2 - beta; //Winkel an der Spitze = zwischen Gerade und einer Seite

	float a = cos(alpha) * cos(alpha) * (v - glm::dot(v, v_a) * v_a) * (v - glm::dot(v, v_a) * v_a) - sin(alpha) * sin(alpha) * (glm::dot(v, v_a)) * (glm::dot(v, v_a));
	float b = 2 * cos(alpha) * cos(alpha) * (v - glm::dot(v, v_a) * (glm::dot(v_a,(p-p_a))) - (glm::dot((p-p_a), v_a)) * v_a) - 2 * sin(alpha) * sin(alpha) * glm::dot(v, v_a) * glm::dot((p-p_a), v_a);
	float c = cos(alpha) * cos(alpha) * ((p-p_a) - glm::dot((p-p_a), v_a) * v_a) * ((p-p_a) - glm::dot((p-p_a), v_a) * v_a) - sin(alpha) * sin(alpha) * glm::dot((p-p_a), v_a) * glm::dot((p-p_a), v_a);

	float possibleT[3];

	float x1;
	float x2;

	solveQuadratic(a, b, c, x1, x2);

	//schauen ob die intersection zwischen Spitze und Basis ist
	glm::vec3 q1 = p + v*x1
	if (x1 > 0 && (glm::dot(v_a, (q1 - center_))) > 0 && (glm::dot(v_a, (q1 - center2_))) < 0){
		possibleT[0] = x1;
	}

	glm::vec3 q2 = p + v*x2
	if (x2 > 0 && (glm::dot(v_a, (q2 - center_))) > 0 && (glm::dot(v_a, (q2 - center2_))){
		possibleT[1] = x2;
	}

	//unten
	v_a = glm::normalize(v_a);
	glm::vec3 c = glm::normalize(center_);
	glm::vec3 origin = glm::normalize(ray.origin);
	glm::vec3 direction = glm::normalize(ray.direction);

	float x3;
	intersectDisk(v_a, c, radius, origin, direction, x3);
	possibleT[2] = x3;

	float t = possibleT[0];
	for (int i = 1; i < 4; i++){
		if (t == 0 && possibleT[i] > 0){
			t = possibleT[i]
		}
		else if(possibleT[i] < t && possibleT[i] > 0){
			t = possibleT[i]
		}
	}

	if (t > 0){
		intersection = p + v*t;

		if(t == x1 || t == x2){
			glm::vec3 b = intersection - p_a;
			float r = (glm::dot(b, v_a))/glm::length(v_a);
			glm::vec3 f = p_a + (r/glm::length(v_a))*v_a;
			normal = intersection - f;
		}

		else if(t == x3){
		normal = v_a;
		}

		return true;
	}

	else {
		return false;

	}
}

std::ostream& Cone::print(std::ostream& os) const{
	Shape::print(os);
	//os << "Name: " << get_name() << ", Color: " << get_color().r << " " << get_color().g << " " << get_color().b << "\n";
	os << "Mittelpunkt Basis: " << center_.x << " " << center_.y << " ";
	os << center_.z << "," << "Radius: " << radius_; << "," << "Spitze: ";
	os << center2_.x << " " << center2_.y << " " << center2_.z;

	return os;
}
<|endoftext|>


<commit_before>#ifndef __CPREL_BDDDOMAIN_MANAGER_HH__
#define __CPREL_BDDDOMAIN_MANAGER_HH__

#include <iostream>
#include <iomanip>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/static_assert.hpp>
//#include <cudd/cuddInt.h>
#include <obj/cuddObj.hh>
#include <limits>

namespace MPG { namespace VarImpl {

    namespace Limits {
      /**
       * \brief Number of bits to represent an element inside a relation
       * tuple.
       * \ingroup DomRepr
       *
       * The maximum number that can be part of relation's tuple is 2^bbv.
       * - Setting this attribute to 5 will allow to represent positive integers
       *   of 32 bits.
       */
      const int bbv = 5;
      /**
       * \brief Number of bits of the maximum arity that can be represented
       * \ingroup DomRepr
       *
       * The maximum arity that a relation can have is 2^ba.
       * - Setting this attribute to 3 will allow to represent up to 8-ary relations
       */
      const int ba = 3;
      /**
       * \brief Number of bits used to represent each element of a tuple
       * \ingroup DomRepr
       */
      const int bitsPerInteger = 1 << bbv;
      /**
       * \brief Number of bits used to represent the arity
       * \ingroup DomRepr
       */
      const int arity = 1 << ba;
      /**
       * \brief Maximum number that can be represented by the current
       * configuration of the manager.
       * \ingroup DomRepr
       */
      const unsigned int maxValue = (1L << bitsPerInteger) - 1;
      /**
       * \brief Ensures that the library is compiled on an architecture in which the
       * bits in an integer fits in the bdd representation. This is because most of the
       * operations on tuples or anything that has a bdd representation behind use the
       * int type to input and output values.
       * \ingroup DomRepr
       */

      //  BOOST_STATIC_ASSERT(std::numeric_limits<int>::digits <= bitsPerInteger
      //                      && "The BDD configuration is wrong for this built");
    }

    class BddManager;
    typedef boost::shared_ptr<BddManager> PManager;
    /**
       \brief Class to interact with the underlying bdd library.
       \ingroup DomRepr

       A common design of BDD libraries is to provide a space where
       all the bdd nodes are allocated and the operations are
       performed. The manager will abstract this in order to decouple
       the domain representation from a particular implementation.

       The manager is configured by two main constants that will
       define the number of bdd variables that will be used.

       This class is also in charge of controlling te life time of the
       bdd objects. There is one global object for all the constraint
       system and no assumption on thread safety can be made on it.
     */
    class BddManager : private boost::noncopyable {
    private:
      /// Only one single instance of this class is allowed at run time
      static PManager _instance;
      /// Bdd abstraction offered by CUDD
      Cudd factory_;
      /// \name Constructors and destructor
      //@{
      /// Constructor that initializes the BDD manager of CUDD
      BddManager (void)
	: factory_(Limits::bitsPerInteger * Limits::arity,
		   0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0)
      {
	/// \todo: The existence of shiftLeft needs that the manager is initialized
	/// with the number of variables. Fix that method in order to permute only existent vars
      }
      /// Creates an instace of this object
      static void create() {
	_instance.reset( new BddManager, &deleter );
      }
      /// Destructor that releases the BDD manager of CUDD
      ~BddManager (void) {
	std::cout << "Destroyed BDD manager: " << references() << std::endl;
	//std::cout << "Manager stats" << std::endl;
	stats(std::cout);
      }
      //@}
      /// Method called by the managed pointer when destructed
      static void deleter(BddManager *ptr) {
	delete ptr;
      }
      int references(void) {
	return Cudd_CheckZeroRef(factory_.getManager());
      }
    public:
      /// Returns an instance of the manager
      static PManager instance(void) {
	if (_instance.get() != NULL)
	  return _instance;
	create();
	return _instance;
      }
      /// \name Access
      //@{
      /// Returns the factory
      Cudd* getFactory(void) {
	return &factory_;
      }
      /// Returns the bdd manager
      DdManager* manager(void) {
	return factory_.getManager();
      }
      /// Returns the constant \c true
      BDD one(void) {
	return factory_.bddOne();
      }
      /// Returns the constant \c false
      BDD zero(void) {
	return factory_.bddZero();
      }
      /// Prints manager statistics to \a os
      void stats(std::ostream& os) const {

	auto usedMemory = Cudd_ReadMemoryInUse(factory_.getManager());
	//    os << "\tMemory in use: " <<  (usedMemory / 1024)  << " KB" << std::endl;
	auto gcTime = Cudd_ReadGarbageCollectionTime(factory_.getManager());
	//os << "\tGC time: " <<  gcTime  << " ms." << std::endl;
	auto gcs =  Cudd_ReadGarbageCollections(factory_.getManager());
	//os << "\tGC triggered " << gcs << " times" << std::endl;

	{
	  std::cout << "|" << std::setfill('-') << std::setw(14) << "-+"
		    << std::setw(14) << "-+" << std::setw(14) << "-|" << std::endl;
	  std::cout << "|" << "Memory (MB) " <<  "|"  << "GC (s.)" << " |" << "GC steps" << " |" << std::endl;
	  std::cout << "|" << std::setfill('-') << std::setw(14) << "-+"
		    << std::setw(14) << "-+" << std::setw(14) << "-|" << std::endl;
	  /*
	    This will print a table in the form:
            |--------------+---------+----------------|
            | Memmory (MB) | GC (s.) | Number of GC's |
            |--------------+---------+----------------|
	  */
	  os << "|" <<  (usedMemory / 1048576.0)   << "|" << (gcTime / 1000.0) << "|" << gcs << "|" << std::endl;
	}
      }
      //@}
    };

    /**
     * \brief Returns the factory used for all the bdds
     * \ingroup DomRepr
     */
    inline
    Cudd* factoryPtr(void) {
      return BddManager::instance()->getFactory();
    }
    inline
    Cudd& factory(void) {
      return *factoryPtr();
    }
    /**
     * \brief Returns the manager
     * \ingroup DomRepr
     */
    inline
    DdManager* dd(void) {
      return BddManager::instance()->manager();
    }
    /**
     * \brief Returns logical true
     * \ingroup DomRepr
     */
    inline
    BDD one(void) {
      return BddManager::instance()->one();
    }
    /**
     * \brief Returns logical false
     * \ingroup DomRepr
     */
    inline
    BDD zero(void) {
      return BddManager::instance()->zero();
    }
    /**
     * \brief Oututs manager statistics to \a os
     * \ingroup DomRepr
     */
    inline
    void stats(std::ostream& os) {
      BddManager::instance()->stats(os);
    }
  }}
#endif
<commit_msg>Fixed statistics printing<commit_after>#ifndef __CPREL_BDDDOMAIN_MANAGER_HH__
#define __CPREL_BDDDOMAIN_MANAGER_HH__

#include <iostream>
#include <iomanip>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/static_assert.hpp>
//#include <cudd/cuddInt.h>
#include <obj/cuddObj.hh>
#include <limits>

namespace MPG { namespace VarImpl {

    namespace Limits {
      /**
       * \brief Number of bits to represent an element inside a relation
       * tuple.
       * \ingroup DomRepr
       *
       * The maximum number that can be part of relation's tuple is 2^bbv.
       * - Setting this attribute to 5 will allow to represent positive integers
       *   of 32 bits.
       */
      const int bbv = 5;
      /**
       * \brief Number of bits of the maximum arity that can be represented
       * \ingroup DomRepr
       *
       * The maximum arity that a relation can have is 2^ba.
       * - Setting this attribute to 3 will allow to represent up to 8-ary relations
       */
      const int ba = 3;
      /**
       * \brief Number of bits used to represent each element of a tuple
       * \ingroup DomRepr
       */
      const int bitsPerInteger = 1 << bbv;
      /**
       * \brief Number of bits used to represent the arity
       * \ingroup DomRepr
       */
      const int arity = 1 << ba;
      /**
       * \brief Maximum number that can be represented by the current
       * configuration of the manager.
       * \ingroup DomRepr
       */
      const unsigned int maxValue = (1L << bitsPerInteger) - 1;
      /**
       * \brief Ensures that the library is compiled on an architecture in which the
       * bits in an integer fits in the bdd representation. This is because most of the
       * operations on tuples or anything that has a bdd representation behind use the
       * int type to input and output values.
       * \ingroup DomRepr
       */

      //  BOOST_STATIC_ASSERT(std::numeric_limits<int>::digits <= bitsPerInteger
      //                      && "The BDD configuration is wrong for this built");
    }

    class BddManager;
    typedef boost::shared_ptr<BddManager> PManager;
    /**
       \brief Class to interact with the underlying bdd library.
       \ingroup DomRepr

       A common design of BDD libraries is to provide a space where
       all the bdd nodes are allocated and the operations are
       performed. The manager will abstract this in order to decouple
       the domain representation from a particular implementation.

       The manager is configured by two main constants that will
       define the number of bdd variables that will be used.

       This class is also in charge of controlling te life time of the
       bdd objects. There is one global object for all the constraint
       system and no assumption on thread safety can be made on it.
     */
    class BddManager : private boost::noncopyable {
    private:
      /// Only one single instance of this class is allowed at run time
      static PManager _instance;
      /// Bdd abstraction offered by CUDD
      Cudd factory_;
      /// \name Constructors and destructor
      //@{
      /// Constructor that initializes the BDD manager of CUDD
      BddManager (void)
	: factory_(Limits::bitsPerInteger * Limits::arity,
		   0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0)
      {
	/// \todo: The existence of shiftLeft needs that the manager is initialized
	/// with the number of variables. Fix that method in order to permute only existent vars
      }
      /// Creates an instace of this object
      static void create() {
	_instance.reset( new BddManager, &deleter );
      }
      /// Destructor that releases the BDD manager of CUDD
      ~BddManager (void) {
	std::cout << "Destroyed BDD manager: " << references() << std::endl;
	//std::cout << "Manager stats" << std::endl;
	stats(std::cout);
      }
      //@}
      /// Method called by the managed pointer when destructed
      static void deleter(BddManager *ptr) {
	delete ptr;
      }
      int references(void) {
	return Cudd_CheckZeroRef(factory_.getManager());
      }
    public:
      /// Returns an instance of the manager
      static PManager instance(void) {
	if (_instance.get() != NULL)
	  return _instance;
	create();
	return _instance;
      }
      /// \name Access
      //@{
      /// Returns the factory
      Cudd* getFactory(void) {
	return &factory_;
      }
      /// Returns the bdd manager
      DdManager* manager(void) {
	return factory_.getManager();
      }
      /// Returns the constant \c true
      BDD one(void) {
	return factory_.bddOne();
      }
      /// Returns the constant \c false
      BDD zero(void) {
	return factory_.bddZero();
      }
      /// Prints manager statistics to \a os
      void stats(std::ostream& os) const {

	auto usedMemory = Cudd_ReadMemoryInUse(factory_.getManager());
	//    os << "\tMemory in use: " <<  (usedMemory / 1024)  << " KB" << std::endl;
	auto gcTime = Cudd_ReadGarbageCollectionTime(factory_.getManager());
	//os << "\tGC time: " <<  gcTime  << " ms." << std::endl;
	auto gcs =  Cudd_ReadGarbageCollections(factory_.getManager());
	//os << "\tGC triggered " << gcs << " times" << std::endl;

	{

	  os  << "|" << std::setfill('-') << std::setw(14) << "+"
              << std::setw(14) << "-+" << std::setw(14) << "-|" << std::endl;
	  os  << std::setfill(' ')
              << setiosflags(std::ios::left)
              << "|" << std::setw(13) << "Memory (MB)"
              << std::setw(14) << "|GC (s.)"
              << std::setw(14) << "|GC steps" << "|"
              << std::endl;

          os << setiosflags(std::ios::right) << "|" << std::setfill('-') << std::setw(14) << "-+"
		    << std::setw(14) << "-+" << std::setw(14) << "-|" << std::endl;

          os << std::setfill(' ') <<  setiosflags(std::ios::right)  << "|"
             << std::setw(13) << (usedMemory / 1048576.0)  << "|"
             << std::setw(13) << (gcTime / 1000.0) << "|"
             << std::setw(13) << gcs << "|"
             << std::endl;

          os << "|" << std::setfill('-') << std::setw(14) << "+"
             << std::setw(14) << "-+" << std::setw(14) << "-|" << std::endl;
	}
      }
      //@}
    };

    /**
     * \brief Returns the factory used for all the bdds
     * \ingroup DomRepr
     */
    inline
    Cudd* factoryPtr(void) {
      return BddManager::instance()->getFactory();
    }
    inline
    Cudd& factory(void) {
      return *factoryPtr();
    }
    /**
     * \brief Returns the manager
     * \ingroup DomRepr
     */
    inline
    DdManager* dd(void) {
      return BddManager::instance()->manager();
    }
    /**
     * \brief Returns logical true
     * \ingroup DomRepr
     */
    inline
    BDD one(void) {
      return BddManager::instance()->one();
    }
    /**
     * \brief Returns logical false
     * \ingroup DomRepr
     */
    inline
    BDD zero(void) {
      return BddManager::instance()->zero();
    }
    /**
     * \brief Oututs manager statistics to \a os
     * \ingroup DomRepr
     */
    inline
    void stats(std::ostream& os) {
      BddManager::instance()->stats(os);
    }
  }}
#endif
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkTextActor3D.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

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

#include "vtkObjectFactory.h"
#include "vtkCamera.h"
#include "vtkImageActor.h"
#include "vtkImageData.h"
#include "vtkTransform.h"
#include "vtkTextProperty.h"
#include "vtkRenderer.h"
#include "vtkWindow.h"
#include "vtkFreeTypeUtilities.h"
#include "vtkMatrix4x4.h"
#include "vtkMath.h"

vtkCxxRevisionMacro(vtkTextActor3D, "1.2");
vtkStandardNewMacro(vtkTextActor3D);

vtkCxxSetObjectMacro(vtkTextActor3D, TextProperty, vtkTextProperty);

// ----------------------------------------------------------------------------
vtkTextActor3D::vtkTextActor3D()
{
  this->Input        = NULL;
  this->ImageActor   = NULL;
  this->ImageData    = NULL;
  this->TextProperty = NULL;

  this->BuildTime.Modified();

  this->SetTextProperty(vtkTextProperty::New());
  this->TextProperty->Delete();
}

// --------------------------------------------------------------------------
vtkTextActor3D::~vtkTextActor3D()
{
  this->SetTextProperty(NULL);
  this->SetInput(NULL);

  if (this->ImageActor)
    {
    this->ImageActor->Delete();
    this->ImageActor = NULL;
    }

  if (this->ImageData)
    {
    this->ImageData->Delete();
    this->ImageData = NULL;
    }
}

// --------------------------------------------------------------------------
void vtkTextActor3D::ShallowCopy(vtkProp *prop)
{
  vtkTextActor3D *a = vtkTextActor3D::SafeDownCast(prop);
  if (a != NULL)
    {
    this->SetInput(a->GetInput());
    this->SetTextProperty(a->GetTextProperty());
    }

  this->Superclass::ShallowCopy(prop);
}

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

double* vtkTextActor3D::GetBounds()
{
  if (this->ImageActor)
    {
    return this->ImageActor->GetBounds();
    }

  return NULL;
}

// --------------------------------------------------------------------------
void vtkTextActor3D::ReleaseGraphicsResources(vtkWindow *win)
{
  if (this->ImageActor)
    {
    this->ImageActor->ReleaseGraphicsResources(win);
    }

  this->Superclass::ReleaseGraphicsResources(win);
}

// --------------------------------------------------------------------------
int vtkTextActor3D::RenderOverlay(vtkViewport *viewport)
{
  int rendered_something = 0;

  if (this->UpdateImageActor() && this->ImageActor)
    {
    rendered_something += this->ImageActor->RenderOverlay(viewport);
    }

  return rendered_something;
}

// --------------------------------------------------------------------------
int vtkTextActor3D::RenderTranslucentGeometry(vtkViewport *viewport)
{
  int rendered_something = 0;

  if (this->UpdateImageActor() && this->ImageActor)
    {
    rendered_something +=
      this->ImageActor->RenderTranslucentGeometry(viewport);
    }

  return rendered_something;
}

// --------------------------------------------------------------------------
int vtkTextActor3D::RenderOpaqueGeometry(vtkViewport *viewport)
{
  int rendered_something = 0;

  if (this->UpdateImageActor() && this->ImageActor)
    {
    rendered_something +=
      this->ImageActor->RenderOpaqueGeometry(viewport);
    }

  return rendered_something;
}

// --------------------------------------------------------------------------
int vtkTextActor3D::UpdateImageActor()
{
  // Need text prop

  if (!this->TextProperty)
    {
    vtkErrorMacro(<<"Need a text property to render text actor");
    return 0;
    }

  // No input, don't render

  if (!this->Input)
    {
    return 0;
    }

  // Do we need to (re-)render the text ?
  // Yes if:
  //  - instance has been modified since last build
  //  - text prop has been modified since last build
  //  - ImageData ivar has not been allocated yet

  if (this->GetMTime() > this->BuildTime ||
      this->TextProperty->GetMTime() > this->BuildTime ||
      !this->ImageData)
    {
    //cout << "Need to re-render " << this->GetMTime() << ", " <<  this->TextProperty->GetMTime() << ", " << this->BuildTime << endl;

    this->BuildTime.Modified();

    // Get the bounding box of the text to render

    vtkFreeTypeUtilities *fu = vtkFreeTypeUtilities::GetInstance();
    if (!fu)
      {
      vtkErrorMacro(<<"Failed getting the FreeType utilities instance");
      return 0;
      }

    int text_bbox[4];
    fu->GetBoundingBox(this->TextProperty, this->Input, text_bbox);
    if (!fu->IsBoundingBoxValid(text_bbox))
      {
      return 0;
      }

    // The bounding box was the area that is going to be filled with pixels
    // given a text origin of (0, 0). Now get the real size we need, i.e.
    // the full extent from the origin to the bounding box.

    int text_size[2];
    text_size[0] = (text_bbox[1] - text_bbox[0] + 1) + abs(text_bbox[0]);
    text_size[1] = (text_bbox[3] - text_bbox[2] + 1) + abs(text_bbox[2]);

    // If the RGBA image data is too small, resize it to the next power of 2
    // WARNING: at this point, since this image is going to be a texture
    // we should limit its size or query the hardware

    if (!this->ImageData)
      {
      this->ImageData = vtkImageData::New();
      this->ImageData->SetScalarTypeToUnsignedChar();
      this->ImageData->SetNumberOfScalarComponents(4);
      this->ImageData->SetSpacing(1.0, 1.0, 1.0);
      }

    // If the current image data is too small to render the text,
    // or more than twice as big (too hungry), then resize

    int img_dims[3], new_img_dims[3];
    this->ImageData->GetDimensions(img_dims);

    if (img_dims[0] < text_size[0] || img_dims[1] < text_size[1] ||
        text_size[0] * 2 < img_dims[0] || text_size[1] * 2 < img_dims[0])
      {
      new_img_dims[0] = 1 << (int)ceil(log((double)text_size[0]) / log(2.0));
      new_img_dims[1] = 1 << (int)ceil(log((double)text_size[1]) / log(2.0));
      new_img_dims[2] = 1;
      if (new_img_dims[0] != img_dims[0] ||
          new_img_dims[1] != img_dims[1] ||
          new_img_dims[2] != img_dims[2])
        {
        //cout << "I need: " << text_size[0] << "x" << text_size[1] << ", I resize to: " << new_img_dims[0] << "x" << new_img_dims[1] << endl;
        this->ImageData->SetDimensions(new_img_dims);
        this->ImageData->AllocateScalars();
        this->ImageData->UpdateInformation();
        this->ImageData->SetUpdateExtent(this->ImageData->GetWholeExtent());
        this->ImageData->PropagateUpdateExtent();
        if (this->ImageActor)
          {
          this->ImageActor->SetDisplayExtent(
            this->ImageData->GetWholeExtent());
          }
        }
      }

    // Render inside the image data

    int x = (text_bbox[0] < 0 ? -text_bbox[0] : 0);
    int y = (text_bbox[2] < 0 ? -text_bbox[2] : 0);

#if 0
    char *ptr = (char*)this->ImageData->GetScalarPointer();
    int nb_comp = this->ImageData->GetNumberOfScalarComponents();
    char *ptr_end = ptr + this->ImageData->GetNumberOfPoints() * nb_comp;
    memset(ptr, 0, ptr_end - ptr);
    ptr += nb_comp - 1;
    while (ptr < ptr_end)
      {
      *ptr = 255.0;
      ptr += nb_comp;
      }
#else
    memset(this->ImageData->GetScalarPointer(),
           0,
           (this->ImageData->GetNumberOfPoints() *
            this->ImageData->GetNumberOfScalarComponents()));
#endif

    if (!fu->RenderString(
          this->TextProperty, this->Input, x, y, this->ImageData))
      {
      vtkErrorMacro(<<"Failed rendering text to buffer");
      return 0;
      }

    // Set the image data origin so that oriented text is placed properly
    // Also take shadow into account, we want the text to be on the baseline

    if (this->TextProperty->GetShadow())
      {
      // this is wrong
      //x += this->TextProperty->GetShadowOffset()[0];
      //y += this->TextProperty->GetShadowOffset()[1];
      }
    this->ImageData->SetOrigin(-x, -y, 0);
    }

  // Associate the image data (should be up to date now) to the image actor

  if (!this->ImageActor)
    {
    this->ImageActor = vtkImageActor::New();
    this->ImageActor->InterpolateOn();
    }

  this->ImageActor->SetInput(this->ImageData);

  // Position the actor
  // Which one is faster ?

#if 1
  vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
  this->GetMatrix(matrix);
  this->ImageActor->SetUserMatrix(matrix);
  matrix->Delete();
#else
  this->ImageActor->SetPosition(this->GetPosition());
  this->ImageActor->SetScale(this->GetScale());
  this->ImageActor->SetOrientation(this->GetOrientation());
#endif

  return 1;
}

// --------------------------------------------------------------------------
void vtkTextActor3D::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Input: " << (this->Input ? this->Input : "(none)") << "\n";

  if (this->TextProperty)
    {
    os << indent << "Text Property:\n";
    this->TextProperty->PrintSelf(os, indent.GetNextIndent());
    }
  else
    {
    os << indent << "Text Property: (none)\n";
    }
}
<commit_msg>and now fix TestSetGet<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTextActor3D.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

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

#include "vtkObjectFactory.h"
#include "vtkCamera.h"
#include "vtkImageActor.h"
#include "vtkImageData.h"
#include "vtkTransform.h"
#include "vtkTextProperty.h"
#include "vtkRenderer.h"
#include "vtkWindow.h"
#include "vtkFreeTypeUtilities.h"
#include "vtkMatrix4x4.h"
#include "vtkMath.h"

vtkCxxRevisionMacro(vtkTextActor3D, "1.3");
vtkStandardNewMacro(vtkTextActor3D);

vtkCxxSetObjectMacro(vtkTextActor3D, TextProperty, vtkTextProperty);

// ----------------------------------------------------------------------------
vtkTextActor3D::vtkTextActor3D()
{
  this->Input        = NULL;
  this->ImageActor   = NULL;
  this->ImageData    = NULL;
  this->TextProperty = NULL;

  this->BuildTime.Modified();

  this->SetTextProperty(vtkTextProperty::New());
  this->TextProperty->Delete();
}

// --------------------------------------------------------------------------
vtkTextActor3D::~vtkTextActor3D()
{
  this->SetTextProperty(NULL);
  this->SetInput(NULL);

  if (this->ImageActor)
    {
    this->ImageActor->Delete();
    this->ImageActor = NULL;
    }

  if (this->ImageData)
    {
    this->ImageData->Delete();
    this->ImageData = NULL;
    }
}

// --------------------------------------------------------------------------
void vtkTextActor3D::ShallowCopy(vtkProp *prop)
{
  vtkTextActor3D *a = vtkTextActor3D::SafeDownCast(prop);
  if (a != NULL)
    {
    this->SetInput(a->GetInput());
    this->SetTextProperty(a->GetTextProperty());
    }

  this->Superclass::ShallowCopy(prop);
}

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

double* vtkTextActor3D::GetBounds()
{
  if (this->ImageActor)
    {
    return this->ImageActor->GetBounds();
    }

  static double unknown_bounds[6];
  vtkMath::UninitializeBounds(unknown_bounds);
  return unknown_bounds;
}

// --------------------------------------------------------------------------
void vtkTextActor3D::ReleaseGraphicsResources(vtkWindow *win)
{
  if (this->ImageActor)
    {
    this->ImageActor->ReleaseGraphicsResources(win);
    }

  this->Superclass::ReleaseGraphicsResources(win);
}

// --------------------------------------------------------------------------
int vtkTextActor3D::RenderOverlay(vtkViewport *viewport)
{
  int rendered_something = 0;

  if (this->UpdateImageActor() && this->ImageActor)
    {
    rendered_something += this->ImageActor->RenderOverlay(viewport);
    }

  return rendered_something;
}

// --------------------------------------------------------------------------
int vtkTextActor3D::RenderTranslucentGeometry(vtkViewport *viewport)
{
  int rendered_something = 0;

  if (this->UpdateImageActor() && this->ImageActor)
    {
    rendered_something +=
      this->ImageActor->RenderTranslucentGeometry(viewport);
    }

  return rendered_something;
}

// --------------------------------------------------------------------------
int vtkTextActor3D::RenderOpaqueGeometry(vtkViewport *viewport)
{
  int rendered_something = 0;

  if (this->UpdateImageActor() && this->ImageActor)
    {
    rendered_something +=
      this->ImageActor->RenderOpaqueGeometry(viewport);
    }

  return rendered_something;
}

// --------------------------------------------------------------------------
int vtkTextActor3D::UpdateImageActor()
{
  // Need text prop

  if (!this->TextProperty)
    {
    vtkErrorMacro(<<"Need a text property to render text actor");
    return 0;
    }

  // No input, don't render

  if (!this->Input)
    {
    return 0;
    }

  // Do we need to (re-)render the text ?
  // Yes if:
  //  - instance has been modified since last build
  //  - text prop has been modified since last build
  //  - ImageData ivar has not been allocated yet

  if (this->GetMTime() > this->BuildTime ||
      this->TextProperty->GetMTime() > this->BuildTime ||
      !this->ImageData)
    {
    //cout << "Need to re-render " << this->GetMTime() << ", " <<  this->TextProperty->GetMTime() << ", " << this->BuildTime << endl;

    this->BuildTime.Modified();

    // Get the bounding box of the text to render

    vtkFreeTypeUtilities *fu = vtkFreeTypeUtilities::GetInstance();
    if (!fu)
      {
      vtkErrorMacro(<<"Failed getting the FreeType utilities instance");
      return 0;
      }

    int text_bbox[4];
    fu->GetBoundingBox(this->TextProperty, this->Input, text_bbox);
    if (!fu->IsBoundingBoxValid(text_bbox))
      {
      return 0;
      }

    // The bounding box was the area that is going to be filled with pixels
    // given a text origin of (0, 0). Now get the real size we need, i.e.
    // the full extent from the origin to the bounding box.

    int text_size[2];
    text_size[0] = (text_bbox[1] - text_bbox[0] + 1) + abs(text_bbox[0]);
    text_size[1] = (text_bbox[3] - text_bbox[2] + 1) + abs(text_bbox[2]);

    // If the RGBA image data is too small, resize it to the next power of 2
    // WARNING: at this point, since this image is going to be a texture
    // we should limit its size or query the hardware

    if (!this->ImageData)
      {
      this->ImageData = vtkImageData::New();
      this->ImageData->SetScalarTypeToUnsignedChar();
      this->ImageData->SetNumberOfScalarComponents(4);
      this->ImageData->SetSpacing(1.0, 1.0, 1.0);
      }

    // If the current image data is too small to render the text,
    // or more than twice as big (too hungry), then resize

    int img_dims[3], new_img_dims[3];
    this->ImageData->GetDimensions(img_dims);

    if (img_dims[0] < text_size[0] || img_dims[1] < text_size[1] ||
        text_size[0] * 2 < img_dims[0] || text_size[1] * 2 < img_dims[0])
      {
      new_img_dims[0] = 1 << (int)ceil(log((double)text_size[0]) / log(2.0));
      new_img_dims[1] = 1 << (int)ceil(log((double)text_size[1]) / log(2.0));
      new_img_dims[2] = 1;
      if (new_img_dims[0] != img_dims[0] ||
          new_img_dims[1] != img_dims[1] ||
          new_img_dims[2] != img_dims[2])
        {
        //cout << "I need: " << text_size[0] << "x" << text_size[1] << ", I resize to: " << new_img_dims[0] << "x" << new_img_dims[1] << endl;
        this->ImageData->SetDimensions(new_img_dims);
        this->ImageData->AllocateScalars();
        this->ImageData->UpdateInformation();
        this->ImageData->SetUpdateExtent(this->ImageData->GetWholeExtent());
        this->ImageData->PropagateUpdateExtent();
        if (this->ImageActor)
          {
          this->ImageActor->SetDisplayExtent(
            this->ImageData->GetWholeExtent());
          }
        }
      }

    // Render inside the image data

    int x = (text_bbox[0] < 0 ? -text_bbox[0] : 0);
    int y = (text_bbox[2] < 0 ? -text_bbox[2] : 0);

#if 0
    char *ptr = (char*)this->ImageData->GetScalarPointer();
    int nb_comp = this->ImageData->GetNumberOfScalarComponents();
    char *ptr_end = ptr + this->ImageData->GetNumberOfPoints() * nb_comp;
    memset(ptr, 0, ptr_end - ptr);
    ptr += nb_comp - 1;
    while (ptr < ptr_end)
      {
      *ptr = 255.0;
      ptr += nb_comp;
      }
#else
    memset(this->ImageData->GetScalarPointer(),
           0,
           (this->ImageData->GetNumberOfPoints() *
            this->ImageData->GetNumberOfScalarComponents()));
#endif

    if (!fu->RenderString(
          this->TextProperty, this->Input, x, y, this->ImageData))
      {
      vtkErrorMacro(<<"Failed rendering text to buffer");
      return 0;
      }

    // Set the image data origin so that oriented text is placed properly
    // Also take shadow into account, we want the text to be on the baseline

    if (this->TextProperty->GetShadow())
      {
      // this is wrong
      //x += this->TextProperty->GetShadowOffset()[0];
      //y += this->TextProperty->GetShadowOffset()[1];
      }
    this->ImageData->SetOrigin(-x, -y, 0);
    }

  // Associate the image data (should be up to date now) to the image actor

  if (!this->ImageActor)
    {
    this->ImageActor = vtkImageActor::New();
    this->ImageActor->InterpolateOn();
    }

  this->ImageActor->SetInput(this->ImageData);

  // Position the actor
  // Which one is faster ?

#if 1
  vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
  this->GetMatrix(matrix);
  this->ImageActor->SetUserMatrix(matrix);
  matrix->Delete();
#else
  this->ImageActor->SetPosition(this->GetPosition());
  this->ImageActor->SetScale(this->GetScale());
  this->ImageActor->SetOrientation(this->GetOrientation());
#endif

  return 1;
}

// --------------------------------------------------------------------------
void vtkTextActor3D::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Input: " << (this->Input ? this->Input : "(none)") << "\n";

  if (this->TextProperty)
    {
    os << indent << "Text Property:\n";
    this->TextProperty->PrintSelf(os, indent.GetNextIndent());
    }
  else
    {
    os << indent << "Text Property: (none)\n";
    }
}
<|endoftext|>


<commit_before>#include "Accumulate.h"
#include "../Data.h"

VariableAccumulate::VariableAccumulate(const Options& iOptions, const Data& iData) : Variable(iOptions, iData),
      mTimeWindow(Global::MV) {
   // Which base variable should be accumulated?
   iOptions.getRequiredValue("baseVariable", mBaseVariable);
   //! Over how many hours should the variable be accumulated?
   //! Defaults to the beginning of the forecast period
   iOptions.getValue("timeWindow", mTimeWindow);

   loadOptionsFromBaseVariable();
   iOptions.check();
}

float VariableAccumulate::computeCore(int iDate,
                    int iInit,
                    float iOffset,
                    const Location& iLocation,
                    const Member& iMember,
                    Input::Type iType) const {

   float startOffset = 0;
   if(Global::isValid(mTimeWindow)) {
      if(iType == Input::typeObservation) {
         // Allowed to be negative
         startOffset = iOffset - mTimeWindow;
      }
      if(Global::isValid(mTimeWindow) && iOffset > mTimeWindow) {
         startOffset = iOffset - mTimeWindow;
      }
   }

   std::string dataset = iMember.getDataset();
   std::vector<float> offsets = mData.getInput(dataset)->getOffsets();
   float total = 0;
   for(int i = 0; i < offsets.size(); i++) {
      float offset = offsets[i];
      if(offset > startOffset && offset <= iOffset) {
         float value = mData.getValue(iDate, iInit, offset, iLocation, iMember, mBaseVariable);
         if(Global::isValid(value))
            total += value;
         else
            return Global::MV;
      }
   }

   return total;
}

std::string VariableAccumulate::getBaseVariable() const {
   // TODO:
   std::stringstream ss;
   if(Global::isValid(mTimeWindow))
      ss << mBaseVariable << "_" << (int) mTimeWindow;
   else
      ss << mBaseVariable << "_Acc";
   return ss.str();
}
<commit_msg>Bug fix in VariableAccumulate for observations<commit_after>#include "Accumulate.h"
#include "../Data.h"

VariableAccumulate::VariableAccumulate(const Options& iOptions, const Data& iData) : Variable(iOptions, iData),
      mTimeWindow(Global::MV) {
   // Which base variable should be accumulated?
   iOptions.getRequiredValue("baseVariable", mBaseVariable);
   //! Over how many hours should the variable be accumulated?
   //! Defaults to the beginning of the forecast period
   iOptions.getValue("timeWindow", mTimeWindow);

   loadOptionsFromBaseVariable();
   iOptions.check();
}

float VariableAccumulate::computeCore(int iDate,
                    int iInit,
                    float iOffset,
                    const Location& iLocation,
                    const Member& iMember,
                    Input::Type iType) const {

   float total = 0;
   ///////////////////////////////
   // Accumulating observations //
   ///////////////////////////////
   // When accumulating observations, we are allowed to look at yesterday's values.
   // This can happen for low offsets, where the accumulation window crosses into yesterday
   if(iType == Input::typeObservation) {
      float startOffset = iOffset - mTimeWindow; // Allowed to be negative
      std::string dataset = iMember.getDataset();
      std::vector<float> offsets = mData.getInput(dataset)->getOffsets();
      for(int i = 0; i < offsets.size(); i++) {
         float offset = offsets[i];
         if(offset < 24) { // Observations should never have offsets above 24, but just in case
            // Use a value from today
            if(offset > startOffset && offset <= iOffset) {
               float value = mData.getValue(iDate, iInit, offset, iLocation, iMember, mBaseVariable);
               if(Global::isValid(value))
                  total += value;
               else
                  return Global::MV;
            }
            // Use a value from yesterday
            else if(offset > startOffset+24 && offset <= iOffset + 24) {
               int date = Global::getDate(iDate, -24); // yesterday
               float value = mData.getValue(date, iInit, offset, iLocation, iMember, mBaseVariable);
               if(Global::isValid(value))
                  total += value;
               else
                  return Global::MV;
            }
         }
      }
   }
   ////////////////////////////
   // Accumulating forecasts //
   ////////////////////////////
   // Only accumulate values for forecasts valid at this initialization date/time
   else {
      if(Global::isValid(mTimeWindow) && iOffset > mTimeWindow) {
         // Do a regular sum between start and end offsets
         float startOffset = iOffset - mTimeWindow;
         std::string dataset = iMember.getDataset();
         std::vector<float> offsets = mData.getInput(dataset)->getOffsets();
         for(int i = 0; i < offsets.size(); i++) {
            float offset = offsets[i];
            if(offset > startOffset && offset <= iOffset) {
               float value = mData.getValue(iDate, iInit, offset, iLocation, iMember, mBaseVariable);
               if(Global::isValid(value))
                  total += value;
               else
                  return Global::MV;
            }
         }
      }
      else {
         return Global::MV;
      }
   }

   return total;
}

std::string VariableAccumulate::getBaseVariable() const {
   // TODO:
   std::stringstream ss;
   if(Global::isValid(mTimeWindow))
      ss << mBaseVariable << "_" << (int) mTimeWindow;
   else
      ss << mBaseVariable << "_Acc";
   return ss.str();
}
<|endoftext|>


<commit_before>/***************************************************************************
 *  @file       node.hpp
 *  @author     Alan.W
 *  @date       17  July 2014
 *  @remark     Implementation of CLRS algorithms, using C++ templates.
 ***************************************************************************/
#ifndef CUT_ROD_HPP
#define CUT_ROD_HPP

#include <algorithm>
#include <iterator>
#include <limits>

namespace ch15 {

template<typename Iter>
typename std::iterator_traits<Iter>::value_type
cut_rod(Iter first, typename std::iterator_traits<Iter>::difference_type len);

/**
 * @brief cut_rod
 *          return the optimal solution without using dynamic programming
 * @param first
 * @param len
 *
 * @complx  O(2^n)
 * @page    363, CLRS
 */
template<typename Iter>
inline typename std::iterator_traits<Iter>::value_type
cut_rod(Iter first, typename std::iterator_traits<Iter>::difference_type len)
{
    using ValueType =   typename std::iterator_traits<Iter>::value_type;
    using SizeType  =   typename std::iterator_traits<Iter>::difference_type;

    //! stop condition
    if(len == 0)
        return 0;

    //! initialize it as -infinity
    ValueType ret = std::numeric_limits<ValueType>::min();

    //! iteration with recursion
    for(SizeType count = 0 ; count != len ; ++count)
        ret =   std::max(ret, *(first + count) + cut_rod(first, len - count - 1));

    return ret;
}

}

#endif // CUT_ROD_HPP
<commit_msg>add an abstract class for the two algorithms  On branch ch15 	modified:   ch15/cut_rod.hpp<commit_after>/***************************************************************************
 *  @file       node.hpp
 *  @author     Alan.W
 *  @date       17  July 2014
 *  @remark     Implementation of CLRS algorithms, using C++ templates.
 ***************************************************************************/
#ifndef CUT_ROD_HPP
#define CUT_ROD_HPP

#include <algorithm>
#include <iterator>
#include <limits>

namespace ch15 {

template<typename Iter>
typename std::iterator_traits<Iter>::value_type
cut_rod(Iter first, typename std::iterator_traits<Iter>::difference_type len);

template<typename Iter>
class RodCutter;

/**
 * @brief cut_rod
 *          return the optimal solution without using dynamic programming
 * @param first     the first iterator of p
 * @param len       n
 *
 * @complx  O(2^n)
 * @page    363, CLRS
 */
template<typename Iter>
inline typename std::iterator_traits<Iter>::value_type
cut_rod(Iter first, typename std::iterator_traits<Iter>::difference_type len)
{
    using ValueType =   typename std::iterator_traits<Iter>::value_type;
    using SizeType  =   typename std::iterator_traits<Iter>::difference_type;

    //! stop condition
    if(len == 0)
        return 0;

    //! initialize it as -infinity
    ValueType ret = std::numeric_limits<ValueType>::min();

    //! iteration with recursion
    for(SizeType count = 0 ; count != len ; ++count)
        ret = std::max(ret, *(first + count) + cut_rod(first,len - count - 1));

    return ret;
}

/**
 * @brief The RodCutter class
 *
 * abstract class
 */
template<typename Iter>
class RodCutter
{
public:
    using ValueType =   typename    std::iterator_traits<Iter>::value_type;
    using SizeType  =   typename    std::iterator_traits<Iter>::difference_type;
    using Container =               std::vector<ValueType>;

    ValueType operator()(Iter first, SizeType len)
    {
        return dynamic_program(first, len);
    }

    ~RodCutter(){}

protected:
    Container   vec;

    virtual ValueType dynamic_program(Iter first, SizeType len) = 0;
};

}//namespace
#endif // CUT_ROD_HPP
<|endoftext|>


<commit_before>/*
 * ScriptCheck.cpp
 *
 *  Created on: Sep 2, 2014
 *      Author: ranger.shi
 */
#include "VmScriptRun.h"
#include "tx.h"
#include "util.h"
#include <boost/foreach.hpp>
CVmScriptRun::CVmScriptRun() {
	RawAccont.clear();
	NewAccont.clear();
	height = 0;
}
vector<shared_ptr<CAccount> > &CVmScriptRun::GetRawAccont() {
	return RawAccont;
}
vector<shared_ptr<CAccount> > &CVmScriptRun::GetNewAccont() {
	return NewAccont;
}

bool CVmScriptRun::intial(shared_ptr<CBaseTransaction> & Tx, CAccountViewCache& view, int nheight) {

	listTx = Tx;
	height = nheight;
	vector<unsigned char> vScript;

	if (Tx.get()->nTxType != CONTRACT_TX) {
		LogPrint("vm", "%s\r\n", "err param");
		return false;
	}

	CContractTransaction* secure = static_cast<CContractTransaction*>(Tx.get());
	if (pScriptDBTip->GetScript(secure->scriptRegId, vScript)) {
		CDataStream stream(vScript, SER_DISK, CLIENT_VERSION);
		try {
			stream >> vmScript;
		} catch (exception& e) {
			throw runtime_error("CVmScriptRun::intial() Unserialize to vmScript error:" + string(e.what()));
		}
	}

	if (vmScript.IsValid() == false)
		return false;

	for (auto& tx : secure->vAccountRegId) {
		auto tem = make_shared<CAccount>();
		view.GetAccount(tx, *tem.get());
		RawAccont.push_back(tem);
	}

	vector<unsigned char> strContract;
	pMcu = make_shared<CVir8051>(vmScript.Rom, strContract);
	return true;
}

CVmScriptRun::~CVmScriptRun() {

}
tuple<bool, uint64_t, string> CVmScriptRun:: run(shared_ptr<CBaseTransaction>& Tx, CAccountViewCache& view, int nheight,
		uint64_t nBurnFactor) {

	CContractTransaction* tx = static_cast<CContractTransaction*>(Tx.get());
	int maxstep = tx->llFees/nBurnFactor;
	tuple<bool, uint64_t, string> mytuple;
	if (!intial(Tx, view, nheight)) {
		mytuple = std::make_tuple (false, 0, string("VmScript inital Failed\n"));
		return mytuple;
	}
	unsigned int  step = pMcu.get()->run(maxstep,this);
	if (0 == step) {
		mytuple = std::make_tuple (false, 0, string("VmScript run Failed\n"));
		return mytuple;
	}
	shared_ptr<vector<unsigned char>> retData = pMcu.get()->GetRetData();
	CDataStream Contractstream(*retData.get(), SER_DISK, CLIENT_VERSION);
	vector<CVmOperate> retvmcode;
	Contractstream >> retvmcode;

	if (!CheckOperate(retvmcode)) {
		mytuple = std::make_tuple (false, 0, string("VmScript CheckOperate Failed \n"));
		return mytuple;
	}
	if (!OpeatorAccount(retvmcode, view)) {
		mytuple = std::make_tuple (false, 0, string("VmScript OpeatorSecureAccount Failed\n"));
		return mytuple;
	}
	uint64_t spend = step*nBurnFactor;
	mytuple = std::make_tuple (true, spend, string("VmScript Sucess\n"));
	return mytuple;
}

shared_ptr<CAccount> CVmScriptRun::GetNewAccount(shared_ptr<CAccount>& vOldAccount) {
	if (NewAccont.size() == 0)
		return NULL;
	vector<shared_ptr<CAccount> >::iterator Iter;
	for (Iter = NewAccont.begin(); Iter != NewAccont.end(); Iter++) {
		shared_ptr<CAccount> temp = *Iter;
		if (temp.get()->keyID == vOldAccount.get()->keyID) {
			NewAccont.erase(Iter);
			return temp;
		}
	}
	return NULL;
}
shared_ptr<CAccount> CVmScriptRun::GetAccount(shared_ptr<CAccount>& Account) {
	if (RawAccont.size() == 0)
		return NULL;
	vector<shared_ptr<CAccount> >::iterator Iter;
	for (Iter = RawAccont.begin(); Iter != RawAccont.end(); Iter++) {
		shared_ptr<CAccount> temp = *Iter;
		if (Account.get()->keyID == temp.get()->keyID) {
			return temp;
		}
	}
	return NULL;
}

bool CVmScriptRun::CheckOperate(const vector<CVmOperate> &listoperate) const {
	// judge contract rulue
	uint64_t addmoey, miusmoney;
	for (auto& it : listoperate) {

		if (it.opeatortype == ADD_FREE || it.opeatortype == ADD_SELF_FREEZD || it.opeatortype == ADD_FREEZD) {
			//addmoey += atoi64((char*) it.money);
		}
		if (it.opeatortype == MINUS_FREE || it.opeatortype == MINUS_SELF_FREEZD || it.opeatortype == MINUS_FREEZD) {
			//miusmoney += atoi64((char*) it.money);
		}
		if (addmoey != miusmoney)
			return false;

	}
	return true;
}
vector_unsigned_char& CVmScriptRun::GetAccountID(CVmOperate value) {
	vector_unsigned_char accountid;
	if (value.type == ACCOUNTID) {
		accountid.assign(value.accountid, value.accountid + 6);
	} else if (value.type == KEYID) {
		accountid.assign(value.accountid, value.accountid + 20);
	} else {
		return accountid;
	}
}
shared_ptr<vector<CVmOperate>> CVmScriptRun::GetOperate() const {
	auto tem = make_shared<vector<CVmOperate>>();
	shared_ptr<vector<unsigned char>> retData = pMcu.get()->GetRetData();
	CDataStream Contractstream(*retData.get(), SER_DISK, CLIENT_VERSION);
	vector<CVmOperate> retvmcode;
	;
	Contractstream >> retvmcode;
	return tem;
}

bool CVmScriptRun::OpeatorAccount(const vector<CVmOperate>& listoperate, CAccountViewCache& view) {

	NewAccont.clear();
	for (auto& it : listoperate) {
		CFund fund;
		fund.value = atoi64((char*) it.money);
		fund.nHeight = it.outheight + height;
		//fund.uTxHash = listTx.get()->GetHash();

		auto tem = make_shared<CAccount>();
		vector_unsigned_char accountid = GetAccountID(it);
		if (accountid.size() == 0) {
			return false;
		}

		view.GetAccount(accountid, *tem.get());
		shared_ptr<CAccount> vmAccount = GetAccount(tem);
		if (vmAccount.get() == NULL) {
			RawAccont.push_back(tem);
		}
		shared_ptr<CAccount> vnewAccount = GetNewAccount(tem);
		if (vnewAccount.get() != NULL) {
			vmAccount = vnewAccount;
		}

		if (fund.nFundType == FREEZD_FUND) {
			CFund vFind = vmAccount.get()->FindFund(vmAccount.get()->vFreeze, fund.scriptID);
			fund.nHeight = vFind.nHeight;
		}

		LogPrint("vm", "muls account:%s\r\n", vmAccount.get()->ToString().c_str());
		LogPrint("vm", "fund:%s\r\n", fund.ToString().c_str());
		if (it.opeatortype == ADD_FREE || it.opeatortype == ADD_SELF_FREEZD || it.opeatortype == ADD_FREEZD) {
			vmAccount.get()->AddMoney((OperType)it.opeatortype,fund);
			}
		else if (it.opeatortype == MINUS_FREE || it.opeatortype == MINUS_SELF_FREEZD || it.opeatortype == MINUS_FREEZD) {
			CContractTransaction* tx = static_cast<CContractTransaction*>(listTx.get());
			vmAccount.get()->MinusMoney((OperType)it.opeatortype,height,fund,tx->scriptRegId);
			}
		else
		{
			LogPrint("vm", "fund:vm operte error\r\n");
		}
		// about operate account undo
		uint64_t retValue;
		bool flag = true;//vmAccount.get()->OperateAccount((OperType) it.opeatortype, fund, &retValue);
		LogPrint("vm", "after muls account:%s\r\n", vmAccount.get()->ToString().c_str());
		if (flag) {
			return false;
		}
		NewAccont.push_back(vmAccount);

	}
	return true;
}

vector_unsigned_char& CVmScriptRun::GetScriptID()
{
	CContractTransaction* tx = static_cast<CContractTransaction*>(listTx.get());
	return tx->scriptRegId;
}
int CVmScriptRun::GetComfirHeight()
{
	return height;
}
uint256 CVmScriptRun::GetCurTxHash()
{
	return listTx.get()->GetHash();
}
<commit_msg>function modify Signed-off-by: bess <776536184@qq.com><commit_after>/*
 * ScriptCheck.cpp
 *
 *  Created on: Sep 2, 2014
 *      Author: ranger.shi
 */
#include "VmScriptRun.h"
#include "tx.h"
#include "util.h"
#include <boost/foreach.hpp>
CVmScriptRun::CVmScriptRun() {
	RawAccont.clear();
	NewAccont.clear();
	height = 0;
}
vector<shared_ptr<CAccount> > &CVmScriptRun::GetRawAccont() {
	return RawAccont;
}
vector<shared_ptr<CAccount> > &CVmScriptRun::GetNewAccont() {
	return NewAccont;
}

bool CVmScriptRun::intial(shared_ptr<CBaseTransaction> & Tx, CAccountViewCache& view, int nheight) {

	listTx = Tx;
	height = nheight;
	vector<unsigned char> vScript;

	if (Tx.get()->nTxType != CONTRACT_TX) {
		LogPrint("vm", "%s\r\n", "err param");
		return false;
	}

	CContractTransaction* secure = static_cast<CContractTransaction*>(Tx.get());
	if (pScriptDBTip->GetScript(secure->scriptRegId, vScript)) {
		CDataStream stream(vScript, SER_DISK, CLIENT_VERSION);
		try {
			stream >> vmScript;
		} catch (exception& e) {
			throw runtime_error("CVmScriptRun::intial() Unserialize to vmScript error:" + string(e.what()));
		}
	}

	if (vmScript.IsValid() == false)
		return false;

	for (auto& tx : secure->vAccountRegId) {
		auto tem = make_shared<CAccount>();
		view.GetAccount(tx, *tem.get());
		RawAccont.push_back(tem);
	}

	vector<unsigned char> strContract;
	pMcu = make_shared<CVir8051>(vmScript.Rom, strContract);
	return true;
}

CVmScriptRun::~CVmScriptRun() {

}
tuple<bool, uint64_t, string> CVmScriptRun:: run(shared_ptr<CBaseTransaction>& Tx, CAccountViewCache& view, int nheight,
		uint64_t nBurnFactor) {

	CContractTransaction* tx = static_cast<CContractTransaction*>(Tx.get());
	int maxstep = tx->llFees/nBurnFactor;
	tuple<bool, uint64_t, string> mytuple;
	if (!intial(Tx, view, nheight)) {
		mytuple = std::make_tuple (false, 0, string("VmScript inital Failed\n"));
		return mytuple;
	}
	unsigned int  step = pMcu.get()->run(maxstep,this);
	if (0 == step) {
		mytuple = std::make_tuple (false, 0, string("VmScript run Failed\n"));
		return mytuple;
	}
	shared_ptr<vector<unsigned char>> retData = pMcu.get()->GetRetData();
	CDataStream Contractstream(*retData.get(), SER_DISK, CLIENT_VERSION);
	vector<CVmOperate> retvmcode;
	Contractstream >> retvmcode;

	if (!CheckOperate(retvmcode)) {
		mytuple = std::make_tuple (false, 0, string("VmScript CheckOperate Failed \n"));
		return mytuple;
	}
	if (!OpeatorAccount(retvmcode, view)) {
		mytuple = std::make_tuple (false, 0, string("VmScript OpeatorSecureAccount Failed\n"));
		return mytuple;
	}
	uint64_t spend = step*nBurnFactor;
	mytuple = std::make_tuple (true, spend, string("VmScript Sucess\n"));
	return mytuple;
}

shared_ptr<CAccount> CVmScriptRun::GetNewAccount(shared_ptr<CAccount>& vOldAccount) {
	if (NewAccont.size() == 0)
		return NULL;
	vector<shared_ptr<CAccount> >::iterator Iter;
	for (Iter = NewAccont.begin(); Iter != NewAccont.end(); Iter++) {
		shared_ptr<CAccount> temp = *Iter;
		if (temp.get()->keyID == vOldAccount.get()->keyID) {
			NewAccont.erase(Iter);
			return temp;
		}
	}
	return NULL;
}
shared_ptr<CAccount> CVmScriptRun::GetAccount(shared_ptr<CAccount>& Account) {
	if (RawAccont.size() == 0)
		return NULL;
	vector<shared_ptr<CAccount> >::iterator Iter;
	for (Iter = RawAccont.begin(); Iter != RawAccont.end(); Iter++) {
		shared_ptr<CAccount> temp = *Iter;
		if (Account.get()->keyID == temp.get()->keyID) {
			return temp;
		}
	}
	return NULL;
}

bool CVmScriptRun::CheckOperate(const vector<CVmOperate> &listoperate) const {
	// judge contract rulue
	uint64_t addmoey, miusmoney;
	uint64_t temp = 0;
	for (auto& it : listoperate) {

		if (it.opeatortype == ADD_FREE || it.opeatortype == ADD_SELF_FREEZD || it.opeatortype == ADD_FREEZD) {
			memcpy(&temp,it.money,sizeof(it.money));
			addmoey += temp;
		}
		if (it.opeatortype == MINUS_FREE || it.opeatortype == MINUS_SELF_FREEZD || it.opeatortype == MINUS_FREEZD) {
			memcpy(&temp,it.money,sizeof(it.money));
			miusmoney += temp;
		}
		if (addmoey != miusmoney)
			return false;

	}
	return true;
}
vector_unsigned_char& CVmScriptRun::GetAccountID(CVmOperate value) {
	vector_unsigned_char accountid;
	if (value.type == ACCOUNTID) {
		accountid.assign(value.accountid, value.accountid + 6);
	} else if (value.type == KEYID) {
		accountid.assign(value.accountid, value.accountid + 20);
	} else {
		return accountid;
	}
}
shared_ptr<vector<CVmOperate>> CVmScriptRun::GetOperate() const {
	auto tem = make_shared<vector<CVmOperate>>();
	shared_ptr<vector<unsigned char>> retData = pMcu.get()->GetRetData();
	CDataStream Contractstream(*retData.get(), SER_DISK, CLIENT_VERSION);
	vector<CVmOperate> retvmcode;
	;
	Contractstream >> retvmcode;
	return tem;
}

bool CVmScriptRun::OpeatorAccount(const vector<CVmOperate>& listoperate, CAccountViewCache& view) {

	NewAccont.clear();
	for (auto& it : listoperate) {
		CContractTransaction* tx = static_cast<CContractTransaction*>(listTx.get());
		CFund fund;
		memcpy(&fund.value,it.money,sizeof(it.money));
		fund.nHeight = it.outheight + height;
		fund.scriptID = tx->scriptRegId;

		auto tem = make_shared<CAccount>();
		vector_unsigned_char accountid = GetAccountID(it);
		if (accountid.size() == 0) {
			return false;
		}

		view.GetAccount(accountid, *tem.get());
		shared_ptr<CAccount> vmAccount = GetAccount(tem);
		if (vmAccount.get() == NULL) {
			RawAccont.push_back(tem);
		}
		shared_ptr<CAccount> vnewAccount = GetNewAccount(tem);
		if (vnewAccount.get() != NULL) {
			vmAccount = vnewAccount;
		}

		if (fund.nFundType == FREEZD_FUND) {
			CFund vFind = vmAccount.get()->FindFund(vmAccount.get()->vFreeze, fund.scriptID);
			fund.nHeight = vFind.nHeight;
		}

		LogPrint("vm", "muls account:%s\r\n", vmAccount.get()->ToString().c_str());
		LogPrint("vm", "fund:%s\r\n", fund.ToString().c_str());
		bool ret = vmAccount.get()->OperateAccount((OperType)it.opeatortype,fund,height);

		LogPrint("vm", "after muls account:%s\r\n", vmAccount.get()->ToString().c_str());
		if (ret) {
			return false;
		}
		NewAccont.push_back(vmAccount);

	}
	return true;
}

vector_unsigned_char& CVmScriptRun::GetScriptID()
{
	CContractTransaction* tx = static_cast<CContractTransaction*>(listTx.get());
	return tx->scriptRegId;
}
int CVmScriptRun::GetComfirHeight()
{
	return height;
}
uint256 CVmScriptRun::GetCurTxHash()
{
	return listTx.get()->GetHash();
}
<|endoftext|>


<commit_before><commit_msg>Fix broken separator sizing and positioning.<commit_after><|endoftext|>


<commit_before>#pragma once

#include "acmacs-base/float.hh"
#include "acmacs-base/xlnt.hh"
#include "acmacs-whocc/sheet.hh"

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

namespace acmacs::xlsx::inline v1
{
    namespace xlnt
    {
        class Doc;

        class Sheet : public acmacs::sheet::Sheet
        {
          public:
            Sheet(::xlnt::worksheet&& src) : sheet_{std::move(src)} {}

            std::string name() const override { return sheet_.title(); }
            size_t number_of_rows() const override { return sheet_.highest_row(); }
            size_t number_of_columns() const override { return sheet_.highest_column().index; }

            static inline date::year_month_day make_date(const ::xlnt::datetime& dt, size_t /*row*/, size_t /*col*/)
            {
                // if (dt.hour || dt.minute || dt.second || dt.microsecond)
                //     AD_WARNING("xlnt datetime at {:c}{} contains time: {}", col + 'A', row + 1, dt.to_string());
                return date::year{dt.year} / date::month{static_cast<unsigned>(dt.month)} / dt.day;
            }

            acmacs::sheet::cell_t cell(size_t row, size_t col) const override // row and col are zero based
            {
                const ::xlnt::cell_reference ref{static_cast<::xlnt::column_t::index_t>(col + 1), static_cast<::xlnt::row_t>(row + 1)};
                if (!sheet_.has_cell(ref))
                    return acmacs::sheet::cell::empty{};

                const auto cell = sheet_.cell(ref);
                switch (cell.data_type()) { // ~/AD/build/acmacs-build/build/xlnt/include/xlnt/cell/cell_type.hpp
                    case ::xlnt::cell_type::empty:
                        return acmacs::sheet::cell::empty{};
                    case ::xlnt::cell_type::boolean:
                        return cell.value<bool>();
                    case ::xlnt::cell_type::inline_string:
                    case ::xlnt::cell_type::shared_string:
                    case ::xlnt::cell_type::formula_string:
                        if (const auto val = cell.value<std::string>(); !val.empty())
                            return val;
                        else
                            return acmacs::sheet::cell::empty{};
                    case ::xlnt::cell_type::number:
                        if (cell.is_date())
                            return make_date(cell.value<::xlnt::datetime>(), row, col);
                        else if (const auto vald = cell.value<double>(); !float_equal(vald, std::round(vald)))
                            return vald;
                        else
                            return static_cast<long>(cell.value<long long>());
                    case ::xlnt::cell_type::date:
                        return make_date(cell.value<::xlnt::datetime>(), row, col);
                    case ::xlnt::cell_type::error:
                        return acmacs::sheet::cell::error{};
                }
                return acmacs::sheet::cell::empty{};
            }

            acmacs::sheet::cell_spans_t cell_spans(size_t row, size_t col) const override
            {
                const ::xlnt::cell_reference ref{static_cast<::xlnt::column_t::index_t>(col + 1), static_cast<::xlnt::row_t>(row + 1)};
                if (!sheet_.has_cell(ref))
                    return {};
                const auto cell = sheet_.cell(ref);
                acmacs::sheet::cell_spans_t spans;
                // if (const auto fill = cell.fill(); fill.type() == ::xlnt::fill_type::pattern) {
                //     const auto fill_pattern = fill.pattern_fill();

                //     const auto get_color = [](const auto& col) -> std::string {
                //         if (col.is_set() && col.get().type() == ::xlnt::color_type::rgb) {
                //             const auto rgb = col.get().rgb();
                //             return fmt::format("#{:02x}{:02x}{:02x}", rgb.red(), rgb.green(), rgb.blue());
                //         }
                //         else
                //             return {};
                //     };

                //     const std::string foreground = get_color(fill_pattern.foreground()), background = get_color(fill_pattern.background());
                //     if (!foreground.empty() || !background.empty())
                //         spans.push_back(acmacs::sheet::cell_span_t{0, 1, foreground, background});
                // }

                // size_t first{0};
                // for (const auto& run : cell.value<::xlnt::rich_text>().runs()) {
                //     if (run.second.is_set()) {
                //         std::string color_value;
                //         if (run.second.get().has_color()) {
                //             if (const auto color = run.second.get().color(); color.type() == ::xlnt::color_type::rgb)
                //                 color_value = color.rgb().hex_string();
                //         }
                //         spans.push_back(acmacs::sheet::cell_span_t{first, run.first.size(), color_value});
                //     }
                //     first += run.first.size();
                // }
                return spans;
            }

          private:
            ::xlnt::worksheet sheet_;
        };

        class Doc
        {
          public:
            size_t number_of_sheets() const { return workbook_.sheet_count(); }
            std::shared_ptr<Sheet> sheet(size_t sheet_no) { return std::make_shared<Sheet>(workbook_.sheet_by_index(sheet_no)); }

          protected:
            Doc(std::string_view filename) : workbook_{::xlnt::path{std::string{filename}}} {}

          private:
            ::xlnt::workbook workbook_;
        };

    } // namespace xlnt

} // namespace acmacs::xlsx::inline v1

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>xlsx2html<commit_after>#pragma once

#include "acmacs-base/float.hh"
#include "acmacs-base/xlnt.hh"
#include "acmacs-whocc/sheet.hh"

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

namespace acmacs::xlsx::inline v1
{
    namespace xlnt
    {
        class Doc;

        class Sheet : public acmacs::sheet::Sheet
        {
          public:
            Sheet(::xlnt::worksheet&& src) : sheet_{std::move(src)} {}

            std::string name() const override { return sheet_.title(); }
            size_t number_of_rows() const override { return sheet_.highest_row(); }
            size_t number_of_columns() const override { return sheet_.highest_column().index; }

            static inline date::year_month_day make_date(const ::xlnt::datetime& dt, size_t /*row*/, size_t /*col*/)
            {
                // if (dt.hour || dt.minute || dt.second || dt.microsecond)
                //     AD_WARNING("xlnt datetime at {:c}{} contains time: {}", col + 'A', row + 1, dt.to_string());
                return date::year{dt.year} / date::month{static_cast<unsigned>(dt.month)} / dt.day;
            }

            acmacs::sheet::cell_t cell(size_t row, size_t col) const override // row and col are zero based
            {
                const ::xlnt::cell_reference ref{static_cast<::xlnt::column_t::index_t>(col + 1), static_cast<::xlnt::row_t>(row + 1)};
                if (!sheet_.has_cell(ref))
                    return acmacs::sheet::cell::empty{};

                const auto cell = sheet_.cell(ref);
                switch (cell.data_type()) { // ~/AD/build/acmacs-build/build/xlnt/include/xlnt/cell/cell_type.hpp
                    case ::xlnt::cell_type::empty:
                        return acmacs::sheet::cell::empty{};
                    case ::xlnt::cell_type::boolean:
                        return cell.value<bool>();
                    case ::xlnt::cell_type::inline_string:
                    case ::xlnt::cell_type::shared_string:
                    case ::xlnt::cell_type::formula_string:
                        if (const auto val = cell.value<std::string>(); !val.empty())
                            return val;
                        else
                            return acmacs::sheet::cell::empty{};
                    case ::xlnt::cell_type::number:
                        if (cell.is_date())
                            return make_date(cell.value<::xlnt::datetime>(), row, col);
                        else if (const auto vald = cell.value<double>(); !float_equal(vald, std::round(vald)))
                            return vald;
                        else
                            return static_cast<long>(cell.value<long long>());
                    case ::xlnt::cell_type::date:
                        return make_date(cell.value<::xlnt::datetime>(), row, col);
                    case ::xlnt::cell_type::error:
                        return acmacs::sheet::cell::error{};
                }
                return acmacs::sheet::cell::empty{};
            }

            acmacs::sheet::cell_spans_t cell_spans(size_t row, size_t col) const override
            {
                const ::xlnt::cell_reference ref{static_cast<::xlnt::column_t::index_t>(col + 1), static_cast<::xlnt::row_t>(row + 1)};
                if (!sheet_.has_cell(ref))
                    return {};
                acmacs::sheet::cell_spans_t spans;
                // const auto cell = sheet_.cell(ref);
                // if (const auto fill = cell.fill(); fill.type() == ::xlnt::fill_type::pattern) {
                //     const auto fill_pattern = fill.pattern_fill();

                //     const auto get_color = [](const auto& col) -> std::string {
                //         if (col.is_set() && col.get().type() == ::xlnt::color_type::rgb) {
                //             const auto rgb = col.get().rgb();
                //             return fmt::format("#{:02x}{:02x}{:02x}", rgb.red(), rgb.green(), rgb.blue());
                //         }
                //         else
                //             return {};
                //     };

                //     const std::string foreground = get_color(fill_pattern.foreground()), background = get_color(fill_pattern.background());
                //     if (!foreground.empty() || !background.empty())
                //         spans.push_back(acmacs::sheet::cell_span_t{0, 1, foreground, background});
                // }

                // size_t first{0};
                // for (const auto& run : cell.value<::xlnt::rich_text>().runs()) {
                //     if (run.second.is_set()) {
                //         std::string color_value;
                //         if (run.second.get().has_color()) {
                //             if (const auto color = run.second.get().color(); color.type() == ::xlnt::color_type::rgb)
                //                 color_value = color.rgb().hex_string();
                //         }
                //         spans.push_back(acmacs::sheet::cell_span_t{first, run.first.size(), color_value});
                //     }
                //     first += run.first.size();
                // }
                return spans;
            }

          private:
            ::xlnt::worksheet sheet_;
        };

        class Doc
        {
          public:
            size_t number_of_sheets() const { return workbook_.sheet_count(); }
            std::shared_ptr<Sheet> sheet(size_t sheet_no) { return std::make_shared<Sheet>(workbook_.sheet_by_index(sheet_no)); }

          protected:
            Doc(std::string_view filename) : workbook_{::xlnt::path{std::string{filename}}} {}

          private:
            ::xlnt::workbook workbook_;
        };

    } // namespace xlnt

} // namespace acmacs::xlsx::inline v1

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright (C) 2015 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "service/migration_task.hh"

#include "message/messaging_service.hh"
#include "gms/failure_detector.hh"
#include "db/schema_tables.hh"
#include "frozen_mutation.hh"
#include "migration_manager.hh"

namespace service {

static logging::logger mlogger("migration_task");

future<> migration_task::run_may_throw(distributed<service::storage_proxy>& proxy, const gms::inet_address& endpoint)
{
    if (!gms::get_failure_detector().local().is_alive(endpoint)) {
        mlogger.error("Can't send migration request: node {} is down.", endpoint);
        return make_ready_future<>();
    }
    netw::messaging_service::msg_addr id{endpoint, 0};
    return service::get_local_migration_manager().merge_schema_from(id).handle_exception([](std::exception_ptr e) {
        try {
            std::rethrow_exception(e);
        } catch (const exceptions::configuration_exception& e) {
            mlogger.error("Configuration exception merging remote schema: {}", e.what());
        }
    });
}

}
<commit_msg>migration_manager: downgrade frightening "Can't send migration request" ERROR<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright (C) 2015 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "service/migration_task.hh"

#include "message/messaging_service.hh"
#include "gms/failure_detector.hh"
#include "db/schema_tables.hh"
#include "frozen_mutation.hh"
#include "migration_manager.hh"

namespace service {

static logging::logger mlogger("migration_task");

future<> migration_task::run_may_throw(distributed<service::storage_proxy>& proxy, const gms::inet_address& endpoint)
{
    if (!gms::get_failure_detector().local().is_alive(endpoint)) {
        mlogger.warn("Can't send migration request: node {} is down.", endpoint);
        return make_ready_future<>();
    }
    netw::messaging_service::msg_addr id{endpoint, 0};
    return service::get_local_migration_manager().merge_schema_from(id).handle_exception([](std::exception_ptr e) {
        try {
            std::rethrow_exception(e);
        } catch (const exceptions::configuration_exception& e) {
            mlogger.error("Configuration exception merging remote schema: {}", e.what());
        }
    });
}

}
<|endoftext|>


<commit_before>/*!
*	@file	MinimumWeightTriangulation.cpp
*	@brief	Functions for minimum weight triangulation
*/

#include "MinimumWeightTriangulation.h"

namespace psalm
{

/*!
*	Sets default attributes for the minimum-weight triangulation algorithm:
*	The objective function is set to be a minimum-area function.
*/

MinimumWeightTriangulation::MinimumWeightTriangulation()
{
	objective_function = minimum_area;
}

/*!
*	Applies triangulation algorithm to the input mesh. The function
*	requires the input mesh to consist solely of unconnected points. If
*	this is not the case, the function will abort.
*
*	@param input_mesh Mesh that will be triangulated.
*
*	@return true if the mesh could be triangulated, else false. Errors may
*	occur when the topology of the mesh is already defined.
*/

bool MinimumWeightTriangulation::apply_to(mesh& input_mesh)
{
	if(	input_mesh.num_faces() > 0 ||
		input_mesh.num_edges() > 0)
		return(false);

	size_t n = input_mesh.num_vertices();

	indices = new size_t*[n];		// store minimum indices (private member)
	double** weights = new double*[n];	// store weights of triangulation (only required locally)

	for(size_t i = 0; i < n; i++)
	{
		indices[i] = new size_t[n];
		weights[i] = new double[n];

		// Initialize weights array correctly
		if(i < n-1)
			weights[i][i+1] = 0;
		if(i < n-2)
			weights[i][i+2] = objective_function(	input_mesh.get_vertex(i),
								input_mesh.get_vertex(i+1),
								input_mesh.get_vertex(i+2));
	}

	size_t j = 2;
	while(j++ < n-1)	// this is correct -- the loop is supposed to start
				// with j == 3
	{
		for(size_t i = 0; i < n-j; i++)
		{
			size_t k = i+j;

			// Find minimum
			double min_weight = std::numeric_limits<double>::max();
			size_t min_index = std::numeric_limits<size_t>::max();
			for(size_t m = i+1; m < k; m++)
			{
				double res =	weights[i][m]+
						weights[m][k]+objective_function(	input_mesh.get_vertex(i),
											input_mesh.get_vertex(m),
											input_mesh.get_vertex(k));

				if(res < min_weight)
				{
					min_weight = res;
					min_index = m;
				}
			}

			weights[i][k] = min_weight;
			indices[i][k] = min_index;
		}
	}

	// Now weights[0][n-1] contains the weight of the minimal
	// triangulation. Construct triangulation using the stored indices.
	bool result = construct_triangulation(input_mesh, 0, n-1);

	for(size_t i = 0; i < n; i++)
	{
		delete[] weights[i];
		delete[] indices[i];
	}

	delete[] weights;
	delete[] indices;

	/*
		Mark _all_ vertices as boundary vertices. Upon subdivision, the
		boundary vertices will not be changed and we need to identify
		them when storing the subdivided mesh.
	*/

	for(size_t i = 0; i < input_mesh.num_vertices(); i++)
		input_mesh.get_vertex(i)->set_on_boundary();

	return(result);
}

/*!
*	Using the array of indices that achieve the minimum of the
*	minimum-weight triangulation, this function constructs the actual
*	triangulation of the mesh.
*
*	This function calls itself recursively.
*
*	@param input_mesh Mesh for which the triangles are constructed
*	@param i Smallest index for constructing a triangle
*	@param k Largest index for constructing a triangle
*
*	@return true if the triangulation could be constructed, else false.
*/

bool MinimumWeightTriangulation::construct_triangulation(mesh& input_mesh, size_t i, size_t k)
{
	// abort
	if(i+2 == k)
		input_mesh.add_face(	input_mesh.get_vertex(i),	// TODO: Check errors for mesh::add_face()
					input_mesh.get_vertex(i+1),
					input_mesh.get_vertex(k));

	// use minimum index to branch off
	else
	{
		size_t j = indices[i][k];
		if(j != i+1)
		{
			if(!construct_triangulation(input_mesh, i, j))
				return(false);
		}

		input_mesh.add_face(	input_mesh.get_vertex(i),	// TODO: Check errors for mesh::add_face()
					input_mesh.get_vertex(j),
					input_mesh.get_vertex(k));

		if(j != k-1)
		{
			if(!construct_triangulation(input_mesh, j, k))
				return(false);
		}
	}

	return(true);
}

} // end of namespace "psalm"
<commit_msg>Added check for `MinimumWeightTriangulation`<commit_after>/*!
*	@file	MinimumWeightTriangulation.cpp
*	@brief	Functions for minimum weight triangulation
*/

#include "MinimumWeightTriangulation.h"

namespace psalm
{

/*!
*	Sets default attributes for the minimum-weight triangulation algorithm:
*	The objective function is set to be a minimum-area function.
*/

MinimumWeightTriangulation::MinimumWeightTriangulation()
{
	objective_function = minimum_area;
}

/*!
*	Applies triangulation algorithm to the input mesh. The function
*	requires the input mesh to consist solely of unconnected points. If
*	this is not the case, the function will abort.
*
*	@param input_mesh Mesh that will be triangulated.
*
*	@return true if the mesh could be triangulated, else false. Errors may
*	occur when the topology of the mesh is already defined.
*/

bool MinimumWeightTriangulation::apply_to(mesh& input_mesh)
{
	if(	input_mesh.num_faces() > 0 ||
		input_mesh.num_edges() > 0)
		return(false);

	size_t n = input_mesh.num_vertices();
	if(n < 3)
		return(false);

	indices = new size_t*[n];		// store minimum indices (private member)
	double** weights = new double*[n];	// store weights of triangulation (only required locally)

	for(size_t i = 0; i < n; i++)
	{
		indices[i] = new size_t[n];
		weights[i] = new double[n];

		// Initialize weights array correctly
		if(i < n-1)
			weights[i][i+1] = 0;
		if(i < n-2)
			weights[i][i+2] = objective_function(	input_mesh.get_vertex(i),
								input_mesh.get_vertex(i+1),
								input_mesh.get_vertex(i+2));
	}

	size_t j = 2;
	while(j++ < n-1)	// this is correct -- the loop is supposed to start
				// with j == 3
	{
		for(size_t i = 0; i < n-j; i++)
		{
			size_t k = i+j;

			// Find minimum
			double min_weight = std::numeric_limits<double>::max();
			size_t min_index = std::numeric_limits<size_t>::max();
			for(size_t m = i+1; m < k; m++)
			{
				double res =	weights[i][m]+
						weights[m][k]+objective_function(	input_mesh.get_vertex(i),
											input_mesh.get_vertex(m),
											input_mesh.get_vertex(k));

				if(res < min_weight)
				{
					min_weight = res;
					min_index = m;
				}
			}

			weights[i][k] = min_weight;
			indices[i][k] = min_index;
		}
	}

	// Now weights[0][n-1] contains the weight of the minimal
	// triangulation. Construct triangulation using the stored indices.
	bool result = construct_triangulation(input_mesh, 0, n-1);

	for(size_t i = 0; i < n; i++)
	{
		delete[] weights[i];
		delete[] indices[i];
	}

	delete[] weights;
	delete[] indices;

	/*
		Mark _all_ vertices as boundary vertices. Upon subdivision, the
		boundary vertices will not be changed and we need to identify
		them when storing the subdivided mesh.
	*/

	for(size_t i = 0; i < input_mesh.num_vertices(); i++)
		input_mesh.get_vertex(i)->set_on_boundary();

	return(result);
}

/*!
*	Using the array of indices that achieve the minimum of the
*	minimum-weight triangulation, this function constructs the actual
*	triangulation of the mesh.
*
*	This function calls itself recursively.
*
*	@param input_mesh Mesh for which the triangles are constructed
*	@param i Smallest index for constructing a triangle
*	@param k Largest index for constructing a triangle
*
*	@return true if the triangulation could be constructed, else false.
*/

bool MinimumWeightTriangulation::construct_triangulation(mesh& input_mesh, size_t i, size_t k)
{
	// abort
	if(i+2 == k)
		input_mesh.add_face(	input_mesh.get_vertex(i),	// TODO: Check errors for mesh::add_face()
					input_mesh.get_vertex(i+1),
					input_mesh.get_vertex(k));

	// use minimum index to branch off
	else
	{
		size_t j = indices[i][k];
		if(j != i+1)
		{
			if(!construct_triangulation(input_mesh, i, j))
				return(false);
		}

		input_mesh.add_face(	input_mesh.get_vertex(i),	// TODO: Check errors for mesh::add_face()
					input_mesh.get_vertex(j),
					input_mesh.get_vertex(k));

		if(j != k-1)
		{
			if(!construct_triangulation(input_mesh, j, k))
				return(false);
		}
	}

	return(true);
}

} // end of namespace "psalm"
<|endoftext|>