xtorcga
Version:
Xtor Compute Geometry Algorithm Libary 计算几何算法库
162 lines (161 loc) • 5.81 kB
JavaScript
"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;