/* Copyright (c) 1997-2004
   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_SPRINGEMBEDDER_WINDOW_H
#define _POLYMAKE_SPRINGEMBEDDER_WINDOW_H "$Project: polymake $$Id: SpringEmbedderWindow.h,v 1.5 2005/02/21 17:25:43 gawrilow Exp $"

#include <cstdlib>
#include <cmath>
#include <SpringEmbedder.h>
#include <random_generators.h>
#include <Matrix.h>
#include <Map.h>

namespace polymake { namespace graph {

class SpringEmbedderWindow {
   SpringEmbedder SE;

protected:  
   typedef Map<std::string, double> param_map;
   typedef Map<std::string, bool > iparam_map;
   param_map params;
   iparam_map iparams;
   param_map defaults;
   int max_iter;
   long seed;
   Matrix<double> Points;

public:
   SpringEmbedderWindow(const SpringEmbedder& SE_arg, int maxiter_arg, long seed_arg)
      : SE(SE_arg), max_iter(maxiter_arg), seed(seed_arg)
   {
      params["viscosity"] = SE.get_viscosity();
      iparams["viscosity"]=false;
      params["inertion"] = SE.get_inertion();
      iparams["inertion"]=false;
      params["repulsion"] = SE.get_repulsion();
      iparams["repulsion"]=true;
      if(SE.has_obj_function()) {
	 params["orientation"] = SE.get_obj_factor();
	 iparams["orientation"]=true;
      }
      params["max_iter"] = maxiter_arg;
      params["delay"] = 50;
      params["step"] = 0;
      params["continue"] = 0;
      defaults = params;
      UniformRNG< Vector<double> > random_points(3, seed);
      SE.start_points(random_points.begin());
   }

   const Matrix<double>& get_points() const { return Points; }

   const param_map& get_params() const { return params; }
   const iparam_map& get_iparams() const { return iparams; }

   double get_param(const std::string& key) { return params[key]; }

   void set_param(const std::string& key, double value) { params[key] = value; }

   bool get_iparam(const std::string& key) { return iparams[key]; }

   void set_iparam(const std::string& key, bool value) { iparams[key] = value; }

   void set_facet(const Set<int>& vertices)
   {
      SE.set_fixed_vertices(vertices);
   }

   void reset()
   {
      UniformRNG< Vector<double> > random_points(3, seed);
      SE.start_points(random_points.begin());
      params["viscosity"] = defaults["viscosity"];
      params["inertion"] = defaults["inertion"];
      params["repulsion"] = defaults["repulsion"];
      params["orientation"] = defaults["orientation"];
      params["step"] = 0;
      params["continue"] = 0;
   }

   void adjust_params()
   {
      SE.set_viscosity(params["viscosity"]);
      SE.set_inertion(params["inertion"]);
      SE.set_repulsion(params["repulsion"]);
      SE.set_objective_factor(params["orientation"]);
   }

   template <typename Iterator>
   void start_points(Iterator src)
   {
      SE.start_points(src);
   }

   bool compute_points(int max_iter_arg = 10000)
   {
      bool equilibrium = SE.calculate(max_iter_arg);
      Points = SE.get();
      return equilibrium;
   }
};

} }

#endif // _POLYMAKE_SPRINGEMBEDDER_WINDOW_H

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