码迷,mamicode.com
首页 > 其他好文 > 详细

编程模拟自然(一):如何画一颗静态树

时间:2015-06-06 16:27:26      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

  万物初始之前,宇宙是无边无际混沌的黑暗,只有元之灵穿行其间。元对这无边的黑暗十分不满,就轻轻一敲键盘,说:“要有光”,于是世间就有了光。元称“光”为“昼”,称“黑暗”为“夜”。亮光隐去,黑暗重临,从此,世间就有了昼与夜的交替。这是元创世的第一天。

  这个二次元世界诞生之初伴有一只程序猿,Ta的名字叫元。


 

第一章 二叉树必须是最好的树!

  元就是这样想的,为了表达对这种数据结构的崇拜之情,决定在这个世界造出一颗真实的树,一开始的构想是这样的

技术分享

 

  “正所谓树极生三干,三干生六枝,六枝生十二叶。” 然而这并不是一颗二叉树。

 


 

第二章 黄金分割現れる

  树每递归一层需要按一定比例缩放,元苦苦冥想良久,终于找到了一个无限不循环小数,它的小数点后64位是这样的

  0.6180339887 4989484820 4586834365 6381177203 0917980576 2862135448 6227...

  [从左至右,比例系数依次是0.618, 0.5, 1, 1.6]

技术分享

  当然树干的粗细也得缩放,元是想将这东西种在伊甸园的土地上的,那就再截去下方的子树

技术分享
  
  “啊哈,这下叫二叉树没错了吧。”
 
  “既然配图这么暗黄,就称这个无理数为黄金分割比例吧!”元心里想了想。
 

 

第三章 不对称与伪随机

  不对称才是美?不对称才是美?!所以元就在树的节点位置加入了伪随机扰动。

技术分享

 

  “说点什么好呢?”

 


第四章 更多的子树

  元一直认为这个世界有时候是需要偏见的,二叉树肯定是最好的树。

  虽然现在不止两个子树。

技术分享

 

  “高清大图才能欣赏的过瘾。”你可以尝试目标另存为。

 


 第五章 绿叶与果实

  在树的末梢长出叶子和果实,一颗树终于成型了。

技术分享

 

  “对暗黄系简直审美疲劳,画风是该换一换了。”

  “结束了,据说第六天还要加班造人?!”

 


后记 

  -- 亚,我饿了

  -- 夏,我去给你摘果子

  ...

  -- 亚,那个猿又在树上看着我们

  -- 别管Ta,吃果子咯

  -- 嗯哪

  ...

  ...

  -- 夏,我一直以为那是只狗呢

  ...

 

技术分享
    Dim ph As Graphics
    Dim PaintBoard As Bitmap
    Dim centerX, centerY As Long
    Dim modeSequence() As Integer = {4, 5, 4, 6, 5, 6, 1, 2, 1, 3, 2, 3}
    Dim rnd As New Random
    Public Function Calculator(ByVal x As Double, ByVal y As Double, ByVal mode As Integer, ByVal r As Double, ByVal depth As Integer, ByVal radio As Double) As Double()
        Dim R2 As Double
        r = r * radio
        R2 = Math.Sqrt(3) * (r / 2)
        Dim Position(2) As Double
        Dim tempRnd As Double = 1 * rnd.Next(depth, 20) / 10
        If mode = 1 Then
            x = 0 : y = -r * tempRnd
        ElseIf mode = 2 Then
            x = -R2 * tempRnd : y = (r / 2) * tempRnd
        ElseIf mode = 3 Then
            x = R2 * tempRnd : y = (r / 2) * tempRnd
        ElseIf mode = 4 Then
            x = -R2 * tempRnd : y = -(r / 2) * tempRnd
        ElseIf mode = 5 Then
            x = R2 * tempRnd : y = -(r / 2) * tempRnd
        ElseIf mode = 6 Then
            x = 0 : y = r * tempRnd
        End If
        Position(0) = x
        Position(1) = y
        Position(2) = r
        Return Position
    End Function
    Public Sub PaintLine(ByVal x As Double, ByVal y As Double, ByVal mode As Integer, ByVal r As Double, ByVal depth As Integer, ByVal radio As Double)
        Dim position() As Double
        Dim tempR As Double
        Dim tempWidth As Double
        Dim tempColor As Color
        Dim tempRnd As Integer = rnd.Next(1, 3)
        Dim tempAlpha As Integer
        For j = 0 To 1
            For pff = 0 To tempRnd
                position = Calculator(x, y, modeSequence((mode - 1) * 2 + j), r, depth, radio)
                Dim LineVector As New Vector2D(position(0), position(1))
                LineVector.x *= rnd.NextDouble
                LineVector.y *= rnd.NextDouble
                LineVector.SetMag(IIf(depth <= 1, 20, position(2)))
                position(0) = LineVector.x
                position(1) = LineVector.y
                Dim tempMag As Double = LineVector.Magnitude
                Dim PointList As New List(Of PointF)
                For m = 1 To tempMag
                    LineVector.SetMag(m)
                    PointList.Add(New PointF(x + LineVector.x, y + LineVector.y))
                Next
                If PointList.Count >= 2 Then
                    Dim tempNext As Double = rnd.NextDouble
                    tempAlpha = rnd.Next(20, 100)
                    For p = 0 To PointList.Count - 2
                        tempR = r * 0.015 * depth
                        tempWidth = IIf(depth <= 1, Math.Sin(p / 6) * 10, tempR - p / PointList.Count * (tempR - tempR * radio + r * 0.015 * radio))
                        tempColor = IIf(depth <= 1, Color.FromArgb(tempAlpha, Color.Green), Color.Black)
                        If depth <= 1 Then
                            If tempNext < 0.01 Then
                                tempWidth = Math.Sin(p / 6) * 20
                                tempColor = Color.FromArgb(rnd.Next(200, 255), Color.Red)
                            End If
                        End If
                        ph.DrawLine(New Pen(tempColor, tempWidth), PointList(p), PointList(p + 1))
                    Next
                End If
                PaintHexgon(position(0) + x, position(1) + y, modeSequence((mode - 1) * 2 + j), tempMag, depth - 1, radio)
            Next
        Next
    End Sub
    Public Sub PaintHexgon(ByVal x As Double, ByVal y As Double, ByVal mode As Integer, ByVal r As Double, ByVal depth As Integer, ByVal radio As Double)
        If depth > 0 Then
            If mode = 0 Then
                ph.DrawLine(New Pen(Brushes.Black, r * 0.02 * depth), New PointF(x, y), New PointF(x, y + r))
                PaintLine(x, y, 1, r, depth, radio)
            Else
                PaintLine(x, y, mode, r, depth, radio)
            End If
        End If
    End Sub
    画树
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        PaintBoard = New Bitmap(PictureBox1.Width, PictureBox1.Height)
        ph = Graphics.FromImage(PaintBoard)
        ph.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
        centerX = PictureBox1.Width / 2 : centerY = PictureBox1.Height / 2
        PaintHexgon(centerX, centerY, 0, 200, 5, 0.6180339887)
         PaintHexgon(centerX, centerY, 0, 20, 5, 1.61812)
        PictureBox1.Image = PaintBoard
    End Sub
VB.NET源码

 

编程模拟自然(一):如何画一颗静态树

标签:

原文地址:http://www.cnblogs.com/experdot/p/4556672.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!