function showMess()
{
var a=numA.value;
var b=numB.value;
var c=a-b;
var d=a*b;
var e=a/b;
a=parsInt(numA.value);
b=parsInt(numB.value);
var f=a+b;
messBox.innerText="A-B="+c+"\n"+
"A*B="+d+"\n"+
"A/B="+e+"\n"+
"A+B="+f;
}
程序编到这里,仍然有两个问题:
1.在输入框中输入数据后,须点击“绘图”按钮,输出窗口才会被刷新。
2.几乎所有的绘图软件都提供了另外一种所见所得的数据输入方式,对于这种几何图形,更直观的方式是通过拖动图形的关键点来即时改变其形状,我们暂且称之为屏幕输入。
这里先解决第一个问题,唯有如此,才能解决第二个问题。
进一步调整代码:
<script>
function Cycloid(){}
function formSetup()
{
var RR,rr,pp;
var drawing=function(){}
var resetCycle=function(){}
var dataVerify=function(){}
var initComponents=function(){}
var addEvent=function(){}
}
</script>
大家都是玩复形的高手,所以,我们这里只需就程序设计的思路和代码的结构展开讨论。
对于 mandbrot 集,我们有伪代码:
扫描 C 平面
{
对当前扫描点进行几何变换(如果需要的话).......变换模块
对当前点按给定的算法(如:z=z^2+c)进行迭代....迭代模块
根据迭代结果对当前点进行着色.................着色模块
}
把里面的功能模块独立出来写成函数,我们很容易就能写出 mandbort 集的 javascript 代码框架:
function Mandbrot()
{
var iterator=function(){} //迭代算法
var transPlane=function(){} //对扫描平面进行几何变换
var setColor=function(){} //设置当前扫描点的颜色
var scanCplane=function(){} //扫描 C 平面
}
在窗体代模块中,我们设置几个变量:
var Zr=0,Zi=0,Cr=0,Ci=0,eM=2,eT=20;
其中 z=(Zr,Zi)、c=(Cr,Ci)、eM(逃逸半径)、eT(逃逸时间),Cr、Ci暂时没用。
function Mandbrot(p,c,mC,M)//定义了一个 Mandbrot 函数
{
var iterator=function(x,y,a,b){} //Mandbrot内嵌函数
var transPlane=function(){} //Mandbrot内嵌函数
var setColor=function(e){} //Mandbrot内嵌函数
var scanCplane=function(){} //Mandbrot内嵌函数
var scanZplane=function(){} //Mandbrot内嵌函数
if(is_M)scanCplane();
else scanZplane();
} // Mandbrot 能完成一系列的功能,可以有返回值,也可以没有
function formSetup()
{
Mandbrot(p,c,mC,M);//调用 Mandbrot 函数
//这里的 Mandbrot 是一个完成特定功能的程序模块
//这就是结构化编程
}
=========================================
将代码调整为:
function Mandbrot()//定义了一个 Mandbrot 类(对象模板)
{
var iterator=function(x,y,a,b){} //Mandbrot私有方法
var transPlane=function(){} //Mandbrot私有方法
var setColor=function(e){} //Mandbrot私有方法
var scanCplane=function(){} //Mandbrot私有方法
var scanZplane=function(){} //Mandbrot私有方法
var showSet=function(p,c,mC,M) //Mandbrot私有方法
{
if(is_M)scanCplane();
else scanZplane();
}
前面发过一个题为“逝去的美丽_朱丽娅粒子”的帖子,之所以说是“逝去的美丽”,是因为人们通常是在给定阈值的前提下,欣赏其临界点整个参数平面内 Mandbrot 集和 Julia 集的最终结构,然而,在形成这种最终结构之前,迭代模型的迭代轨迹却被人们忽视,这种迭代轨迹,就像流星的轨迹一样,消失在过去的时光里,如果换个角度去观察它,我们会发现,它是非常绚丽多姿的。
这里所说的轨迹并非横向的而是纵向的:迭代模型中,e 数组记录下了某一特定点经过迭代而产生的一组数据,这一组数据所表示的轨迹,是为横向轨迹,暂且把它叫做 julia 粒子,而平面内某一路径上所有点的 julia 粒子的集合,我们称之为纵向轨迹,或者说是 julia 粒子系统。(我不懂专业,这里的用辞纯属杜撰,能说明白就好)
为简单见,特归纳如下:
Mandbrot 集:c 变 z 不变,扫描二维平面
Julia 集:z 变 c 不变,扫描二维平面
Julia 粒子:z,c 同时变,扫描一维路径
程序中所使用的路径是两点间的线段,如果用曲线路径,代码会更加复杂。
依上所述,程序在窗体中加入了一个用来输入两点坐标和显示路径的画布 lCanvas,一个用来显示 julia 粒子的画布 pCanvas,以及 Pt(Et倍数)、Lw(线宽)、Ps(路径上的扫描点数)等参数输入框。
路径参数的输入与 29 楼的万花曲线规相同,至于算法,代码并不复杂,只是多了一个动画效果,相信大家花点时间是不会有什么困难的。
很多文章都有讨论 julia 集和 mandbrot 集的关系,如:
mandbrot 集是 julia 集字典;
mandbrot 集是 julia 集缩略图;
mandbrot 集是 julia 集特征集;
mandbrot 集是宏观布局,julia 集是微观结构;
基于上术理由,我们就把形成结构前迭代轨迹中的所有点称之为 julia 粒子。
既然 mandbrot 集中的每一个点都是 julia 集,那么,我们可以这样理解:mandbrot 集是 c 平面的分辨率达到极限时 julia 集的集合,而每一个 julia 集则是在点平面 z 上的扫描图像。程序中,c 平面被映射到 720*480 的画布,被分成 720*480 个点,这时 c 平面的分辨率达到极限,我们看到的每一个 julia 集就是一个点了。
如果 c 平面的概念分辨率为 10*10,我们反过来将画布映射到 c 平面,那么,画布便被分割成 10*10 个小平面,尽管小,但每个平面包含有 72*48 个像素,比点平面大多了,当然,相应的 julia 集也就能显示其结构了。这样我们便得到了特定分辨率下的 julia 集图谱!
老港老师的画板技术已是登峰造极,别说是我们,就是画板的作者,都应该向您致敬!再次谢谢老师们对本贴的支持!!!
从上面的讨论可以看出:就 julia 集和 mandbrot 集的关系来说,mandbrot 集承载的是宏观体系,而 julia 集则蕴涵的是微观结构,这就好像现实世界的整个宇宙天体和物质粒子一样,所以,当我们在缩放 mandbrot 集时,实际上是用天文望远镜或宇宙飞船在观察广袤的宏观宇宙,而缩放 julia 集就好像是用电子显微镜或纳米机器人在探索深邃的微观粒子。
然而,大家知道,宇宙中是存在着黑洞的。对于 mandbrot 集来说,如果是在标准的 c 平面上,虽然多有黑黑的大块,也还不至于有什么特别的感觉,但是,c 平面一经扭曲变形,情形就不同了。比方说:1/c 平面,所有的图像都被黑色包围。如果宇宙中的某个黑洞也这样翻转过来,不知道是个什么样的场景,应该是很恐怖的。
于是,我们在常规的迭代模型中加入一个类似于 newton 迭代算法中的收敛性监察代码,当迭代轨迹中的前后两点的变化小于给定的阈值,则停止迭代,使得那些令人迷茫的黑洞变得光亮起来: