# 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: JReality.pm 7574 2007-01-19 12:18:11Z thilosch $ use strict; use JavaView; require 'JReality.def'; package JReality::File; use Struct ( [ '@ISA' => 'JavaView::File' ], ); sub header { my ($self) = shift; my $obj_name = shift; my $title=$self->title; if (!length($title)) { $title="unnamed"; } return <<"."; /*--------------------HEADER $title--------------------*/ import de.jreality.shader.CommonAttributes; setAccessibility(true); synchronized(root) { $obj_name = new SceneGraphComponent(); $obj_name.setName("$title"); root.addChild($obj_name); /*----------------------------------------*/ . } sub trailer { return <<"."; root.notify(); } return; . } sub toString { dbg_print(" called JReality::File->toString .. ") if $Switches::d; my ($self) = shift; my $n_geom = shift; my $obj_name = "geom$n_geom"; my $text = $self->header($obj_name); my $number = 0; foreach my $geometry (@{$self->geometries}) { $text .= $geometry->toString($number, $obj_name); $number++; } $text .= $self->trailer; return $text; } sub print_it { my ($self) = @_; $self->SUPER::print_it; } ############################################################################################## # # Basis class for all graphical objects handled by jreality # package JReality::geometry; my $thickness_factor = 40; sub new { my $class = shift; my $self = { @_ }; #hashmap bless $self, $class; $self->initialize; return $self; } sub initialize { my $self=shift; if (! exists $self->{name}) { $self->{name}="geometry"; } if (! exists $self->{points}) { croak( ref($self), "::initialize: parameter 'points' missing" ); } if (! exists $self->{pointSet_dim}) { croak( ref($self), "::initialize: parameter 'pointSet_dim' missing" ); } $self->{pointSet_point_flag} ||= "show"; if (! exists $self->{points_thickness}) { $self->{points_thickness}=$JReality::default::points_thickness; } $self->{pointSet_thicknesses_flag} ||= exists $self->{points_thicknesses_list} ? "show" : "hide"; if (! exists $self->{points_color}) { $self->{points_color}= $Visual::Color::vertices; #$JReality::default::points_color; } ## JReality "bug" (see above comment) #if(! exists $self->{number_of_points}) { # $self->{number_of_points} = @{$self->{points}} ; #} } sub appearance { my $self = shift; my $obj_name = shift; # print "name 2:" . "$obj_name"; my @colors = ($self->{points_color} =~ /\d+/g); map {$_ = $_ / 255} @colors; #FIXME: points thickness my $point_thickness = $self->{points_thickness} / $thickness_factor; my $text =<<"."; appearance = new Appearance(); . if($self->{pointSet_point_flag} eq "show") { $text .=<<"."; appearance.setAttribute(de.jreality.shader.CommonAttributes.VERTEX_DRAW, true); appearance.setAttribute(de.jreality.shader.CommonAttributes.SPHERES_DRAW, true); . } else { $text .=<<"."; appearance.setAttribute(de.jreality.shader.CommonAttributes.VERTEX_DRAW, false); appearance.setAttribute(de.jreality.shader.CommonAttributes.SPHERES_DRAW, false); . } $text .=<<"."; $obj_name.setAppearance(appearance); . return $text; } sub add_point_colors { my $self = shift; my $text = ""; $text .= "colors = new double[]{ "; for(my $i=0; $i < (@{$self->{points}}); $i++) { my @colors; if (exists $self->{points_colors_list}) { @colors = split(" ",${$self->{points_colors_list}}[$i]); } else { @colors = ($self->{points_color} =~ /\d+/g); } map {$_ = $_ / 255} @colors; $text .= join(",", @colors); if($i + 1 != @{$self->{points}}) { $text .= ", \n"; } } $text .= " }; \n"; return $text; } ## scale coordinates such that mean distance to barycenter == 1; ## TODO: for interactive components this does not make sense, ## in particular for the schlegel interactive where coordinates ## are here (1,0,0),(2,0,0),(3,0,0) ... ## TODO: for geometries with multiple elements this does ## not work properly sub scale { my $self = shift(@_); my @coords = @_; ## barycenter my @c; my $N = scalar @{$self->{points}}; for(my $i=0; $i < $N; $i++) { for(my $k=0; $k < 3; $k++) { @c[$k] += 1/$N * @coords[3*$i + $k]; } } ## mean distance to barycenter my $dist = 0; for(my $i=0; $i < $N; ++$i) { my @p; for(my $k=0; $k < 3; ++$k) { @p[$k] += (@c[$k] - @coords[3*$i+$k]); } $dist += sqrt(@p[0]*@p[0] + @p[1]*@p[1] + @p[2]*@p[2]); } $dist = $dist/$N; ## change coordinates if($dist != 0) { for(my $i=0; $i < $N; $i++) { for(my $k=0; $k < 3; $k++) { @coords[3*$i+$k] = @c[$k] + (1/$dist)*(@coords[3*$i+$k] - @c[$k]); } } } return @coords; } sub pointSet { my ($self) = @_; my $text=<<"."; /*--------------------$self->{name}--------------------*/ pts = new double[][]{ . dbg_print ("generating pointset for jreality ...") if $Switches::d; my @points; foreach my $point (@{$self->{points}}) { # chomp $point; my @coord = split /\s+/, $point; ## HACK; for Visual::Graph dimension ($pointSet_dim) is set to 3, although ## the graph is the Schlegel diagram of a 3-polytope if(@coord == 2) { push @coord, "0"; } my $line = "{".(join(",", @coord))."}"; push @points, $line; } $text .= (join(",\n",@points))."\n};//pts \n"; $text .= $self->pointLabels; return $text; } sub pointLabels { my ($self) = @_; my $labels = $self->{points_labels_list}; my $text = "labels = new String[]{"; my @labels; if(defined($labels)) { for(my $i=0; $i < @{$self->{points}}; ++$i) { push @labels, "\"".($labels->($i))."\""; } } $text .= join(",",@labels); $text .= "};\n"; return $text; } # use only for displaying pointsets sub trailer { my ($self) = shift; my $number = shift; my $obj_name = shift; my $n_points = @{$self->{points}}; my $text .=<<"."; psf = new PointSetFactory(); psf.setVertexCount($n_points); psf.setVertexCoordinates(pts); if(labels.length == $n_points) psf.setVertexLabels(labels); . $text .= $self->add_point_colors; $text .=<<"."; psf.setVertexColors( new DoubleArrayArray.Inlined(colors, 3)); psf.update(); part1=new SceneGraphComponent(); part1.setGeometry(psf.getGeometry()); part1.setName("PointSet $number"); part1.setAppearance(appearance); $obj_name.addChild(part1); /*----------------------------------------*/ . return $text; } # use only for displaying pointsets sub toString { ## generate data for jreality application dbg_print("called JReality::geometry->toString ..") if $Switches::d; my ($self) = shift; my $number = shift; my $obj_name = shift; return $self->pointSet . $self->pointLabels . $self->appearance($obj_name) . $self->trailer($number, $obj_name) ; } ############################################################################################## # # Wire model (e.g. a graph) # package JReality::wire; use vars '@ISA'; @ISA=qw( JReality::geometry ); sub new { my $class = shift; my $self = { @_ }; #hashmap bless $self, $class; $self->initialize; return $self; } sub appearance { my $self = shift; my $obj_name = shift; my $text = $self->SUPER::appearance($obj_name); if($self->{lines_color} =~ /\s*0\s+0\s+0\s*/) { $self->{lines_color} = "70 70 70"; } my @line_colors = ($self->{lines_color} =~ /\d+/g); map {$_ = $_ / 255} @line_colors; my $lines_thickness = $self->{lines_thickness} / $thickness_factor; if( $self->{lineSet_line_flag} eq "hide") { $text .= "appearance.setAttribute(CommonAttributes.TUBES_DRAW,false);\nappearance.setAttribute(CommonAttributes.EDGE_DRAW,false);\n"; } else { $text .= "appearance.setAttribute(CommonAttributes.TUBES_DRAW,true);\nappearance.setAttribute(CommonAttributes.EDGE_DRAW,true);\n"; } $text .= <<"."; appearance.setAttribute( "lineShader.diffuseColor", new java.awt.Color((float)@line_colors[0] ,(float)@line_colors[1],(float)@line_colors[2]) ); . return $text; } sub initialize { my $self=shift; $self->SUPER::initialize; if (! exists $self->{lines}) { croak( ref($self), "::initialize: parameter 'lines' missing" ); } $self->{lineSet_line_flag} ||= "show"; $self->{lineSet_arrow_flag} ||= "hide"; if (! exists $self->{lines_thickness}) { $self->{lines_thickness}=$JReality::default::lines_thickness; } $self->{lineSet_thicknesses_flag} ||= exists $self->{lines_thicknesses_list} ? "show" : "hide"; if (! exists $self->{lines_color}) { $self->{lines_color}= $Visual::Color::edges; #$JReality::default::lines_color; } } sub add_line_colors { my $self = shift; my $text = ""; $text .= "lineColors = new double[]{ "; for(my $i=0; $i < (@{$self->{lines}}); $i++) { my @colors; if (exists $self->{lines_colors_list}) { map { s/\s*0\s+0\s+0\s*/70 70 70/; } @{$self->{lines_colors_list}}; @colors = split(" ",${$self->{lines_colors_list}}[$i]); } else { @colors = ($self->{lines_color} =~ /\d+/g); } map {$_ = $_ / 255} @colors; $text .= join(",", @colors); if($i + 1 != @{$self->{lines}}) { $text .= ", \n"; } } $text .= " }; \n"; return $text; } sub lineSet { my ($self) = @_; my $text .="lines = new int[][]{ "; dbg_print ("generating lineset for jreality ...") if $Switches::d; my @lines = (@{$self->{lines}}); map { $_=$self->process_line($_)} @lines; $text .= join(",", @lines); $text .= " }; \n"; return $text; } sub process_line { my ($self, $line) = @_; my $text .= "{ "; my @indices = ( $line =~ /\d+/g); @indices = reverse @indices; $text .= join(",", @indices); $text .= " } \n"; return $text; } sub trailer { my $self = shift; my $number = shift; my $obj_name = shift; my $n_points = @{$self->{points}}; my $n_lines = @{$self->{lines}}; my $text .=<<"."; ilsf = new IndexedFaceSetFactory(); ilsf.setLineCount($n_lines); ilsf.setVertexCount($n_points); ilsf.setEdgeIndices(lines); ilsf.setVertexCoordinates(pts); if(labels.length == $n_points) ilsf.setVertexLabels(labels); . ## point appearance $text .= $self->SUPER::add_point_colors; $text .=<<"."; ilsf.setVertexColors(new DoubleArrayArray.Inlined(colors, 3) ); . $text .= $self->add_line_colors; $text .=<<"."; ilsf.setEdgeColors( new DoubleArrayArray.Inlined(lineColors, 3) ); ilsf.update(); part1=new SceneGraphComponent(); part1.setGeometry(ilsf.getGeometry()); part1.setAppearance(appearance); part1.setName("LineSet $number"); $obj_name.addChild(part1); /*----------------------------------------*/ . return $text; } sub toString { dbg_print("called JReality::wire->toString ..") if $Switches::d; my $self = shift; my $number = shift; my $obj_name = shift; my $text = ""; $text .= $self->SUPER::pointSet; $text .= $self->lineSet; $text .= $self->appearance($obj_name); $text .= $self->trailer($number, $obj_name); return $text; } ################################################################ # # Solid 2-d or 3-d body # package JReality::solid; use vars '@ISA'; @ISA=qw( JReality::geometry ); sub initialize { my $self=shift; $self->SUPER::initialize; if (! exists $self->{faces}) { croak( ref($self), "::initialize: parameter 'faces; missing\n" ); } $self->{faceSet_face_flag} ||= "show"; $self->{faceSet_backface_flag} ||= "hide"; $self->{faceSet_edge_flag} ||= "show"; if (! exists $self->{faces_color}) { $self->{faces_color}= $Visual::Color::facets; #$JReality::default::faces_color; } if (! exists $self->{edges_thickness}) { $self->{edges_thickness}=$JReality::default::lines_thickness; } if (! exists $self->{edges_color}) { #$self->{edges_color}=$JReality::default::lines_color; $self->{edges_color}=$Visual::Color::edges; } if(defined $self->{material_flag}) { $self->{faceSet_backface_flag} = $self->{material_flag}; $self->{material_diffuseColor} ||= $JReality::default::diffuseColor; $self->{material_emissiveColor} ||= $JReality::default::emissiveColor; $self->{material_shininess} ||= $JReality::default::shininess; $self->{material_specularColor} ||= $JReality::default::specularColor; $self->{material_transparency} ||= $JReality::default::transparency; } else { $self->{material_flag} = "hide"; } } sub add_face_colors { my $self = shift; my $text = ""; $text .= "faceColors = new double[]{ "; for(my $i=0; $i < (@{$self->{faces}}); $i++) { my @colors; if (exists $self->{faces_colors_list}) { @colors = split(" ",${$self->{faces_colors_list}}[$i]); } else { @colors = ($self->{faces_color} =~ /\d+/g); } map {$_ = $_ / 255} @colors; $text .= join(",", @colors); if($i + 1 != @{$self->{faces}}) { $text .= ", \n"; } } $text .= " }; \n"; return $text; } sub appearance { my $self = shift; my $obj_name = shift; my $text = $self->SUPER::appearance($obj_name); $text .= <<"."; appearance.setAttribute(CommonAttributes.POLYGON_SHADER +"."+CommonAttributes.SMOOTH_SHADING,false); . if( $self->{material_flag} =~ "show") { my $transparency = ($self->{material_transparency}); $text .= <<"."; appearance.setAttribute(CommonAttributes.TRANSPARENCY_ENABLED,true); appearance.setAttribute(CommonAttributes.TRANSPARENCY,$transparency); . } if( $self->{faceSet_edge_flag} eq "hide") { $text .= "appearance.setAttribute(CommonAttributes.TUBES_DRAW,false);\nappearance.setAttribute(CommonAttributes.EDGE_DRAW,false);\n"; } else { $text .= "appearance.setAttribute(CommonAttributes.TUBES_DRAW,true);\nappearance.setAttribute(CommonAttributes.EDGE_DRAW,true);\n"; } if( $self->{faceSet_face_flag} eq "hide") { $text .= <<"."; appearance.setAttribute(CommonAttributes.FACE_DRAW, false); . } if($self->{edges_color} =~ /\s*0\s+0\s+0\s*/) { $self->{edges_color} = "70 70 70"; } my @edge_colors = ($self->{edges_color} =~ /\d+/g); map {$_ = $_ / 255} @edge_colors; #FIXME: edge thicknesses my $edges_thickness = $self->{edges_thickness} / $thickness_factor; # $text .= "appearance.setAttribute(CommonAttributes.LINE_SHADER+\".\"+CommonAttributes.TUBE_RADIUS,$edges_thickness);\n"; $text .= <<"."; appearance.setAttribute(CommonAttributes.LINE_SHADER +"."+ CommonAttributes.DIFFUSE_COLOR, new java.awt.Color((float)@edge_colors[0] ,(float)@edge_colors[1],(float)@edge_colors[2])); . return $text; } sub faceSet { my ($self) = @_; my $text .="faces = new int[][]{ "; dbg_print ("generating faceset for jreality ...") if $Switches::d; my @faces = (@{$self->{faces}}); map { $_=$self->process_face($_)} @faces; $text .= join(",", @faces); $text .= " }; \n"; return $text; } sub process_face { my ($self, $face) = @_; my $text .= "{ "; my @indices = ( $face =~ /\d+/g); @indices = reverse @indices; $text .= join(",", @indices); $text .= " } \n"; return $text; } sub trailer { my $self = shift; my $number = shift; my $obj_name = shift; my $n_faces = @{$self->{faces}}; my $n_points = @{$self->{points}}; my $text .=<<"."; IndexedFaceSetFactory ifsf = new de.jreality.geometry.IndexedFaceSetFactory(); ifsf.setGenerateFaceNormals(true); ifsf.setGenerateVertexNormals(true); ifsf.setGenerateEdgesFromFaces(true); ifsf.setVertexCount($n_points); ifsf.setFaceCount($n_faces); ifsf.setVertexCoordinates(pts); ifsf.setFaceIndices(faces); if(labels.length == $n_points) { ifsf.setVertexLabels(labels); } . $text .= $self->SUPER::add_point_colors; $text .=<<"."; ifsf.setVertexColors( new DoubleArrayArray.Inlined(colors, 3)); . $text .= $self->add_face_colors; $text .=<<"."; ifsf.setFaceColors( new DoubleArrayArray.Inlined(faceColors, 3)); ifsf.update(); part1=new SceneGraphComponent(); part1.setGeometry(ifsf.getGeometry()); part1.setName("FaceSet $number"); part1.setAppearance(appearance); $obj_name.addChild(part1); /*----------------------------------------*/ . return $text; } sub toString { dbg_print("called JReality::solid->toString ..") if $Switches::d; my $self = shift; my $number = shift; my $obj_name = shift; my $text = ""; $text .= $self->SUPER::pointSet; $text .= $self->faceSet; $text .= $self->appearance($obj_name); $text .= $self->trailer($number, $obj_name); return $text; } 1 # Local Variables: # mode:perl # c-basic-offset:3 # End: