Class: CyberarmEngine::AABBTree::AABBNode

Inherits:
Object
  • Object
show all
Defined in:
lib/cyberarm_engine/trees/aabb_node.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent:, object:, bounding_box:) ⇒ AABBNode

Returns a new instance of AABBNode.



9
10
11
12
13
14
15
16
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 9

def initialize(parent:, object:, bounding_box:)
  @parent = parent
  @object = object
  @bounding_box = bounding_box

  @a = nil
  @b = nil
end

Instance Attribute Details

#aObject

Returns the value of attribute a.



7
8
9
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 7

def a
  @a
end

#bObject

Returns the value of attribute b.



7
8
9
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 7

def b
  @b
end

#bounding_boxObject

Returns the value of attribute bounding_box.



6
7
8
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 6

def bounding_box
  @bounding_box
end

#objectObject

Returns the value of attribute object.



6
7
8
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 6

def object
  @object
end

#parentObject

Returns the value of attribute parent.



6
7
8
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 6

def parent
  @parent
end

Instance Method Details

#child_of?(leaf) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 105

def child_of?(leaf)
  self == leaf.a || self == leaf.b
end

#disown_child(leaf) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 91

def disown_child(leaf)
  value = other(leaf)
  raise "Can not replace child of a leaf!" if @parent.leaf?
  raise "Node is not a child of parent!" unless leaf.child_of?(@parent)

  if @parent.a == self
    @parent.a = value
  else
    @parent.b = value
  end

  @parent.update_bounding_box
end

#insert_subtree(leaf) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 32

def insert_subtree(leaf)
  if leaf?
    new_node = AABBNode.new(parent: nil, object: nil, bounding_box: @bounding_box.union(leaf.bounding_box))

    new_node.a = self
    new_node.b = leaf

    new_node
  else
    cost_a = @a.bounding_box.volume + @b.bounding_box.union(leaf.bounding_box).volume
    cost_b = @b.bounding_box.volume + @a.bounding_box.union(leaf.bounding_box).volume

    if cost_a == cost_b
      cost_a = @a.proximity(leaf)
      cost_b = @b.proximity(leaf)
    end

    if cost_b < cost_a
      self.b = @b.insert_subtree(leaf)
    else
      self.a = @a.insert_subtree(leaf)
    end

    @bounding_box = @bounding_box.union(leaf.bounding_box)

    self
  end
end

#leaf?Boolean

Returns:

  • (Boolean)


28
29
30
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 28

def leaf?
  @object
end

#other(leaf) ⇒ Object



87
88
89
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 87

def other(leaf)
  @a == leaf ? @b : @a
end

#proximity(leaf) ⇒ Object



109
110
111
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 109

def proximity(leaf)
  (@bounding_box - leaf.bounding_box).sum.abs
end

#remove_subtree(leaf) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 74

def remove_subtree(leaf)
  if leaf
    self
  elsif leaf.parent == self
    other_child = other(leaf)
    other_child.parent = @parent
    other_child
  else
    leaf.parent.disown_child(leaf)
    self
  end
end

#search_subtree(collider, items = []) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 61

def search_subtree(collider, items = [])
  if @bounding_box.intersect?(collider)
    if leaf?
      items << self
    else
      @a.search_subtree(collider, items)
      @b.search_subtree(collider, items)
    end
  end

  items
end

#update_bounding_boxObject



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/cyberarm_engine/trees/aabb_node.rb', line 113

def update_bounding_box
  node = self

  unless node.leaf?
    node.bounding_box = node.a.bounding_box.union(node.b.bounding_box)

    while (node = node.parent)
      node.bounding_box = node.a.bounding_box.union(node.b.bounding_box)
    end
  end
end