GlassCube

For construction of image, a “glass cube” is helpful for snapping points. An additional tool displays one.


namespace eval GlassCube {
  namespace import ::tcl::mathfunc::* ::tcl::mathop::*
  
  proc p3D {x y z} {
    dict create\
      x [+ 125.0 $x]\
      y [+ 125.0 $y]\
      z [+ 125.0 $z]
  }
  
  variable center [p3D 0 0 0]
  
  variable baseCube [list\
      [p3D -50 -50 -50]\
      [p3D  50 -50 -50]\
      [p3D  50  50 -50]\
      [p3D -50  50 -50]\
      [p3D -50 -50  50]\
      [p3D  50 -50  50]\
      [p3D  50  50  50]\
      [p3D -50  50  50]]
  
  proc dotOptions 3Dpoint {
    list -x [dict get $3Dpoint x]  -y [dict get $3Dpoint y]
  }
  
  variable dots [lmap pt $baseCube {obj new dot {*}[dotOptions $pt]}]
  
  proc line {a b} {
    variable dots
    obj new line [lindex $dots $a] [lindex $dots $b]
  }
  
  variable group [obj new group -constraint {
      gravity
      noprint
      linecolor
      linewidth
    } [line 4 5] [line 5 6] [line 6 7] [line 7 4]\
      [line 0 4] [line 1 5] [line 2 6] [line 3 7]\
      [line 0 1] [line 1 2] [line 2 3] [line 3 0]]

  variable phi 0
  variable chi 0 
}
proc GlassCube::rotate {x y phi cX cY} {
  # coords x, y rotated by phi around cX, cY
  set c [cos $phi]
  set s [sin $phi]
  list\
    [expr {($x - $cX) * $c - ($y - $cY) * $s + $cX}]\
    [expr {($y - $cY) * $c + ($x - $cX) * $s + $cY}]
}
proc GlassCube::rotateYaxis {3Dpoint phi} {
  variable center
  set cX [dict get $center x]
  set cY [dict get $center z]
  set x [dict get $3Dpoint x]
  set y [dict get $3Dpoint z]
  lassign [rotate $x $y $phi $cX $cY] x y
  dict set 3Dpoint x $x
  dict set 3Dpoint z $y
}
proc GlassCube::rotateXaxis {3Dpoint phi} {
  variable center
  set cX [dict get $center z]
  set cY [dict get $center y]
  set x [dict get $3Dpoint z]
  set y [dict get $3Dpoint y]
  lassign [rotate $x $y $phi $cX $cY] x y
  dict set 3Dpoint z $x
  dict set 3Dpoint y $y
}
proc GlassCube::rotateCube {cube phi chi} {
  set cube [lmap pt $cube {rotateYaxis $pt $phi}]
  set cube [lmap pt $cube {rotateXaxis $pt $chi}]
}
proc GlassCube::glassCube {} {
  variable phi
  variable chi
  variable group
  variable baseCube
  variable dots
  foreach dot $dots p3d [rotateCube $baseCube [degree $phi] [degree $chi]] {
    $dot configure {*}[dotOptions $p3d]
  }
  $group draw
}
proc GlassCube::pi args [subst -novariable {expr "[acos -1] $args"}]
proc GlassCube::slider {canvas {onoff on}} {
  destroy $canvas.horizontal $canvas.vertical
  if {$onoff} then {
    variable group
    foreach element [$group elements] {
      if {[incr i] < 5} then {
        $element configure -outline grey72
      } elseif {$i < 9} then {
        $element configure -outline grey60 
      } else {
        $element configure -outline grey30
      }
    }
    set horizontal [scale $canvas.horizontal -orient horizontal\
        -from -90 -to 90 -resolution -1 -showvalue no\
        -variable [namespace current]::phi\
        -command [list apply [list num {
            glassCube
          } [namespace current]]]]
    set vertical [scale $canvas.vertical -orient vertical\
        -from 90 -to -90 -resolution -1 -showvalue no\
        -variable [namespace current]::chi\
        -command [list apply [list num {
            glassCube
          } [namespace current]]]]
    place $horizontal -anchor sw -relwidth 1.0 -relx 0.0 -rely 1.0\
      -width -[winfo reqwidth $vertical]
    place $vertical -anchor ne -relheight 1.0 -relx 1.0 -rely 0.0\
      -height -[winfo reqheight $horizontal]
    bind $horizontal <<ControlClick>> "$horizontal set 0; break"
    bind $vertical <<ControlClick>> "$vertical set 0; break"
    set group
  }
}

© Wolf-Dieter Busch | Home | Sitemap | Urheber | A-Z