/* Copyright (c) 1997-2010
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Darmstadt, Germany)
   http://www.polymake.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.
--------------------------------------------------------------------------------
   $Project: polymake $$Id: bounding_box.cc 9991 2010-12-12 23:36:28Z gawrilow $
*/

#include "polymake/client.h"
#include "polymake/Rational.h"
#include "polymake/Vector.h"
#include "polymake/Matrix.h"
#include "polymake/ListMatrix.h"

namespace polymake { namespace polytope {

Matrix<Rational>
bounding_box(const Matrix<Rational>& V, const Rational& surplus_k, const bool voronoi)
{
   if (surplus_k<0) throw std::runtime_error("bounding_box: surplus value must be non-negative");
   
   const int d=V.cols();
   Vector<Rational> min_vector(d), max_vector(d);
   int i=V.rows()-1;
   while (i>=0 && !V(i,0)) --i;
   if (i<0) throw std::runtime_error("bounding_box: no bounded vertices for box.");

   min_vector=max_vector=V[i].slice(0,d);
   for (--i ; i>=0; --i)
      if (V(i,0))
         for (int j=1; j<d; ++j)
            assign_min_max(min_vector[j], max_vector[j], V(i,j));

   Vector<Rational> surplus=surplus_k*(max_vector-min_vector);
   // the following is useful for visualization if we do not have enough vertices in the Voronoi diagram
   if (voronoi) 
      for (int j=1; j<d; ++j)
         if (surplus[j]==0) surplus[j]=1;
   
   max_vector+=surplus;
   min_vector-=surplus;

   ListMatrix< Vector<Rational> > af(0,d);
   for (int j=1; j<d; ++j) {
      af /= ( max_vector[j] | unit_vector<Rational>(d-1,j-1,-1));
      af /= (-min_vector[j] | unit_vector<Rational>(d-1,j-1));
   }

   return af;
}

UserFunction4perl("# @category Visualization"
                  "# Introduce artificial boundary facets (which are always vertical,"
                  "# i.e., the last coordinate is zero) to allow for bounded images of "
                  "# unbounded polyhedra (e.g. Voronoi polyhedra)."
                  "# If the //voronoi// flag is set, the last direction is left unbounded."
                  "# @param Matrix V vertices that should be in the box"
                  "# @param Rational surplus_k size of the bounding box relative to the box spanned by //V//"
                  "# @param Bool voronoi useful for visualizations of Voronoi diagrams that do not have enough vertices"
                  "#  default value is 0."
                  "# @return Matrix",
                  &bounding_box, "bounding_box(Matrix<Rational> $; $=0)");

} } 

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