返回列表 回复 发帖
关于数据的输入,到现在暂且告一段落,接下来讨论作图,也即 html5 的画布 canvas。
    在此之前,我们稍事休息,有两个问题在这里说明一下:
    一、这里的讨论有一个默认的前提,那就是各位朋友应该对编程语言具备一定的知识,这种知识的来源有两个途径,首先,所有的编程语言都有相通的地方;其次,对于 html、css、javascript 这三种语言的细节,应该先作些功课,我手上倒是有些资料,打了个包,260 MB,可我不知道怎么传,如有需要,给个邮箱地址。
    二、解释一下本贴的主题“几何画板下的编程思考”。
    前面提到过,几何画板作为很多算法的形象演练,是个绝妙的工具,比方说,hilbert 曲线的制作,除了原生的字符串重写系统,其他的诸如,迭代、递归、矩阵都可以,但不怎么轻松。然而在几何画板里,通过逆向思维,把 hilbert 曲线的过程倒过来,竟然找到了一种既简单又巧妙的方法。各位老师的画板作品,更是让我心动,虽然弄不明白其中的数学原理,却使我明白了一个道理,我们原来编的程序都是那么生硬,是因为没有在数据可视化上下功夫。
    下面就是受几何画板的启发编写的万花曲线规(须在 ie10 下运行),如果可以继续的话,后面将以它为蓝本进行讨论。
htm0010.jpg
万花曲线规html.rar (2.18 KB)
谢谢各位老师,很专业,也很诚恳,真的是很高兴。
    如果不嫌冒昧的话,我在这里想和大家说几句推心置腹的话:几何画板作复变分形,体现出了老师们超凡卓越的能力,给人们展现的不仅仅是专业上的造诣,更多的是精神上的感动,至少我是被感动了。我总是觉得,老师们的业绩非常伟大,但也未免太过悲壮,几何画板玩分形,太辛苦了,希望老师们别怪罪,我说的是心里话。
    无论是几何画板还是复变分形,我真的不敢恭维自己。老师们越是包容我心里越是惭愧,跟着这个论坛学了这么多东西,怎么样才能对得起大家呢,开这个帖子的时候,我是犹豫了很久的:就 javascript 而言,深度和广度我都不具备,myzam 老师说得对,javascript 资料、教程和网站有很多,这是画板论坛,在这里专门讨论 javascript 是很不合时宜的。想了很久,最后大起胆子决定以“几何画板下的编程思考”为题来展开讨论,我知道这个祸闯大了,第一,对于我来说,题目太大了,编程的思维模式和行为习惯是个仁者见仁智者见智的问题。第二,这个题目不准确,让人以为是要对几何画板的功能进行编程模拟,在此特向大家道歉!
    我想把题目改成:“几何画板带给编程者的思考”,又觉得怪怪的,我的意思是:就编程来说,几何画板改变了我的行为习惯和思维模式。唉,总之,说来说去,结结吧吧的。哪位老师若有高见,请不吝赐教,谢谢了!
    实际上,脚本语言 javascript 是编程世界里的一个冤大头,对于不熟悉它的人来说,其问题出在“脚本”二字上,这里不展开,只是建议大家从认识上去掉“脚本”两个字,javascript 它就是一门纯粹的算法语言。对于熟悉它的人来说,建议看一下
    http://blog.csdn.net/uoyevoli/article/details/744915
和其他的有关文章。重复一下:javascript 作为 web 浏览器的前端脚本语言有着渗透网络世界所有领域的趋势。
    这个帖子之所以到现在要歇一下,就是希望得到各位老师的提携和指点,以使帖子朝着正确的方向走下去(如果可以的话)。
    上面贴出的那个“万花曲线规”,不是要讨论它的算法和实现,而是我们将要讨论更为高级的一种数据输入方式:屏幕输入。
    再次谢谢各位老师的包容和指教!!!
就软件界面而言,如果程序只涉及到文本,数据的输入有了前面介绍的两种方式即:键盘输入和鼠标输入(不是很准确)也可以应付一般的情况了。若需要绘图,则屏幕输入方式就显得非常重要。比方说:作复变分形时,在 mandbrot 集中寻找 julia 集,以及复分形的缩放,只用现有的输入方式会使得编程很是艰难。
    html5 用来处理图形图像的 canvas(画布) 元素,提供了一个二维接口 getContext('2d'),脚本语言就是通过这个接口来进行图形图像编程的。如:
      <canvas id=mCanvas width=300 height=200></canvas>
    这里放置了一个名为 mCanvas,宽高为 300,200 的画布,画布的默认状态是透明的。由于解释起来比较繁复和啰嗦,我都写入到了代码的注释里面。
New1.gif
canvas 绘图功能非常强大,虽然目前只提供 2D 接口,但当下网上关于 canvas 3D 应用的视觉冲击力简直是不可思议。就 2D 来说,photoshop 的很多功能和特效都可以通过 javascript 不难的编程实现,在动画方面,flash 已经不能望其项背了。
    从程序运行效果来看,现有的参数输入方式,已经显得很笨拙,必须改善其性能,不过接下来的讨论会稍为艰难一点,谢谢大家的耐心!
htm0100.rar (1.45 KB)
很多人不太愿意搭理 javascript,它不就是个前端脚本工具吗,做大型网站有的是后台脚本语言,况且,从美工的角度来考虑,有了html 和 css 网页就可以做得很炫很酷,只是在设计页面交互功能和简单动画时用到 javascript 而已。
    其实,简单的说,html+css+javascript 可以做两个方面的事情,一是做网页,二是做软件。做网页不是这个帖子讨论的内容,我们要讨论的是如何使用 javascript 开发软件,太多的人没朝这方面去想,尽管现在 javascript 像个疯子一样在网络世界横行霸道,但也只是个敲边鼓,跑龙套的角色。
    就软件开发而言:第一,网络世界涌现出越来越多的在线软件,像雨后春笋。第二,这个帖子的开篇有提示过,“把文件的扩展名 .htm 改为 .hta 然后双击该文件,好了,我们竟然开发出了一个软件!”,之所以这样说,首先这是事实,其次,这可以成为我们学习 javascript 的动力,为我们学习 javascript 找到一个足以自豪的理由!
    如果有学习过可视化编程,如:vb,vc,c#,我们会发现:在工程项目的代码文件夹中,主要的有两类文件,一是算法代码,二是窗体代码,算法代码就是一般意义上的数据处理的程序代码,这一点,帖子在后面的复变分形中会涉及一些,真要讨论算法的话,得另外开个专题。为扣主题,本贴只讨论第二个方面的问题,窗体代码,也就是软件的界面代码,为方便见,以后我们把软件的界面就称之为窗体,也就是 html 的 body 元素。
    窗体代码主要作三件事:
    1.在窗体(body)中放置程序需要的对象(元素)。
    2.给各对象添加事件。
    3.编写事件的响应代码。
    这就是可视化编程要做的事情,我们就按照这种结构来编写我们的 javascript 代码。大家从前一个文件 htm0100.htm 中可以看得出来,窗体中只放置了五六个对象,其代码就显得有些拥挤不堪。事实上,它不像软件代码,只是个网页代码而已,并且会给后面的编程带来难以想象的麻烦。
    为此,我们编写一个名为 formSetup 的窗体函数,里面再嵌套 initComponents 放置对象,addEvent 添加事件和相应事件响应等函数,如是,我们的代码看起来像这个样子:
<script>
    function drawing()
    {
    }
    function formSetup()
    {
        var dataVerify=function(){}
        var addEvent=function(){}
        var initComponents=function(){}
    }
</script>
<body></body>
    没有新的内容,只是调整了一下结构。到现在,我们这才真的有点编程、做软件的意思了!
htm0101.rar (1.91 KB)
程序编到这里,仍然有两个问题:
    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>
New.gif
这里,我们有一个基本的原则:除非万不得已,一般不在算法代码中处理窗体元素的各种数据,而算法中需要的各种参数,应该在窗体函数 formSetup 中预处理完毕后通过函数调用传递过去,开发大型软件时,这一点显得尤为重要。
htm0102.rar (1.42 KB)
由于代码是以万花曲线规为蓝本,代码中的 R、r、p 分别为定圆半径、动圆半径、笔孔。在程序输出窗口的画布中,设置了三个关键点:定圆圆心、动圆圆心、笔孔。为简化编程其中只有动圆圆心、笔孔被设置为可控屏幕点。R 由 mCanvas 的鼠标滚轮事件控制(这样安排主要是为了后面复分形的缩放留出代码空间),r、p 则通过 mCanvas 的鼠标拖拽来操纵。
    鼠标滚轮事件的代码很简单,和前面的一样,不再赘述。然而,鼠标拖拽却比较麻烦。一个鼠标拖拽动作包括三个事件:
    onmousedown 在对象上按下鼠标
    onmousemove 在对象上移动鼠标
      onmouseup 在对象上释放鼠标
    像大多数绘图软件的鼠标吸附(捕捉)功能一样,再加上一个吸附(捕捉)半径,就可以编写鼠标拖拽事件的程序代码了。
New1.gif
    关于数据输入,讨论到这里就告一段落了。由于我们编写的是小程序,窗体设计中的诸如菜单栏、工具条、快捷按钮,属性面板,弹出窗口等等,本贴就不再涉及了。
    万花曲线规中还用到动画效果和多图层技术,这些我们将留在后续的复分形编程中讨论。
htm0103.rar (1.89 KB)
30# 周传高
谢谢版主的提携,非常感谢!!!
大家都是玩复形的高手,所以,我们这里只需就程序设计的思路和代码的结构展开讨论。
    对于 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暂时没用。
3.gif
htm0201.rar (933 Bytes)
后面我们将一步一步地完善其代码。
前面讨论的 canvas 绘图用的是矢量模式,而作复分形是复平面的逐点扫描,必须用另外一种
模式,即位图模式。html5 用一维数组来存储 canvas 画布上从左到右从上到下每一个像素的颜色数据:r,g,b,a,分别为红、绿、蓝、alpha 通道(不透明度),其取值均为 0-255。
    这样,一维数组从第 0 个元素开始,每四个元素存储 canvas 画布的一个像素的颜色数据,
javascript 就是通过修改这个数组的各个元素的值来实现位图模式绘图的。
    在窗体代码中,我们增加了 initmSet 和 mSet 两个函数,前者用来初始化或重设扫描平面的数据,后者用来启动算法程序。
    在算法代码中,为简单见,我们使用的是 z=z^2+c 模型。原文件给出了详细的注释。
3.jpg

    在 ZR、ZI 的输入框中滚动鼠标,会看到一些在别的软件中不太容易看到的景象,我们的
代码才刚刚起步,就能有如此的成绩,相信大家会有兴趣走下去。
    后面的讨论会越来越艰难,我们将放慢节奏,祝大家学习愉快!!!
htm0202.rar (2.14 KB)
现在,我们在程序中增加缩放模块,下面是放大图像的原理图:
New.jpg
放大(缩小)图像实际上就是把当前的复平面裁剪(扩大)后重新映射到画布。对此,我们为 mCanvas 画布增加一个鼠标滚轮事件并在窗体代码中增加 scalePlane 和 changeET 两个函数,scalePlane 用来修改复平面,changeET 则用来修改逃逸时间阈值。
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
图像缩放的算法和屏幕输入的设计有很多,我们这里使用的是最简单的一种。当我们熟练了以后,就可以对其功能和模式进行扩展。
    程序编到这里,代码仍然是非常的简单,但是,它却可以让我们随着鼠标滚轮的滚动在硬件允许的精度下来探索 mandbrot 集中所有的细节。
htm0203.rar (2.21 KB)
返回列表