bpmatrixjs 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,32 @@
1
+ interface RectGeometryData {
2
+ geometry: Float32Array;
3
+ uv: Float32Array;
4
+ width: number;
5
+ height: number;
6
+ radius: number;
7
+ }
8
+ /**
9
+ * 数值钳制
10
+ * @param value 当前值
11
+ * @param min 最小值
12
+ * @param max 最大值
13
+ * @returns 钳制结果
14
+ */
15
+ /**
16
+ * 生成矩形几何
17
+ * 以(0, 0)为中心
18
+ * 圆角半径会自动限制到半宽半高的较小值
19
+ * @param width 宽度
20
+ * @param height 高度
21
+ * @param radius 圆角半径
22
+ * @returns 几何数据
23
+ */
24
+ declare const CreateRectGeometry: (width: number, height: number, radius?: number) => RectGeometryData;
25
+ /**
26
+ * 矩形几何工具
27
+ */
28
+ declare const Rect: {
29
+ CreateGeometry: (width: number, height: number, radius?: number) => RectGeometryData;
30
+ };
31
+ export { CreateRectGeometry, Rect };
32
+ export type { RectGeometryData };
@@ -0,0 +1,134 @@
1
+ import { Clamp } from "../Utils/index.js";
2
+ /**
3
+ * 生成矩形边界点
4
+ * @param halfWidth 半宽
5
+ * @param halfHeight 半高
6
+ * @param radius 圆角半径
7
+ * @returns 边界点列表
8
+ */
9
+ const CreatePerimeterPoints = (halfWidth, halfHeight, radius) => {
10
+ if (halfWidth === 0 || halfHeight === 0) {
11
+ return [];
12
+ }
13
+ if (radius === 0) {
14
+ return [
15
+ [halfWidth, halfHeight],
16
+ [halfWidth, -halfHeight],
17
+ [-halfWidth, -halfHeight],
18
+ [-halfWidth, halfHeight],
19
+ ];
20
+ }
21
+ const segments = GetCornerSegments(radius);
22
+ const points = [];
23
+ PushArc(points, halfWidth - radius, halfHeight - radius, radius, Math.PI * 0.5, 0, segments, true);
24
+ PushArc(points, halfWidth - radius, -halfHeight + radius, radius, 0, -Math.PI * 0.5, segments, false);
25
+ PushArc(points, -halfWidth + radius, -halfHeight + radius, radius, -Math.PI * 0.5, -Math.PI, segments, false);
26
+ PushArc(points, -halfWidth + radius, halfHeight - radius, radius, Math.PI, Math.PI * 0.5, segments, false);
27
+ return points;
28
+ };
29
+ /**
30
+ * 添加圆角圆弧点
31
+ * @param points 点数组
32
+ * @param centerX 圆心X
33
+ * @param centerY 圆心Y
34
+ * @param radius 圆角半径
35
+ * @param startAngle 起始弧度
36
+ * @param endAngle 结束弧度
37
+ * @param segments 分段数
38
+ * @param includeStart 是否包含起始点
39
+ * @returns 无返回值
40
+ */
41
+ const PushArc = (points, centerX, centerY, radius, startAngle, endAngle, segments, includeStart) => {
42
+ const startIndex = includeStart ? 0 : 1;
43
+ for (let index = startIndex; index <= segments; index += 1) {
44
+ const t = index / segments;
45
+ const angle = startAngle + (endAngle - startAngle) * t;
46
+ const x = centerX + Math.cos(angle) * radius;
47
+ const y = centerY + Math.sin(angle) * radius;
48
+ points.push([x, y]);
49
+ }
50
+ };
51
+ /**
52
+ * 生成位置缓冲
53
+ * @param points 边界点列表
54
+ * @returns 位置缓冲
55
+ */
56
+ const CreateGeometryBuffer = (points) => {
57
+ if (points.length < 3) {
58
+ return new Float32Array(0);
59
+ }
60
+ const geometry = [];
61
+ for (let index = 0; index < points.length; index += 1) {
62
+ const current = points[index];
63
+ const next = points[(index + 1) % points.length];
64
+ geometry.push(0, 0, current[0], current[1], next[0], next[1]);
65
+ }
66
+ return new Float32Array(geometry);
67
+ };
68
+ /**
69
+ * 生成UV缓冲
70
+ * @param points 边界点列表
71
+ * @param width 宽度
72
+ * @param height 高度
73
+ * @returns UV缓冲
74
+ */
75
+ const CreateUvBuffer = (points, width, height) => {
76
+ if (points.length < 3 || width === 0 || height === 0) {
77
+ return new Float32Array(0);
78
+ }
79
+ const uv = [];
80
+ const halfWidth = width * 0.5;
81
+ const halfHeight = height * 0.5;
82
+ for (let index = 0; index < points.length; index += 1) {
83
+ const current = points[index];
84
+ const next = points[(index + 1) % points.length];
85
+ uv.push(0.5, 0.5, (current[0] + halfWidth) / width, (current[1] + halfHeight) / height, (next[0] + halfWidth) / width, (next[1] + halfHeight) / height);
86
+ }
87
+ return new Float32Array(uv);
88
+ };
89
+ /**
90
+ * 计算圆角分段数
91
+ * @param radius 圆角半径
92
+ * @returns 分段数
93
+ */
94
+ const GetCornerSegments = (radius) => {
95
+ return Math.max(2, Math.ceil(radius / 8));
96
+ };
97
+ /**
98
+ * 数值钳制
99
+ * @param value 当前值
100
+ * @param min 最小值
101
+ * @param max 最大值
102
+ * @returns 钳制结果
103
+ */
104
+ /**
105
+ * 生成矩形几何
106
+ * 以(0, 0)为中心
107
+ * 圆角半径会自动限制到半宽半高的较小值
108
+ * @param width 宽度
109
+ * @param height 高度
110
+ * @param radius 圆角半径
111
+ * @returns 几何数据
112
+ */
113
+ const CreateRectGeometry = (width, height, radius = 0) => {
114
+ const safeWidth = Math.max(0, width);
115
+ const safeHeight = Math.max(0, height);
116
+ const halfWidth = safeWidth * 0.5;
117
+ const halfHeight = safeHeight * 0.5;
118
+ const safeRadius = Clamp(radius, 0, Math.min(halfWidth, halfHeight));
119
+ const points = CreatePerimeterPoints(halfWidth, halfHeight, safeRadius);
120
+ return {
121
+ geometry: CreateGeometryBuffer(points),
122
+ uv: CreateUvBuffer(points, safeWidth, safeHeight),
123
+ width: safeWidth,
124
+ height: safeHeight,
125
+ radius: safeRadius,
126
+ };
127
+ };
128
+ /**
129
+ * 矩形几何工具
130
+ */
131
+ const Rect = {
132
+ CreateGeometry: CreateRectGeometry,
133
+ };
134
+ export { CreateRectGeometry, Rect };
@@ -0,0 +1 @@
1
+ export { CreateRectGeometry, Rect, type RectGeometryData } from "./Rect.js";
@@ -0,0 +1 @@
1
+ export { CreateRectGeometry, Rect } from "./Rect.js";
@@ -0,0 +1,130 @@
1
+ import { type Vec2Like } from "./Vec2.js";
2
+ type Mat3Data = [
3
+ number,
4
+ number,
5
+ number,
6
+ number,
7
+ number,
8
+ number,
9
+ number,
10
+ number,
11
+ number
12
+ ];
13
+ interface Mat3Like {
14
+ data: Mat3Data;
15
+ }
16
+ /**
17
+ * 3x3矩阵
18
+ * @class
19
+ * @implements Mat3Like
20
+ * @example
21
+ * ```ts
22
+ * const mat3 = new Mat3([1, 0, 0, 0, 1, 0, 0, 0, 1]);
23
+ * ```
24
+ */
25
+ declare class Matrix3 implements Mat3Like {
26
+ /**
27
+ * 矩阵数组
28
+ * 采用列主序:
29
+ * [m00, m10, m20, m01, m11, m21, m02, m12, m22]
30
+ */
31
+ data: Mat3Data;
32
+ /**
33
+ * 创建3x3矩阵
34
+ * @param data 矩阵数组
35
+ */
36
+ constructor(data?: Readonly<Mat3Data>);
37
+ /**
38
+ * 设置为单位矩阵
39
+ * @returns 当前矩阵
40
+ */
41
+ identity(): this;
42
+ /**
43
+ * 设置矩阵数组
44
+ * @param data 矩阵数组
45
+ * @returns 当前矩阵
46
+ */
47
+ set(data: Readonly<Mat3Data>): this;
48
+ /**
49
+ * 设置平移分量
50
+ * @param vec2 平移向量
51
+ * @returns 当前矩阵
52
+ */
53
+ setTranslate(vec2: Readonly<Vec2Like>): this;
54
+ /**
55
+ * 设置缩放分量
56
+ * @param vec2 缩放向量
57
+ * @returns 当前矩阵
58
+ */
59
+ setScale(vec2: Readonly<Vec2Like>): this;
60
+ /**
61
+ * 设置旋转分量
62
+ * @param angle 弧度
63
+ * @returns 当前矩阵
64
+ */
65
+ setRotation(angle: number): this;
66
+ /**
67
+ * 获取平移分量
68
+ * @param vec2 输出向量
69
+ * @returns 输出向量
70
+ */
71
+ getTranslate(vec2?: Vec2Like): Vec2Like;
72
+ /**
73
+ * 获取缩放分量
74
+ * @param vec2 输出向量
75
+ * @returns 输出向量
76
+ */
77
+ getScale(vec2?: Vec2Like): Vec2Like;
78
+ /**
79
+ * 获取旋转弧度
80
+ * @returns 旋转弧度
81
+ */
82
+ getRotation(): number;
83
+ /**
84
+ * 矩阵乘法
85
+ * 传入标量时执行标量乘法
86
+ * 传入一个矩阵时执行当前矩阵右乘目标矩阵
87
+ * 传入两个矩阵时执行 a * b 并写回当前矩阵
88
+ * @param value 标量或矩阵a
89
+ * @param mat3 矩阵b
90
+ * @returns 当前矩阵
91
+ */
92
+ mul(value: number | Readonly<Mat3Like>, mat3?: Readonly<Mat3Like>): this;
93
+ /**
94
+ * 转置矩阵
95
+ * @returns 当前矩阵
96
+ */
97
+ transpose(): this;
98
+ /**
99
+ * 求矩阵行列式
100
+ * @returns 行列式
101
+ */
102
+ det(): number;
103
+ /**
104
+ * 求逆矩阵
105
+ * 不可逆时保持原矩阵不变
106
+ * @returns 当前矩阵
107
+ */
108
+ invert(): this;
109
+ /**
110
+ * 复制目标矩阵
111
+ * @param mat3 目标矩阵
112
+ * @returns 当前矩阵
113
+ */
114
+ copy(mat3: Readonly<Mat3Like>): this;
115
+ /**
116
+ * 克隆矩阵
117
+ * @returns 新的矩阵实例
118
+ */
119
+ clone(): Matrix3;
120
+ /**
121
+ * 判断矩阵是否完全相等
122
+ * @param mat3 目标矩阵
123
+ * @returns 是否相等
124
+ */
125
+ equals(mat3: Readonly<Mat3Like>): boolean;
126
+ private multiplyData;
127
+ }
128
+ declare const Mat3: typeof Matrix3;
129
+ export { Mat3, Matrix3 };
130
+ export type { Mat3Data, Mat3Like };
@@ -0,0 +1,294 @@
1
+ import { Vec2 } from "./Vec2.js";
2
+ /**
3
+ * 3x3矩阵
4
+ * @class
5
+ * @implements Mat3Like
6
+ * @example
7
+ * ```ts
8
+ * const mat3 = new Mat3([1, 0, 0, 0, 1, 0, 0, 0, 1]);
9
+ * ```
10
+ */
11
+ class Matrix3 {
12
+ /**
13
+ * 矩阵数组
14
+ * 采用列主序:
15
+ * [m00, m10, m20, m01, m11, m21, m02, m12, m22]
16
+ */
17
+ data;
18
+ /**
19
+ * 创建3x3矩阵
20
+ * @param data 矩阵数组
21
+ */
22
+ constructor(data) {
23
+ this.data = CreateIdentityData();
24
+ if (data !== undefined) {
25
+ this.set(data);
26
+ }
27
+ }
28
+ /**
29
+ * 设置为单位矩阵
30
+ * @returns 当前矩阵
31
+ */
32
+ identity() {
33
+ this.data[0] = 1;
34
+ this.data[1] = 0;
35
+ this.data[2] = 0;
36
+ this.data[3] = 0;
37
+ this.data[4] = 1;
38
+ this.data[5] = 0;
39
+ this.data[6] = 0;
40
+ this.data[7] = 0;
41
+ this.data[8] = 1;
42
+ return this;
43
+ }
44
+ /**
45
+ * 设置矩阵数组
46
+ * @param data 矩阵数组
47
+ * @returns 当前矩阵
48
+ */
49
+ set(data) {
50
+ this.data[0] = data[0];
51
+ this.data[1] = data[1];
52
+ this.data[2] = data[2];
53
+ this.data[3] = data[3];
54
+ this.data[4] = data[4];
55
+ this.data[5] = data[5];
56
+ this.data[6] = data[6];
57
+ this.data[7] = data[7];
58
+ this.data[8] = data[8];
59
+ return this;
60
+ }
61
+ /**
62
+ * 设置平移分量
63
+ * @param vec2 平移向量
64
+ * @returns 当前矩阵
65
+ */
66
+ setTranslate(vec2) {
67
+ this.data[6] = vec2.x;
68
+ this.data[7] = vec2.y;
69
+ return this;
70
+ }
71
+ /**
72
+ * 设置缩放分量
73
+ * @param vec2 缩放向量
74
+ * @returns 当前矩阵
75
+ */
76
+ setScale(vec2) {
77
+ const rotation = this.getRotation();
78
+ const cos = Math.cos(rotation);
79
+ const sin = Math.sin(rotation);
80
+ this.data[0] = cos * vec2.x;
81
+ this.data[1] = sin * vec2.x;
82
+ this.data[3] = -sin * vec2.y;
83
+ this.data[4] = cos * vec2.y;
84
+ return this;
85
+ }
86
+ /**
87
+ * 设置旋转分量
88
+ * @param angle 弧度
89
+ * @returns 当前矩阵
90
+ */
91
+ setRotation(angle) {
92
+ const scale = this.getScale();
93
+ const cos = Math.cos(angle);
94
+ const sin = Math.sin(angle);
95
+ this.data[0] = cos * scale.x;
96
+ this.data[1] = sin * scale.x;
97
+ this.data[3] = -sin * scale.y;
98
+ this.data[4] = cos * scale.y;
99
+ return this;
100
+ }
101
+ /**
102
+ * 获取平移分量
103
+ * @param vec2 输出向量
104
+ * @returns 输出向量
105
+ */
106
+ getTranslate(vec2 = new Vec2()) {
107
+ vec2.x = this.data[6];
108
+ vec2.y = this.data[7];
109
+ return vec2;
110
+ }
111
+ /**
112
+ * 获取缩放分量
113
+ * @param vec2 输出向量
114
+ * @returns 输出向量
115
+ */
116
+ getScale(vec2 = new Vec2()) {
117
+ vec2.x = Math.hypot(this.data[0], this.data[1]);
118
+ vec2.y = Math.hypot(this.data[3], this.data[4]);
119
+ return vec2;
120
+ }
121
+ /**
122
+ * 获取旋转弧度
123
+ * @returns 旋转弧度
124
+ */
125
+ getRotation() {
126
+ return Math.atan2(this.data[1], this.data[0]);
127
+ }
128
+ /**
129
+ * 矩阵乘法
130
+ * 传入标量时执行标量乘法
131
+ * 传入一个矩阵时执行当前矩阵右乘目标矩阵
132
+ * 传入两个矩阵时执行 a * b 并写回当前矩阵
133
+ * @param value 标量或矩阵a
134
+ * @param mat3 矩阵b
135
+ * @returns 当前矩阵
136
+ */
137
+ mul(value, mat3) {
138
+ if (typeof value === "number") {
139
+ this.data[0] *= value;
140
+ this.data[1] *= value;
141
+ this.data[2] *= value;
142
+ this.data[3] *= value;
143
+ this.data[4] *= value;
144
+ this.data[5] *= value;
145
+ this.data[6] *= value;
146
+ this.data[7] *= value;
147
+ this.data[8] *= value;
148
+ return this;
149
+ }
150
+ const left = mat3 === undefined ? this.data : value.data;
151
+ const right = mat3 === undefined ? value.data : mat3.data;
152
+ return this.multiplyData(left, right);
153
+ }
154
+ /**
155
+ * 转置矩阵
156
+ * @returns 当前矩阵
157
+ */
158
+ transpose() {
159
+ const m01 = this.data[3];
160
+ const m02 = this.data[6];
161
+ const m12 = this.data[7];
162
+ this.data[3] = this.data[1];
163
+ this.data[6] = this.data[2];
164
+ this.data[7] = this.data[5];
165
+ this.data[1] = m01;
166
+ this.data[2] = m02;
167
+ this.data[5] = m12;
168
+ return this;
169
+ }
170
+ /**
171
+ * 求矩阵行列式
172
+ * @returns 行列式
173
+ */
174
+ det() {
175
+ const a00 = this.data[0];
176
+ const a10 = this.data[1];
177
+ const a20 = this.data[2];
178
+ const a01 = this.data[3];
179
+ const a11 = this.data[4];
180
+ const a21 = this.data[5];
181
+ const a02 = this.data[6];
182
+ const a12 = this.data[7];
183
+ const a22 = this.data[8];
184
+ return a00 * (a11 * a22 - a21 * a12)
185
+ - a01 * (a10 * a22 - a20 * a12)
186
+ + a02 * (a10 * a21 - a20 * a11);
187
+ }
188
+ /**
189
+ * 求逆矩阵
190
+ * 不可逆时保持原矩阵不变
191
+ * @returns 当前矩阵
192
+ */
193
+ invert() {
194
+ const a00 = this.data[0];
195
+ const a10 = this.data[1];
196
+ const a20 = this.data[2];
197
+ const a01 = this.data[3];
198
+ const a11 = this.data[4];
199
+ const a21 = this.data[5];
200
+ const a02 = this.data[6];
201
+ const a12 = this.data[7];
202
+ const a22 = this.data[8];
203
+ const b00 = a11 * a22 - a21 * a12;
204
+ const b01 = -(a10 * a22 - a20 * a12);
205
+ const b02 = a10 * a21 - a20 * a11;
206
+ const b10 = -(a01 * a22 - a21 * a02);
207
+ const b11 = a00 * a22 - a20 * a02;
208
+ const b12 = -(a00 * a21 - a20 * a01);
209
+ const b20 = a01 * a12 - a11 * a02;
210
+ const b21 = -(a00 * a12 - a10 * a02);
211
+ const b22 = a00 * a11 - a10 * a01;
212
+ const determinant = a00 * b00 + a01 * b01 + a02 * b02;
213
+ if (determinant === 0) {
214
+ return this;
215
+ }
216
+ const inverseDeterminant = 1 / determinant;
217
+ this.data[0] = b00 * inverseDeterminant;
218
+ this.data[1] = b01 * inverseDeterminant;
219
+ this.data[2] = b02 * inverseDeterminant;
220
+ this.data[3] = b10 * inverseDeterminant;
221
+ this.data[4] = b11 * inverseDeterminant;
222
+ this.data[5] = b12 * inverseDeterminant;
223
+ this.data[6] = b20 * inverseDeterminant;
224
+ this.data[7] = b21 * inverseDeterminant;
225
+ this.data[8] = b22 * inverseDeterminant;
226
+ return this;
227
+ }
228
+ /**
229
+ * 复制目标矩阵
230
+ * @param mat3 目标矩阵
231
+ * @returns 当前矩阵
232
+ */
233
+ copy(mat3) {
234
+ return this.set(mat3.data);
235
+ }
236
+ /**
237
+ * 克隆矩阵
238
+ * @returns 新的矩阵实例
239
+ */
240
+ clone() {
241
+ return new Matrix3(this.data);
242
+ }
243
+ /**
244
+ * 判断矩阵是否完全相等
245
+ * @param mat3 目标矩阵
246
+ * @returns 是否相等
247
+ */
248
+ equals(mat3) {
249
+ return this.data[0] === mat3.data[0]
250
+ && this.data[1] === mat3.data[1]
251
+ && this.data[2] === mat3.data[2]
252
+ && this.data[3] === mat3.data[3]
253
+ && this.data[4] === mat3.data[4]
254
+ && this.data[5] === mat3.data[5]
255
+ && this.data[6] === mat3.data[6]
256
+ && this.data[7] === mat3.data[7]
257
+ && this.data[8] === mat3.data[8];
258
+ }
259
+ multiplyData(left, right) {
260
+ const a00 = left[0];
261
+ const a10 = left[1];
262
+ const a20 = left[2];
263
+ const a01 = left[3];
264
+ const a11 = left[4];
265
+ const a21 = left[5];
266
+ const a02 = left[6];
267
+ const a12 = left[7];
268
+ const a22 = left[8];
269
+ const b00 = right[0];
270
+ const b10 = right[1];
271
+ const b20 = right[2];
272
+ const b01 = right[3];
273
+ const b11 = right[4];
274
+ const b21 = right[5];
275
+ const b02 = right[6];
276
+ const b12 = right[7];
277
+ const b22 = right[8];
278
+ this.data[0] = a00 * b00 + a01 * b10 + a02 * b20;
279
+ this.data[1] = a10 * b00 + a11 * b10 + a12 * b20;
280
+ this.data[2] = a20 * b00 + a21 * b10 + a22 * b20;
281
+ this.data[3] = a00 * b01 + a01 * b11 + a02 * b21;
282
+ this.data[4] = a10 * b01 + a11 * b11 + a12 * b21;
283
+ this.data[5] = a20 * b01 + a21 * b11 + a22 * b21;
284
+ this.data[6] = a00 * b02 + a01 * b12 + a02 * b22;
285
+ this.data[7] = a10 * b02 + a11 * b12 + a12 * b22;
286
+ this.data[8] = a20 * b02 + a21 * b12 + a22 * b22;
287
+ return this;
288
+ }
289
+ }
290
+ const CreateIdentityData = () => {
291
+ return [1, 0, 0, 0, 1, 0, 0, 0, 1];
292
+ };
293
+ const Mat3 = Matrix3;
294
+ export { Mat3, Matrix3 };
@@ -0,0 +1,171 @@
1
+ import type { Mat3Like } from "./Mat3.js";
2
+ interface Vec2Like {
3
+ x: number;
4
+ y: number;
5
+ }
6
+ /**
7
+ * 2D向量
8
+ * @class
9
+ * @implements Vec2Like
10
+ * @description 2D向量类
11
+ * @example
12
+ * ```ts
13
+ * const vec2 = new Vec2(x, y);
14
+ * ```
15
+ */
16
+ declare class Vector2 implements Vec2Like {
17
+ /**
18
+ * X分量
19
+ */
20
+ x: number;
21
+ /**
22
+ * Y分量
23
+ */
24
+ y: number;
25
+ /**
26
+ * 创建2D向量
27
+ * @param x X分量
28
+ * @param y Y分量
29
+ */
30
+ constructor(x?: number, y?: number);
31
+ /**
32
+ * 当前向量加上目标向量
33
+ * @param vec2 目标向量
34
+ * @returns 当前向量
35
+ */
36
+ add(vec2: Readonly<Vec2Like>): this;
37
+ /**
38
+ * 当前向量减去目标向量
39
+ * @param vec2 目标向量
40
+ * @returns 当前向量
41
+ */
42
+ sub(vec2: Readonly<Vec2Like>): this;
43
+ /**
44
+ * 当前向量按分量乘以目标向量
45
+ * @param vec2 目标向量
46
+ * @returns 当前向量
47
+ */
48
+ mul(vec2: Readonly<Vec2Like>): this;
49
+ /**
50
+ * 当前向量按分量除以目标向量
51
+ * @param vec2 目标向量
52
+ * @returns 当前向量
53
+ */
54
+ div(vec2: Readonly<Vec2Like>): this;
55
+ /**
56
+ * 计算与目标向量的点乘
57
+ * @param vec2 目标向量
58
+ * @returns 点乘结果
59
+ */
60
+ dot(vec2: Readonly<Vec2Like>): number;
61
+ /**
62
+ * 计算与目标向量的叉乘
63
+ * @param vec2 目标向量
64
+ * @returns 叉乘结果
65
+ */
66
+ crs(vec2: Readonly<Vec2Like>): number;
67
+ /**
68
+ * 计算与目标向量的距离
69
+ * @param vec2 目标向量
70
+ * @returns 距离
71
+ */
72
+ dist(vec2: Readonly<Vec2Like>): number;
73
+ /**
74
+ * 计算与目标向量的距离平方
75
+ * @param vec2 目标向量
76
+ * @returns 距离平方
77
+ */
78
+ distSq(vec2: Readonly<Vec2Like>): number;
79
+ /**
80
+ * 获取向量长度
81
+ * @returns 向量长度
82
+ */
83
+ len(): number;
84
+ /**
85
+ * 获取向量长度平方
86
+ * @returns 向量长度平方
87
+ */
88
+ lenSq(): number;
89
+ /**
90
+ * 将当前向量归一化
91
+ * @returns 当前向量
92
+ */
93
+ normal(): this;
94
+ /**
95
+ * 复制目标向量的分量到当前向量
96
+ * @param vec2 目标向量
97
+ * @returns 当前向量
98
+ */
99
+ copy(vec2: Readonly<Vec2Like>): this;
100
+ /**
101
+ * 克隆当前向量
102
+ * @returns 新的向量实例
103
+ */
104
+ clone(): Vector2;
105
+ /**
106
+ * 设置向量分量
107
+ * @param x X分量
108
+ * @param y Y分量
109
+ * @returns 当前向量
110
+ */
111
+ set(x: number, y: number): this;
112
+ /**
113
+ * 设置X分量
114
+ * @param x X分量
115
+ * @returns 当前向量
116
+ */
117
+ setX(x: number): this;
118
+ /**
119
+ * 设置Y分量
120
+ * @param y Y分量
121
+ * @returns 当前向量
122
+ */
123
+ setY(y: number): this;
124
+ /**
125
+ * 应用矩阵变换
126
+ * @param mat3 目标矩阵
127
+ * @returns 当前向量
128
+ */
129
+ apply(mat3: Readonly<Mat3Like>): this;
130
+ /**
131
+ * 按分量取较大值
132
+ * @param vec2 目标向量
133
+ * @returns 当前向量
134
+ */
135
+ max(vec2: Readonly<Vec2Like>): this;
136
+ /**
137
+ * 按分量取较小值
138
+ * @param vec2 目标向量
139
+ * @returns 当前向量
140
+ */
141
+ min(vec2: Readonly<Vec2Like>): this;
142
+ /**
143
+ * 将当前向量限制在最小值和最大值之间
144
+ * @param min 最小向量
145
+ * @param max 最大向量
146
+ * @returns 当前向量
147
+ */
148
+ clamp(min: Readonly<Vec2Like>, max: Readonly<Vec2Like>): this;
149
+ /**
150
+ * 乘以标量
151
+ * @param value 标量
152
+ * @returns 当前向量
153
+ */
154
+ scl(value: number): this;
155
+ /**
156
+ * 获取向量弧度
157
+ * 传入目标向量时,返回与目标向量的夹角弧度
158
+ * @param vec2 目标向量
159
+ * @returns 弧度值
160
+ */
161
+ angle(vec2?: Readonly<Vec2Like>): number;
162
+ /**
163
+ * 判断是否与目标向量完全相等
164
+ * @param vec2 目标向量
165
+ * @returns 是否相等
166
+ */
167
+ equals(vec2: Readonly<Vec2Like>): boolean;
168
+ }
169
+ declare const Vec2: typeof Vector2;
170
+ export { Vec2, Vector2 };
171
+ export type { Vec2Like };
@@ -0,0 +1,251 @@
1
+ /**
2
+ * 2D向量
3
+ * @class
4
+ * @implements Vec2Like
5
+ * @description 2D向量类
6
+ * @example
7
+ * ```ts
8
+ * const vec2 = new Vec2(x, y);
9
+ * ```
10
+ */
11
+ class Vector2 {
12
+ /**
13
+ * X分量
14
+ */
15
+ x;
16
+ /**
17
+ * Y分量
18
+ */
19
+ y;
20
+ /**
21
+ * 创建2D向量
22
+ * @param x X分量
23
+ * @param y Y分量
24
+ */
25
+ constructor(x = 0, y = 0) {
26
+ this.x = x;
27
+ this.y = y;
28
+ }
29
+ /**
30
+ * 当前向量加上目标向量
31
+ * @param vec2 目标向量
32
+ * @returns 当前向量
33
+ */
34
+ add(vec2) {
35
+ this.x += vec2.x;
36
+ this.y += vec2.y;
37
+ return this;
38
+ }
39
+ /**
40
+ * 当前向量减去目标向量
41
+ * @param vec2 目标向量
42
+ * @returns 当前向量
43
+ */
44
+ sub(vec2) {
45
+ this.x -= vec2.x;
46
+ this.y -= vec2.y;
47
+ return this;
48
+ }
49
+ /**
50
+ * 当前向量按分量乘以目标向量
51
+ * @param vec2 目标向量
52
+ * @returns 当前向量
53
+ */
54
+ mul(vec2) {
55
+ this.x *= vec2.x;
56
+ this.y *= vec2.y;
57
+ return this;
58
+ }
59
+ /**
60
+ * 当前向量按分量除以目标向量
61
+ * @param vec2 目标向量
62
+ * @returns 当前向量
63
+ */
64
+ div(vec2) {
65
+ this.x /= vec2.x;
66
+ this.y /= vec2.y;
67
+ return this;
68
+ }
69
+ /**
70
+ * 计算与目标向量的点乘
71
+ * @param vec2 目标向量
72
+ * @returns 点乘结果
73
+ */
74
+ dot(vec2) {
75
+ return this.x * vec2.x + this.y * vec2.y;
76
+ }
77
+ /**
78
+ * 计算与目标向量的叉乘
79
+ * @param vec2 目标向量
80
+ * @returns 叉乘结果
81
+ */
82
+ crs(vec2) {
83
+ return this.x * vec2.y - this.y * vec2.x;
84
+ }
85
+ /**
86
+ * 计算与目标向量的距离
87
+ * @param vec2 目标向量
88
+ * @returns 距离
89
+ */
90
+ dist(vec2) {
91
+ return Math.sqrt(this.distSq(vec2));
92
+ }
93
+ /**
94
+ * 计算与目标向量的距离平方
95
+ * @param vec2 目标向量
96
+ * @returns 距离平方
97
+ */
98
+ distSq(vec2) {
99
+ const dx = this.x - vec2.x;
100
+ const dy = this.y - vec2.y;
101
+ return dx * dx + dy * dy;
102
+ }
103
+ /**
104
+ * 获取向量长度
105
+ * @returns 向量长度
106
+ */
107
+ len() {
108
+ return Math.sqrt(this.lenSq());
109
+ }
110
+ /**
111
+ * 获取向量长度平方
112
+ * @returns 向量长度平方
113
+ */
114
+ lenSq() {
115
+ return this.x * this.x + this.y * this.y;
116
+ }
117
+ /**
118
+ * 将当前向量归一化
119
+ * @returns 当前向量
120
+ */
121
+ normal() {
122
+ const length = this.len();
123
+ if (length === 0) {
124
+ return this;
125
+ }
126
+ this.x /= length;
127
+ this.y /= length;
128
+ return this;
129
+ }
130
+ /**
131
+ * 复制目标向量的分量到当前向量
132
+ * @param vec2 目标向量
133
+ * @returns 当前向量
134
+ */
135
+ copy(vec2) {
136
+ this.x = vec2.x;
137
+ this.y = vec2.y;
138
+ return this;
139
+ }
140
+ /**
141
+ * 克隆当前向量
142
+ * @returns 新的向量实例
143
+ */
144
+ clone() {
145
+ return new Vector2(this.x, this.y);
146
+ }
147
+ /**
148
+ * 设置向量分量
149
+ * @param x X分量
150
+ * @param y Y分量
151
+ * @returns 当前向量
152
+ */
153
+ set(x, y) {
154
+ this.x = x;
155
+ this.y = y;
156
+ return this;
157
+ }
158
+ /**
159
+ * 设置X分量
160
+ * @param x X分量
161
+ * @returns 当前向量
162
+ */
163
+ setX(x) {
164
+ this.x = x;
165
+ return this;
166
+ }
167
+ /**
168
+ * 设置Y分量
169
+ * @param y Y分量
170
+ * @returns 当前向量
171
+ */
172
+ setY(y) {
173
+ this.y = y;
174
+ return this;
175
+ }
176
+ /**
177
+ * 应用矩阵变换
178
+ * @param mat3 目标矩阵
179
+ * @returns 当前向量
180
+ */
181
+ apply(mat3) {
182
+ const x = this.x;
183
+ const y = this.y;
184
+ this.x = mat3.data[0] * x + mat3.data[3] * y + mat3.data[6];
185
+ this.y = mat3.data[1] * x + mat3.data[4] * y + mat3.data[7];
186
+ return this;
187
+ }
188
+ /**
189
+ * 按分量取较大值
190
+ * @param vec2 目标向量
191
+ * @returns 当前向量
192
+ */
193
+ max(vec2) {
194
+ this.x = Math.max(this.x, vec2.x);
195
+ this.y = Math.max(this.y, vec2.y);
196
+ return this;
197
+ }
198
+ /**
199
+ * 按分量取较小值
200
+ * @param vec2 目标向量
201
+ * @returns 当前向量
202
+ */
203
+ min(vec2) {
204
+ this.x = Math.min(this.x, vec2.x);
205
+ this.y = Math.min(this.y, vec2.y);
206
+ return this;
207
+ }
208
+ /**
209
+ * 将当前向量限制在最小值和最大值之间
210
+ * @param min 最小向量
211
+ * @param max 最大向量
212
+ * @returns 当前向量
213
+ */
214
+ clamp(min, max) {
215
+ this.x = Math.min(Math.max(this.x, min.x), max.x);
216
+ this.y = Math.min(Math.max(this.y, min.y), max.y);
217
+ return this;
218
+ }
219
+ /**
220
+ * 乘以标量
221
+ * @param value 标量
222
+ * @returns 当前向量
223
+ */
224
+ scl(value) {
225
+ this.x *= value;
226
+ this.y *= value;
227
+ return this;
228
+ }
229
+ /**
230
+ * 获取向量弧度
231
+ * 传入目标向量时,返回与目标向量的夹角弧度
232
+ * @param vec2 目标向量
233
+ * @returns 弧度值
234
+ */
235
+ angle(vec2) {
236
+ if (vec2 === undefined) {
237
+ return Math.atan2(this.y, this.x);
238
+ }
239
+ return Math.atan2(this.crs(vec2), this.dot(vec2));
240
+ }
241
+ /**
242
+ * 判断是否与目标向量完全相等
243
+ * @param vec2 目标向量
244
+ * @returns 是否相等
245
+ */
246
+ equals(vec2) {
247
+ return this.x === vec2.x && this.y === vec2.y;
248
+ }
249
+ }
250
+ const Vec2 = Vector2;
251
+ export { Vec2, Vector2 };
@@ -0,0 +1,2 @@
1
+ export { Mat3, Matrix3, type Mat3Data, type Mat3Like } from "./Mat3.js";
2
+ export { Vec2, Vector2, type Vec2Like } from "./Vec2.js";
@@ -0,0 +1,2 @@
1
+ export { Mat3, Matrix3 } from "./Mat3.js";
2
+ export { Vec2, Vector2 } from "./Vec2.js";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 数值钳制
3
+ * @param value 当前值
4
+ * @param min 最小值
5
+ * @param max 最大值
6
+ * @returns 钳制结果
7
+ */
8
+ declare const Clamp: (value: number, min: number, max: number) => number;
9
+ export { Clamp };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 数值钳制
3
+ * @param value 当前值
4
+ * @param min 最小值
5
+ * @param max 最大值
6
+ * @returns 钳制结果
7
+ */
8
+ const Clamp = (value, min, max) => {
9
+ return Math.min(Math.max(value, min), max);
10
+ };
11
+ export { Clamp };
package/lib/index.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import * as Geometry from "./Geometry/index.js";
2
+ import * as Math from "./Math/index.js";
3
+ import * as Utils from "./Utils/index.js";
4
+ declare const BPMatrixJS: {
5
+ Geometry: typeof Geometry;
6
+ Math: typeof Math;
7
+ Utils: typeof Utils;
8
+ };
9
+ export default BPMatrixJS;
10
+ export { BPMatrixJS, Geometry, Math, Utils };
package/lib/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import * as Geometry from "./Geometry/index.js";
2
+ import * as Math from "./Math/index.js";
3
+ import * as Utils from "./Utils/index.js";
4
+ const BPMatrixJS = {
5
+ Geometry,
6
+ Math,
7
+ Utils,
8
+ };
9
+ export default BPMatrixJS;
10
+ export { BPMatrixJS, Geometry, Math, Utils };
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "bpmatrixjs",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./lib/index.js",
6
+ "module": "./lib/index.js",
7
+ "types": "./lib/index.d.ts",
8
+ "files": [
9
+ "lib"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "types": "./lib/index.d.ts",
14
+ "import": "./lib/index.js"
15
+ },
16
+ "./Math": {
17
+ "types": "./lib/Math/index.d.ts",
18
+ "import": "./lib/Math/index.js"
19
+ },
20
+ "./Math/*": {
21
+ "types": "./lib/Math/*.d.ts",
22
+ "import": "./lib/Math/*.js"
23
+ },
24
+ "./Geometry": {
25
+ "types": "./lib/Geometry/index.d.ts",
26
+ "import": "./lib/Geometry/index.js"
27
+ },
28
+ "./Geometry/*": {
29
+ "types": "./lib/Geometry/*.d.ts",
30
+ "import": "./lib/Geometry/*.js"
31
+ },
32
+ "./Utils": {
33
+ "types": "./lib/Utils/index.d.ts",
34
+ "import": "./lib/Utils/index.js"
35
+ }
36
+ },
37
+ "scripts": {
38
+ "dev": "vite --host",
39
+ "build": "npm run build:lib && npm run build:app",
40
+ "build:app": "tsc && vite build",
41
+ "build:lib": "tsc -p tsconfig.lib.json",
42
+ "preview": "vite preview",
43
+ "lint": "eslint .",
44
+ "lint:fix": "eslint . --fix",
45
+ "pack:check": "npm pack --dry-run"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^24.0.13",
49
+ "@eslint/js": "^9.32.0",
50
+ "@stylistic/eslint-plugin": "^5.2.3",
51
+ "eslint": "^9.32.0",
52
+ "globals": "^16.3.0",
53
+ "typescript": "~6.0.2",
54
+ "typescript-eslint": "^8.38.0",
55
+ "vite": "^8.1.1"
56
+ }
57
+ }