Skip to main content

RRT Algorithm Visualization in Python

I'm continuing my experiment in procedural generation by "exploring" a fascinating algorithm for generating procedural trees. The rapidly-exploring random tree algorithm, or RRT for short, is a Monte-Carlo method traditionally used for autonomous navigation. However, before I dive into the code, let me show you this algorithm's result in an image.

(Source: Wikipedia)

It's a fractal! A stochastic fractal, to be precise.

And so began my journey to replicate this algorithm, not for robotic navigation, but for artistic purposes. I decided to write the code for my implementation with Python since the PIL library makes it easy to quickly generate images.

import random
import math
from PIL import Image, ImageDraw

WIDTH = 500
HEIGHT = 500
RECURSIONS = 125

class Node:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.parent = None

    def __repr__(self):
        return (self.x, self.y)

    def distance(self, other):
        return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)

    def get_nearest(self, nodes, rnd):
        dlist = [(node.distance(rnd), node) for node in nodes]
        dlist.sort()
        return dlist[0][1]

    def turn(self, to, extend_length=10.0):
        d, theta = self.distance(to), math.atan2(to.y - self.y, to.x - self.x)
        if d > extend_length:
            to = Node(self.x + extend_length * math.cos(theta), self.y + extend_length * math.sin(theta))
        to.parent = self
        return to

    def generate_path(self, path):
        path.append((self.x, self.y))
        if self.parent is not None:
            self.parent.generate_path(path)

img = Image.new('RGB', (WIDTH, HEIGHT), (255, 255, 255))
draw = ImageDraw.Draw(img)

nodes = []
nodes.append(Node(random.randint(0, WIDTH), random.randint(0, HEIGHT)))

for i in range(RECURSIONS):
    rnd = Node(random.randint(0, WIDTH), random.randint(0, HEIGHT))
    nearest_node = nodes[0].get_nearest(nodes, rnd)
    new_node = nearest_node.turn(rnd)
    nodes.append(new_node)
    draw.line((nearest_node.x, nearest_node.y, new_node.x, new_node.y), fill=(0, 0, 0))

try:
    img.show()
    #save image
    img.save('rrt.png')
except(TypeError):
    pass

Comments