🏹
TypeScriptで簡単な3次元ベクトルクラスを作ってみる
色々機能足りないけどとりあえず作ってみた。
Vec3クラス
class Vec3 {
public x: number
public y: number
public z: number
constructor(x: number, y: number, z: number) {
this.x = x;
this.y = y;
this.z = z;
}
メソッド
JavaScriptのMathみたいに作りたかったので全部staticにしてみた。
// 正規化
static normalized(vec3: Vec3): Vec3 {
const vec_length = Vec3.norm(vec3);
return new Vec3(vec3.x / vec_length, vec3.y / vec_length, vec3.z / vec_length);
}
// 加算
static add(a: Vec3, b: Vec3): Vec3 {
return new Vec3(a.x + b.x, a.y + b.y, a.z + b.z);
}
// 減算
static minus(a: Vec3, b: Vec3): Vec3 {
return new Vec3(a.x - b.x, a.y - b.y, a.z - b.z);
}
// スカラー倍
static multiple_scalar(vec3: Vec3, n: number): Vec3 {
return new Vec3(vec3.x * n, vec3.y * n, vec3.z * n);
}
// スカラー割
static divide_scalar(vec3: Vec3, n: number): Vec3 {
return new Vec3(vec3.x / n, vec3.y / n, vec3.z / n);
}
// ノルム
static norm(vec3: Vec3): number {
return Math.sqrt(vec3.x ** 2 + vec3.y ** 2 + vec3.z ** 2);
}
// 内積
static dot(a: Vec3, b: Vec3): number {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
// 外積
static outer(a: Vec3, b: Vec3): Vec3{
return new Vec3(a.y * b.z - a.z * b.y, -(a.x * b.z - a.z * b.x), a.x * b.y - a.y * b.x);
}
// 射影
static project(a: Vec3, b: Vec3): Vec3 {
const dot_a_b = Vec3.dot(a, b);
const b_length_pow = Vec3.norm(b) ** 2;
return Vec3.divide_scalar(Vec3.multiple_scalar(b, dot_a_b), b_length_pow);
}
その他入れてみたメソッド
equalメソッド
2つのベクトルの要素が全て同じ場合true、それ以外ならfalseを返す。
0.0000001未満までなら誤差として同じにする
static equal(a: Vec3, b: Vec3): boolean{
return (a.x - b.x) * Math.pow(10, 7) < 1
&& (a.y - b.y) * Math.pow(10, 7) < 1
&& (a.z - b.z) * Math.pow(10, 7) < 1;
}
コード全体
export class Vec3 {
public x: number
public y: number
public z: number
constructor(x: number, y: number, z: number) {
this.x = x;
this.y = y;
this.z = z;
}
// 正規化
static normalized(vec3: Vec3): Vec3 {
const vec_length = Vec3.norm(vec3);
return new Vec3(vec3.x / vec_length, vec3.y / vec_length, vec3.z / vec_length);
}
// イコール
static equal(a: Vec3, b: Vec3): boolean{
// aとbの差が0.0000001以下の時は同じとする
return (a.x - b.x) * Math.pow(10, 7) < 1
&& (a.y - b.y) * Math.pow(10, 7) < 1
&& (a.z - b.z) * Math.pow(10, 7) < 1;
}
// 加算
static add(a: Vec3, b: Vec3): Vec3 {
return new Vec3(a.x + b.x, a.y + b.y, a.z + b.z);
}
// 減算
static minus(a: Vec3, b: Vec3): Vec3 {
return new Vec3(a.x - b.x, a.y - b.y, a.z - b.z);
}
// スカラー倍
static multiple_scalar(vec3: Vec3, n: number): Vec3 {
return new Vec3(vec3.x * n, vec3.y * n, vec3.z * n);
}
// スカラー割
static divide_scalar(vec3: Vec3, n: number): Vec3 {
return new Vec3(vec3.x / n, vec3.y / n, vec3.z / n);
}
// ノルム
static norm(vec3: Vec3): number {
return Math.sqrt(vec3.x ** 2 + vec3.y ** 2 + vec3.z ** 2);
}
// 内積
static dot(a: Vec3, b: Vec3): number {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
// 外積
static outer(a: Vec3, b: Vec3): Vec3{
return new Vec3(a.y * b.z - a.z * b.y, -(a.x * b.z - a.z * b.x), a.x * b.y - a.y * b.x);
}
// 射影
static project(a: Vec3, b: Vec3): Vec3 {
const dot_a_b = Vec3.dot(a, b);
const b_length_pow = Vec3.norm(b) ** 2;
return Vec3.divide_scalar(Vec3.multiple_scalar(b, dot_a_b), b_length_pow);
}
}
参考図書
3Dグラフィックのための数学
Discussion