F#中不同深度绘制分形的算法
algorithm for drawing xFractal at differents depths in F#
以上是本post标题中提到的xFractal。我需要实现一个函数,允许 f#sharp 使用辅助 img_Util 模块在不同的深度绘制分形。我被建议使用以下代码,它允许在不同深度绘制 sierpinski 三角形作为模板:
open ImgUtil
let rec triangle bmp len (x,y) =
if len < 33 then
setBox red (x,y) (x+len,y+len) bmp
else
let half = len / 2
do triangle bmp half (x+half/2,y)
do triangle bmp half (x,y+half)
do triangle bmp half (x+half,y+half)
do runSimpleApp "Sierpinski" 600 600 (fun bmp -> triangle bmp 512
(30,30) |> ignore)
但我用上面的模板尝试了很多不同的东西。我试过在基本情况下画一个正方形。我也试过让基本案例可以说是一片雪花。我可以让递归为每个新深度绘制最里面的元素,但我无法绘制其他所有元素。谁能帮我?向我解释算法?
这是另一个提示。对于 Sierpiński 三角形,从高度和宽度均为单位长度的等腰三角形开始。这样我们就不必担心我们正在绘制它的 canvas 的尺寸。对于每一代,将高度和宽度除以二。
对于您的 X,您需要将边除以三,而子级位置的偏移量由单位正方形大小的两倍的数字描述。
请注意,程序中有一个故意的错误:在三角形的情况下,它绘制了两次从起点发出的世代。
open System.Drawing
open System.Windows.Forms
let genLoops depth scale extent figure startPt =
let offsets dist (x, y) =
List.map (fun (ox, oy) ->
x + ox * dist, y + oy * dist )
let rec aux n size pt =
if n = 0 then
match offsets (size / extent) pt figure with
| [] -> invalidOp "Empty figure"
| p::ps -> [p::ps @ [p]]
else
pt::offsets (size / scale) pt figure
|> List.collect (aux (n - 1) (size / scale))
aux depth 1. startPt
type MyForm(loops) as this =
inherit Form()
let bm() = new Bitmap(this.ClientSize.Width, this.ClientSize.Height)
let mutable bitmap = bm()
let mapToPoint(x, y) =
Point(int(x * float(bitmap.Width - 1)),
int(y * float(bitmap.Height - 1)) )
override me.OnResize _ =
bitmap <- bm()
me.Invalidate()
override __.OnPaint arg =
let g = arg.Graphics
g.Clear Color.White
for loop in loops do
Seq.map mapToPoint loop
|> Seq.pairwise
|> Seq.iter (fun (p0, p1) ->
g.DrawLine (new Pen(Color.Black), p0, p1) )
g.DrawImage(bitmap, 0, 0)
let triangle = [0., 0.; -0.5, 1.; 0.5, 1.]
(new MyForm(genLoops 5 2. 1. triangle (0.5, 0.))).Show()
以上是本post标题中提到的xFractal。我需要实现一个函数,允许 f#sharp 使用辅助 img_Util 模块在不同的深度绘制分形。我被建议使用以下代码,它允许在不同深度绘制 sierpinski 三角形作为模板:
open ImgUtil
let rec triangle bmp len (x,y) =
if len < 33 then
setBox red (x,y) (x+len,y+len) bmp
else
let half = len / 2
do triangle bmp half (x+half/2,y)
do triangle bmp half (x,y+half)
do triangle bmp half (x+half,y+half)
do runSimpleApp "Sierpinski" 600 600 (fun bmp -> triangle bmp 512
(30,30) |> ignore)
但我用上面的模板尝试了很多不同的东西。我试过在基本情况下画一个正方形。我也试过让基本案例可以说是一片雪花。我可以让递归为每个新深度绘制最里面的元素,但我无法绘制其他所有元素。谁能帮我?向我解释算法?
这是另一个提示。对于 Sierpiński 三角形,从高度和宽度均为单位长度的等腰三角形开始。这样我们就不必担心我们正在绘制它的 canvas 的尺寸。对于每一代,将高度和宽度除以二。
对于您的 X,您需要将边除以三,而子级位置的偏移量由单位正方形大小的两倍的数字描述。
请注意,程序中有一个故意的错误:在三角形的情况下,它绘制了两次从起点发出的世代。
open System.Drawing
open System.Windows.Forms
let genLoops depth scale extent figure startPt =
let offsets dist (x, y) =
List.map (fun (ox, oy) ->
x + ox * dist, y + oy * dist )
let rec aux n size pt =
if n = 0 then
match offsets (size / extent) pt figure with
| [] -> invalidOp "Empty figure"
| p::ps -> [p::ps @ [p]]
else
pt::offsets (size / scale) pt figure
|> List.collect (aux (n - 1) (size / scale))
aux depth 1. startPt
type MyForm(loops) as this =
inherit Form()
let bm() = new Bitmap(this.ClientSize.Width, this.ClientSize.Height)
let mutable bitmap = bm()
let mapToPoint(x, y) =
Point(int(x * float(bitmap.Width - 1)),
int(y * float(bitmap.Height - 1)) )
override me.OnResize _ =
bitmap <- bm()
me.Invalidate()
override __.OnPaint arg =
let g = arg.Graphics
g.Clear Color.White
for loop in loops do
Seq.map mapToPoint loop
|> Seq.pairwise
|> Seq.iter (fun (p0, p1) ->
g.DrawLine (new Pen(Color.Black), p0, p1) )
g.DrawImage(bitmap, 0, 0)
let triangle = [0., 0.; -0.5, 1.; 0.5, 1.]
(new MyForm(genLoops 5 2. 1. triangle (0.5, 0.))).Show()