/* 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.
*/

#ident "$Project: polymake $$Id: bounding_box.cc,v 1.2 2004/06/22 16:23:10 gawrilow Exp $"

#include <Rational.h>
#include <Poly.h>
#include <Vector.h>
#include <Matrix.h>
#include <ListMatrix.h>

namespace polymake { namespace polytope {

void bounding_box(Poly& p, const char* vertices_section, const char* bounding_box_section, const int bnd_percent)
{
   const Matrix<Rational> V=p.give(vertices_section);
   const int d=V.cols();
   Vector<Rational> min_vector(d-1), max_vector(d-1);
   int i=V.rows()-1;
   while (i>=0 && V(i,0)==0) --i;
   if (i<0) return;

   min_vector=max_vector=V[i].slice(0,d-1);
   for (--i ; i>=0; --i)
      if (V(i,0)!=0)
	 for (int j=1; j<d-1; ++j) {
	    const Rational& x=V(i,j);
	    if (x>max_vector[j])
	       max_vector[j]=x;
	    else if (x<min_vector[j])
	       min_vector[j]=x;
	 }

   Vector<Rational> surplus=Rational(bnd_percent,100)*(max_vector-min_vector);
   // the following is useful if we do not have enough vertices in the Voronoi diagram
   for (int j=1; j<d-1; ++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-1; ++j) {
      af /= ( max_vector[j] | unit_vector<Rational>(d-1,j-1,-1));
      af /= (-min_vector[j] | unit_vector<Rational>(d-1,j-1));
   }
   p.take(bounding_box_section) << af;
}

} } 

using namespace polymake;

/** @file bounding_box
 *
 *  Introduce artificial boundary facets (which are always vertical, i.e., last coordinate is zero) to allow
 *  for bounded images of unbounded polyhedra (e.g., Voroni polyhedra).  <bnd_percent> defaults to 10.
 *
 *  @synopsis bounding_box <file> <vertices_section> <bounding_box_section> [<bnd_percent>]
 *
 *  @reading <vertices_section>
 *  @writing <bounding_box_section> 
 */

int main(int argc, char *argv[])
{
   if (argc<4 || argc>5) {
      cerr << "usage: " << argv[0] << " <file> <vertices_section> <bounding_box_section> [<bnd_percent>]" << endl;
      return 1;
   }
   try {
      Poly p(argv[1], ios::in | ios::out);
      const int bnd_percent=(argc>4)? atoi(argv[4]) : 10;
      polytope::bounding_box(p,argv[2],argv[3],bnd_percent);
   } catch (const std::exception& e) {
      cerr << e.what() << endl;
      return 1;
   }
   return 0;
}
