新增math库
This commit is contained in:
261
packages/math/tests/Vector2.test.ts
Normal file
261
packages/math/tests/Vector2.test.ts
Normal file
@@ -0,0 +1,261 @@
|
||||
import { Vector2 } from '../src/Vector2';
|
||||
|
||||
declare global {
|
||||
var expectFloatsEqual: (actual: number, expected: number, epsilon?: number) => void;
|
||||
}
|
||||
|
||||
describe('Vector2', () => {
|
||||
describe('构造函数和基础属性', () => {
|
||||
test('默认构造函数应创建零向量', () => {
|
||||
const v = new Vector2();
|
||||
expect(v.x).toBe(0);
|
||||
expect(v.y).toBe(0);
|
||||
});
|
||||
|
||||
test('应正确设置x和y值', () => {
|
||||
const v = new Vector2(3, 4);
|
||||
expect(v.x).toBe(3);
|
||||
expect(v.y).toBe(4);
|
||||
});
|
||||
|
||||
test('length属性应正确计算', () => {
|
||||
const v = new Vector2(3, 4);
|
||||
expect(v.length).toBe(5);
|
||||
});
|
||||
|
||||
test('lengthSquared属性应正确计算', () => {
|
||||
const v = new Vector2(3, 4);
|
||||
expect(v.lengthSquared).toBe(25);
|
||||
});
|
||||
|
||||
test('angle属性应正确计算', () => {
|
||||
const v = new Vector2(1, 0);
|
||||
expect(v.angle).toBe(0);
|
||||
|
||||
const v2 = new Vector2(0, 1);
|
||||
expectFloatsEqual(v2.angle, Math.PI / 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('基础运算', () => {
|
||||
test('set方法应正确设置值', () => {
|
||||
const v = new Vector2();
|
||||
v.set(5, 6);
|
||||
expect(v.x).toBe(5);
|
||||
expect(v.y).toBe(6);
|
||||
});
|
||||
|
||||
test('copy方法应正确复制值', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(3, 4);
|
||||
v2.copy(v1);
|
||||
expect(v2.x).toBe(1);
|
||||
expect(v2.y).toBe(2);
|
||||
});
|
||||
|
||||
test('clone方法应创建相同的新实例', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = v1.clone();
|
||||
expect(v2.x).toBe(1);
|
||||
expect(v2.y).toBe(2);
|
||||
expect(v2).not.toBe(v1);
|
||||
});
|
||||
|
||||
test('add方法应正确相加', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(3, 4);
|
||||
v1.add(v2);
|
||||
expect(v1.x).toBe(4);
|
||||
expect(v1.y).toBe(6);
|
||||
});
|
||||
|
||||
test('subtract方法应正确相减', () => {
|
||||
const v1 = new Vector2(5, 7);
|
||||
const v2 = new Vector2(2, 3);
|
||||
v1.subtract(v2);
|
||||
expect(v1.x).toBe(3);
|
||||
expect(v1.y).toBe(4);
|
||||
});
|
||||
|
||||
test('multiply方法应正确数乘', () => {
|
||||
const v = new Vector2(2, 3);
|
||||
v.multiply(4);
|
||||
expect(v.x).toBe(8);
|
||||
expect(v.y).toBe(12);
|
||||
});
|
||||
|
||||
test('divide方法应正确数除', () => {
|
||||
const v = new Vector2(8, 12);
|
||||
v.divide(4);
|
||||
expect(v.x).toBe(2);
|
||||
expect(v.y).toBe(3);
|
||||
});
|
||||
|
||||
test('divide方法应在除以零时抛出错误', () => {
|
||||
const v = new Vector2(1, 2);
|
||||
expect(() => v.divide(0)).toThrow('不能除以零');
|
||||
});
|
||||
});
|
||||
|
||||
describe('向量运算', () => {
|
||||
test('dot方法应正确计算点积', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(3, 4);
|
||||
expect(v1.dot(v2)).toBe(11); // 1*3 + 2*4 = 11
|
||||
});
|
||||
|
||||
test('cross方法应正确计算叉积', () => {
|
||||
const v1 = new Vector2(1, 0);
|
||||
const v2 = new Vector2(0, 1);
|
||||
expect(v1.cross(v2)).toBe(1);
|
||||
});
|
||||
|
||||
test('normalize方法应正确归一化向量', () => {
|
||||
const v = new Vector2(3, 4);
|
||||
v.normalize();
|
||||
expectFloatsEqual(v.length, 1);
|
||||
expectFloatsEqual(v.x, 0.6);
|
||||
expectFloatsEqual(v.y, 0.8);
|
||||
});
|
||||
|
||||
test('零向量归一化应保持不变', () => {
|
||||
const v = new Vector2(0, 0);
|
||||
v.normalize();
|
||||
expect(v.x).toBe(0);
|
||||
expect(v.y).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('几何运算', () => {
|
||||
test('distanceTo方法应正确计算距离', () => {
|
||||
const v1 = new Vector2(0, 0);
|
||||
const v2 = new Vector2(3, 4);
|
||||
expect(v1.distanceTo(v2)).toBe(5);
|
||||
});
|
||||
|
||||
test('angleTo方法应正确计算夹角', () => {
|
||||
const v1 = new Vector2(1, 0);
|
||||
const v2 = new Vector2(0, 1);
|
||||
expectFloatsEqual(v1.angleTo(v2), Math.PI / 2);
|
||||
});
|
||||
|
||||
test('projectOnto方法应正确投影', () => {
|
||||
const v1 = new Vector2(2, 2);
|
||||
const v2 = new Vector2(1, 0);
|
||||
const projected = v1.projectOnto(v2);
|
||||
expect(projected.x).toBe(2);
|
||||
expect(projected.y).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('变换操作', () => {
|
||||
test('rotate方法应正确旋转向量', () => {
|
||||
const v = new Vector2(1, 0);
|
||||
v.rotate(Math.PI / 2);
|
||||
expectFloatsEqual(v.x, 0, 1e-10);
|
||||
expectFloatsEqual(v.y, 1, 1e-10);
|
||||
});
|
||||
|
||||
test('reflect方法应正确反射向量', () => {
|
||||
const v = new Vector2(1, 1);
|
||||
const normal = new Vector2(0, 1);
|
||||
v.reflect(normal);
|
||||
expectFloatsEqual(v.x, 1);
|
||||
expectFloatsEqual(v.y, -1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('插值和限制', () => {
|
||||
test('lerp方法应正确插值', () => {
|
||||
const v1 = new Vector2(0, 0);
|
||||
const v2 = new Vector2(10, 10);
|
||||
v1.lerp(v2, 0.5);
|
||||
expect(v1.x).toBe(5);
|
||||
expect(v1.y).toBe(5);
|
||||
});
|
||||
|
||||
test('clampLength方法应正确限制长度', () => {
|
||||
const v = new Vector2(6, 8); // 长度为10
|
||||
v.clampLength(5);
|
||||
expectFloatsEqual(v.length, 5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('比较操作', () => {
|
||||
test('equals方法应正确比较向量', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(1, 2);
|
||||
const v3 = new Vector2(1.0001, 2);
|
||||
|
||||
expect(v1.equals(v2)).toBe(true);
|
||||
expect(v1.equals(v3, 0.001)).toBe(true);
|
||||
expect(v1.equals(v3, 0.00001)).toBe(false);
|
||||
});
|
||||
|
||||
test('exactEquals方法应检查完全相等', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(1, 2);
|
||||
const v3 = new Vector2(1.0001, 2);
|
||||
|
||||
expect(v1.exactEquals(v2)).toBe(true);
|
||||
expect(v1.exactEquals(v3)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('静态方法', () => {
|
||||
test('Vector2.add应创建新的相加结果', () => {
|
||||
const v1 = new Vector2(1, 2);
|
||||
const v2 = new Vector2(3, 4);
|
||||
const result = Vector2.add(v1, v2);
|
||||
|
||||
expect(result.x).toBe(4);
|
||||
expect(result.y).toBe(6);
|
||||
expect(v1.x).toBe(1); // 原向量不变
|
||||
expect(v1.y).toBe(2);
|
||||
});
|
||||
|
||||
test('Vector2.fromAngle应从角度创建单位向量', () => {
|
||||
const v = Vector2.fromAngle(Math.PI / 2);
|
||||
expectFloatsEqual(v.x, 0, 1e-10);
|
||||
expectFloatsEqual(v.y, 1, 1e-10);
|
||||
});
|
||||
|
||||
test('Vector2.fromPolar应从极坐标创建向量', () => {
|
||||
const v = Vector2.fromPolar(5, 0);
|
||||
expect(v.x).toBe(5);
|
||||
expectFloatsEqual(v.y, 0, 1e-10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('静态常量', () => {
|
||||
test('静态常量应具有正确的值', () => {
|
||||
expect(Vector2.ZERO.x).toBe(0);
|
||||
expect(Vector2.ZERO.y).toBe(0);
|
||||
expect(Vector2.ONE.x).toBe(1);
|
||||
expect(Vector2.ONE.y).toBe(1);
|
||||
expect(Vector2.RIGHT.x).toBe(1);
|
||||
expect(Vector2.RIGHT.y).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('字符串转换', () => {
|
||||
test('toString应返回正确格式', () => {
|
||||
const v = new Vector2(1.2345, 2.6789);
|
||||
const str = v.toString();
|
||||
expect(str).toContain('1.234');
|
||||
expect(str).toContain('2.679');
|
||||
});
|
||||
|
||||
test('toArray应返回数组', () => {
|
||||
const v = new Vector2(1, 2);
|
||||
const arr = v.toArray();
|
||||
expect(arr).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
test('toObject应返回对象', () => {
|
||||
const v = new Vector2(1, 2);
|
||||
const obj = v.toObject();
|
||||
expect(obj).toEqual({ x: 1, y: 2 });
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user