#!/bin/sh # \ exec tclsh "$0" ${1+"$@"} #!/bin/sh # \ exec tclsh "$0" ${1+"$@"} proc rint { i } { # Generate a random interger in the range [0..i). set mx 1000000 if { [ expr $mx < $i ] } { set i $mx } if { [ expr 0 >= $i ] } { set i 1 } set bs [ expr $mx/$i ] while { 1 } { set r [ expr int(rand()*$mx)/$bs ] if { [ expr $r < $i ] } { return $r } } } # $Log: gen-polygons,v $ # Revision 1.1 2004/03/25 16:48:32 rclayton # Initial revision # # Local Variables: # mode: tcl # tcl-application: "tclsh" # End: #!/bin/sh # \ exec tclsh "$0" ${1+"$@"} namespace eval point { proc add { p1 p2 } { # Add the point p1 to the point p2; return the new point. set x [ expr [ get.x $p2 ] + [ get.x $p1 ] ] set y [ expr [ get.y $p2 ] + [ get.y $p1 ] ] return [ make $x $y ] } proc dot.product { p1 p2 } { # Return the dot product of the given points. return [ expr [ get.x $p1 ]*[ get.x $p2 ] + [ get.y $p1 ]*[ get.y $p2 ] ] } proc get.x pt { # Return the given point's x coordinate. return [ lindex $pt 0 ] } proc get.y pt { # Return the given point's y coordinate. return [ lindex $pt 1 ] } proc make { x y } { # Return a point with the given coordinates. return [ list $x $y ] } proc random { } { # Return a randomly generated point somewhere in the unit square centered # at the origin. set x [ expr 0.5 - rand() ] set y [ expr 0.5 - rand() ] return [ make $x $y ] } proc rotate { pt angle } { # Rotate the given point about the origin through the given angle; return # the rotated point. set cos_a [ expr cos($angle) ] set sin_a [ expr sin($angle) ] set x [ dot.product $pt [ make $cos_a -$sin_a ] ] set y [ dot.product $pt [ make $sin_a $cos_a ] ] return [ make $x $y ] } proc sub { p1 p2 } { # Subtract the point p1 from the point p2; return the new point. set x [ expr [ get.x $p2 ] - [ get.x $p1 ] ] set y [ expr [ get.y $p2 ] - [ get.y $p1 ] ] return [ make $x $y ] } } # $Log: gen-polygons,v $ # Revision 1.1 2004/03/25 16:48:32 rclayton # Initial revision # #!/bin/sh # \ exec tclsh "$0" ${1+"$@"} proc oops emsg { # Print the given error message and die. puts stderr "emsg." exit 1 } # $Log: gen-polygons,v $ # Revision 1.1 2004/03/25 16:48:32 rclayton # Initial revision # # Local Variables: # mode: tcl # tcl-application: "tclsh" # End: #!/bin/sh # \ exec tclsh "$0" ${1+"$@"} namespace eval minmax { variable epsilon 0.001 proc max { a b } { variable epsilon if { [ expr $a - $b < $epsilon ] } { return $b } \ else { return $a } } proc min { a b } { variable epsilon if { [ expr $a - $b < $epsilon ] } { return $a } \ else { return $b } } } # $Log: gen-polygons,v $ # Revision 1.1 2004/03/25 16:48:32 rclayton # Initial revision # # Local Variables: # mode: tcl # tcl-application: "tclsh" # End: proc find.maxs { polygon } { # Return as a point the maximum x and y of the points in the given polygon. set p [ lindex $polygon 0 ] set max_x [ point::get.x $p ] set max_y [ point::get.x $p ] foreach p $polygon { set max_x [ minmax::max $max_x [ point::get.x $p ] ] set max_y [ minmax::max $max_y [ point::get.y $p ] ] } return [ point::make $max_x $max_y ] } proc find.mins { polygon } { # Return as a point the minimum x and y of the points in the given polygon. set p [ lindex $polygon 0 ] set min_x [ point::get.x $p ] set min_y [ point::get.x $p ] foreach p $polygon { set min_x [ minmax::min $min_x [ point::get.x $p ] ] set min_y [ minmax::min $min_y [ point::get.y $p ] ] } return [ point::make $min_x $min_y ] } proc gen.poly sides { # Return a randomly-generated regular polygon with the given number of sides. set center [ point::random ] set vertex [ point::random ] set pi 3.14159265 set angle [ expr 2*$pi/$sides ] for { set i 0 } { $i < $sides } { incr i } { set p [ rotate $center $vertex [ expr $angle*$i ] ] if { 0 } { puts stderr "rotate $vertex around $center by $a to get $p" } lappend poly $p } return $poly } proc normalize.polygon poly { # Normalize the given polygon so it falls within the unit square centered at # the origin. set mins [ find.mins $poly ] set maxs [ find.maxs $poly ] if { 0 } { puts stderr "mins $mins" puts stderr "maxs $maxs" } set x_size [ expr [ point::get.x $maxs ] - [ point::get.x $mins ] ] set y_size [ expr [ point::get.y $maxs ] - [ point::get.y $mins ] ] set scale [ minmax::max $x_size $y_size ] set scale [ expr 1.0/$scale ] if { 0 } { puts stderr "scale $scale" } set trans [ point::make [ expr [ point::get.x $mins ] + $x_size/2.0 ] \ [ expr [ point::get.y $mins ] + $y_size/2.0 ] ] if { 0 } { puts stderr "trans $trans" } foreach p $poly { set p [ point::sub $p $trans ] lappend npoly [ point::make [ expr [ point::get.x $p ]*$scale ] \ [ expr [ point::get.y $p ]*$scale ] ] } return $npoly } proc print.polygon { outs poly } { # Write to the given output stream the given polygon. if { 0 } { puts stderr "poly $poly" } set poly [ normalize.polygon $poly ] if { 0 } { puts stderr "normalized poly $poly" } set sep "" foreach p $poly { set x [ scale.val [ point::get.x $p ] ] set y [ scale.val [ point::get.y $p ] ] puts -nonewline $outs "$sep$x $y" set sep " " } puts $outs "" } proc rotate { p1 p2 angle } { # Rotate the point p1 about the point p2 for the given angle and return the # new point. set p [ point::sub $p2 $p1 ] set p [ point::rotate $p $angle ] set p [ point::add $p $p2 ] return $p } proc scale.val v { # Return the given value scaled to the range [-100, 100] set scale 10000.0 return [ expr int($v*$scale + 0.5)/$scale ] } set sides { } set polygons 1 foreach i $argv { switch -regexp -- $i { {-s[0-9?]*} { if { [ regexp -- {-s([0-9]+)$} $i _ sds ] } { lappend sides $sds } \ elseif { [ regexp -- {-s\?$} $i _ ] } { lappend sides [ expr [ rint 10 ] + 3 ] } \ else { oops "\"$i\" is an invalid option" } } default { oops "\"$i\" is an unrecognized option" } } } if { [ llength $sides ] == 0 } { lappend sides [ expr [ rint 10 ] + 3 ] } foreach s $sides { for { set i 0 } { $i < $polygons } { incr i } { set poly [ gen.poly $s ] print.polygon stdout $poly } } # $Log: gen-polygons,v $ # Revision 1.1 2004/03/25 16:48:32 rclayton # Initial revision # # Revision 1.1 2004/03/11 18:30:58 rclayton # Initial revision # # Local Variables: # mode: tcl # tcl-application: "tclsh" # End: