You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
359 lines
8.2 KiB
359 lines
8.2 KiB
2 years ago
|
#
|
||
|
# This script uses a vtkTkRenderWidget to create a
|
||
|
# Tk widget that is associated with a vtkRenderWindow.
|
||
|
#
|
||
|
# First we include the VTK Tcl packages which will make available
|
||
|
# all of the vtk commands to Tcl
|
||
|
#
|
||
|
package require vtk
|
||
|
package require vtkinteraction
|
||
|
|
||
|
set RANGE 150
|
||
|
set MAX_ITERATIONS_1 $RANGE
|
||
|
set MAX_ITERATIONS_2 $RANGE
|
||
|
set XRAD 200
|
||
|
set YRAD 200
|
||
|
|
||
|
#
|
||
|
# Create firt Mandelbrot viewer
|
||
|
#
|
||
|
vtkImageMandelbrotSource mandelbrot1
|
||
|
mandelbrot1 SetMaximumNumberOfIterations [expr int($MAX_ITERATIONS_1)]
|
||
|
mandelbrot1 SetWholeExtent [expr -$XRAD] [expr $XRAD-1] \
|
||
|
[expr -$YRAD] [expr $YRAD-1] \
|
||
|
0 0
|
||
|
set sample [expr 1.3 / $XRAD]
|
||
|
mandelbrot1 SetSampleCX $sample $sample $sample $sample
|
||
|
mandelbrot1 SetOriginCX -0.72 0.22 0.0 0.0
|
||
|
mandelbrot1 SetProjectionAxes 0 1 2
|
||
|
|
||
|
vtkLookupTable table1
|
||
|
table1 SetTableRange 0 $RANGE
|
||
|
table1 SetNumberOfColors $RANGE
|
||
|
table1 Build
|
||
|
table1 SetTableValue [expr $RANGE - 1] 0.0 0.0 0.0 0.0
|
||
|
|
||
|
vtkImageMapToColors map1
|
||
|
map1 SetInputConnection [mandelbrot1 GetOutputPort]
|
||
|
map1 SetOutputFormatToRGB
|
||
|
map1 SetLookupTable table1
|
||
|
|
||
|
vtkImageViewer viewer
|
||
|
viewer SetInputConnection [map1 GetOutputPort]
|
||
|
viewer SetColorWindow 255.0
|
||
|
viewer SetColorLevel 127.5
|
||
|
[viewer GetActor2D] SetPosition $XRAD $YRAD
|
||
|
|
||
|
#
|
||
|
# Create second Mandelbrot viewer
|
||
|
#
|
||
|
vtkImageMandelbrotSource mandelbrot2
|
||
|
mandelbrot2 SetMaximumNumberOfIterations [expr int($MAX_ITERATIONS_2)]
|
||
|
mandelbrot2 SetWholeExtent [expr -$XRAD] [expr $XRAD-1] \
|
||
|
[expr -$YRAD] [expr $YRAD-1] \
|
||
|
0 0
|
||
|
set sample [expr 1.3 / $XRAD]
|
||
|
mandelbrot2 SetSampleCX $sample $sample $sample $sample
|
||
|
mandelbrot2 SetOriginCX -0.72 0.22 0.0 0.0
|
||
|
mandelbrot2 SetProjectionAxes 2 3 1
|
||
|
|
||
|
vtkLookupTable table2
|
||
|
table2 SetTableRange 0 $RANGE
|
||
|
table2 SetNumberOfColors $RANGE
|
||
|
table2 Build
|
||
|
table2 SetTableValue [expr $RANGE - 1] 0.0 0.0 0.0 0.0
|
||
|
|
||
|
vtkImageMapToColors map2
|
||
|
map2 SetInputConnection [mandelbrot2 GetOutputPort]
|
||
|
map2 SetOutputFormatToRGB
|
||
|
map2 SetLookupTable table2
|
||
|
|
||
|
vtkImageViewer viewer2
|
||
|
viewer2 SetInputConnection [map2 GetOutputPort]
|
||
|
viewer2 SetColorWindow 256.0
|
||
|
viewer2 SetColorLevel 127.5
|
||
|
[viewer2 GetActor2D] SetPosition $XRAD $YRAD
|
||
|
|
||
|
#
|
||
|
# Create the GUI: two vtkTkImageViewer widgets and a quit/reset buttons
|
||
|
#
|
||
|
wm withdraw .
|
||
|
set top [toplevel .top]
|
||
|
wm protocol .top WM_DELETE_WINDOW ::vtk::cb_exit
|
||
|
wm title .top "Mandelbrot Viewer"
|
||
|
|
||
|
set f1 [frame $top.f1]
|
||
|
|
||
|
pack $f1 \
|
||
|
-side bottom \
|
||
|
-fill both -expand f
|
||
|
|
||
|
#
|
||
|
# Create the image viewer widget for set 1
|
||
|
#
|
||
|
set manFrame [frame $f1.man]
|
||
|
set julFrame [frame $f1.jul]
|
||
|
|
||
|
pack $manFrame $julFrame \
|
||
|
-side left \
|
||
|
-padx 3 -pady 3 \
|
||
|
-fill both -expand f
|
||
|
|
||
|
set manView [vtkTkImageViewerWidget $manFrame.view \
|
||
|
-iv viewer \
|
||
|
-width [expr $XRAD*2] \
|
||
|
-height [expr $YRAD*2]]
|
||
|
|
||
|
set manRange [label $manFrame.range \
|
||
|
-text "Mandelbrot Range: 0 - $RANGE"]
|
||
|
|
||
|
set quit [button $manFrame.quit \
|
||
|
-text "Quit" \
|
||
|
-command ::vtk::cb_exit]
|
||
|
|
||
|
#
|
||
|
# Create the image viewer widget for set 2
|
||
|
#
|
||
|
pack $manView $manRange $quit \
|
||
|
-side top \
|
||
|
-padx 2 -pady 2 \
|
||
|
-fill both -expand f
|
||
|
|
||
|
set julView [vtkTkImageViewerWidget $julFrame.view \
|
||
|
-iv viewer2 \
|
||
|
-width [expr $XRAD*2] \
|
||
|
-height [expr $YRAD*2]]
|
||
|
|
||
|
set julRange [label $julFrame.range \
|
||
|
-text "Julia Range: 0 - $RANGE"]
|
||
|
|
||
|
set reset [button $julFrame.reset \
|
||
|
-text "Reset" \
|
||
|
-command Reset]
|
||
|
|
||
|
pack $julView $julRange $reset \
|
||
|
-side top \
|
||
|
-padx 2 -pady 2 \
|
||
|
-fill both -expand f
|
||
|
#
|
||
|
# The equation label
|
||
|
#
|
||
|
set equation [label $top.equation \
|
||
|
-text "X = X^2 + C"]
|
||
|
|
||
|
pack $equation \
|
||
|
-side bottom \
|
||
|
-fill x -expand f
|
||
|
|
||
|
#
|
||
|
# Create the default bindings
|
||
|
#
|
||
|
::vtk::bind_tk_imageviewer_widget $manView
|
||
|
::vtk::bind_tk_imageviewer_widget $julView
|
||
|
|
||
|
#
|
||
|
# Override some of the bindings
|
||
|
#
|
||
|
foreach {widget master slave} [list $manView 1 2 $julView 2 1] {
|
||
|
|
||
|
set iren [[[$widget GetImageViewer] GetRenderWindow] GetInteractor]
|
||
|
set istyle [$iren GetInteractorStyle]
|
||
|
|
||
|
# Zoom in
|
||
|
|
||
|
$istyle RemoveObservers LeftButtonPressEvent
|
||
|
$istyle AddObserver LeftButtonPressEvent \
|
||
|
[list StartZoom $iren]
|
||
|
|
||
|
$istyle RemoveObservers LeftButtonReleaseEvent
|
||
|
$istyle AddObserver LeftButtonReleaseEvent \
|
||
|
[list EndZoom $iren $master $slave]
|
||
|
|
||
|
# Zoom out
|
||
|
|
||
|
$istyle RemoveObservers RightButtonPressEvent
|
||
|
$istyle AddObserver RightButtonPressEvent \
|
||
|
[list ZoomOut $iren $master $slave]
|
||
|
|
||
|
$istyle RemoveObservers RightButtonReleaseEvent
|
||
|
|
||
|
# Pan
|
||
|
|
||
|
$istyle RemoveObservers MiddleButtonPressEvent
|
||
|
$istyle AddObserver MiddleButtonPressEvent \
|
||
|
[list Pan $iren $master $slave]
|
||
|
|
||
|
$istyle RemoveObservers MiddleButtonReleaseEvent
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Update the display
|
||
|
#
|
||
|
proc MandelbrotUpdate {} {
|
||
|
global MAX_ITERATIONS_1 MAX_ITERATIONS_2 RANGE
|
||
|
global manView julView manRange julRange
|
||
|
|
||
|
mandelbrot1 SetMaximumNumberOfIterations [expr int($MAX_ITERATIONS_1)]
|
||
|
mandelbrot2 SetMaximumNumberOfIterations [expr int($MAX_ITERATIONS_1)]
|
||
|
|
||
|
set tmp [mandelbrot1 GetOriginCX]
|
||
|
set cr [lindex $tmp 0]
|
||
|
set ci [lindex $tmp 1]
|
||
|
set xr [lindex $tmp 2]
|
||
|
set xi [lindex $tmp 3]
|
||
|
|
||
|
mandelbrot1 Update
|
||
|
set tmp [[mandelbrot1 GetOutput] GetScalarRange]
|
||
|
set min [lindex $tmp 0]
|
||
|
set max [lindex $tmp 1]
|
||
|
$manRange configure -text "C = $cr + i $ci, Mandelbrot Range: $min - $max"
|
||
|
eval table1 SetTableRange [expr $min - 1] $max
|
||
|
set MAX_ITERATIONS_1 [expr $min + $RANGE]
|
||
|
|
||
|
mandelbrot2 Update
|
||
|
set tmp [[mandelbrot2 GetOutput] GetScalarRange]
|
||
|
set min [lindex $tmp 0]
|
||
|
set max [lindex $tmp 1]
|
||
|
$julRange configure -text "X = $xr + i $xi, Julia Range: $min - $max"
|
||
|
eval table2 SetTableRange [expr $min - 1] $max
|
||
|
set MAX_ITERATIONS_2 [expr $min + $RANGE]
|
||
|
|
||
|
$manView Render
|
||
|
$julView Render
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Reset both sets
|
||
|
#
|
||
|
proc Reset {} {
|
||
|
global MAX_ITERATIONS_1 MAX_ITERATIONS_2 RANGE XRAD
|
||
|
|
||
|
set MAX_ITERATIONS_2 $RANGE
|
||
|
set MAX_ITERATIONS_1 $RANGE
|
||
|
|
||
|
set sample [expr 1.3 / $XRAD]
|
||
|
mandelbrot1 SetSampleCX $sample $sample $sample $sample
|
||
|
mandelbrot1 SetOriginCX -0.72 0.22 0.0 0.0
|
||
|
|
||
|
set sample [expr 1.3 / $XRAD]
|
||
|
mandelbrot2 SetSampleCX $sample $sample $sample $sample
|
||
|
mandelbrot2 SetOriginCX -0.72 0.22 0.0 0.0
|
||
|
|
||
|
MandelbrotUpdate
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Zoom in
|
||
|
#
|
||
|
proc StartZoom {iren} {
|
||
|
global X Y
|
||
|
|
||
|
set pos [$iren GetEventPosition]
|
||
|
set X [lindex $pos 0]
|
||
|
set Y [lindex $pos 1]
|
||
|
}
|
||
|
|
||
|
proc EndZoom {iren master slave} {
|
||
|
global X Y XRAD YRAD
|
||
|
|
||
|
# Put origin in middle.
|
||
|
|
||
|
set pos [$iren GetEventPosition]
|
||
|
set x [expr [lindex $pos 0] - $XRAD]
|
||
|
set y [expr [lindex $pos 1] - $YRAD]
|
||
|
set X [expr $X - $XRAD]
|
||
|
set Y [expr $Y - $YRAD]
|
||
|
|
||
|
# Sort
|
||
|
|
||
|
if {$X < $x} {
|
||
|
set tmp $X
|
||
|
set X $x
|
||
|
set x $tmp
|
||
|
}
|
||
|
if {$Y < $y} {
|
||
|
set tmp $Y
|
||
|
set Y $y
|
||
|
set y $tmp
|
||
|
}
|
||
|
|
||
|
# Middle/radius
|
||
|
|
||
|
set xMid [expr 0.5 * ($x + $X)]
|
||
|
set yMid [expr 0.5 * ($y + $Y)]
|
||
|
set xDim [expr ($X - $x)]
|
||
|
set yDim [expr ($Y - $y)]
|
||
|
|
||
|
# Determine scale
|
||
|
|
||
|
if { $xDim <= 4 && $yDim <= 4} {
|
||
|
# Box too small. Zoom into point.
|
||
|
set scale 0.5
|
||
|
} else {
|
||
|
# Relative to window dimensions
|
||
|
set xDim [expr 1.0 * $xDim / (2*$XRAD)]
|
||
|
set yDim [expr 1.0 * $yDim / (2*$YRAD)]
|
||
|
# Take the largest
|
||
|
if {$xDim > $yDim} {
|
||
|
set scale $xDim
|
||
|
} else {
|
||
|
set scale $yDim
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mandelbrot$master Pan $xMid $yMid 0.0
|
||
|
mandelbrot$master Zoom $scale
|
||
|
mandelbrot$slave CopyOriginAndSample mandelbrot$master
|
||
|
|
||
|
MandelbrotUpdate
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Zoom out
|
||
|
#
|
||
|
proc ZoomOut {iren master slave} {
|
||
|
global XRAD YRAD
|
||
|
|
||
|
# Put origin in middle.
|
||
|
|
||
|
set pos [$iren GetEventPosition]
|
||
|
set x [expr [lindex $pos 0] - $XRAD]
|
||
|
set y [expr [lindex $pos 1] - $YRAD]
|
||
|
|
||
|
set scale 2.0
|
||
|
|
||
|
# Compute new origin.
|
||
|
|
||
|
mandelbrot$master Pan $x $y 0.0
|
||
|
mandelbrot$master Zoom $scale
|
||
|
mandelbrot$slave CopyOriginAndSample mandelbrot$master
|
||
|
|
||
|
MandelbrotUpdate
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Pan
|
||
|
#
|
||
|
proc Pan {iren master slave} {
|
||
|
global XRAD YRAD
|
||
|
|
||
|
# Put origin in middle.
|
||
|
|
||
|
set pos [$iren GetEventPosition]
|
||
|
set x [expr [lindex $pos 0] - $XRAD]
|
||
|
set y [expr [lindex $pos 1] - $YRAD]
|
||
|
|
||
|
set scale 2.0
|
||
|
|
||
|
# Compute new origin.
|
||
|
|
||
|
mandelbrot$master Pan $x $y 0.0
|
||
|
mandelbrot$slave CopyOriginAndSample mandelbrot$master
|
||
|
|
||
|
MandelbrotUpdate
|
||
|
}
|
||
|
|
||
|
MandelbrotUpdate
|
||
|
|
||
|
|