Created
November 8, 2023 16:56
-
-
Save granolocks/efb9127426b34045c59a02e4551873e9 to your computer and use it in GitHub Desktop.
simple (rough) oct-tree implementation in ruby.. still a bit buggy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 [email protected]?(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