lib/mageo/tetrahedron.rb in mageo-0.0.5 vs lib/mageo/tetrahedron.rb in mageo-0.1.0

- old
+ new

@@ -2,35 +2,130 @@ # coding: utf-8 # # 直交座標系 3次元空間内の四面体を表現するクラス。 # -class Mageo::Tetrahedron < Mageo::Polyhedron +#class Mageo::Tetrahedron < Mageo::Polyhedron +class Mageo::Tetrahedron class InitializeError < Exception; end - # vertices には四面体の頂点を順不同で入れた Array。 - def initialize( vertices ) - raise InitializeError if vertices.class != Array - raise InitializeError if vertices.size != 4 - vertices.each do |vertex| - raise InitializeError if vertex.size != 3 - raise InitializeError unless vertex.methods.include?( :[] ) - raise InitializeError unless vertex.methods.include?( :map ) + VERTEX_INDICES_OF_TRIANGLES = [ [ 0, 1, 2 ], [ 1, 2, 3 ], [ 2, 3, 0 ], [ 3, 0, 1 ] ] + + attr_reader :vertices + + class TypeError < StandardError; end + class NotImplementError < StandardError; end + + def edges + results = [] + triangles.each do |triangle| + triangle.edges.each do |edge| + results << edge unless results.include_eql?(edge) + end end + return results + end + + def triangles + results = VERTEX_INDICES_OF_TRIANGLES.map do |indices| + Mageo::Triangle.new( *(indices.map{|i| @vertices[i] }) ) + end + return results + end + + #面で囲まれた空間の中にあれば true を返す。 + def inside?( pos ) + raise TypeError if pos.class == Mageo::Vector3DInternal + + result = true + triangles.each do |triangle| + result = false unless triangle.same_side?( center, pos.to_v3d ) + end + return result + end + + def include?(pos, tolerance = 0.0) + raise TypeError if pos.class == Mageo::Vector3DInternal + + return true if inside?( pos ) + triangles.each do |triangle| + #pp pos + #pp triangle + return true if triangle.include?(pos.to_v3d, tolerance) + end + return false + end + + #各頂点の座標の平均値を返す。 + def center + tmp = Mageo::Vector3D[ 0.0, 0.0, 0.0 ] + @vertices.each do |vertex| + tmp += vertex + end + return tmp * ( 1.0 / @vertices.size.to_f ) # 座標の平均の算出 + end + + def translate!(vector) + @vertices.map! do |pos| + pos + vector + end + end + + def translate(vector) + result = Marshal.load(Marshal.dump(self)) + result.translate! vector + result + end + + def shared_vertices(other, tolerance = 0.0) + results = [] + @vertices.each do |sv| + flag = false + other.vertices.each do |ov| + flag = true if (ov - sv).r <= tolerance + end + results << sv if flag + end + results + end + + #private + + #def vertices_include?(vertex, vertices, tolerance) + #end + + + ## v0, v1, v2, v3 are 四面体の頂点 + def initialize( v0, v1, v2, v3 ) + #raise InitializeError if vertices.class != Array + #raise InitializeError if vertices.size != 4 + #vertices.each do |vertex| + # raise InitializeError if vertex.size != 3 + # raise InitializeError unless vertex.methods.include?( :[] ) + # raise InitializeError unless vertex.methods.include?( :map ) + #end + #@vertices = vertices.map { |vertex| vertex.to_v3d } + vertices = [v0, v1, v2, v3] vertices.each do |vertex| raise InitializeError if vertex.class == Mageo::Vector3DInternal end - @vertices = vertices.map { |vertex| vertex.to_v3d } + @vertices = vertices.map {|v| v.to_v3d} - @vertex_indices_of_triangles = [ - [ 0, 1, 2 ], - [ 1, 2, 3 ], - [ 2, 3, 0 ], - [ 3, 0, 1 ], - ] - raise InitializeError, "volume is zero." if volume == 0.0 end + + # 体積を返す + def volume + result = 0.0 + [ [ 0, 1, 2 ], [ 1, 2, 3 ], [ 2, 3, 0 ], [ 3, 0, 1 ] ].each do |tri_vertices| + vectors = tri_vertices.map { |i| @vertices[i] - center } + volume = Mageo::Vector3D.scalar_triple_product( *vectors ).abs + volume /= 6.0 + result += volume + end + return result + end + end