/** * 当向量以数组的方式出现,一个计算单元库 * @Description : 向量数组 * @Author : 赵耀圣 * @QQ : 549184003 * @Date : 2021-08-02 15:09:33 * @LastEditTime : 2021-08-02 15:50:16 * @FilePath : \cga.js\src\math\VecArray.ts */ import { Polygon } from "../struct/3d/Polygon" import { Polyline } from "../struct/3d/Polyline" import { Vec2 } from "./Vec2" import { Vec3 } from './Vec3'; import { ArrayList } from '../struct/data/ArrayList'; const ckeckVec = (vs: any, component: number) => { if (vs.length % component !== 0) throw ("向量组件数量不一样") } export class vector { /** * 检测相邻没有重复点 */ static uniqueNeighbor(vs: number[], component: number = 3) { for (let i = 0; i < vs.length; i += component) { for (let j = i + 3; j < vs.length;) { let lensq = 0 for (let c = 0; c < component; c++) { lensq += (vs[i + c] - vs[j + c]) * (vs[i + c] - vs[j + c]) } if (Math.sqrt(lensq) < 1e-5) vs.splice(j, component) else break; } } return vs; } /** * 去除任意重复点 * @param vs 向量数组 * @param component 向量组件数量 * @returns 无重复向量数组 */ static unique(vs: number[], component: number = 3) { for (let i = 0; i < vs.length; i += component) { for (let j = i + 3; j < vs.length;) { let lensq = 0 for (let c = 0; c < component; c++) { lensq += (vs[i + c] - vs[j + c]) * (vs[i + c] - vs[j + c]) } if (Math.sqrt(lensq) < 1e-5) vs.splice(j, component) else j += component } } return vs; } /** * 翻转向量数组 * @param vecs 向量数组 * @param component 组件数量 * @returns */ static reverse(vecs: number[], component: number = 3) { ckeckVec(vecs, component); const length = vecs.length; for (let i = 0; i < length; i += component) { vecs.unshift(...vecs.splice(i, component)) } return vecs; } /** * 点积 * @param vecs * @returns */ static dot(...vecs: number[]) { if (vecs.length % 2 !== 0) throw ("两个向量组件数量不一样") const len = vecs.length / 2; let dot = 0; for (let i = 0; i < len; i++) { dot += vecs[i] * vecs[len + i]; } return dot; } /** * 长度平方 * @param vecs * @returns */ static distanceSq(...vecs: number[]) { if (vecs.length % 2 !== 0) throw ("向量组件数量不一样") const len = vecs.length / 2; let lenSq = 0; for (let i = 0; i < len; i++) { var d = (vecs[i] - vecs[len + i]); lenSq += d * d; } return lenSq; } /** * 长度 * @param vecs * @returns */ static distance(...vecs: number[]) { return Math.sqrt(this.distanceSq(...vecs)); } /** * 相加 * @param vecs * @returns */ static add(...vecs: number[]) { if (vecs.length % 2 !== 0) throw ("两个向量组件数量不一样") if (Array.isArray(vecs[0]) && Array.isArray(vecs[1])) { for (let i = 0; i < vecs[0].length; i++) { vecs[0][i] += vecs[1][i]; } return vecs[0] } if (vecs.length % 2 !== 0) console.error("VecArray:distanceSq 向量错误!!!"); const len = vecs.length / 2; let res: number[] = []; for (let i = 0; i < len; i++) { res[i] = res[len + i] + res[i]; } return res; } /** * 相减 * @param vecs * @returns */ static sub(...vecs: number[]): number[] { ckeckVec(vecs, 2); if (Array.isArray(vecs[0]) && Array.isArray(vecs[1])) { for (let i = 0; i < vecs[0].length; i++) { vecs[0][i] -= vecs[1][i]; } return vecs[0] } if (vecs.length % 2 !== 0) console.error("VecArray:distanceSq 向量错误!!!"); const len = vecs.length / 2; let res: number[] = []; for (let i = 0; i < len; i++) { res[i] = res[i] - res[len + i]; } return res; } /** * 相乘 * @param vecs * @returns */ static mul(...vecs: number[]) { ckeckVec(vecs, 2); if (Array.isArray(vecs[0]) && Array.isArray(vecs[1])) { for (let i = 0; i < vecs[0].length; i++) { vecs[0][i] *= vecs[1][i]; } return vecs[0] } if (vecs.length % 2 !== 0) console.error("VecArray:distanceSq 向量错误!!!"); const len = vecs.length / 2; let res: number[] = []; for (let i = 0; i < len; i++) { res[i] = res[i] * res[len + i]; } return res; } /** * 获取矢量数组的i个矢量 * @param vecs * @param i * @param component * @returns */ static getVecAt(vecs: number[], i: number, component: number = 3): number[] { return [vecs[3 * i], vecs[3 * i + 1], vecs[3 * i + 2]] } /** * 在第 i 个位置插入一个向量 * @param vecs * @param i * @param vec */ static insertAt(vecs: number[], i: number, ...vec: number[]) { vecs.splice(i * vecs.length, 0, ...vecs); } // /** * 是否逆时针 * counterclockwise */ static isCCW(shape: Array | ArrayList, component: number = 3): boolean { let d = 0; if (shape instanceof Polyline || shape instanceof Polygon) for (let i = 0; i < shape.length; i++) { const pt = shape.get(i); const ptnext = shape.get((i + 1) % shape.length); d += -0.5 * (ptnext.y + pt.y) * (ptnext.x - pt.x); } else if (Array.isArray(shape) && shape.length > 0) { if (shape[0] instanceof Vec3 || shape[0] instanceof Vec2) { for (let i = 0; i < shape.length; i++) { const pt: Vec3 | Vec2 = shape[i] as any; const ptnext: Vec3 | Vec2 = shape[(i + 1) % shape.length] as any; d += -0.5 * (ptnext.y + pt.y) * (ptnext.x - pt.x); } } else if (!isNaN(shape[0] as any)) { for (let i = 0; i < shape.length; i += component) { const ptx: number = shape[i] as any; const pty: number = shape[(i + 1) % shape.length] as any; const ptnextx = shape[(i + 3) % shape.length] as any; const ptnexty = shape[(i + 4) % shape.length] as any; d += -0.5 * (ptnexty + pty) * (ptnextx - ptx); } } } return d > 0; } }