分形程序高级技巧入门教程--第九到十二章

                 分形程序高级技巧入门教程--第九到十二章
                         housisong@gmail.com

摘要:
    本系列文章是写给分形编程爱好者的一个入门教程;文章章节包括(规划中的,可能增删):
    一.复数迭代的mandelbrot集合; 二.颜色平滑的简单周期算法; 三.迭代逃逸次数插值的颜色平滑;
    四.使用sin函数做颜色平滑; 五.一个更有效的迭代逃逸次数插值公式; 六.使用误差扩散来杜绝色差感;
    七.集合内部的颜色; 八.julia集合; 九.迭代生成的复数值的插值;
    十.迭代生成的复数值的高阶插值; 十一.图形的放大和旋转; 十二.复数初始值的变换;
    十三.固定颜色表; 十四.设计图案的映射; 十五.纹理映射; 十六.并行计算;
    十七.更多的迭代方程和颜色方案; 十八.高次mandelbrot集合; 十九.其他分形的介绍、分形动画

正文:
   (9-12章完整项目源代码: http://cid-10fa89dec380323f.office.live.com/self.aspx/.Public/hssFractal9%5E_12.zip )
   (我的其他分形相关文章: http://blog.csdn.net/housisong/category/382024.aspx )


九.迭代生成的复数值的插值
   迭代逃逸时的复数值也可以作为颜色函数的参数,比如:


其中,把"迭代值"的距离值带入了颜色函数中,产生的图片如下:
(当然x和y值也可以作为颜色参数,甚至于整个迭代过程中产生的值都是不错的颜色参数!)

由于迭代次数的不同,造成生成的颜色产生了较强的阶梯;要去掉该阶梯我们可以进行一个简单的插值,
前面对迭代逃逸次数进行了插值(结果为iter),那么正好就可以用该值来对迭代值进行线性插值!
插值系数: s=iter-(long)iter; //得到0--1之间的一个值,用来表示两次迭代值之间的权重
插值方程: sx=x(i)*s+x(i-1)*(1-s);
          sy=y(i)*s+y(i-1)*(1-s);
这样得到的结果就是连续的了,代码如下:


生成的图片如下:


十.迭代生成的复数值的高阶插值
   前面得到的颜色结果虽然连续,但看起来还是不够平滑;这是因为两次迭代值之间的关系可能并不是线性的关系;
我们可能很难去推导出迭代值的实际关系,但我们可以用通用的高次插值曲线来近似的拟合它,
比如我们使用常用的3次卷积来试试:
插值系数: s=iter-(long)iter;
插值方程: sx=x(i)*SinXDivX(2-s)+x(i-1)*SinXDivX(1-s)+x(i-2)*SinXDivX(s)+x(i-3)*SinXDivX(1+s);
          sy=y(i)*SinXDivX(2-s)+y(i-1)*SinXDivX(1-s)+y(i-2)*SinXDivX(s)+y(i-3)*SinXDivX(1+s);
其中SinXDivX为:          
           (a+2)*x^3 - (a+3)*x^2 +1       (0<=x<1)
    h(x)=  a*x^3 - 5*a*x^2 + 8*a*x - 4*a  (1<=x<2)
           0                              (2<=x)
     (其中a一般取-0.5..-1)
代码如下:
     

生成的图片如下:


(可以试试卷积核中取不同a的效果)

在数据插值中,B样条插值(B-Spline)也是一个非常常用的插值算法,B样条插值的插值核:
           x^3/2 - x^2 + 2/3               (0<=x<1)
    h(x) = (2-x)^3/6                       (1<=x<2)
           0                               (2<=x)
代码如下:


生成的图片如下:

(这里的插值结果看起来比3次卷积的效果好些)

我把颜色函数稍微修改了一下,代码如下:

生成的图片如下:



重点:迭代过程中生成的数据都可以作为颜色函数的参数(color=f(iter,i,x[],y[],等);)!
更广义的迭代值插值函数为:
   z=g(s,t(z[k]),t(z[k-1]),...,t(z[k-(N-1)]));
  这里g代表插值核,s代表插值系数,t代表变换函数,z代表迭代值数组,k代表起始数组坐标(比如k=i-1),
  N代表使用迭代值的个数;
请试试,不同的k和各种t函数的效果!


十一.图形的放大和旋转
  我们前面定义的TViewRect{ double x0,y0,r};结构已经能很好的支持缩放了,调节r的大小
就是放大或缩小,x0和y0代表的是缩放的中心点; 要支持旋转,我们增加一个成员,
角度seta(单位为度):
 
坐标点(x,y)的旋转方程为:
    rsin=sin(viewRect.seta*(PI/180));
    rcos=cos(viewRect.seta*(PI/180));
    new_x= (x-viewRect.x0)*rcos + (y-viewRect.y0)*rsin + viewRect.x0;
    new_y=-(x-viewRect.x0)*rsin + (y-viewRect.y0)*rcos + viewRect.y0;
复数初始值在迭代前经过该旋转变换,就达到了旋转图片的目的,代码如下:


测试缩放和旋转的代码如下:



生成的图片如下:

(放大M集的一个小区域)

(旋转45度)


十二.复数初始值的变换
   复数初始值在迭代前可以经过旋转变换,当然也可以在该阶段经过更多的变换函数,
比如tan变换:

生成的图片如下:

复数倒数作为变换函数会怎样呢?

生成的图片如下:

(1/C面)

我们甚至也可以把其他分形算法合并进来,比如用julia迭代作为变换函数:

测试代码:


生成的图片如下:

 

 


  • 0
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值