Skip to content

Instantly share code, notes, and snippets.

@granolocks
Created November 8, 2023 16:56
Show Gist options
  • Save granolocks/efb9127426b34045c59a02e4551873e9 to your computer and use it in GitHub Desktop.
Save granolocks/efb9127426b34045c59a02e4551873e9 to your computer and use it in GitHub Desktop.
simple (rough) oct-tree implementation in ruby.. still a bit buggy
require 'pry'
module Oct
MAX_POINTS_PER_CELL = 10
ROOT_CELL_SCALE = 100
Point3 = Struct.new(:x,:y,:z)
class Cell
attr_accessor :points, :children, :origin, :dimension_scale, :subdivided
def initialize(origin = Point3.new(0,0,0), dimension_scale = ROOT_CELL_SCALE)
@points = []
@children = []
@subdivided = false
@origin = origin
@dimension_scale = dimension_scale
end
def add_point(point)
if !contains?(point)
return false
end
if @points.length > MAX_POINTS_PER_CELL && !@subdivided
subdivide
end
if @subdivided
@children.each do |child|
if child.add_point(point)
break
end
end
else
@points << point
end
return true
end
def contains?(point)
@origin.x <= point.x && point.x < @origin.x + @dimension_scale &&
@origin.y <= point.y && point.y < @origin.y + @dimension_scale &&
@origin.z <= point.z && point.z < @origin.z + @dimension_scale
end
def subdivide
x = @origin.x
y = @origin.y
z = @origin.z
child_scale = dimension_scale / 2
2.times do |i|
y_val = origin.y + (i * child_scale)
@children << Cell.new(Point3.new(x, y_val, z ), child_scale)
@children << Cell.new(Point3.new(x + child_scale, y_val, z ), child_scale)
@children << Cell.new(Point3.new(x, y_val, z + child_scale), child_scale)
@children << Cell.new(Point3.new(x + child_scale, y_val, z + child_scale), child_scale)
end
@subdivided = true
end
def print(depth = 0)
indent = "\t" * depth
puts indent + "points: " + @points.to_s
puts indent + "origin: " + @origin.to_s
@children.each_with_index do |child,i|
puts indent + "\tchild #{i}"
child.print(depth + 1)
end
puts
end
def count_points
return @points.length + (@children.length > 0 ? @children.map(&:count_points).inject(:+) : 0)
end
end
class Tree
def initialize
@root = Cell.new
end
def add_point(point)
if !@root.contains?(point)
binding.pry
end
@root.add_point(point)
end
def root
@root
end
end
end
t = Oct::Tree.new
50.times do |i|
p = Oct::Point3.new(i,2,3)
t.add_point(p)
end
t.root.print
binding.pry
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment