UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

205 lines (204 loc) 6.7 kB
"use strict"; import { BufferAttribute, BufferGeometry, Vector3 } from "three"; import { TypeAssert } from "../../../engine/poly/Assert"; export var PointsCountMode = /* @__PURE__ */ ((PointsCountMode2) => { PointsCountMode2["SEGMENTS_COUNT"] = "segments count"; PointsCountMode2["SEGMENTS_LENGTH"] = "segments length"; return PointsCountMode2; })(PointsCountMode || {}); export const POINTS_COUNT_MODE = ["segments count" /* SEGMENTS_COUNT */, "segments length" /* SEGMENTS_LENGTH */]; export var JoinMode = /* @__PURE__ */ ((JoinMode2) => { JoinMode2["ABC"] = "abc"; JoinMode2["ACB"] = "acb"; JoinMode2["AB"] = "ab"; JoinMode2["BC"] = "bc"; JoinMode2["AC"] = "ac"; return JoinMode2; })(JoinMode || {}); export const JOIN_MODES = ["abc" /* ABC */, "acb" /* ACB */, "ab" /* AB */, "ac" /* AC */, "bc" /* BC */]; export class Circle3Points { constructor(params) { this.params = params; this.a = new Vector3(); this.b = new Vector3(); this.c = new Vector3(); this.an = new Vector3(); this.bn = new Vector3(); this.cn = new Vector3(); this.ac = new Vector3(); this.ab = new Vector3(); this.ab_x_ac = new Vector3(); this.part0 = new Vector3(); this.part1 = new Vector3(); this.divider = 1; this.a_center = new Vector3(); this.center = new Vector3(); this.normal = new Vector3(); this.radius = 1; this.x = new Vector3(); this.y = new Vector3(); this.z = new Vector3(); this.angle_ab = 1; this.angle_ac = 1; this.angle_bc = 1; this.angle = 2 * Math.PI; this.x_rotated = new Vector3(); this._created_geometries = {}; } created_geometries() { return this._created_geometries; } create(a, b, c) { this.a.copy(a); this.b.copy(b); this.c.copy(c); this._compute_axis(); this._create_arc(); this._create_center(); } _create_arc() { this._compute_angle(); const points_count = this._points_count(); const positions = new Array(points_count * 3); const indices = new Array(points_count); const angle_increment = this.angle / (points_count - 1); this.x_rotated.copy(this.x).multiplyScalar(this.radius); let i = 0; for (i = 0; i < points_count; i++) { this.x_rotated.copy(this.x).applyAxisAngle(this.normal, angle_increment * i).multiplyScalar(this.radius).add(this.center); this.x_rotated.toArray(positions, i * 3); if (i > 0) { indices[(i - 1) * 2] = i - 1; indices[(i - 1) * 2 + 1] = i; } } if (this.params.full) { indices.push(i - 1); indices.push(0); } const geometry = new BufferGeometry(); geometry.setAttribute("position", new BufferAttribute(new Float32Array(positions), 3)); geometry.setIndex(indices); if (this.params.addIdAttribute || this.params.addIdnAttribute) { const ids = new Array(points_count); for (let i2 = 0; i2 < ids.length; i2++) { ids[i2] = i2; } if (this.params.addIdAttribute) { geometry.setAttribute("id", new BufferAttribute(new Float32Array(ids), 1)); } const idns = ids.map((id) => id / (points_count - 1)); if (this.params.addIdnAttribute) { geometry.setAttribute("idn", new BufferAttribute(new Float32Array(idns), 1)); } } this._created_geometries.arc = geometry; } _create_center() { if (!this.params.center) { return; } const geometry = new BufferGeometry(); const positions = [this.center.x, this.center.y, this.center.z]; geometry.setAttribute("position", new BufferAttribute(new Float32Array(positions), 3)); this._created_geometries.center = geometry; } _compute_axis() { this.ac.copy(this.c).sub(this.a); this.ab.copy(this.b).sub(this.a); this.ab_x_ac.copy(this.ab).cross(this.ac); this.divider = 2 * this.ab_x_ac.lengthSq(); this.part0.copy(this.ab_x_ac).cross(this.ab).multiplyScalar(this.ac.lengthSq()); this.part1.copy(this.ac).cross(this.ab_x_ac).multiplyScalar(this.ab.lengthSq()); this.a_center.copy(this.part0).add(this.part1).divideScalar(this.divider); this.radius = this.a_center.length(); this.normal.copy(this.ab_x_ac).normalize(); this.center.copy(this.a).add(this.a_center); } _compute_angle() { if (!this.params.arc) { return; } if (this.params.full) { this.x.copy(this.a).sub(this.center).normalize(); this.angle = 2 * Math.PI; } else { this.an.copy(this.a).sub(this.center).normalize(); this.bn.copy(this.b).sub(this.center).normalize(); this.cn.copy(this.c).sub(this.center).normalize(); this._set_x_from_joinMode(); this.y.copy(this.normal); this.z.copy(this.x).cross(this.y).normalize(); this.angle_ab = this.an.angleTo(this.bn); this.angle_ac = this.an.angleTo(this.cn); this.angle_bc = this.bn.angleTo(this.cn); this._set_angle_from_joinMode(); } } _points_count() { const mode = this.params.pointsCountMode; switch (mode) { case "segments count" /* SEGMENTS_COUNT */: { return this.params.segmentsCount + 1; } case "segments length" /* SEGMENTS_LENGTH */: { let perimeter = Math.PI * this.radius * this.radius; if (!this.params.full) { perimeter *= Math.abs(this.angle) / (Math.PI * 2); } return Math.ceil(perimeter / this.params.segmentsLength); } } TypeAssert.unreachable(mode); } _set_x_from_joinMode() { const joinMode = this.params.joinMode; this.x.copy(this.a).sub(this.center).normalize(); switch (joinMode) { case "abc" /* ABC */: { return this.x.copy(this.an); } case "acb" /* ACB */: { return this.x.copy(this.an); } case "ab" /* AB */: { return this.x.copy(this.an); } case "ac" /* AC */: { return this.x.copy(this.an); } case "bc" /* BC */: { return this.x.copy(this.bn); } } TypeAssert.unreachable(joinMode); } _set_angle_from_joinMode() { const joinMode = this.params.joinMode; switch (joinMode) { case "abc" /* ABC */: { this.angle = this.angle_ab + this.angle_bc; return; } case "acb" /* ACB */: { this.angle = this.angle_ac + this.angle_bc; this.angle *= -1; return; } case "ab" /* AB */: { this.angle = this.angle_ab; return; } case "ac" /* AC */: { this.angle = this.angle_ac; this.angle *= -1; return; } case "bc" /* BC */: { this.angle = this.angle_bc; return; } } TypeAssert.unreachable(joinMode); } }