Created
April 27, 2013 23:10
-
-
Save kristopolous/5475117 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
############################################################# | |
# # | |
# Program: mzoom # | |
# Author: dw # | |
# Date: 2007-07-07 # | |
# Purpose: Explore the Mandelbrot set in bash! # | |
# Usage: See below # | |
# Version: 1.01.6930 # | |
# # | |
############################################################# | |
#### Usage: Run with no arguments, program will draw full mandelbrot set. After set is complete, | |
#### use the arrow keys to navigate to the upper left corner of an area you want to zoom into, | |
#### then press the "z" key once, use the right arrow key again to move to the right, you are now | |
#### deciding how big of a "box" to draw around the area, when you are far enough to the right, | |
#### press the "z" key one more time, this will draw a box roughly around the area to be zoomed | |
#### into, after a brief pause, the program will zoom into the area you selected. Repeat process | |
#### to continue zooming, use control c to exit. | |
#### As your level of zoom increases, you'll want to increase the number of iterations, you can | |
#### do this by pressing the "i" key while in zoom mode, anytime before pressing the second "z", | |
#### this will increase the max iterations by 50 each time. | |
#### This program uses integer math to explore the Mandelbrot set, it will not zoom in as far as | |
#### a "real" Mandelbrot explorer, but floating point was just too slow in bash, you'll know when | |
#### you hit the limit, I have tested it to about 2,000,000 magnification. My bash/python hybred | |
#### version zooms much further and is over 40 times faster. :-) | |
#### GET CURRENT SCREEN SIZE - METHOD 1 | |
w=`tput cols` | |
e=`tput lines` | |
#### DO WE HAVE A SCREEN SIZE? IF NOT, TRY METHOD 2 | |
if [ ! "$w" ] | |
then | |
#### GET CURRENT SCREEN SIZE - METHOD 2 | |
w=`stty -a | grep rows | awk -F ";" '{print$3}' | awk '{print$2}'` | |
e=`stty -a | grep rows | awk -F ";" '{print$2}' | awk '{print$2}'` | |
#### HOW ABOUT NOW? | |
if [ ! "$w" ] | |
then | |
clear;echo;echo "COULD NOT OBTAIN SCREEN SIZE";echo;exit | |
fi | |
fi | |
#### SET MAX X & Y | |
((w = w - 1));((e = e - 1));maxy="$e";maxx="$w" | |
#### SETUP THE COLOR VARIABLES | |
off="\033[0m";gry="\033[1;0m";red="\033[1;31m";grn="\033[1;32m";yel="\033[1;33m" | |
blu="\033[1;34m";pur="\033[1;35m";aqu="\033[1;36m";wht="\033[1;37m" | |
#### SET THE BC PRECESION | |
pre=20 | |
#### SETUP THE MANDELBROT VARIABLES | |
si=$(echo "scale=$pre;(2.5)" | bc) ### length of side = 2.5 | |
c=$(echo "scale=$pre;(-2.00)" | bc) ### acorner = -2 | |
k=$(echo "scale=$pre;(-1.25)" | bc) ### bcorner = -1.25 | |
it=100 ### iterations = 100 | |
#### SETUP THE COLOR ARRAYS | |
for (( i = 16; i < 255; i++ )); do | |
p[$(( i - 16 ))]="\033[38;5;${i}m" | |
done | |
#p[1]="$gry";p[2]="$wht";p[3]="$red";p[4]="$grn";p[5]="$yel" | |
#p[6]="$blu";p[7]="$pur";p[8]="$aqu";p[9]="$wht" | |
nsi=$(echo "scale=$pre;(2.5)" | bc) | |
#### THE MAIN ROUTINE | |
mandelbrot() | |
{ | |
#### FILL THE COLOR ARRAY | |
x=1;z=0;xx=1 | |
while ((x < it)) | |
do | |
((z++)) | |
if ((z > 250)) | |
then | |
z=1 | |
fi | |
pix["$x"]="${p[$z]}""$xx" | |
((x++));((xx++)) | |
if ((xx > 250)) | |
then | |
xx=1 | |
fi | |
done | |
#### AUTO CALCULATE ASPECT RATIO | |
ar=$(echo "scale=$pre;($w/$e)/2" | bc) | |
gr=$(echo "scale=$pre;($si/($w/$ar))" | bc) | |
#### MULTIPLIER FOR INTEGER MATH IS 2^27 SO WE USE A 27 BIT SHIFT IN THE MAIN LOOP | |
mul=134217728;clear;m=0;n=0;pxl="M";g=`echo "$gr" | awk '{print(int($1*'"$mul"'))}'` | |
hr=$(echo "scale=$pre;($si/$e)" | bc);h=`echo "$hr" | awk '{print(int($1*'"$mul"'))}'` | |
gcr=$(echo "scale=$pre;(($gr+$c)*$mul)" | bc);gc=`echo "$gcr" | awk '{print(int($1))}'` | |
mhkr=$(echo "scale=$pre;(($hr+$k)*$mul)" | bc);mhk=`echo "$mhkr" | awk '{print(int($1))}'` | |
ngc="$gc";writexy="tput cup";((mul4 = mul << 2)) | |
#### PRINT ZOOM RATIO, ITERATIONS AND COORDINATES AT LOWER LEFT CORNER OF SCREEN | |
mag1=$(echo "scale=$pre;(2.5/$nsi)" | bc);echo -e "$wht" | |
mag2=`echo "$mag1" | awk '{print int($0)}'` | |
$writexy $((maxy - 3)) 0;echo -n " ZOOM = $mag2" | |
$writexy $((maxy - 2)) 0;echo -n " ACORNER = $c " | |
$writexy $((maxy - 1)) 0;echo -n " BCORNER = $k " | |
$writexy $((maxy - 0)) 0;echo -n " ITERATIONS = $it " | |
#### THE MAIN LOOP WITH 27 BIT SHIFT | |
while ((m < e)) | |
do | |
x=1;tput cup $m $n | |
while ((x < it)) | |
do | |
((v = (a * b) >> 27));((a = (aq - bq) + ngc));((b = (v << 1) + mhk)) | |
((aq = (a * a) >> 27));((bq = (b * b) >> 27)) | |
if ((aq + bq > mul4)) | |
then | |
echo -en ${pix[$x]};((x = it)) | |
fi | |
((x++)) | |
done | |
a=0;b=0;aq=0;bq=0;((n++));((ngc = ngc + g)) | |
if ((n > w)) | |
then | |
n=0;((m++));ngc=gc;((mhk = mhk + h)) | |
fi | |
done | |
echo -en "$off" | |
} | |
#### THE ZOOM ROUTINE | |
zoomin() | |
{ | |
zoom=0;x=0;y=0;maxy="$e";maxx="$w";beenhere=0 | |
read_keys() | |
{ | |
key="";read -sn1 key | |
case "$key" in | |
A) ((y--));if ((y < 0));then y=0;fi | |
;; | |
B) ((y++));if ((y > maxy));then ((y--));fi | |
;; | |
D) ((x--));if ((x < 0));then x=0;fi | |
;; | |
C) ((x++));if ((x > maxx));then ((x--));fi | |
;; | |
i) ((it = it + 50));tput cup $maxy 0;echo -en "$red ITERATIONS = $it $off" | |
;; | |
z) ((zoom++));beenhere=1 | |
;; | |
esac | |
} | |
while ((zoom != 2)) | |
do | |
if ((zoom == 1)) && ((beenhere == 1));then x1="$x";y1="$y";beenhere=0;fi | |
if ((zoom == 2)) && ((beenhere == 1));then x2="$x";y2="$y";beenhere=0;zoom=3;fi | |
if ((zoom != 2));then read_keys;fi | |
if ((beenhere == 0));then tput cup $y $x;echo -en "$wht#$off";fi | |
done | |
X1="$x1";Y1="$y1";X2="$x";Y2="$y";Y1org="$Y1";X1org="$X1";X2org="$X2" | |
if ((X1 >= X2));then clear;echo;echo "X2 MUST BE GREATER THAN X1";echo;exit;fi | |
#### DRAW CRAPPY BOX | |
((dif = X2 - X1));xx="$X1";((xxx = xx + dif));tput cup $Y1 $X1 | |
while ((xx < xxx)) | |
do | |
((xx++));tput cup $Y1 $xx;echo -en "$wht#$off" | |
done | |
xx="$Y1";((xxx = xx + (dif >> 1)));tput cup $Y1 $X1 | |
while ((xx < xxx)) | |
do | |
((xx++));if ((xx > maxy)); then xxx="$maxy";fi | |
tput cup $xx $X1;echo -en "$wht#$off" | |
done | |
Y2="$xx";((xx = X1));tput cup $Y2 $X1;((xxx = X1 + dif)) | |
while ((xx < xxx)) | |
do | |
((xx++));tput cup $Y2 $xx;echo -en "$wht#$off" | |
done | |
xx="$Y1";((xxx = xx + (dif >> 1)));((X1 = X1 + dif));tput cup $Y1 $X1 | |
while ((xx < xxx)) | |
do | |
((xx++));if ((xx > maxy)); then xxx="$maxy";fi | |
tput cup $xx $X1;echo -en "$wht#$off" | |
done | |
#### SET COORDINATES FOR ZOOMED IN AREA | |
nc=$(echo "scale=$pre;(($X1org*$gr)+$c)" | bc) | |
nk=$(echo "scale=$pre;(($Y1org*$hr)+$k)" | bc) | |
nsi=$(echo "scale=$pre;(($X2org-$X1org)*$gr)" | bc) | |
c="$nc";k="$nk";si="$nsi";ngc=0;mhk=0;gc=0;hk=0 | |
sleep 1 | |
} | |
#### THE INFINITE LOOP | |
while [ 1 ] | |
do | |
mandelbrot | |
tput cup $maxy 0;echo -en "$grn READY TO ZOOM IN $off" | |
zoomin | |
done | |
exit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment