Перекрывающиеся деревья в лесу L-системы - PullRequest
3 голосов
/ 01 октября 2011

Я создал программу, использующую графику черепах Python, которая имитирует рост деревьев в лесу.Есть три дерева, которые выбираются случайным образом, и их начальные координаты и углы также выбираются случайным образом.Я выбрал несколько классных рисунков деревьев, но у меня проблема в том, что многие деревья накладываются друг на друга, поэтому вместо того, чтобы выглядеть как лес, он выглядит как картина плохого пятилетнего ребенка.

Есть ли способ сделать это перекрытие менее обычным?Когда вы смотрите на лес, некоторые деревья и их листья пересекаются, но это определенно не выглядит следующим образом:не уверен, как с этим бороться.

Вот мой код:

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()

Ответы [ 2 ]

2 голосов
/ 25 сентября 2012

Я думаю, что проблема заключается скорее в регулярности элементов среди самих деревьев, а не в их расположении как таковом.

Возможное решение - добавить мутации.Для глобального контроля над «замедленным ростом» можно было бы подавить, скажем, 5% производственных приложений.Это должно дать более редкие деревья, которые следуют за моделью более свободно.

Для более точного контроля вы можете подавить каждую продукцию с другим весом.

Извлечь Алгоритмическая красота растений раздел 1.7 Стохастические L-системы подробнее.Они используют вероятность, чтобы выбрать из нескольких вариантов одного правила.

2 голосов
/ 01 октября 2011

Из моего понимания L-системы есть целая грамматика, которая выбрана не случайно. Не могли бы вы рассказать, как работают ваши грамматики? Я полагаю, что вы можете несколько ограничить направление, в котором растут ваши деревья, создав ограниченный набор постановок с закрытым концом, которые идут где-то более чем на 90 градусов от начального угла.

Но тогда вы не можете полностью рандомизировать начальный угол ... Вам, вероятно, нужно просто рандомизировать его в определенном диапазоне? Конечно, если у вас есть L-система, которая генерирует все случайным образом, она будет выглядеть как куча шума. Есть цель наложить ограничение на ваши начальные условия; у каждой грамматики есть начальный символ, и вам нужно воспользоваться начальным символом, чтобы генерировать вещи, которые имеют смысл. Я предполагаю, что вы хотите, чтобы ваш начальный символ всегда был направлен вверх.

Но я долгое время не изучал L-системы, поэтому ответь мне чуть-чуть солью.

Edit:

Это интересное ограничение, накладываемое тем, что это звучит как то, что деревья делают естественным образом. В природе я думаю, что это происходит потому, что только определенное количество солнечного света может проникнуть в данный участок земли, поэтому, если дерево где-то уже растет, ничто другое не может этого сделать.

Будучи специалистом по искусственному интеллекту, я люблю превращать реальные решения в интересные эвристики. Какую эвристику мы ищем здесь? Ну, «участок земли» в 2-й системе координат - это просто диапазон x-координат. Может быть, есть что-то, что заставляет рост терять импульс, если в каком-то произвольном диапазоне х растущего листа слишком много материала? (не xrange Python, а диапазон x-координат, некоторое значение «delta», если хотите).

...