module Penrose
open System
open System.Drawing
open System.Drawing.Imaging
let xm = 1024
let ym = 768
let gl = (1.0 + Math.Sqrt(5.0)) / 2.0 // 黄金比
let OutBitmap = new Bitmap(xm, ym, PixelFormat.Format24bppRgb)
let g = Graphics.FromImage(OutBitmap)
g.Clear(Color.White)
let rot_point (x1, y1) (x2, y2) r n =
let x = (x2 - x1) * n
let y = (y2 - y1) * n
let r = r * (-1.0) * Math.PI
(x * Math.Cos(r) - y * Math.Sin(r) + x1,
x * Math.Sin(r) + y * Math.Cos(r) + y1)
let center (x1, y1) (x2, y2) =
((x2 - x1) / 2.0 + x1, (y2 - y1) / 2.0 + y1)
let draw_point (x1, y1) (x2, y2) c =
let ix1 = int x1
let ix2 = int x2
let iy1 = int y1
let iy2 = int y2
if ix1 <= xm + 100 && iy1 <= ym + 100 &&
ix1 >= -100 && iy1 >= -100 &&
ix2 <= xm + 100 && iy2 <= ym + 100 &&
ix2 >= -100 && iy2 >= -100 then
g.DrawLine(c, ix1, iy1, ix2, iy2)
let rec draw_list l c =
match l with
| [] -> ()
| h :: [] -> ()
| p1 :: p2 :: t ->
draw_point p1 p2 c
draw_list (p2 :: t) c
let rec make_kite a b n =
let c = rot_point a b 0.2 1.0
let d = rot_point a b 0.4 1.0
if n = 0 then
draw_list [a; b; c; d; a] Pens.Black
// draw_list [center a b; center c d] Pens.Red
// draw_list [center b c; center d a] Pens.Red
else
kite_deflation a b c d (n - 1)
and
kite_deflation a b c d n =
let e = rot_point b c 0.4 1.0
let f = rot_point d c -0.4 1.0
make_dart a e n
make_dart a f n
make_kite b c n
make_kite d f n
and
make_dart a c n =
let b = rot_point c a 0.6 1.0
let d = rot_point c a -0.6 1.0
if n = 0 then
draw_list [a;b;c;d;a] Pens.Black
// draw_list [center a b; center c d] Pens.Red
// draw_list [center b c; center d a] Pens.Red
else
dart_deflation a b c d (n - 1)
and
dart_deflation a b c d n =
let e = rot_point a c -0.2 1.0
let f = rot_point a c 0.2 1.0
make_kite a e n
make_dart b e n
make_dart d f n
let kite_dart a b c d n t =
let x = (a, b)
let y = (c, d)
if t = 0 then
make_dart x y n
else
make_kite x (rot_point x y -0.2 1.0) n
kite_dart -1000.0 200.0 2000.0 400.0 10 0
OutBitmap.Save(@".\Penrose.png", ImageFormat.Png)
g.Dispose()