summaryrefslogtreecommitdiff
path: root/Examples/GIFPlot/Tcl/mandel/mandel.tcl
blob: 3e1600bc12b69b4a4e471a33cebfeb5dec39dd74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
catch { load ./gifplot[info sharedlibextension] }
source display.tcl
set tcl_precision 17
set f [FrameBuffer -args 400 400]
set cmap [ColorMap -args cmap]
set p2 [Plot2D -args $f -3 -2 1 2]

set xmin -3
set xmax 1
set ymin -2.0
set ymax 2.0
set tolerance 240
set filename mandel.gif

# Make a plot from the above parms

proc make_plot {} {
    global p2 cmap tolerance
    global xmin ymin xmax ymax filename
    $p2 setrange $xmin $ymin $xmax $ymax
    $p2 start
    . config -cursor watch
    update
    mandel $p2 $tolerance
    . config -cursor arrow
    [$p2 cget -frame] writeGIF $cmap $filename
    display_image $filename $p2 set_zoom
}


# Take some screen coordinates and set global min and max values 

proc set_zoom {p2 mxmin mymin mxmax mymax x1 y1 x2 y2} {
    global xmin ymin xmax ymax

    set frame [$p2 cget -frame]
    set width [$frame cget -width]
    set height [$frame cget -height]

    if {$x1 < 0} {set x1 0}
    if {$x1 > ($width)} {set x1 $width}
    if {$x2 < 0} {set x2 0}
    if {$x2 > ($width)} {set x2 $width}
    if {$x1 < $x2} {set ixmin $x1; set ixmax $x2} {set ixmin $x2; set ixmax $x1}

    if {$y1 < 0} {set y1 0}
    if {$y1 > ($height)} {set y1 $height}
    if {$y2 < 0} {set y2 0}
    if {$y2 > ($height)} {set y2 $height}
    if {$y1 < $y2} {set iymin $y1; set iymax $y2} {set iymin $y2; set iymax $y1}

    # Now determine new min and max values based on screen location

    set xmin [expr {$mxmin + ($mxmax-$mxmin)*($ixmin)/($width)}]
    set xmax [expr {$mxmin + ($mxmax-$mxmin)*($ixmax)/($width)}]
    set ymin [expr {$mymin + ($mymax-$mymin)*(($height)-($iymax))/($height)}]
    set ymax [expr {$mymin + ($mymax-$mymin)*(($height)-($iymin))/($height)}]

    catch {make_plot}
}

# Box drag constrained to a square
proc BoxDrag { w x y} {
    global box
    catch {$w delete $box(last)}
    set x1 [lrange $box(anchor) 0 0]
    set y1 [lrange $box(anchor) 1 1]
    set dx [expr {$x - $x1}]
    set dy [expr {$y - $y1}]
    if {abs($dy) > abs($dx)} {set dx $dy}
    set newx [expr {$x1 + $dx}]
    set newy [expr {$y1 + $dx}]
    set box(last) [eval {$w create rect} $box(anchor) {$newx $newy -tag box -outline white}]
}


proc BoxFinish {w x y p2 mxmin mymin mxmax mymax func } {
    global box
    set start $box(anchor)
    set x1 [lrange $box(anchor) 0 0]
    set y1 [lrange $box(anchor) 1 1]
    set dx [expr {$x - $x1}]
    set dy [expr {$y - $y1}]
    if {($dx == 0) || ($dy == 0)} {
	catch {$w delete $box(last)}
	return
    }
    if {abs($dy) > abs($dx)} {set dx $dy}
    set newx [expr {$x1 + $dx}]
    set newy [expr {$y1 + $dx}]
    $w config -cursor watch
    update
# Call the handler function
    $func $p2 $mxmin $mymin $mxmax $mymax $x1 $y1 $newx $newy
    catch {$w delete $box(last)}
    $w config -cursor arrow
}


# Create a few frames

wm title . Mandelbrot
frame .title -relief groove -borderwidth 1
label .title.name -text "Mandelbrot Set" 
button .title.quit -text "Quit" -command "exit"
button .title.about -text "About" -command "about"
pack .title.name -side left
pack .title.quit .title.about -side right

frame .func -relief groove -borderwidth 1

frame .func.xrange
label .func.xrange.xrlabel -text "X range" -width 12
entry .func.xrange.xmin -textvar xmin -width 8
label .func.xrange.xtolabel -text "to"
entry .func.xrange.xmax -textvar xmax -width 8
pack  .func.xrange.xrlabel .func.xrange.xmin .func.xrange.xtolabel .func.xrange.xmax -side left

frame .func.yrange
label .func.yrange.yrlabel -text "Y range" -width 12
entry .func.yrange.ymin -textvar ymin -width 8
label .func.yrange.ytolabel -text "to"
entry .func.yrange.ymax -textvar ymax -width 8
pack  .func.yrange.yrlabel .func.yrange.ymin .func.yrange.ytolabel .func.yrange.ymax -side left

frame .func.npoints 
label .func.npoints.label -text "Tolerance " -width 12
entry .func.npoints.npoints -textvar tolerance -width 8
scale .func.npoints.scale -from 0 -to 2500 -variable tolerance -orient horizontal -showvalue false \
                          -sliderlength 13 -bigincrement 10 -resolution 10
pack .func.npoints.label .func.npoints.npoints .func.npoints.scale -side left

pack .func.xrange .func.yrange .func.npoints -side top -fill x

# Filename dialog

frame .save -relief groove -borderwidth 1

frame .save.file
label .save.file.label -text "Save as" -width 12
entry .save.file.filename -textvar filename -width 20
pack .save.file.label .save.file.filename -side left
pack .save.file -side left -fill x
button .save.go -text "Plot" -command "make_plot"
pack .save.go -side right

bind .save.file.filename <Return> {make_plot}

pack .title .func .save -side top -fill both

proc about { } {
    toplevel .about -width 350

    message .about.m -text "\
Mandelbrot Set\n\n\
Copyright (c) 1997\n\
Dave Beazley\n\
University of Utah\n\n\
Creates a plot of the Mandelbrot set.  Any displayed image can be zoomed by clicking and \
dragging.  Although the main calculation is written in C, it may take awhile for each \
image to be calculated (be patient).   Image quality can be improved at the expense of speed \
by increasing the tolerance value.\n"

button .about.okay -text "Ok" -command {destroy .about}

pack .about.m .about.okay -side top
focus .about.okay
}

make_plot