| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| class Vec2 extends Float32Array { |
| constructor(v?: unknown, y?: unknown) { |
| super(2); |
| if (v instanceof Vec2 || v instanceof Float32Array || (v instanceof Array && v.length == 2)) { |
| this[0] = v[0]; |
| this[1] = v[1]; |
| } else if (typeof v === "number" && typeof y === "number") { |
| this[0] = v; |
| this[1] = y; |
| } else if (typeof v === "number") { |
| this[0] = v; |
| this[1] = v; |
| } |
| } |
| xy(x: number, y: number): Vec2 { |
| if (y != undefined) { |
| this[0] = x; |
| this[1] = y; |
| } else this[0] = this[1] = x; |
| return this; |
| } |
| get x(): number { |
| return this[0]; |
| } |
| set x(v: number) { |
| this[0] = v; |
| } |
| get y(): number { |
| return this[1]; |
| } |
| set y(v: number) { |
| this[1] = v; |
| } |
| len(): number { |
| return Math.sqrt(this[0] * this[0] + this[1] * this[1]); |
| } |
| fromAdd(a: number[], b: number[]): Vec2 { |
| this[0] = a[0] + b[0]; |
| this[1] = a[1] + b[1]; |
| return this; |
| } |
| fromSub(a: number[] | Vec2, b: number[] | Vec2): Vec2 { |
| this[0] = a[0] - b[0]; |
| this[1] = a[1] - b[1]; |
| return this; |
| } |
| fromScale(a: number[] | Vec2, s: number): Vec2 { |
| this[0] = a[0] * s; |
| this[1] = a[1] * s; |
| return this; |
| } |
| fromLerp(a: number[] | Vec2, b: number[] | Vec2, t: number): Vec2 { |
| const tt = 1 - t; |
| this[0] = a[0] * tt + b[0] * t; |
| this[1] = a[1] * tt + b[1] * t; |
| return this; |
| } |
| /** Used to get data from a flat buffer of vectors, useful when building geometery */ |
| fromBuf(ary: number[], idx: number): Vec2 { |
| this[0] = ary[idx]; |
| this[1] = ary[idx + 1]; |
| return this; |
| } |
| /** Pust vector components onto an array, useful when building geometery */ |
| pushTo(ary: number[]): Vec2 { |
| ary.push(this[0], this[1]); |
| return this; |
| } |
| add(v: number[]): Vec2 { |
| this[0] += v[0]; |
| this[1] += v[1]; |
| return this; |
| } |
| addRaw(x: number, y: number): Vec2 { |
| this[0] += x; |
| this[1] += y; |
| return this; |
| } |
| sub(v: number[]): Vec2 { |
| this[0] -= v[0]; |
| this[1] -= v[1]; |
| return this; |
| } |
| scale(v: number): Vec2 { |
| this[0] *= v; |
| this[1] *= v; |
| return this; |
| } |
| norm(out?: number[] | Vec2): number[] | Vec2 | undefined { |
| const mag = Math.sqrt(this[0] * this[0] + this[1] * this[1]); |
| if (mag == 0) return this; |
| out = out || this; |
| out[0] = this[0] / mag; |
| out[1] = this[1] / mag; |
| return out; |
| } |
| perpCCW(): Vec2 { |
| const x = this[0]; |
| this[0] = -this[1]; |
| this[1] = x; |
| return this; |
| } |
| static add(a: number[], b: number[]): Vec2 { |
| return new Vec2().fromAdd(a, b); |
| } |
| static sub(a: number[], b: number[]): Vec2 { |
| return new Vec2().fromSub(a, b); |
| } |
| static scale(v: number[], s: number): Vec2 { |
| return new Vec2().fromScale(v, s); |
| } |
| static lerp(v0: number[], v1: number[], t: number): Vec2 { |
| return new Vec2().fromLerp(v0, v1, t); |
| } |
| static len(v0: Vec2, v1: Vec2): number { |
| return Math.sqrt((v0[0] - v1[0]) ** 2 + (v0[1] - v1[1]) ** 2); |
| } |
| /** Create an Iterator Object that allows an easy way to loop a Float32Buffer |
| * @example |
| * let buf = new Float32Array( 2 * 10 ); |
| * for( let v of Vec3.bufIter( buf ) ){console.log( v )}; |
| */ |
| // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types |
| static bufIter(buf: number[]) { |
| let i = 0; |
| const result = { value: new Vec2(), done: false }, |
| len = buf.length, |
| next = () => { |
| if (i >= len) result.done = true; |
| else { |
| result.value.fromBuf(buf, i); |
| i += 2; |
| } |
| return result; |
| }; |
| return { |
| [Symbol.iterator]() { |
| return { next }; |
| }, |
| }; |
| } |
| } |
| export default Vec2; |