Class: Aims::Volume
Overview
A volume is defined by a minimum of four planes that intersect in a minimum of four points. The normals of the planes must all point outward. This is tested
Class Method Summary collapse
-
.choose(list, num, head = []) ⇒ Object
Quick recursive method for calculating combinations.
-
.intersection_points(planes) ⇒ Array
Return an array of tuples that define the vertices of intersection of these planes Vertices are removed that lie in front of any plane.
Instance Method Summary collapse
-
#bounding_box ⇒ Object
Return the bounding box for this volume.
-
#contains_point(x, y, z) ⇒ Object
A volume contains a point if it lies behind all the planes.
-
#initialize(planes) ⇒ Volume
constructor
A new instance of Volume.
-
#max_point ⇒ Object
Return the point on the bounding box that represents the maximum value of any cartesian coordinate (the upper right corner).
-
#min_point ⇒ Object
Return the point on the bounding box that represents the minimum value of any cartesian coordinate (the lower left corner).
Methods included from Vectorize
Constructor Details
#initialize(planes) ⇒ Volume
Returns a new instance of Volume.
72 73 74 75 76 77 78 79 80 |
# File 'lib/aims/volume.rb', line 72 def initialize(planes) points = Volume.intersection_points(planes) if (4 > points.size) raise "Planes do not intersect in a closed volume." end @points = points @planes = planes end |
Class Method Details
.choose(list, num, head = []) ⇒ Object
Quick recursive method for calculating combinations
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/aims/volume.rb', line 14 def Volume.choose(list, num, head = []) _head = head.dup _list = list.dup _num = num if _num == 0 return [_head] end new_heads = [] while _list.size > _num-1 h = _head + [_list.shift] new_heads += Volume.choose(_list, num-1, h) end return new_heads end |
.intersection_points(planes) ⇒ Array
Return an array of tuples that define the vertices of intersection of these planes Vertices are removed that lie in front of any plane
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/aims/volume.rb', line 39 def Volume.intersection_points(planes) combos = Volume.choose(planes, 3) points = [] combos.each{|c| n1 = c[0].unit_normal n2 = c[1].unit_normal n3 = c[2].unit_normal d = Matrix[n1, n2,n3].transpose.det # The determinant is zero if any two planes are parallel unless (d == 0) p1 = c[0].any_point_on_plane p2 = c[1].any_point_on_plane p3 = c[2].any_point_on_plane # This defines the point of intersection of three planes. points << (cross(n2,n3)*dot(p1, n1) + cross(n3,n1)*dot(p2,n2) + cross(n1,n2)*dot(p3, n3))*(1/d) end } # Only keep the points that are behind all planes keepers = [] points.each{|pt| keep = true planes.each {|pl| keep = (pl.distance_to_point(pt[0], pt[1], pt[2]) <= 0) break unless keep } keepers << pt if keep } return keepers end |
Instance Method Details
#bounding_box ⇒ Object
Return the bounding box for this volume
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/aims/volume.rb', line 83 def bounding_box unless @bbox p = @points[0] minX = p[0] maxX = p[0] minY = p[1] maxY = p[1] minZ = p[2] maxZ = p[2] @points.each{|p| minX = p[0] if p[0] < minX maxX = p[0] if p[0] > maxX minY = p[1] if p[1] < minY maxY = p[1] if p[1] > maxY minZ = p[2] if p[2] < minZ maxZ = p[2] if p[2] > maxZ } @max = Vector[maxX, maxY,maxZ] @min = Vector[minX, minY, minZ] @bbox = Volume.new([Plane.new(-1,0,0, minX, minY, minZ), Plane.new(0,-1,0, minX, minY, minZ), Plane.new(0,0,-1, minX, minY, minZ), Plane.new(1,0,0, maxX, maxY, maxZ), Plane.new(0,1,0, maxX, maxY, maxZ), Plane.new(0,0,1, maxX, maxY, maxZ)]) end @bbox end |
#contains_point(x, y, z) ⇒ Object
A volume contains a point if it lies behind all the planes
131 132 133 134 135 136 137 138 |
# File 'lib/aims/volume.rb', line 131 def contains_point(x,y,z) behind = true @planes.each{|p| behind = (0 >= p.distance_to_point(x,y,z)) break if not behind } return behind end |
#max_point ⇒ Object
Return the point on the bounding box that represents the maximum value of any cartesian coordinate (the upper right corner)
114 115 116 117 118 119 |
# File 'lib/aims/volume.rb', line 114 def max_point # generate the bounding box if not already done bounding_box # return the max @max end |
#min_point ⇒ Object
Return the point on the bounding box that represents the minimum value of any cartesian coordinate (the lower left corner).
123 124 125 126 127 128 |
# File 'lib/aims/volume.rb', line 123 def min_point # generate the bounding box if not already done bounding_box # return the min @min end |