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

Popular posts from this blog

Emotion Classification NN with Keras Transformers and TensorFlow

  In this post, I discuss an emotional classification model I created and trained for the Congressional App Challenge last month. It's trained on the Google GoEmotions dataset and can detect the emotional qualities of a text. First, create a training script and initialize the following variables. checkpoint = 'distilbert-base-uncased' #model to fine-tune weights_path = 'weights/' #where weights are saved batch_size = 16 num_epochs = 5 Next, import the dataset with the Hugging Face datasets library. dataset = ds . load_dataset( 'go_emotions' , 'simplified' ) Now, we can create train and test splits for our data. def generate_split(split): text = dataset[split] . to_pandas()[ 'text' ] . to_list() labels = [ int (a[ 0 ]) for a in dataset[split] . to_pandas()[ 'labels' ] . to_list()] return (text, labels) (x_text, x_labels) = generate_split( 'train' ) (y_text, y_labels) =...

Multithreaded Infinite Procedural Terrain with LODs in Unity

Infinitely procedurally generated terrain can be a lot of fun in games. I can't tell you how much fun I've had exploring worlds in games like Minecraft . Unfortunately, as so many overly-ambitious indie developers will tell you, it takes a lot of work to make procedural worlds performant without a lot  of work. Thankfully, there's a solution: multithreading. Wait, don't leave! Multithreading is a lot simpler than you might think, and in this post, I'll show you how to create infinite, procedural terrain in Unity with just a few lines of code that's fast, beautiful, and even has LODs. The code is below: using System.Collections; using System.Collections.Generic; using System.Threading; using System.Linq; using UnityEngine; public class TerrainGenerator : MonoBehaviour { public Material material; public int chunkSize = 64 ; public int rangeMultiplier = 2 ; public NoiseFilter noiseFilter; public float [] LODDi...