Shade3D 公式

02 vec3 module [ Shade Labo ]


#1

< 02 - 1 Reference >




改訂 - 1( 2016 / 01 / 05 ) :

global 関数を追加

  • vec3list( )



関連記事 :

  • 01 はじめに

module vec3 は vector 演算を扱う class vec3( 小文字で始まる )を提供

vec3 : list を継承した sub class
Shade script の list 引数としてそのまま使用できる


注記

この中で書かれている vec3 は custum class vec3 のことであり、Shade の script reference に書かれている vec3 は list3 あるいは [ float, float, float ] と記述します。


Init

v = vec3( ) ____________ zero vector [0., 0., 0.] が返される
v = vec3( 1, 2, 3 )
v = vec3( [ 4, 5, 6 ] ) ____ リストと同じ内容を持つ vec3
v = vec3( ( 4, 5, 6 ) ) ____ タプルと同じ内容を持つ vec3
v = vec3( vec3 ) ________ vec3 の copy


注意

list を継承しているので list に係わる全ての関数が使用可能であり、内包する要素数を3 以外にすることも、 float 以外の型の代入もできてしまう

vec3 の演算や関数処理では、4 以上の要素は無視され、要素数が 2 以下であったり、型変換の不可能な要素が代入されていれば、エラーとなる


四則演算 scalar = float or int

vec3 = vec3 + vec3
vec3 = vec3 - vec3
vec3 = vec3 / scalar
vec3 = scalar * vec3
vec3 = vec3 * scalar
vec3 = vec3 * vec3 _______この演算は外積を与える


関数

dot( v as vec3 ) as float ___内積
abs( ) as float ___________絶対値 ( ベクトル長さ )
abs2( ) as float __________絶対値の二乗
norm( ) as float _________ 絶対値を返し、単位ベクトル化
length( ) as float ________ 絶対値 ( ベクトル長さ ) abs( ) と同じ


Global 関数

vec3list( L as list ) as list
vec3list( L as tuple ) as list

list / tuple に内包された vec3 に変換可能な全ての要素を vec3 に変換し、リストとして返す
条件に合致しない object はそのままの状態で返される
渡された引数が list / tuple 以外であれば、None が返される

[ vec3, [ vec3, vec3 ] ] = vec3list( [ 1, 2, 3 ], [ [ 4, 5, 6 ], [ 7, 8, 9 ] ] )


#2

< 02 - 2 使用例 >


init

from vec3 import *

v = vec3()	
print v					#  v [0, 0, 0]

v1 = vec3(1, 2, 3)
print v1				# v [ 1, 2, 3 ]
v2 = vec3(v1)
print v2				#  v [ 1, 2, 3 ]

L = [4, 5, 6]
v = vec3(L)			
print v					#  v [ 4, 5, 6 ]

L = (7, 8, 9)
v = vec3(L)			
print v					#  v [ 7, 8, 9 ]

**加減除算**
from vec3 import *

v1 = vec3(0, 1, 2)
v2 = vec3(3, 4, 5)
v3 = v1 + v2
print v3				#  v [ 3, 5, 7 ]


v1 = vec3(1, 2, 3)
v2 = v1/2
print v2				#  v [ 0.5, 1.0, 1.5 ]

**外積, 内積**
from vec3 import *

v1 = vec3(1, 2, 3)
v2 = vec3(3, 4, 5)
v3 = v1*v2				#  外積
print v3				#  v [ -2, 4, -2 ]

v1 = vec3(1, 2, 3)
v2 = vec3(3, 4, 5)
v3 = v1.dot(v2)			#  内積
print v3				#  26

**その他の関数**
from vec3 import *

v = vec3(1, 2, 3)
print v.abs()			#  3.74165738677	絶対値 = 長さ
print v.length()		#  3.74165738677	長さ = 絶対値
print v.abs2()			#  14	絶対値の二乗


v = vec3(1, 2, 3)
v.norm()				#  単位ベクトル化
print v					#  v [ 0.267261241912, 0.534522483825, 0.801783725737 ]

v = vec3(1, 2, 3)
r = v.norm()			#  単位ベクトル化し、絶対値を返す
print r					#  3.74165738677
print v					#  v [ 0.267261241912, 0.534522483825, 0.801783725737 ]

**global 関数** vec3 に変換可能な全ての要素を vec3 に変換し、リストとして返す ( 2016 / 01 / 05 ) 改訂
from vec3 import *

L = [ [1, 2, 3], [4, 5,6], [7, 8, 9], [ (1, 2, 3), (4, 5, 6), (7, 8, 9) ], [ (1, 2, 3), (4, 5, 6), (7, 8, 9) ]  ]
L = vec3list(L)
print L

#4

< 02 - 3 code >


改訂 - 1( 2015 / 12 / 30 ) : minor 改訂
改訂 - 2( 2016 / 01 / 05 ) : global 関数 vec3list( ) を追加




次のコードを copy して shade の script palette あるいは text editor 等に paste、ファイル名 vec3.py で保存し、所定の場所にインストールします。

インストール方法は [ 01 はじめに ] を参照下さい。

# -*- coding: utf-8 -*-


#  Ver.1.0
#		公開版リリース
#
#  Ver.1.0.1
#		予定していた quaternion の仕様変更委より、 quaternion に係わる記述を削除
#
#  Ver.1.1
#		global 関数 vec3list( L as list ) as list を追加
#			list / tuple に内包された vec3 に変換可能な全ての要素を vec3 に変換し、リストとして返す
#			global 関数 vec3List( ), vec3List_2( ) の機能を含み、より汎用性がある 
#
#		global 関数 vec3List( ), ve3List_2( ) は上記の ve3list( ) で代替可能



#	注記
#
#	この中で書かれている vec3 は custum class vec3 のことであり、
#	Shade の scropt reference で書かれている vec3 に対しては
#	list3, [ float, float, float ] と記述する


#  dummy class

#	matrix_x は vec3 = vec3* matrix を定義するために設けられた dummy class
#	class matrix は matrix_x の sub class で、別の module 内で定義される				
class matrix_x(list) :
	def vec3_cross_matrix(self, vec3, err) :
		pass
	


class vec3(list) :

	#	list を継承した sub class
	
	#	vec3 の型のまま Shade の list 型引数 [ , , ] として与えることが可
	

	#	 init
	#		v = vec3( )					zero vector [0., 0., 0.] が返される
	#		v = vec3( 1, 2, 3 )		
	#		v = vec3( [4, 5, 6] )		リストと同じ内容を持つ vec3
	#		v = vec3( (7, 8, 9 ) )		タプルと同じ内容を持つ vec3
	#		v = vec3( vec3 )			vec3 の copy
	
	
	#	注意
	#		list を継承しているので list に係わる全ての関数が使用可能であり、内包する要素数を
	#		3 以外にすることも、 float 以外の型の代入もできてしまう
	#
	#		vec3 の演算や関数処理では、4 以上の要素は無視され、要素数が 2 以下であったり、
	#		型変換の不可能な要素が代入されていれば、エラーとなる
	
		
	#	四則演算	数学的に定義されていない四則演算は全てエラーとなる
	#
	#								scalar = float or int	
	#		vec3 = vec3 + vec3
	#		vec3 = vec3 - vec3
	#		vec3 = vec3 / scalar	
	#		vec3 = scalar * vec3	
	#		vec3 = vec3 * scalar	
	#		vec3 = vec3 * vec3		この演算は外積を与える
	#
	#		以下の演算も可能になっているが、使用は推奨できない
	#			vec3 = vec3 + [ float, float, float ]
	#			vec3 = vec3 - [ float, float, float ]	
	#			vec3 = vec3 * [ float, float, float ]	
	
	
	#	関数
	#		dot( v as vec3 ) as float	内積
	#		abs( ) as float				絶対値 ( ベクトル長さ )
	#		abs2( ) as float			絶対値の二乗
	#		norm( ) as float			絶対値を返し、単位ベクトル化
	#		length( ) as float			絶対値 ( ベクトル長さ )
	

		

	#	init( )	#####
	
	def __init__(self, *value) :
		if len(value) == 0 :									#  v = vec3()
			self.extend([0., 0., 0.])
		elif len(value) == 3 :									#  v = vec3(float, float, float)   or   v = vec3(int, int, int)
			self.extend(value)
		elif len(value) == 1 and isinstance(value[0], list) :	#  v = vec3(list)   or   v = vec3(vec)   or   v = vec3(matrix)
			self.extend(value[0][0:3])
		elif len(value) == 1 and isinstance(value[0], tuple) :	#  v = vec3(tuple)
			self.extend(value[0][0:3])
		else :
			raise Vec3Error(0, 'init')

			
			
	
	#	print	#####
	
	def __repr__(self) :			#  print
		if len(self) == 3 :
			return 'v [ %s, %s, %s ]' % (self[0], self[1], self[2])
		else :
			return 'ir-v %s' % (self[:])
				
					
	
	
	#	四則演算	#####
		
	def __add__(self, value):		#  vec3 + vec3
		try :
			return vec3([self[0] + value[0], self[1] + value[1], self[2] + value[2]])
		except :
			raise Vec3Error(1, 'add')
			
	def __radd__(self, value):		#  object + vec3    定義されない演算
		raise Vec3Error(2, 'radd')

	def __sub__(self, value):		#  vec3 - vec3
		try :
			return vec3([self[0] - value[0], self[1] - value[1], self[2] - value[2]])
		except :
			raise Vec3Error(1, 'sub')
		
	def __rsub__(self, value):		#  object - vec3    定義されない演算
		raise Vec3Error(2, 'rsub')
					
	def __neg__(self):				#  -vec3	
		try :
			return vec3([ -self[0] , -self[1] , -self[2]])	
		except :
			raise Vec3Error(1, 'neg')
	
	def __div__(self, value) :		#  vec3 / scalar
		try :
			return vec3([float(self[0])/value, float(self[1])/value, float(self[2])/value])
		except :
			raise Vec3Error(1, 'div')
		
	def __rdiv__(self, value):		#  object / vec3    定義されない演算
		raise Vec3Error(2, 'rdiv')
			
	def __pow__(self, value) :		#  vec3 ** object    定義されない演算
		raise Vec3Error(2, 'pow')
		
	def __rpow__(self, value) :		#  object ** vec3    定義されない演算
		raise Vec3Error(2, 'rpow')
		
		
	def __mul__(self, value):		#  vec3 * vec3 ( 外積 ),  vec3*scalar,  vec3 = vec3 * matrix,  vec3 = vec3 * quaternion
		err = []
		try :
			if isinstance(value, vec3) :											#  vec3 * vec3 ( 外積 )
				return vec3([self[1]*value[2] - self[2]*value[1], self[2]*value[0] - self[0]*value[2], self[0]*value[1] - self[1]*value[0]])
			elif isinstance(value, float) or isinstance(value, int) :				#  vec3*scalar
				return vec3([self[0]*value, self[1]*value, self[2]*value])
			elif isinstance(value, matrix_x) :										#  vec3 * matrix
				return value.vec3_cross_matrix(self, err)
			else :
				raise Vec3rError(2, 'mul')
		except :
			if len(err) == 0 :
				raise Vec3Error(1, 'mul')
			else :										#  vec3 * matrix or vec3 * quaternion での error
				raise Vec3Error(-1, err[0])

				
			
	def __rmul__(self, value):		#  scalar * vec3
		try :
			if isinstance(value, float) or isinstance(value, int) :					#  scalar*vec3
				return vec3([self[0]*value, self[1]*value, self[2]*value])
			else :
				raise Vec3Error(2, 'rmul')
		except :
			raise Vec3Error(1, 'rmul')
	

	
	
	
	#	その他の関数		#####

	def dot(self, value) :			#  内積
		try:
			return self[0]*value[0] + self[1]*value[1] + self[2]*value[2]
		except :
			raise Vec3Error(1, 'dot')

			
	def abs(self) :					#   絶対値
		try :
			return (self[0]**2 + self[1]**2 + self[2]**2)**0.5
		except :
			raise Vec3Error(1, 'abs')
		
		
	def abs2(self) :				#  絶対値の二乗
		try :
			return self[0]**2 + self[1]**2 + self[2]**2
		except :
			raise Vec3Error(1, 'abs2')
			
			
	def norm(self) :				#   単位ベクトル化	
		try :
			r = (self[0]**2 + self[1]**2 + self[2]**2)**0.5
			if r != 0 :
				for i in [0, 1, 2] :
					self[i] = self[i]/r	
			else :
				for i in [0, 1, 2] :
					self[i] = 0.
			return r
		except :
			raise Vec3Error(1, 'norm')
			
			
	def length(self) :				#   長さ = 絶対値 abs( ) と同じ
		try :
			return (self[0]**2 + self[1]**2 + self[2]**2)**0.5
		except :
			raise Vec3Error(1, 'length')

		
		
class Vec3Error(ValueError) :
	def __init__(self, index, t) :
		if index == 0 :
			t = '     サポートされていない引数     vec3 ' + t + '     irregular argument'
		elif index == 1 :
			t = '     不正な要素 / 要素数     vec3 ' + t + '     mismatch element / size'
		elif index == 2 :
			t = '     サポートされていない演算     vec3 ' + t + '     unsupportd operand'
				
		super(ValueError, self).__init__(t)	

		
				
#  global 関数

#	引数として渡された list / tuple に内包された vec3 に変換可能な全ての要素を変換し、リストとして返す
# 	条件に合致しない object はそのままの状態で返されるリスト内に含まれる
# 	渡された引数が list / tuple 以外であれば、None が返される
#		[ vec3, [ vec3, vec3 ] ] = vec3list(  [ 1, 2, 3 ], [ [ 4, 5, 6 ], [ 7, 8, 9 ] ] )

def vec3list(value) :
	L = []
	if isinstance(value, list) or isinstance(value, tuple) :
		for obj in value :
			if isinstance(obj, list) or isinstance(obj, tuple) :
				if len(obj) == 3 :
					v = vec3()
					for i in range(3) :
						if isinstance(obj[i], float) or isinstance(obj[i], int) :
							v[i] = obj[i]
						else :
							v = None
							break
							
					if v != None :
						L.append(v)
					else :
						L.append(vec3list(obj))	#  要素 type の不適切な list /tuple は再帰ループへ
				else :
					L.append(vec3list(obj))		#   要素数の不適切な list /tuple は再帰ループへ
			else :
				L.append(obj)		#   list /tuple 以外はそのままリスト内に格納
		return L
	else :
		return None
	
	

#  vec3List( ) と vec3List_2( ) の機能は vec3list( ) で代替可能


		
#	引数として渡された list / tuple 内の第一階層の object の内、
# 	要素数 3 の list / tuple を vec3 に変換した list を返す
# 	条件に合致しない object はそのままの状態で返される
# 	渡された引数が list / tuple 以外であれば、None が返される
#	[ vec3, vec3 ] = vec3List( [ [ 1, 2, 3 ], [ 4, 5, 6 ] )

def vec3List( value ) :			
	if not isinstance(value, list) and not isinstance(value, tuple) :
		return None
	
	L = []
	for obj in value :
		if not isinstance(obj, list) and not isinstance(obj, tuple) :
			L.append(obj)
		elif len(obj) != 3 :
			L.append(obj)
		else :
			L.append(vec3(obj))			
	return L
	

	
# 	引数として渡された list / tuple 内の第二階層の object の内、
#	要素数 3 の list / tuple を vec3 に変換した list を返す
# 	条件に合致しない object はそのままの状態で返される
# 	渡された引数が list / tuple 以外であれば、None が返される
#	[ [ vec3, vec3 ], [ vec3, vec3 ] ] = vec3List_2( [  [ [ 1, 2, 3 ], [ 4, 5, 6 ] ],  [ [ 7, 8, 9 ], [ 0, 1, 2 ]  ] )

def vec3List_2( value ) :			
	if not isinstance(value, list) and not isinstance(value, tuple) :
		return None
	
	L = []
	for obj in value :
		if not isinstance(obj, list) and not isinstance(obj, tuple) :
			L.append(obj)
		else :
			LL = []
			for ob in obj :
				if not isinstance(ob, list) and not isinstance(ob, tuple) :
					LL.append(ob)	
				else :
					if len(ob) != 3 :
						LL.append(ob)
					else :
						LL.append(vec3(ob))
			L.append(LL)		
	return L