UNPKG

xtorcga

Version:

Xtor Compute Geometry Algorithm Libary 计算几何算法库

162 lines (161 loc) 5.81 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Polygon = void 0; var HVec3_1 = require("src/math/HVec3"); var decimal_js_1 = __importDefault(require("decimal.js")); var EPSILON = new decimal_js_1.default(1e-15); var Side; (function (Side) { Side[Side["COPLANAR"] = 0] = "COPLANAR"; Side[Side["FRONT"] = 1] = "FRONT"; Side[Side["BACK"] = 2] = "BACK"; Side[Side["SPANNING"] = 3] = "SPANNING"; })(Side || (Side = {})); /* * @Description : 高精度多边形 * @Author : 赵耀圣 * @QQ : 549184003 * @Date : 2021-08-03 11:11:59 * @LastEditTime : 2021-08-03 15:49:25 * @FilePath : \cga.js\src\csg\polygon.ts */ var Polygon = /** @class */ (function () { function Polygon(vertices) { if (vertices === void 0) { vertices = []; } this.w = new decimal_js_1.default(0); this.normal = new HVec3_1.Vec3; this.vertices = vertices; this.vertices = vertices; if (vertices.length > 0) { this.calcPlane(); } } Polygon.prototype.calcPlane = function () { var a = this.vertices[0], b = this.vertices[1], c = this.vertices[2]; this.normal = b.clone().sub(a).cross(c.clone().sub(a)).normalize(); this.w = this.normal.clone().dot(a); return this; }; Polygon.prototype.flip = function () { this.normal.multiplyScalar(-1); this.w.mul(-1); this.vertices.reverse(); return this; }; /** * @description : 判断点与当前多边形所在的平面的位置关系 * @param {Vec3} vertex * @return {*} * @example : */ Polygon.prototype.classifyVertex = function (vertex) { var side_value = this.normal.dot(vertex).sub(this.w); if (side_value.lessThan(-EPSILON)) { return Side.BACK; } else if (side_value > EPSILON) { return Side.FRONT; } else { return Side.COPLANAR; } }; /** * @description : 判断另一个多边形与当前多边形的位置关系 * @param {Polygon} polygon * @return {*} * @example : */ Polygon.prototype.classifySide = function (polygon) { var vertex, classification, num_positive = 0, num_negative = 0; var vslen = polygon.vertices.length; var i; for (i = 0; i < vslen; i++) { vertex = polygon.vertices[i]; classification = this.classifyVertex(vertex); if (classification === Side.FRONT) { num_positive++; } else if (classification === Side.BACK) { num_negative++; } } if (num_positive === vslen && num_negative === 0) { return Side.FRONT; } else if (num_positive === 0 && num_negative === vslen) { return Side.BACK; } else if (num_positive > 0 && num_negative > 0) { return Side.SPANNING; } else { return Side.COPLANAR; } }; /** * @description : 切割多边形 * @param {Polygon} polygon * @param {Polygon} coplanar_front * @param {Polygon} coplanar_back * @param {Polygon} front * @param {Polygon} back * @return {*} * @example : */ Polygon.prototype.splitPolygon = function (polygon, coplanar_front, coplanar_back, front, back) { if (coplanar_front === void 0) { coplanar_front = []; } if (coplanar_back === void 0) { coplanar_back = []; } if (front === void 0) { front = []; } if (back === void 0) { back = []; } var classification = this.classifySide(polygon); if (classification === Side.COPLANAR) { (this.normal.dot(polygon.normal).greaterThan(0) ? coplanar_front : coplanar_back).push(polygon); } else if (classification === Side.FRONT) { front.push(polygon); } else if (classification === Side.BACK) { back.push(polygon); } else { var i, j, ti, tj, vi, vj, t, v, f = [], b = []; var vslen = void 0; for (i = 0, vslen = polygon.vertices.length; i < vslen; i++) { j = (i + 1) % vslen; vi = polygon.vertices[i]; vj = polygon.vertices[j]; ti = this.classifyVertex(vi); tj = this.classifyVertex(vj); if (ti != Side.BACK) f.push(vi); if (ti != Side.FRONT) b.push(vi); if ((ti | tj) === Side.SPANNING) { t = (this.w.sub(this.normal.dot(vi))).div(this.normal.dot(vj.clone().sub(vi))); v = vi.lerp(vj, t); f.push(v); b.push(v); } } if (f.length >= 3) front.push(new Polygon(f).calcPlane()); if (b.length >= 3) back.push(new Polygon(b).calcPlane()); } }; Polygon.prototype.clone = function () { var i, vslen = this.vertices.length; var polygon = new Polygon(); for (i = 0; i < vslen; i++) { polygon.vertices.push(this.vertices[i].clone()); } polygon.calcPlane(); return polygon; }; return Polygon; }()); exports.Polygon = Polygon;