课后作业3
Q1. 三个分形图形生成的程序解释 每行代码有什么用
newton.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 function seta =f_arg (x,y) if x==0 if y>=0 seta=pi /2 ; else seta=-pi /2 ; end elseif x>0 seta=atan (y/x); elseif x<0 && y>=0 seta=pi +atan (y/x); elseif x<0 && y<0 seta=-pi +atan (y/x); else seta=pi /2 ; end end function f =f_iterat (x,y,n,m,delta) f=0 ; for k=1 :m r=sqrt (x^2 +y^2 ); if r==0 r=1e-9 ; end seta=f_arg(x,y); x2=((n-1 )*r*cos (seta)+r^(1 -n)*cos ((1 -n)*seta))/n; y2=((n-1 )*r*sin (seta)+r^(1 -n)*sin ((1 -n)*seta))/n; dis=sqrt ((x2-x)^2 +(y2-y)^2 ); if dis<delta f=k; break end x=x2; y=y2; end end function newton (n) %牛顿迭代法产生分形图片clc m=16 ; a1=-3 ; a2=3 ; b1=-2 ; b2=2 ; delta=0.001 ; hold on for x=a1:0.02 :a2 for y=b1:0.02 :b2 f=f_iterat(x,y,n,m,delta); if f>0 switch rem (f,7 ) case 0 plot (x,y,'w.' ); case 1 plot (x,y,'b.' ); case 2 plot (x,y,'r.' ); case 3 plot (x,y,'y.' ); case 4 plot (x,y,'g.' ) ; case 5 plot (x,y,'c.' ) ; case 6 plot (x,y,'m.' ); end end end end hold off end
这是一个用于生成牛顿分形(Newton Fractal) 图像的 MATLAB 程序。牛顿分形是通过牛顿迭代法求解复数域上的方程 z^n - 1 = 0 时,根据初始点的不同,迭代收敛到不同根的速度来着色的。
整个程序由三个函数组成:
newton(n): 主函数,负责设置绘图区域、遍历像素点并调用迭代函数,最后根据结果绘图。
f_iterat(…): 核心迭代函数,对给定的初始点 (x, y) 进行牛顿迭代,并返回收敛所需的迭代次数。
f_arg(x,y): 辅助函数,用来计算一个点(复数)的辐角(angle),即 atan2(y,x) 的功能。
juliaSet.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 phi = inline('z^2 - 1.25' ); fixpt1 = (1 + sqrt (6 ))/2 ; fixpt2 = (1 - sqrt (6 ))/2 ; colormap([1 0 0 ; 1 1 1 ]); M = 2 *ones (141 ,361 ); for j =1 :141 , y = -.7 + (j -1 )*.01 ; for i =1 :361 , x = -1.8 + (i -1 )*.01 ; z = x + 1 i *y; zk = z; iflag1 = 0 ; iflag2 = 0 ; kount = 0 ; while kount < 100 & abs (zk) < 2 & iflag1 < 5 & iflag2 < 5 , kount = kount+1 ; zk = phi(zk); err1 = abs (zk-fixpt1); if err1 < 1.e-6 , iflag1 = iflag1 + 1 ; else iflag1 = 0 ; end ; err2 = abs (zk-fixpt2); if err2 < 1.e-6 , iflag2 = iflag2 + 1 ; else iflag2 = 0 ; end ; end ; if iflag1 >= 5 | iflag2 >= 5 | kount >= 100 , M(j ,i ) = 1 ; end ; end ; end ;image([-1.8 1.8 ],[-.7 .7 ],M), axis xy
代码核心逻辑是:对复平面上特定区域(实部 [-1.8,1.8]、虚部 [-0.7,0.7])内的大量初始点,通过迭代函数phi(z)=z²-1.25生成轨道,判断轨道是否有界(收敛到不动点或迭代 100 次仍未发散)。有界点标记为红色,无界点(快速发散)标记为白色,最终绘制出该迭代过程的分形边界图案
yoda.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 load yodapose_low Vt = V; clf patch('Vertices' ,Vt,'Faces' ,F3,'FaceColor' ,[.76 .87 .78 ]); patch('Vertices' ,Vt,'Faces' ,F4,'FaceColor' ,[.76 .87 .78 ]); axis tight equal vis3d drawnow slides = 24 ; yMinValue = min (V(:,2 ,:)); axisValues = axis; yAxesMax = axisValues(4 ); shift = (yAxesMax - yMinValue)/slides; [n,m] = size (V); T = [zeros (n,1 ),shift*ones (n,1 ),zeros (n,1 )]; theta=0 :pi /24 :pi /2 ; n=length (theta); for i =1 :n R=[cos (theta(i )) 0 -sin (theta(i ));0 1 0 ;sin (theta(i )) 0 cos (theta(i ))]; Vt = Vt*R; cla patch('Vertices' ,Vt,'Faces' ,F3,'FaceColor' ,[.76 .87 .78 ]); patch('Vertices' ,Vt,'Faces' ,F4,'FaceColor' ,[.76 .87 .78 ]); axis(axisValues) drawnow hold on pause(0.2 ) end
代码核心功能是:加载一个 3D 模型(包含顶点 V 和两个面集合 F3、F4),先显示模型初始状态,然后通过循环实现模型的旋转动画 (绕 y 轴从 0° 旋转到 90°,分 13 帧,每帧暂停 0.2 秒)。
Q2. 根据三种方法创造自己的分形图形
newton
只需要取一个迭代次数n即可,这里取n = 10 n=10 n = 1 0
代码:
1 2 3 clear n = 10 ; newton(n);
结果:
juliaSet
要想创造新的分形图形只需要修改迭代公式即可,这里将迭代公式定为:
z 2 + 0.285 + 0.01 i z^2+0.285+0.01i
z 2 + 0 . 2 8 5 + 0 . 0 1 i
则通过下式求其不动点
z 2 − x + 0.285 + 0.01 i = 0 z^2-x+0.285+0.01i=0
z 2 − x + 0 . 2 8 5 + 0 . 0 1 i = 0
最终代码为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 phi = inline('z^2 + 0.285 + 0.01i' ); fixpt1 = (1 + 4 *(0.285 + 0.01 i ))/2 ; fixpt2 = (1 - 4 *(0.285 + 0.01 i ))/2 ; colormap([1 0 0 ; 1 1 1 ]); M = 2 *ones (141 ,361 ); for j =1 :141 , y = -.7 + (j -1 )*.01 ; for i =1 :361 , x = -1.8 + (i -1 )*.01 ; z = x + 1 i *y; zk = z; iflag1 = 0 ; iflag2 = 0 ; kount = 0 ; while kount < 100 & abs (zk) < 2 & iflag1 < 5 & iflag2 < 5 , kount = kount+1 ; zk = phi(zk); err1 = abs (zk-fixpt1); if err1 < 1.e-6 , iflag1 = iflag1 + 1 ; else iflag1 = 0 ; end ; err2 = abs (zk-fixpt2); if err2 < 1.e-6 , iflag2 = iflag2 + 1 ; else iflag2 = 0 ; end ; end ; if iflag1 >= 5 | iflag2 >= 5 | kount >= 100 , M(j ,i ) = 1 ; end ; end ; end ;image([-1.8 1.8 ],[-.7 .7 ],M), axis xy
结果:
yoda
这里通过python将奶龙的obj格式3D文件转换为mat文件
python程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 import numpy as npfrom scipy.io import savematimport pywavefrontdef obj_to_mat (obj_file_path, mat_file_path ): """ 将OBJ文件转换为包含V、F3、F4的MAT文件(匹配示例格式) """ scene = pywavefront.Wavefront( obj_file_path, collect_faces=True , parse=True ) V = [] F3 = [] F4 = [] if hasattr (scene, 'vertices' ) and scene.vertices: V = np.array(scene.vertices) for mesh in scene.mesh_list: if hasattr (mesh, 'faces' ) and mesh.faces: for face in mesh.faces: face_indices = np.array(face) + 1 if len (face_indices) == 3 : F3.append(face_indices) elif len (face_indices) == 4 : F4.append(face_indices) data = {} if V.size > 0 : data['V' ] = V if F3: data['F3' ] = np.array(F3) if F4: data['F4' ] = np.array(F4) savemat(mat_file_path, data) print (f"成功转换:{obj_file_path} -> {mat_file_path} " ) print (f"包含的数据:{list (data.keys())} (V:顶点, F3:三角形面, F4:四边形面)" ) if __name__ == "__main__" : obj_file = "nailong1.obj" mat_file = "nailong.mat" obj_to_mat(obj_file, mat_file)
通过修改变换矩阵,使得3D模型绕x轴旋转,由于这个模型的面数比较多,需要将面边缘的线画的更细,并加上一定的透明度,来获得更好的显示效果。
最终代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 clear shg load nailong Vt = V; clf; hold on;axis equal vis3d; patch('Vertices' ,V,'Faces' ,F3,'FaceColor' ,[.76 .87 .78 ],'EdgeColor' ,'k' ,'EdgeAlpha' ,0.1 ,'LineWidth' ,0.1 ); drawnow; slides = 24 ; yMinValue = min (V(:,2 )); shift = (max (V(:,2 )) - yMinValue + 0.1 *max (V(:,2 ))) / slides; n = size (V,1 ); T = [zeros (n,1 ), shift*ones (n,1 ), zeros (n,1 )]; theta = 0 :pi /6 :2 *pi ; n_theta = length (theta); for i = 1 :n_theta R = [1 0 0 ; 0 cos (theta(i )) -sin (theta(i )); 0 sin (theta(i )) cos (theta(i ))]; Vt_rot = Vt * R; cla; patch('Vertices' ,Vt_rot,'Faces' ,F3,'FaceColor' ,[.76 .87 .78 ],'EdgeColor' ,'k' ,'EdgeAlpha' ,0.1 ,'LineWidth' ,0.1 ); axis tight; axis equal; drawnow; pause(0.2 ); end hold off;
结果:
Q3. 牛顿迭代法产生分形图形时给大家的程序是用极坐标的形式来求复数根,请把牛顿迭代求复数跟的极坐标形式推导出来
这个分形图形是通过求解复数方程 z n − 1 = 0 z^n - 1 = 0 z n − 1 = 0 的根而产生的。这个方程在复数平面上有 n 个根,它们均匀分布在单位圆上。
牛顿迭代法的公式为:
z k + 1 = z k − f ( z k ) f ′ ( z k ) z_{k+1} = z_k - \frac{f(z_k)}{f'(z_k)}
z k + 1 = z k − f ′ ( z k ) f ( z k )
其中,z k z_k z k 是第 k 次迭代的近似解,z k + 1 z_{k+1} z k + 1 是下一次迭代的解。
我们要求解的方程是 z n − 1 = 0 z^n - 1 = 0 z n − 1 = 0 。
所以,我们的目标函数是:
f ( z ) = z n − 1 f(z) = z^n - 1
f ( z ) = z n − 1
对它求导,得到:
f ′ ( z ) = n z n − 1 f'(z) = n z^{n-1}
f ′ ( z ) = n z n − 1
将 f ( z ) f(z) f ( z ) 和 f ′ ( z ) f'(z) f ′ ( z ) 代入基本公式:
z k + 1 = z k − z k n − 1 n z k n − 1 z_{k+1} = z_k - \frac{z_k^n - 1}{n z_k^{n-1}}
z k + 1 = z k − n z k n − 1 z k n − 1
⇒ z k + 1 = n z k n − z k n + 1 n z k n − 1 \Rightarrow z_{k+1}=\frac{nz_{k}^{n}-z_{k}^{n}+1}{nz_{k}^{n-1}}
⇒ z k + 1 = n z k n − 1 n z k n − z k n + 1
⇒ z k + 1 = ( n − 1 ) z k n + 1 n z k n − 1 \Rightarrow z_{k+1}=\frac{(n-1)z_{k}^{n}+1}{nz_{k}^{n-1}}
⇒ z k + 1 = n z k n − 1 ( n − 1 ) z k n + 1
⇒ z k + 1 = ( n − 1 ) z k n n z k n − 1 + 1 n z k n − 1 \Rightarrow z_{k+1}=\frac{(n-1)z_{k}^{n}}{nz_{k}^{n-1}}+\frac{1}{nz_{k}^{n-1}}
⇒ z k + 1 = n z k n − 1 ( n − 1 ) z k n + n z k n − 1 1
⇒ z k + 1 = n − 1 n z k + 1 n z k 1 − n \Rightarrow z_{k+1}=\frac{n-1}{n}z_k+\frac{1}{n}z_{k}^{1-n}
⇒ z k + 1 = n n − 1 z k + n 1 z k 1 − n
设当前点 z k = x + i y z_k = x + iy z k = x + i y 。其极坐标形式为:
z k = r ( cos θ + i sin θ ) z_k = r(\cos\theta + i\sin\theta)
z k = r ( cos θ + i sin θ )
其中,r = x 2 + y 2 r = \sqrt{x^2 + y^2} r = x 2 + y 2 是模长,θ = arg ( z k ) \theta = \arg(z_k) θ = arg ( z k ) 是辐角。
根据棣莫弗定理(De Moivre’s formula),复数的幂在极坐标下计算非常方便:
z k m = [ r ( cos θ + i sin θ ) ] m = r m ( cos ( m θ ) + i sin ( m θ ) ) z_k^m = [r(\cos\theta + i\sin\theta)]^m = r^m(\cos(m\theta) + i\sin(m\theta))
z k m = [ r ( cos θ + i sin θ ) ] m = r m ( cos ( m θ ) + i sin ( m θ ) )
我们将这个定理应用到迭代公式 z k + 1 = n − 1 n z k + 1 n z k 1 − n z_{k+1} = \frac{n-1}{n} z_k + \frac{1}{n} z_k^{1-n} z k + 1 = n n − 1 z k + n 1 z k 1 − n 的第二项:
z k 1 − n = r 1 − n ( cos ( ( 1 − n ) θ ) + i sin ( ( 1 − n ) θ ) ) z_k^{1-n} = r^{1-n}(\cos((1-n)\theta) + i\sin((1-n)\theta))
z k 1 − n = r 1 − n ( cos ( ( 1 − n ) θ ) + i sin ( ( 1 − n ) θ ) )
现在,把 z k z_k z k 和 z k 1 − n z_k^{1-n} z k 1 − n 的极坐标形式代回到迭代公式中:
z k + 1 = n − 1 n [ r ( cos θ + i sin θ ) ] + 1 n [ r 1 − n ( cos ( ( 1 − n ) θ ) + i sin ( ( 1 − n ) θ ) ) ] z_{k+1} = \frac{n-1}{n} [r(\cos\theta + i\sin\theta)] + \frac{1}{n} [r^{1-n}(\cos((1-n)\theta) + i\sin((1-n)\theta))]
z k + 1 = n n − 1 [ r ( cos θ + i sin θ ) ] + n 1 [ r 1 − n ( cos ( ( 1 − n ) θ ) + i sin ( ( 1 − n ) θ ) ) ]
合并实部:
x = Re ( z k + 1 ) = n − 1 n r cos θ + 1 n r 1 − n cos ( ( 1 − n ) θ ) x = \text{Re}(z_{k+1}) = \frac{n-1}{n}r\cos\theta + \frac{1}{n}r^{1-n}\cos((1-n)\theta)
x = Re ( z k + 1 ) = n n − 1 r cos θ + n 1 r 1 − n cos ( ( 1 − n ) θ )
⇒ x = 1 n [ ( n − 1 ) r cos θ + r 1 − n cos ( ( 1 − n ) θ ) ] \Rightarrow x=\frac{1}{n}[(n-1)r\cos \theta +r^{1-n}\cos\mathrm{((}1-n)\theta )]
⇒ x = n 1 [ ( n − 1 ) r cos θ + r 1 − n cos ( ( 1 − n ) θ ) ]
合并虚部:
y = Im ( z k + 1 ) = n − 1 n r sin θ + 1 n r 1 − n sin ( ( 1 − n ) θ ) y = \text{Im}(z_{k+1}) = \frac{n-1}{n}r\sin\theta + \frac{1}{n}r^{1-n}\sin((1-n)\theta)
y = Im ( z k + 1 ) = n n − 1 r sin θ + n 1 r 1 − n sin ( ( 1 − n ) θ )
⇒ y = 1 n [ ( n − 1 ) r sin θ + r 1 − n sin ( ( 1 − n ) θ ) ] \Rightarrow y=\frac{1}{n}[(n-1)r\sin \theta +r^{1-n}\sin\mathrm{((}1-n)\theta )]
⇒ y = n 1 [ ( n − 1 ) r sin θ + r 1 − n sin ( ( 1 − n ) θ ) ]
即
z k = 1 n [ ( n − 1 ) r cos θ + r 1 − n cos ( ( 1 − n ) θ ) ] + 1 n [ ( n − 1 ) r sin θ + r 1 − n sin ( ( 1 − n ) θ ) ] i z_k=\frac{1}{n}[(n-1)r\cos \theta +r^{1-n}\cos\mathrm{((}1-n)\theta )]+\frac{1}{n}[(n-1)r\sin \theta +r^{1-n}\sin\mathrm{((}1-n)\theta )]i
z k = n 1 [ ( n − 1 ) r cos θ + r 1 − n cos ( ( 1 − n ) θ ) ] + n 1 [ ( n − 1 ) r sin θ + r 1 − n sin ( ( 1 − n ) θ ) ] i