4

我使用 python 的海龟图形创建了一个程序,用于模拟森林中的树木生长。有 3 种树图案是随机选择的,它们的起始坐标和角度也是随机选择的。我选择了一些看起来很酷的树图案,但我遇到的问题是许多树是重叠的,所以看起来不像是一片森林,它看起来像一幅糟糕的 5 岁孩子的画。

有没有办法让这种重叠不那么常见?当你看一片森林时,有些树和它们的叶子确实重叠,但它绝对不是这样的:

在此处输入图像描述

由于涉及很多随机化,我不知道如何处理这个问题。

这是我的代码:

import turtle
import random

stack = []

#max_it = maximum iterations, word = starting axiom such as 'F', proc_rules are the rules that 
#change the elements of word if it's key is found in dictionary notation, x and y are the 
#coordinates, and turn is the starting angle 

def createWord(max_it, word, proc_rules, x, y, turn):

    turtle.up()
    turtle.home()
    turtle.goto(x, y)
    turtle.right(turn)
    turtle.down()

    t = 0
    while t < max_it:
        word = rewrite(word, proc_rules)
        drawit(word, 5, 20)
        t = t+1


def rewrite(word, proc_rules):

   #rewrite changes the word at each iteration depending on proc_rules

    wordList = list(word)

    for i in range(len(wordList)):
        curChar = wordList[i]
        if curChar in proc_rules:
            wordList[i] = proc_rules[curChar]

    return "".join(wordList)


def drawit(newWord, d, angle):

    #drawit 'draws' the words

    newWordLs = list(newWord)
    for i in range(len(newWordLs)):
        cur_Char = newWordLs[i]
        if cur_Char == 'F':
            turtle.forward(d)
        elif cur_Char == '+':
            turtle.right(angle)
        elif cur_Char == '-':
            turtle.left(angle)
        elif cur_Char == '[':
            state_push()
        elif cur_Char == ']':
            state_pop()


def state_push():

    global stack

    stack.append((turtle.position(), turtle.heading()))


def state_pop():

    global stack

    position, heading = stack.pop()

    turtle.up()
    turtle.goto(position)
    turtle.setheading(heading)
    turtle.down()


def randomStart():

    #x can be anywhere from -300 to 300, all across the canvas
    x = random.randint(-300, 300)

    #these are trees, so we need to constrain the 'root' of each
    # to a fairly narrow range from -320 to -280
    y = random.randint(-320, -280)

    #heading (the angle of the 'stalk') will be constrained 
    #from -80 to -100 (10 degrees either side of straight up)
    heading = random.randint(-100, -80)

    return ((x, y), heading)


def main():

    #define the list for rule sets.
    #each set is iteration range [i_range], the axiom and the rule for making a tree.  
    #the randomizer will select one of these for building.

    rule_sets = []
    rule_sets.append(((3, 5), 'F', {'F':'F[+F][-F]F'}))
    rule_sets.append(((4, 6), 'B', {'B':'F[-B][+ B]', 'F':'FF'}))
    rule_sets.append(((2, 4), 'F', {'F':'FF+[+F-F-F]-[-F+F+F]'}))

    #define the number of trees to build
    tree_count = 50

    #speed up the turtle
    turtle.tracer(10, 0)

    #for each tree...
    for x in range(tree_count):

        #pick a random number between 0 and the length
        #of the rule set -1 - this results in selecting
        #a result randomly from the list of possible rules.

        rand_i = random.randint(0, len(rule_sets) - 1)
        selected_ruleset = rule_sets[rand_i]

        #unpack the tuple stored for this ruleset
        i_range, word, rule = selected_ruleset

        #pick a random number inside the given iteration_range to be the 
        #iteration length for this command list.
        low, high = i_range
        i = random.randint(low, high)

        #get a random starting location and heading for the tree
        start_position, start_heading = randomStart()

        #unpack the x & y coordinates from the position
        start_x, start_y = start_position

        #build the current tree
        createWord(i, word, rule, start_x, start_y, start_heading)

if __name__ == '__main__': main()
4

2 回答 2

2

根据我对 L 系统的理解,有一个完整的语法不是随机选择的。您能否提供有关您的语法如何工作的详细信息?我想你可以通过制作一组有限的、封闭的、从起始角度超过 90 度的作品来限制你的树木生长的方向。

但是你不能完全随机化起始角度......你可能需要在一定范围内随机化它?当然,如果你有一个随机生成所有东西的 L 系统,它看起来就像一堆噪音。限制初始条件是有目的的;每个语法都有一个开始符号,你需要利用你的开始符号来生成有意义的东西。我想您希望您的开始符号始终指向上方。

但是我很长时间没有研究 L 系统了,所以我的回答持保留态度。

编辑:

这是一个有趣的限制,因为它听起来像是树木自然会做的事情。在自然界中,我认为这是因为只有一定量的阳光才能穿过给定的一块土地,所以如果一棵树已经在某个地方生长,那么其他任何东西都无法做到。

作为一名 AI 专家,我喜欢将现实世界的解决方案转化为有趣的启发式方法。我们在这里寻找什么样的启发式方法?好吧,二维坐标系中的“地块”只是 x 坐标的范围。如果在生长的叶子的某个任意 x 范围内有太多东西,也许有一些东西会使生长失去动力?(不是python xrange,而是一系列x坐标,如果你愿意的话,可以是一些“delta”值。)

于 2011-09-30T22:42:50.190 回答
2

我认为问题更多在于树木本身特征的规律性,而不是它们本身的位置。

一个可能的解决方案是添加突变。对于“发育迟缓”的全局控制,您可以抑制 5% 的生产应用程序。这应该会提供更松散地遵循模型的稀疏树。

为了更好地控制,您可以使用不同的权重抑制每个生产。

查看植物的算法之美第 1.7 节随机 L 系统了解更多信息。他们使用概率在单个规则的几个变体中进行选择。

于 2012-09-25T16:18:40.843 回答