# Copyright (c) 1997-2007 # 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 7578 2007-01-21 22:48:26Z gawrilow $ package Visual::Surface; use Struct( [ '@ISA' => 'Visual::PointSet' ], '$Surface', [ '@Facets' => 'check_points(#%)', default => 'croak("Facets missing")' ], '@FacetNeighbors', [ '$FacetLabels' => 'unify_labels(#%)' ], [ '$FacetColor' => 'unify_decor(#%)', merge => '$this->merge_decor(#%)', default => '$Visual::Color::facets' ], [ '$FacetStyle' => 'unify_decor(#%)', merge => '$this->merge_decor(#%)' ], [ '$EdgeColor' => '$Visual::Color::edges' ], '$EdgeStyle', [ '$Closed' => 'undef' ], ); sub new { my $self=&Visual::PointSet::new; $self; } declare %decorations=( %Visual::Polygon::decorations, FacetLabels => enum('hidden') ); # color of faces custom $face_color = "200 200 0"; # color of vertices custom $vertex_color = "200 0 0"; # thickness of arrows in morse matching custom $morse_matching_arrow_size = 1; # color of critical faces of morse matching custom $critical_face_color = "100 0 255"; # size of critical vertices custom $critical_vertex_size = 5; #size of critical edges custom $critical_edge_size = 4; object Surface; # category: Visualization # Visualize the surface as given in @see GEOMETRIC_REALIZATION. # return: Visual::Surface user_method VISUAL(%Visual::Surface::decorations) { my ($this, $decor)=@_; visualize( new Visual::Surface( Surface => $this, Name => $this->name, Vertices => [ convert_to_float($this->GEOMETRIC_REALIZATION) ] , VertexLabels => $this->lookup("VERTEX_LABELS"), Facets => $this->FACETS_CYCLIC, FacetColor => $Visual::Surface::face_color, VertexColor=> $Visual::Surface::vertex_color, $decor )); } package Visual::Surface; # Add the @see Surface.MORSE_MATCHING to the visualization of the Surface. user_method MORSE_MATCHING(%Visual::Surface::decorations) { my ($this, $decor)=@_; my $surface = $this->Surface; my @hd = @{$surface->MORSE_MATCHING}; my @vertices = convert_to_float($surface->GEOMETRIC_REALIZATION); my $dim = 0; my @dims = split(/\s+/,$hd[0]); shift @dims; shift @hd; my @graph; my $i = 0; my %arrow_colors; my @colors = ("200 0 0","100 0 255","0 0 255"); my @barycenters; foreach my $line (@hd) { ++$dim if($i+1 >= $dims[$dim]); chomp $line; my ($face, $edges) = ($line =~ m/^FacetStyle ||= "transparency 0.5"; my $mmatching = new Visual::Graph( Name => "MORSE_MATCHING of " . $surface->name, Graph => \@graph, Coord => \@barycenters, Directed => 1, NodeStyle => "hidden", EdgeColor => \%arrow_colors, EdgeStyle => "thickness $Visual::Surface::morse_matching_arrow_size", $decor ); compose($this,$mmatching); } # Add faces with optional different graphical attributes # args: "PROPERTY_NAME" or [ Faces ] user_method FACES($ %Visual::Polygon::decorations) { my ($self, $faces, $facet_decor)=@_; if (!ref($faces)) { $faces=$self->Surface->give($faces); } my (%edge_decor, %point_decor); if (!exists $facet_decor->{FacetColor} && !exists $facet_decor->{FacetStyle}) { $facet_decor->{FacetColor}=$Visual::Surface::critical_face_color; } $edge_decor{EdgeColor}=delete $facet_decor->{EdgeColor} || $Visual::Surface::critical_face_color; $edge_decor{EdgeStyle}=delete $facet_decor->{EdgeStyle} || "thickness 6"; $point_decor{VertexColor}=delete $facet_decor->{VertexColor} || $Visual::Surface::critical_face_color; $point_decor{VertexStyle}=delete $facet_decor->{VertexStyle} || "thickness 7"; $edge_decor{VertexStyle}="hidden"; $facet_decor->{EdgeStyle}="hidden"; $facet_decor->{VertexStyle}="hidden"; my $labels=$self->Surface->lookup("VERTEX_LABELS"); compose($self, vis_faces($faces, $self->Surface, $labels, $facet_decor, \%edge_decor, \%point_decor)); } sub vis_faces($$$$$$) { my ($facets, $surface, $vertex_labels, $face_decor, $edge_decor, $point_decor)=@_; my $coord = $surface->GEOMETRIC_REALIZATION; map { my @face = /\d+/g; my @params=( Name => $vertex_labels ? join(" ", @{subset($vertex_labels, @face)}) : "@face", Vertices => subset($coord, @face), VertexLabels => $vertex_labels ? subset($vertex_labels, @face) : \@face, ); if ($#face >= 2) { my $i = 0; while( !(${$surface->FACETS}[$i] eq "$_") ) { ++$i; } my $cyclic_facet = ${$surface->FACETS_CYCLIC}[$i]; my $i = 0; my %face_map; map { $face_map{$_} = $i++ } @face; $cyclic_facet = join(" ",map { $face_map{$_} } $cyclic_facet =~ m/\d+/g); new Visual::Polygon( @params, $face_decor, Facet => $cyclic_facet ); } elsif ($#face == 1) { #it's only an edge new Visual::Graph( Graph => [ "{1}", "{0}" ], @params, $edge_decor ); } else { #it's a singular point new Visual::PointSet( @params, $point_decor ); } } @$facets; } sub barycenter(@) { no integer; my @vertices = @_; my @barycenter; foreach my $vertex (@vertices) { my @vertex = split(/\s+/,$vertex); for( my $j = 0; $j <= $#vertex; ++$j) { $barycenter[$j] += $vertex[$j]; } } map { $_ /= (scalar @vertices) } @barycenter; return join(" ",@barycenter); } object Surface; # category: Visualization # Visualize the @see HASSE_DIAGRAM of a polyhedron as a multi-layer graph. # option: seed => random seed value for the node placement # return: Visual::SurfaceLattice user_method VISUAL_FACE_LATTICE(%Visual::Lattice::decorations, { seed => undef }) { my ($this, $decor, $seed)=@_; my ($dims, @graph)=@{$this->HASSE_DIAGRAM}; $graph[0] =~ s/^\s* "Face lattice of ".$this->name, Surface => $this, Graph => \@graph, top_node => $top_node, Directed => 1, ArrowStyle => 0, NodeLabels => \@labels, NodeColor => { $top_node => "0 0 0" }, NodeStyle => sub { $_[0]==$top_node && "hidden" }, EdgeStyle => sub { ($_[0]->incident_nodes)[1]==$top_node && "hidden" }, Coord => hd_embedding($this, "HASSE_DIAGRAM", %$seed), $decor )); } package Visual::SurfaceLattice; use Struct( [ '@ISA' => 'Visual::Lattice' ], '$Surface' ); # Add the @see Surface.MORSE_MATCHING to the visualization of the face lattice of the surface. user_method MORSE_MATCHING(%Visual::Lattice::decorations) { my ($this, $decor)=@_; $decor->{EdgeColor} ||= "255 0 0"; $this->add_matching($this->Surface->MORSE_MATCHING, $decor); visualize($this); } # Add distinguished faces with different graphical attributes @c NodeColor and @c NodeStyle # args: "PROPERTY_NAME" or [ Faces ] user_method FACES($ %Visual::Lattice::decorations) { my ($self, $faces, $decor)=@_; if (!ref($faces)) { $faces=$self->Surface->give($faces); } $decor->{NodeColor} ||= $Visual::Surface::critical_face_color; $self->add_faces($self->Surface->HASSE_DIAGRAM, $faces, $decor); visualize($self); } # Local Variables: # mode: perl # c-basic-offset:3 # End: