Class: Mittsu::Plane

Inherits:
Object
  • Object
show all
Defined in:
lib/mittsu/math/plane.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(normal = Mittsu::Vector3.new(1, 0, 0), constant = 0.0) ⇒ Plane

Returns a new instance of Plane.



5
6
7
# File 'lib/mittsu/math/plane.rb', line 5

def initialize(normal = Mittsu::Vector3.new(1, 0, 0), constant = 0.0)
  @normal, @constant = normal, constant.to_f
end

Instance Attribute Details

#constantObject

Returns the value of attribute constant.



3
4
5
# File 'lib/mittsu/math/plane.rb', line 3

def constant
  @constant
end

#normalObject

Returns the value of attribute normal.



3
4
5
# File 'lib/mittsu/math/plane.rb', line 3

def normal
  @normal
end

Instance Method Details

#==(plane) ⇒ Object



118
119
120
# File 'lib/mittsu/math/plane.rb', line 118

def ==(plane)
  plane.normal == @normal && plane.constant == @constant
end

#apply_matrix4(matrix, normal_matrix = Mittsu::Matrix3.new.normal_matrix(matrix)) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/mittsu/math/plane.rb', line 101

def apply_matrix4(matrix, normal_matrix = Mittsu::Matrix3.new.normal_matrix(matrix))
  v1 = Mittsu::Vector3.new
  v2 = Mittsu::Vector3.new
  # compute new normal based on theory here:
  # http:#www.songho.ca/opengl/gl_normaltransform.html
  new_normal = v1.copy(@normal).apply_matrix3(normal_matrix)
  new_coplanar_point = self.coplanar_point(v2)
  new_coplanar_point.apply_matrix4(matrix)
  self.set_from_normal_and_coplanar_point(new_normal, new_coplanar_point)
  self
end

#cloneObject



122
123
124
# File 'lib/mittsu/math/plane.rb', line 122

def clone
  Mittsu::Plane.new.copy(self)
end

#coplanar_point(target = Mittsu::Vector3.new) ⇒ Object



97
98
99
# File 'lib/mittsu/math/plane.rb', line 97

def coplanar_point(target = Mittsu::Vector3.new)
  target.copy(@normal).multiply_scalar(- @constant)
end

#copy(plane) ⇒ Object



36
37
38
39
40
# File 'lib/mittsu/math/plane.rb', line 36

def copy(plane)
  @normal.copy(plane.normal)
  @constant = plane.constant
  self
end

#distance_to_point(point) ⇒ Object



56
57
58
# File 'lib/mittsu/math/plane.rb', line 56

def distance_to_point(point)
  @normal.dot(point) + @constant
end

#distance_to_sphere(sphere) ⇒ Object



60
61
62
# File 'lib/mittsu/math/plane.rb', line 60

def distance_to_sphere(sphere)
  self.distance_to_point(sphere.center) - sphere.radius
end

#intersect_line(line, target = Mittsu::Vector3.new) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/mittsu/math/plane.rb', line 80

def intersect_line(line, target = Mittsu::Vector3.new)
  v1 = Mittsu::Vector3.new
  direction = line.delta(v1)
  denominator = @normal.dot(direction)
  if denominator.zero?
    # line is coplanar, return origin
    if self.distance_to_point(line.start_point).zero?
      return target.copy(line.start_point)
    end
    # Unsure if this is the correct method to handle this case.
    return nil
  end
  t = -(line.start_point.dot(@normal) + @constant) / denominator
  return nil if t < 0 || t > 1
  target.copy(direction).multiply_scalar(t).add(line.start_point)
end

#intersection_line?(line) ⇒ Boolean

Returns:

  • (Boolean)


73
74
75
76
77
78
# File 'lib/mittsu/math/plane.rb', line 73

def intersection_line?(line)
  # Note: self tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
  start_sign = self.distance_to_point(line.start_point)
  end_sign = self.distance_to_point(line.end_point)
  (start_sign < 0 && end_sign > 0) || (end_sign < 0 && start_sign > 0)
end

#negateObject



50
51
52
53
54
# File 'lib/mittsu/math/plane.rb', line 50

def negate
  @constant *= -1.0
  @normal.negate
  self
end

#normalizeObject



42
43
44
45
46
47
48
# File 'lib/mittsu/math/plane.rb', line 42

def normalize
  # Note: will lead to a divide by zero if the plane is invalid.
  inverse_normal_length = 1.0 / @normal.length
  @normal.multiply_scalar(inverse_normal_length)
  @constant *= inverse_normal_length
  self
end

#ortho_point(point, target = Mittsu::Vector3.new) ⇒ Object



68
69
70
71
# File 'lib/mittsu/math/plane.rb', line 68

def ortho_point(point, target = Mittsu::Vector3.new)
  perpendicular_magnitude = self.distance_to_point(point)
  target.copy(@normal).multiply_scalar(perpendicular_magnitude)
end

#project_point(point, target = Mittsu::Vector3.new) ⇒ Object



64
65
66
# File 'lib/mittsu/math/plane.rb', line 64

def project_point(point, target = Mittsu::Vector3.new)
  self.ortho_point(point, target).sub(point).negate
end

#set(normal, constant) ⇒ Object



9
10
11
12
13
# File 'lib/mittsu/math/plane.rb', line 9

def set(normal, constant)
  @normal.copy(normal)
  @constant = constant.to_f
  self
end

#set_components(x, y, z, w) ⇒ Object



15
16
17
18
19
# File 'lib/mittsu/math/plane.rb', line 15

def set_components(x, y, z, w)
  @normal.set(x, y, z)
  @constant = w.to_f
  self
end

#set_from_coplanar_points(a, b, c) ⇒ Object



27
28
29
30
31
32
33
34
# File 'lib/mittsu/math/plane.rb', line 27

def set_from_coplanar_points(a, b, c)
  v1 = Mittsu::Vector3.new
  v2 = Mittsu::Vector3.new
  normal = v1.sub_vectors(c, b).cross(v2.sub_vectors(a, b)).normalize
  # Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
  self.set_from_normal_and_coplanar_point(normal, a)
  self
end

#set_from_normal_and_coplanar_point(normal, point) ⇒ Object



21
22
23
24
25
# File 'lib/mittsu/math/plane.rb', line 21

def set_from_normal_and_coplanar_point(normal, point)
  @normal.copy(normal)
  @constant = -point.dot(@normal) # must be @normal, not normal, as @normal is normalized
  self
end

#translate(offset) ⇒ Object



113
114
115
116
# File 'lib/mittsu/math/plane.rb', line 113

def translate(offset)
  @constant = @constant - offset.dot(@normal)
  self
end