#! /usr/bin/perl $cmd = join(" ", @ARGV); ($me = $0) =~ s'.*/''; $map = "aitoff"; $style = "solid"; $color = 20; $radius = 1.0; $txscale = 1; while(($_ = shift(@ARGV)) ne "") { $any = @ARGV; if(/^-rect$/) { $map = "rect"; } # rectangular, X=lon, Y=lat elsif(/^-cyl/) { $map = "cyl"; } # rectangular equal-area, X=lon, Y=Z elsif(/^-ait/) { $map = "aitoff"; } # Aitoff elsif(/^-sin/) { $map = "sin"; } # Sinusoidal elsif(/^-st/) { $map = "stereo"; } # Stereographic elsif(/^-t$|^-txno$/) { $txno = shift; } elsif(/^-txfile/) { $txfile = shift; } elsif(/^-txs/) { $txscale = shift; } elsif(/^-line/) { $style = "line"; } elsif(/^-solid/) { $style = "solid"; } elsif(/^-asymp/) { $asymp = 1; } elsif(/^-c/) { $color = shift; } elsif(/^-n$/) { $nunv = shift; } elsif(/^-r$|^-radius/) { $radius = shift; } elsif(/^(\w+)=(.*)/) { eval("\$$1 = $2;"); } else { print "$0: unknown option $_\n"; print STDERR <<EOF; Usage: $0 [-rect|-cyl|-aitoff|-sin|-ster] [-n nu[,nv]] [-color cindex] [-line] \ [-txno txnumber] [-txfile imagename] [-color cindex] > file.speck Generate sphere in partiview mesh form, with texture coordinates for given map projection: -rect rectangular map, X=longitude, Y=latitude -cyl rectangular equal-area, X=lon, Y=cylinder Z -aitoff Aitoff equal-area projection -sin sinusoidal projection -ster stereographic projection (center = +Z pole) -n nu,nv Numbers of grid points in u (lon) and v (lat) directions. -txno texture number -txfile texture image filename -txscale scale texture about (0.5,0.5) point -line make wireframe sphere (default solid) -color color (index into colormap) Defaults: -aitoff -n 41,31 -color $color -txno $txno EOF exit(1); } } if($nunv) { ($nu, $nv) = ($nunv =~ /(\d+),?(\d*)/); $nv = $nu * 3/4 if $nv == 0; } else { $nu = 41; $nv = 31; } $hu = int($nu/2); $hv = int($nv/2); $nu = 2*$hu + 1; $nv = 2*$hv + 1; $pi = 3.1415926535; sub sigma { local($_) = @_; (3 - $_*$_) * $_ * .5; } sub asin { $_[0] = 1, printf STDERR "asin(%g) u%d v%d\n",$_[0],$u,$v if $_[0]*$_[0] > 1; atan2( $_[0], sqrt(1-$_[0]*$_[0]) ); } # Aitoff mapping sub XY2lonlat { local($X, $Y) = @_; local($R2) = $X*$X + $Y*$Y; $R2 = 1 if $R2 > 1; local($z) = sqrt(1 - .5*$R2); local($sq2) = sqrt(2); # tan lon/2 = sqrt(8) * X * z / (2 * (2 z^2 - 1)) # = sqrt(2) * X * z / (1 - r^2) # sin lat = sqrt(2) * Y * z local($lon) = 2 * atan2( $sq2 * $X * $z, 1 - $R2 ); local($lat) = &asin( $sq2 * $Y * $z ); ($lon, $lat); } print "#! /usr/bin/env partiview\n"; print "# $me $cmd\n\n"; $txno = 1 if $txno eq ""; print "texture $txno $txfile\n" if $txfile; print "mesh -t $txno -s $style {\n"; printf "%d %d\n", $nu, $nv; if($map eq "aitoff") { for($v = 0; $v < $nv; $v++) { $vfrac = ($v / ($nv-1)) * 2 - 1; $ay0 = &sigma( $vfrac ); $ay0 *= .99995 if $ay0*$ay0 >= 1; for($u = 0; $u < $nu; $u++) { $ax = &sigma(&sigma(&sigma( $u / ($nu-1) * 2 - 1 ))); $ay = $ay0 * sqrt(1 - $ax*$ax); ($lon, $lat) = &XY2lonlat( $ax, $ay ); &putpoint($lon, $lat, .5 - .5*$ax, .5 - .5*$ay); } print "\n"; } } else { for($v = 0; $v < $nv; $v++) { $vfrac = ($v / ($nv-1)); $vfrac = &sigma( &sigma( $vfrac ) ) if $asymp; $vfrac = .999999 if($v == $nv-1); $lat = (.5 - $vfrac) * $pi; $z = sin($lat); $r = cos($lat); for($u = 0; $u < $nu; $u++) { $ufrac = $u / ($nu-1); $lon = ($ufrac * 2 - 1) * $pi; $x = $r * cos($lon); $y = $r * sin($lon); if($map eq "sin") { $s = .5 + $r * ($ufrac - .5); $t = 1 - $vfrac; } elsif($map eq "rect") { $s = $ufrac; $t = 1 - $vfrac; } elsif($map eq "cyl") { $s = $ufrac; $t = (1 + $z) * .5; } elsif($map eq "stereo") { $s = .5 + $x / ($z < -.99999 ? .99999 : 1 + $z); $t = .5 + $y / ($z < -.999 ? .001 : 1 + $z); } else { # oneface $s = ($x + 1) * .5; $t = ($z + 1) * .5; } &putpoint( $lon, $lat, $s, $t ); } print "\n"; } } print "}\n"; sub putpoint { local($lon, $lat, $s, $t) = @_; local($clon) = cos($lon); local($slon) = sin($lon); local($clat) = cos($lat); local($slat) = sin($lat); printf "%.7f %.7f %.7f %.8f %.8f %.5f %.5f\n", $radius*$clon*$clat, $radius*$slon*$clat, $radius*$slat, $txscale * ($s-0.5) + 0.5, $txscale * ($t-0.5) + 0.5, $lon * 180/$pi, $lat * 180/$pi; }