/* Copyright (c) 1997-2006
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
   http://www.math.tu-berlin.de/polymake,  mailto:polymake@math.tu-berlin.de

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

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

#ifndef _POLYMAKE_GRAPH_SPRING_EMBEDDER_BASE_H
#define _POLYMAKE_GRAPH_SPRING_EMBEDDER_BASE_H "$Project: polymake $$Id: SpringEmbedderBase.h 7487 2006-12-06 15:16:09Z gawrilow $"

#include <Vector.h>
#include <Matrix.h>
#include <Graph.h>
#include <cstdlib>
#include <argv_options.h>

namespace polymake { namespace graph {

template <int dim>
struct se_node_attr {
   typedef FixedVector<double,dim> vector3;
   vector3 x, v;		// current position and velocity

   template <typename Output> friend
   Output& operator<< (GenericOutput<Output>& os, const se_node_attr& a) { return os.top() << a.x; }
};

template <typename Top, typename Traits>
class SpringEmbedderBase : public Traits, public pm::Generic<Top> {
public:
   typedef Traits traits_type;
   typedef typename Traits::node_attr::vector3 vector3;
   typename Traits::graph_type G;

   enum { opt_viscosity, opt_inertion, opt_eps, opt_next };

protected:
   double viscosity, inertion, epsilon, epsilon_2;
   bool gravity;
   vector3 barycenter;

   void init_params(const argv_option *options);
public:
   SpringEmbedderBase(const argv_option *options)
   {
      init_params(options);
      gravity=true;
   }

   /** do the hard job
       @retval true if converged after less than max_iterations
   */
   bool calculate(int max_iterations);

   void set_viscosity(double x) { viscosity=x; }
   void set_inertion(double x) { inertion=x; }
   void set_eps(double eps) { epsilon=eps; epsilon_2 = eps*eps; }

   const double get_viscosity() const { return viscosity; }
   const double get_inertion() const { return inertion; }

   // get the node coordinates in R^d
   Matrix<double> get() const
   {
      Matrix<double> M(G.nodes(), Traits::dim);
      Rows< Matrix<double> >::iterator m_i=rows(M).begin();
      for (typename Entire< Nodes<typename Traits::graph_type> >::const_iterator n=entire(nodes(G));  !n.at_end();  ++n, ++m_i)
	 *m_i = n->x;
      return M;
   }
};
   
} }

#include <SpringEmbedderBase.tcc>

#endif // _POLYMAKE_GRAPH_SPRING_EMBEDDER_BASE_H

// Local Variables:
// mode:C++
// c-basic-offset:3
// End:

