#  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.
#-----------------------------------------------------------------------------
#  $Project: polymake $$Id: povray.rules 7161 2006-03-07 17:50:53Z gawrilow $


package Povray;

# a povray renderer, e.g. povray
custom $viewer;

CONFIGURE {
  $viewer=find_via_path( povray )
  or die "No known povray rendering program found,\n",
         "please specify your favorite viewer in the customization file.\n";
}

# options for povray rendering
custom $cmd_options = "+D +A0.5";

# width of picture
custom $width = 400;

# height of picture
custom $height = 300;

# length of arrow head
custom $headLength = 0.3;

# relative width of arrow head
custom $headWidth = 2;

# thickness of the points
custom $points_thickness = 4.0;

# thickness of the lines/tubes
custom $lines_thickness = 2.0;

# Category: Visualization
# Use @see external.POVRAY for drawing.
label povray

################################################################################
#
#  Implementing the Viewer interface
#
package Povray::Viewer;

use Povray;
use BackgroundViewer;
use Struct [ '@ISA' => 'Poly::SimpleViewer' ];

sub new_drawing {
   my ($self, $title)=@_;
   $self->new_instance;
   $self->graphics=new Povray::File($self->tempfile.".pov", $title);
   $self;
}

sub command {
   my $self=shift;
   my $outputfile = $self->graphics->title;
   $outputfile =~ s|[ /.]|_|g;
   if (-e "${outputfile}.tga") {
      my $i = 1;
      ++$i while (-e "${outputfile}_${i}.tga");
      $outputfile .= "_${i}.tga";
   } else {
      $outputfile .= ".tga";
   }
   "$viewer +P -V $cmd_options +W$width +H$height +O$outputfile " . $self->graphics->workfile .
     "; echo CREATED $outputfile";
}

sub append {
   shift->graphics->append(@_);
}

using namespaces 'Visual::Utilities';

global_method povray.geometry: draw(Visual::Polygon, @) {
   my ($self, $P)=@_;
   my $face=$P->Facet;
   if ($face) {
      $face =~ s/\{\s*(.*)\s*\}/$1/;
   } else {
      $face=join(" ", 0..$#{$P->Vertices});
   }
   my $color=(parse_color($P->FacetColor))[1];

   my @params = ( name => $P->Name,
		  points => $P->Vertices,
		  pointSet_dim => $P->Dim,
		  vertex_colors($P), 
		  vertex_thicknesses($P),
		  edges($P),
		  visible($P),
		  bounding_box($P,$P->Vertices)
		);

   if (@{$P->Vertices} >= 3) {
      if (defined $color) {
	 push @params, faces_color => $color;
      }
      $self->append(new Povray::solid(@params,
				      faces => [ $face ],
				      faceSet_backface_flag => "show",
				      facet_style($P)));
   } else {
      if (defined $color) {
	 push @params, lines_color => $color;
      }
      $self->append(new Povray::wire(@params,
				     lines => [ $face ]));
   }
}

global_method povray.geometry: draw(Visual::Polygons, @) {
   my ($self, $P)=@_;
   my @params = ( name => $P->Name,
		  points => $P->Vertices,
		  pointSet_dim => $P->Dim,
		  faces => [ map { $_->Facet =~ /\{(.*)\}/ ? $1 : $_->Facet } @{$P->Polygons} ],
		  faceSet_backface_flag => "show",
		  vertex_colors($P), 
		  vertex_thicknesses($P),
		  facet_colors($P, scalar @{$P->Polygons}, "FacetColor"), 
		  facet_style($P),
		  edges($P),
		  visible($P),
		  bounding_box($P,$P->Vertices)
		);
   $self->append(new Povray::solid(@params));
}

global_method povray.geometry: draw(Visual::PointSet, @) {
   my ($self, $P)=@_;
   my @params = ( name => $P->Name,
		  points => $P->Points,
		  pointSet_dim => $P->Dim,
		  vertex_colors($P),
		  vertex_thicknesses($P),
		  visible($P),
		  bounding_box($P,$P->Points)
		);
   $self->append(new Povray::geometry(@params));
}

sub bounding_box {
   my ($P, $vertices) = @_;
   my @ll = split(" ",$vertices->[0]);
   my @ur = split(" ",$vertices->[0]);
   foreach (@$vertices) {
      my @vertex = split(" ",$_);
      for my $i (0..$#vertex) {
	 assign_min($ll[$i], $vertex[$i]);
	 assign_max($ur[$i], $vertex[$i]);
      }
   }
   ("min_extent", join(" ",@ll), "max_extent", join(" ",@ur));
}

###########################################################################################
#
#  Writes to a POV file without rendering
#

package Povray::File::Writer;
import Visual::FileWriter(suffix => ".pov");

sub new_drawing {
   my ($self, $title)=@_;
   $self->title=$title;
   $self;
}

###########################################################################################

package default;

# Category: Visualization
# Call @see external.POVRAY with the given visual object.
# args: VisualObject, ...
# option: File => "filename" | "AUTO"
#	  Only store the object in a @c .pov file, don't start the renderer.
#
#	  The @c .pov suffix is automatically added to the file name.
#
#	  Specify @a AUTO if you want the filename be automatically derived from the drawing title.
#
#         You can also use any expression allowed for the perl @c open function,
#         like "-" for terminal output, "&HANDLE" for an already opened file handle,
#         or "| program" for a pipe.

user_function povray(Visual::Object+, { File => undef }) {
   visualize_explicit(@_, "Povray");
}


# Local Variables:
# mode: perl
# c-basic-offset:3
# End:


