#  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.
#-----------------------------------------------------------------------------
#  $Project: polymake $$Id: visual.rules,v 1.23 2004/11/17 16:11:02 witte Exp $

package Visual::Color;

# special TOPAZ blue for an distinguished subcomplex
custom $sub="147 178 255";

# GRAPH in mixed_graph : yellow
custom $primal_gr="255 255 0";

# DUAL_GRAPH in mixed_graph: blue
custom $dual_gr="0 0 255";

# MIXED_GRAPH: black
custom $mixed_gr="0 0 0";

package default;

custom %mixed_graph_params=(
# edge_weight => 1	# increases the ideal length of the mixed edges
);

object SimplicialComplex;

# category: Visualization
# The nodes of the mixed graph are the nodes of the primal @see GRAPH and
# the @see DUAL_GRAPH. Additional to the primal and dual edges, there is
# an edge between a primal and a dual node iff the primal node represents
# a vertex of the corresponding facet of the dual node.

property MIXED_GRAPH
$type="graph";
$temporary=1;


MIXED_GRAPH : FACETS, GRAPH, DUAL_GRAPH, DIM
   client("t_mixed_graph", $this ,map { ("-$_", $mixed_graph_params{$_}) } keys %mixed_graph_params);


sub append_facets(\@$$$$$) {
   my ($elems, $facets, $coord, $vertex_labels, $face_color, $decor) = @_;

   foreach (@$facets) {
      my @face = /\d+/g;
      my @params=( Name => "@face",
		   Vertices => subset($coord, @face),
		   VertexLabels => $vertex_labels ? subset($vertex_labels, @face) : \@face,
		   FacetColor => $face_color,
		 );

      if ($#face >= 2) {
	 my @twofaces = all_subsets_of_k(3,0..$#face);
	 push @$elems, new Visual::Polygons( @params, $decor,
					     (map { new Visual::Polygon( Facet => "{@$_}" ) } @twofaces),
					   );

      } elsif ($#face == 1) {
	 #it's only an edge
	 push @$elems, new Visual::Polygon( @params, $decor );
      }
   }
}


# category: Visualization
# Visualizes the complex.
#
# If @see G_DIM < 4, the @see GRAPH and the faces of dimension < 3
# are visualized using the @see GEOMETRIC_REALIZATION.
#
# Otherwise, the spring embedder and the @see MIXED_GRAPH are used to
# produce coordinates for the visualization.
#
# If @see external.JavaView is used to visualize the complex, all faces of
# one facet build a geometry in the jvx-file, so you may use
# <i>Method -> Effect -> Explode Group of Geometries</i> in the
# @see external.JavaView menu.
#
# option: graph_only => boolean
#         if @c true, use the @see GRAPH for the spring embedder
# option: subcomplex => 'PropertyName'
#         draw the faces of the given subcomplex in a different color

user_method VISUAL(%Visual::Graph::decorations, { graph_only => 0, subcomplex => undef }) {
   my ($this, $decor, $options)=@_;

   my $coord=do {
      if ( $options->{graph_only} ) {
	 spring_embedding_3d($this, "GRAPH");
      } elsif ($this->exists("GEOMETRIC_REALIZATION") &&
	       $this->G_DIM<=3) {
	 [ convert_to_float($this->GEOMETRIC_REALIZATION) ]
      } else {
	 slice(spring_embedding_3d($this, "MIXED_GRAPH", "read-edge-weights", undef), 0, $this->N_VERTICES-1);
      }
   };

   my $labels=$this->lookup("VERTEX_LABELS");
   $labels &&= split_labels($labels);

   my @elems;
   append_facets(@elems, $this->FACETS, $coord, $labels, $Visual::Color::facets, $decor);

   push @elems, new Visual::Graph( Name => 'GRAPH of '.$this->name,
				   Graph => $this->GRAPH,
				   Coord => $coord,
				   NodeLabels => $labels,
				   NodeColor => $Visual::Color::graph,
				   EdgeColor => $Visual::Color::graph,
				   $decor
				 );

   if (defined $options->{subcomplex}) {
      append_facets(@elems, $this->give($options->{subcomplex}), $coord, $labels, $Visual::Color::sub, $decor);
   }
   visualize($this->name, @elems);
}


# category: Visualization
# Uses the spring embedder to visualize the @see GRAPH.
user_method VISUAL_GRAPH(%Visual::Graph::decorations) {
   my ($this, $decor)=@_;
   visualize( new Visual::Graph(
      Name => 'GRAPH of '.$this->name,
      Graph => $this->GRAPH,
      Coord => spring_embedding_3d($this, "GRAPH"),
      NodeLabels => $this->lookup("VERTEX_LABELS"),
      NodeColor => $Visual::Color::graph,
      EdgeColor => $Visual::Color::graph,
      $decor
   ));
}

# category: Visualization
# Uses the spring embedder to visualize the @see DUAL_GRAPH.
user_method VISUAL_DUAL_GRAPH(%Visual::Graph::decorations) {
   my ($this, $decor)=@_;
   visualize( new Visual::Graph(
      Name => 'DUAL_GRAPH of '.$this->name,
      Graph => $this->DUAL_GRAPH,
      Coord => spring_embedding_3d($this, "DUAL_GRAPH"),
      NodeColor => $Visual::Color::graph,
      EdgeColor => $Visual::Color::graph,
      $decor
   ));
}

# category: Visualization
# Uses the spring embedder to visualize the @see MIXED_GRAPH.
user_method VISUAL_MIXED_GRAPH(%Visual::Graph::decorations) {
   my ($this, $decor)=@_;
   my $coord=spring_embedding_3d($this, "MIXED_GRAPH", "read-edge-weights", undef);
   visualize( new Visual::Graph( Name => 'GRAPH of '.$this->name,
				 Graph => $this->GRAPH,
				 Coord => slice($coord,0,$this->N_VERTICES-1),
				 NodeLabels => $this->lookup("VERTEX_LABELS"),
				 NodeColor => $Visual::Color::primal_gr,
				 EdgeColor => $Visual::Color::primal_gr,
			       ),
	      new Visual::Graph( Name => 'DUAL_GRAPH of '.$this->name,
				 Graph => $this->DUAL_GRAPH,
				 Coord => slice($coord, $this->N_VERTICES, $this->N_VERTICES+$this->N_FACETS-1),
				 NodeColor => $Visual::Color::dual_gr,
				 EdgeColor => $Visual::Color::dual_gr,
			       ),
	      new Visual::Graph( Name => 'MIXED_GRAPH of '.$this->name,
				 Graph => $this->MIXED_GRAPH,
				 Coord => $coord,
				 NodeColor => $Visual::Color::mixed_gr,
				 EdgeColor => $Visual::Color::mixed_gr,
				 NodeStyle => "thickness 1",
				 EdgeStyle => "thickness 1",
			       )
	   );
}


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