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

package Geomview::Viewer;

# path to the main geomview executable
custom $geomview;

CONFIGURE {
   $geomview=find_via_path("geomview")
   or die "geomview main program not found\n";
}

# Category: Visualization
# Use @see external.geomview - an alternative tool for the visualization of 3- or 4-dimensional
# geometrical objects.
label geomview

###########################################################################################
#
#  Drawing methods for graphical primitives defined in this module
#

sub vertex_colors {
   my ($P, $n_vertices, $key)=@_;
   $key ||= "VertexColor";
   my @color;
   if (defined (my $color=$P->$key)) {
      if (is_code($color)) {
	 $n_vertices ||= scalar @{$P->Vertices};
	 return ( pointColors => [ map { RGB2float( (@color=Visual::parse_color($color->($_)))
						    ? @color[2..4] : $Visual::Color::vertices ) } 0..($n_vertices-1) ] );
      } elsif (@color=Visual::parse_color($color)) {
	 return ( pointColors => RGB2float(@color[2..4]) );
      }
   }
   return ();
}

sub appearance {
   my ($P,$back_visible)=@_;
   my $get_style=$P->FacetStyle;
   if (defined($get_style) && !is_code($get_style)) {
      if ($get_style =~ $Visual::hidden_re) {
	return ( appearance => "-face edge ".($back_visible?" -backcull":"") );
      } elsif ($get_style =~ $Visual::transparency_re) {
	return ( appearance => "face transparent -edge material { alpha $1 }" );
      }
      undef $get_style;
   }
}

sub facet_colors {
   my ($P, $n_facets)=@_;
   my $get_style=$P->FacetStyle;
   if (defined (my $get_color=$P->FacetColor)) {
      $n_facets ||= scalar @{$P->Facets};
      my @color;
      if (!is_code($get_color)) {
	 @color=Visual::parse_color($get_color);
	 undef $get_color;
      }
      my $default_color=RGB2float(@color ? @color[2..4] : $Visual::Color::facets);
      return ( facetColors => [ map {
#	                           $get_style && $get_style->($_) =~ $Visual::hidden_re
#				   ? "0 0 0 0" :
				   $get_color && (@color=Visual::parse_color($get_color->($_)))
				   ? RGB2float(@color[2..4]) : $default_color
                                } 0..($n_facets-1) ]
	     );
   }
   return ();
}

global_method geomview.geometry: draw(Visual::PointSet, @) {
   my ($self, $P)=@_;
   my $geom=new Geomview::OFF( name => $P->Name,
			       dim => $P->Dim,
			       points => $P->Points,
			       facets => [ ],
			       vertex_colors($P),
			     );
   $self->append($geom);
}

global_method geomview.geometry: draw(Visual::Polygon, @) {
   my ($self, $P)=@_;
   my $face= $P->Facet
             ? [ $P->Facet =~ /\d+/g ]
	     : [ 0..$#{$P->Vertices} ];

   my @params=vertex_colors($P);
   if (defined (my $style=$P->FacetStyle)) {
      if ($style =~ $Visual::hidden_re) {
	 @params=( appearance => "-face +edge" );
      }
   }
   if (!@params) {
      @params=( appearance => "-backcull" );
      if (defined (my $color=(Visual::parse_color($P->FacetColor))[1])) {
	 push @params, facetColors => $color;
      }
   }

   my $geom=new Geomview::OFF( name => $P->Name,
			       points => $P->Vertices,
			       dim => $P->Dim,
			       facets => [ $face ],
			       @params,
			     );
   $self->append($geom);
}

global_method geomview.geometry: draw(Visual::Polygons, @) {
   my ($self, $P)=@_;
   my $geom=new Geomview::OFF( name => $P->Name,
			       points => $P->Vertices,
			       dim => $P->Dim,
			       facets => [ map { [ $_->Facet =~ /\d+/g ] } @{$P->Polygons} ],
			       facet_colors($P, scalar(@{$P->Polygons}), 1),
			     );
   $self->append($geom);
}

###########################################################################################
#
#  Implementation of the Viewer interface
#
package Geomview::Viewer;

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

sub new {
   my $self=&_new;
   $self->graphics=new Geomview::File($self->tempfile.".gcl");
   $self;
}

sub command {
   my $self=shift;
   "$geomview " . $self->graphics->workfile;
}

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

sub append {
   my $self=shift;
   $self->graphics->geom->[-1]->append(@_);
}

###########################################################################################
#
#  Writes to a gcl file without starting a GUI
#

package Geomview::File::Writer;
import Visual::FileWriter(suffix => ".gcl", multiple => 1);

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

package default;

# Category: Visualization
# Call @see external.geomview with the given visual object.
# args: VisualObject, ...
# option: File => "filename" | "AUTO"
#	  Store the objects in a @c gcl (geomview control language) file instead of starting the interactive GUI.
#	  The geometric data in @c OFF format is embedded in the Lisp-style commands, but can be easily extracted
#	  using any text editor, if needed.
#
#	  The @c .gcl 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 geomview(Visual::Object+, { File => undef }) {
   visualize_explicit(@_, "Geomview");
}


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