返回列表 回复 发帖
57# lnszdzg
很好啊!说明这个帖子的讨论还是有点价值的,讨论的过程中,我们并没有纠结在编程语言本身上,其目的就是希望大家不要被语言束缚,设计模式才是最重要的。
很多的迭代模型需要用到 z,c 以外的参数,所以,窗体中新加了 A,B 相应的输入框,后面的newton,nova 要用到 Q,R,这里预先一并加上。
    迭代模型数组形如:
    var mjModels=[{
    para:[],
    default:"",
    func:function(){}
    }},}
    ......
    }},{
    para:[],
    default:"",
    func:function(){}
    }}];
    较之前面的 mjColoring 和 mjTransForm,这里每个元素多设了一个 default 属性,用来记载那些刁钻的参数值,程序没有给出相应的处理代码(大家可以自己试着开发),只是显示在界面中以作提示之用。
    另外,如果把:
    var iterator=function(x,y,a,b)
    {
        return mjModels[mdx].func(x,y,a,b);
    }
    改成:
    iterator=mjModels[mdx].func
    程序的运行速度要快一些,画布越大效果越明显。由于加入了三十几个迭代模型,代码量急剧增加,不过,核心代码就那么几十行。
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
a.jpg
htm0401.rar (6.49 KB)
基于下面的算法,程序给出了六个 newton 迭代模型:
newton: z=z-R[f(z)+c]/f'(z)
   nova: z=z-R[f(z)/f'(z)]+c
    窗体中增加了一个 newton/nova 切换开关 nt 复选框,迭代模型中的实现代码为:
nTa=nT*a,nTb=nT*b
nVa=(1-nT)*a,nVb=(1-nT)*b
    其中:
nT=1 或 0
    也就是:
z=z-R{[f(z)+(nTa,nTb)]/f'(z)}+(nVa,nVb)
     当 R=(1,0) 时,上式便在标准的 newton 和 nova 之间切换。
     就我本人所知道的有关复变分形的知识,程序已接近尾声,在不影响原结构的基础上对程序代码作了较大幅度的调整。
b.jpg
c.jpg
d.jpg
e.jpg
f.jpg
g.jpg
h.jpg
i.jpg
j.jpg
k.jpg
htm0402.rar (7.29 KB)
如果算法改成:
newton: z=R{z-[f(z)+c]/f'(z)}
   nova: z=R{z-[f(z)/f'(z)]}+c
M 集变得疯狂起来,J 集则更加繁复:
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
a.jpg
接下来就是在程序中增加 julia 粒子模块,代码稍为艰难一点,所以,我们的讨论将暂告一段落,稍停一会,祝大家学习愉快!
htm0403.rar (7.31 KB)
前面发过一个题为“逝去的美丽_朱丽娅粒子”的帖子,之所以说是“逝去的美丽”,是因为人们通常是在给定阈值的前提下,欣赏其临界点整个参数平面内 Mandbrot 集和 Julia 集的最终结构,然而,在形成这种最终结构之前,迭代模型的迭代轨迹却被人们忽视,这种迭代轨迹,就像流星的轨迹一样,消失在过去的时光里,如果换个角度去观察它,我们会发现,它是非常绚丽多姿的。
    这里所说的轨迹并非横向的而是纵向的:迭代模型中,e 数组记录下了某一特定点经过迭代而产生的一组数据,这一组数据所表示的轨迹,是为横向轨迹,暂且把它叫做 julia 粒子,而平面内某一路径上所有点的 julia 粒子的集合,我们称之为纵向轨迹,或者说是 julia 粒子系统。(我不懂专业,这里的用辞纯属杜撰,能说明白就好)
    为简单见,特归纳如下:

    Mandbrot 集:c 变 z 不变,扫描二维平面
       Julia 集:z 变 c 不变,扫描二维平面
     Julia 粒子:z,c 同时变,扫描一维路径

    程序中所使用的路径是两点间的线段,如果用曲线路径,代码会更加复杂。
    依上所述,程序在窗体中加入了一个用来输入两点坐标和显示路径的画布 lCanvas,一个用来显示 julia 粒子的画布 pCanvas,以及 Pt(Et倍数)、Lw(线宽)、Ps(路径上的扫描点数)等参数输入框。
    路径参数的输入与 29 楼的万花曲线规相同,至于算法,代码并不复杂,只是多了一个动画效果,相信大家花点时间是不会有什么困难的。
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
a.jpg
    为什么叫“julia 粒子”而不叫“mandbrot 粒子”呢?我们将在接下来的也是最后的一节中讨论“julia 图谱”时再详细说明。
htm0502.rar (8.47 KB)
很多文章都有讨论 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 集图谱!
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
a.jpg
好了,程序写到这里,基本的功能模块都有了,由于 html5 还在开发完善中,.hta 格式的应用程序暂时还未能支持 canvas 画布。剩下的就是图像的渲染,如:陷阱、场线、光照、山水……等等,老师们都是高手,我可是江郎才尽了。真心的祝愿各位老师早日开发出自己的分形软件。
htm0503.rar (8.81 KB)
谢谢推荐那么精彩的帖子,拜读了,以杜老师现在的水平,作个分形软件是没问题的。因我对分形知识的了解非常有限,所以,这个帖子只能就编程谈些粗浅的看法,虽不能在软件开发方面作更广和更深的展开,如能给大家带来一星半点的帮助,也就非常满足了。学习是相互的,一齐努力吧!!!
老港老师的画板技术已是登峰造极,别说是我们,就是画板的作者,都应该向您致敬!再次谢谢老师们对本贴的支持!!!
    从上面的讨论可以看出:就 julia 集和 mandbrot 集的关系来说,mandbrot 集承载的是宏观体系,而 julia 集则蕴涵的是微观结构,这就好像现实世界的整个宇宙天体和物质粒子一样,所以,当我们在缩放 mandbrot 集时,实际上是用天文望远镜或宇宙飞船在观察广袤的宏观宇宙,而缩放 julia 集就好像是用电子显微镜或纳米机器人在探索深邃的微观粒子。
    然而,大家知道,宇宙中是存在着黑洞的。对于 mandbrot 集来说,如果是在标准的 c 平面上,虽然多有黑黑的大块,也还不至于有什么特别的感觉,但是,c 平面一经扭曲变形,情形就不同了。比方说:1/c 平面,所有的图像都被黑色包围。如果宇宙中的某个黑洞也这样翻转过来,不知道是个什么样的场景,应该是很恐怖的。
    于是,我们在常规的迭代模型中加入一个类似于 newton 迭代算法中的收敛性监察代码,当迭代轨迹中的前后两点的变化小于给定的阈值,则停止迭代,使得那些令人迷茫的黑洞变得光亮起来:
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
a.jpg
htm0504.rar (9.16 KB)
70# lnszdzg


    多谢鼓励,老师们的垂青令我汗颜,特别是月城老师,真是个有心人,不胜惶恐。程序写到 julia 图谱,我真的是黔驴技穷了。
    下午在网上看到老外的两个分形:
    lemon:cz^2(z^2+1)/(z^2-1)^2.....http://paulbourke.net/fractals/lemon/
    Guitar:(z^2+z)/(2z^2+c)..........http://paulbourke.net/fractals/guitar/
    摸索了半天,才意识到了 mandbrot 集里面的“黑洞”问题。
复变分形的着色算法对于我来说是个新的课题,前面的程序虽给出了一些代码,是因为编程的需要,都不成熟,甚至有点乱,老师们的那些高端算法,我暂时还不能企及,只能从最基本的开始学习,考虑到还有很多和我一样的初学者,所以,在学习过程中,一有心得,便与大家交流,还望各位老师不吝赐教!
    下面是“逃逸角度”着色算法:(不知道专业上怎么说,只能杜撰了)
    func:function(e)
    {
        var et=e.length-1,ex=e[et].x,ey=e[et].y;
        var co=color[fc].concat(255);
        if(et%eT)
        {
            var sa=sqrt(abs(arct(ey,ex)/pi));
            var ca=sqrt(abs(arct(ex,ey)/pi));
            co[0]=255*sin(sa);            //r 通道
            co[1]=255*sin(ca);            //g 通道
            co[2]=255*sin(sa)*sin(ca);    //b 通道
            co[3]=255*sqrt(et/eT);    //逃逸时间映射 alpha 通道
        }
        return co;
    }
    改变 r、g、b 三个通道的函数模型便得到很多的着色效果:
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
a.jpg
返回列表