#! /usr/bin/env ruby # coding: utf-8 # # 直交座標系 3次元空間内の四面体を表現するクラス。 # #class Mageo::Tetrahedron < Mageo::Polyhedron class Mageo::Tetrahedron class InitializeError < Exception; end 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 {|v| v.to_v3d} 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