CADViewComponent/dist/ThreeCSG.js

480 lines
18 KiB
JavaScript
Raw Normal View History

2018-05-28 09:49:45 +08:00
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var THREE = require("three");
2018-05-28 09:49:45 +08:00
/*jshint esversion: 6 */
var EPSILON = 1e-5, COPLANAR = 0, //共面
2018-05-28 09:49:45 +08:00
FRONT = 1, //前
BACK = 2, SPANNING = 3;
var ThreeBSP = /** @class */ (function () {
function ThreeBSP(geometry) {
2018-05-28 09:49:45 +08:00
// Convert THREE.Geometry to ThreeBSP
var i, _length_i, face, vertex, faceVertexUvs, uvs, polygon, polygons = [], tree;
2018-05-28 09:49:45 +08:00
this.Polygon = Polygon;
this.Vertex = Vertex;
this.Node = Node;
if (geometry instanceof THREE.Geometry) {
this.matrix = new THREE.Matrix4();
}
else if (geometry instanceof THREE.Mesh) {
// #todo: add hierarchy support
geometry.updateMatrix();
this.matrix = geometry.matrix.clone();
geometry = geometry.geometry;
}
else if (geometry instanceof Node) {
this.tree = geometry;
this.matrix = new THREE.Matrix4();
return this;
}
else {
throw 'ThreeBSP: Given geometry is unsupported';
}
for (i = 0, _length_i = geometry.faces.length; i < _length_i; i++) {
face = geometry.faces[i];
faceVertexUvs = geometry.faceVertexUvs[0][i];
polygon = new Polygon();
if (face instanceof THREE.Face3) {
vertex = geometry.vertices[face.a];
uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[0].x, faceVertexUvs[0].y) : null;
vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0], uvs);
vertex.applyMatrix4(this.matrix);
polygon.vertices.push(vertex);
vertex = geometry.vertices[face.b];
uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[1].x, faceVertexUvs[1].y) : null;
vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[1], uvs);
vertex.applyMatrix4(this.matrix);
polygon.vertices.push(vertex);
vertex = geometry.vertices[face.c];
uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[2].x, faceVertexUvs[2].y) : null;
vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[2], uvs);
vertex.applyMatrix4(this.matrix);
polygon.vertices.push(vertex);
}
else if (typeof THREE.Face4) {
vertex = geometry.vertices[face.a];
uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[0].x, faceVertexUvs[0].y) : null;
vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0], uvs);
vertex.applyMatrix4(this.matrix);
polygon.vertices.push(vertex);
vertex = geometry.vertices[face.b];
uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[1].x, faceVertexUvs[1].y) : null;
vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[1], uvs);
vertex.applyMatrix4(this.matrix);
polygon.vertices.push(vertex);
vertex = geometry.vertices[face.c];
uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[2].x, faceVertexUvs[2].y) : null;
vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[2], uvs);
vertex.applyMatrix4(this.matrix);
polygon.vertices.push(vertex);
vertex = geometry.vertices[face.d];
uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[3].x, faceVertexUvs[3].y) : null;
vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[3], uvs);
vertex.applyMatrix4(this.matrix);
polygon.vertices.push(vertex);
}
else {
throw 'Invalid face type at index ' + i;
}
polygon.calculateProperties();
polygons.push(polygon);
}
this.tree = new Node(polygons);
}
//减
ThreeBSP.prototype.subtract = function (other_tree) {
var a = this.tree.clone(), b = other_tree.tree.clone();
2018-05-28 09:49:45 +08:00
a.invert();
a.clipTo(b);
b.clipTo(a);
b.invert();
b.clipTo(a);
b.invert();
a.build(b.allPolygons());
a.invert();
var bsp = new ThreeBSP(a);
2018-05-28 09:49:45 +08:00
bsp.matrix = this.matrix;
return bsp;
};
2018-05-28 09:49:45 +08:00
//结合
ThreeBSP.prototype.union = function (other_tree) {
var a = this.tree.clone(), b = other_tree.tree.clone();
2018-05-28 09:49:45 +08:00
a.clipTo(b);
b.clipTo(a);
b.invert();
b.clipTo(a);
b.invert();
a.build(b.allPolygons());
var bsp = new ThreeBSP(a);
2018-05-28 09:49:45 +08:00
bsp.matrix = this.matrix;
return bsp;
};
2018-05-28 09:49:45 +08:00
//相交
ThreeBSP.prototype.intersect = function (other_tree) {
var a = this.tree.clone(), b = other_tree.tree.clone();
2018-05-28 09:49:45 +08:00
a.invert();
b.clipTo(a);
b.invert();
a.clipTo(b);
b.clipTo(a);
a.build(b.allPolygons());
a.invert();
var bsp = new ThreeBSP(a);
2018-05-28 09:49:45 +08:00
bsp.matrix = this.matrix;
return bsp;
};
ThreeBSP.prototype.toGeometry = function () {
var i, j, matrix = new THREE.Matrix4().getInverse(this.matrix), geometry = new THREE.Geometry(), polygons = this.tree.allPolygons(), polygon_count = polygons.length, polygon, polygon_vertice_count, vertice_dict = {}, vertex_idx_a, vertex_idx_b, vertex_idx_c, vertex, face, verticeUvs;
2018-05-28 09:49:45 +08:00
for (i = 0; i < polygon_count; i++) {
polygon = polygons[i];
polygon_vertice_count = polygon.vertices.length;
for (j = 2; j < polygon_vertice_count; j++) {
verticeUvs = [];
vertex = polygon.vertices[0];
verticeUvs.push(new THREE.Vector2(vertex.uv.x, vertex.uv.y));
vertex = new THREE.Vector3(vertex.x, vertex.y, vertex.z);
vertex.applyMatrix4(matrix);
if (typeof vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] !== 'undefined') {
vertex_idx_a = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z];
}
else {
geometry.vertices.push(vertex);
vertex_idx_a = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] = geometry.vertices.length - 1;
}
vertex = polygon.vertices[j - 1];
verticeUvs.push(new THREE.Vector2(vertex.uv.x, vertex.uv.y));
vertex = new THREE.Vector3(vertex.x, vertex.y, vertex.z);
vertex.applyMatrix4(matrix);
if (typeof vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] !== 'undefined') {
vertex_idx_b = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z];
}
else {
geometry.vertices.push(vertex);
vertex_idx_b = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] = geometry.vertices.length - 1;
}
vertex = polygon.vertices[j];
verticeUvs.push(new THREE.Vector2(vertex.uv.x, vertex.uv.y));
vertex = new THREE.Vector3(vertex.x, vertex.y, vertex.z);
vertex.applyMatrix4(matrix);
if (typeof vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] !== 'undefined') {
vertex_idx_c = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z];
}
else {
geometry.vertices.push(vertex);
vertex_idx_c = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] = geometry.vertices.length - 1;
}
face = new THREE.Face3(vertex_idx_a, vertex_idx_b, vertex_idx_c, new THREE.Vector3(polygon.normal.x, polygon.normal.y, polygon.normal.z));
geometry.faces.push(face);
geometry.faceVertexUvs[0].push(verticeUvs);
}
}
return geometry;
};
ThreeBSP.prototype.toMesh = function (material) {
var geometry = this.toGeometry(), mesh = new THREE.Mesh(geometry, material);
2018-05-28 09:49:45 +08:00
mesh.position.setFromMatrixPosition(this.matrix);
mesh.rotation.setFromRotationMatrix(this.matrix);
return mesh;
};
return ThreeBSP;
}());
2018-05-28 09:49:45 +08:00
exports.ThreeBSP = ThreeBSP;
//多边形
var Polygon = /** @class */ (function () {
function Polygon(vertices, normal, w) {
2018-05-28 09:49:45 +08:00
if (!(vertices instanceof Array)) {
vertices = [];
}
this.vertices = vertices;
if (vertices.length > 0) {
this.calculateProperties();
}
else {
this.normal = this.w = undefined;
}
}
Polygon.prototype.calculateProperties = function () {
var a = this.vertices[0], b = this.vertices[1], c = this.vertices[2];
2018-05-28 09:49:45 +08:00
this.normal = b.clone().subtract(a).cross(c.clone().subtract(a)).normalize();
this.w = this.normal.clone().dot(a);
return this;
};
Polygon.prototype.clone = function () {
var i, vertice_count, polygon = new Polygon();
2018-05-28 09:49:45 +08:00
for (i = 0, vertice_count = this.vertices.length; i < vertice_count; i++) {
polygon.vertices.push(this.vertices[i].clone());
}
polygon.calculateProperties();
return polygon;
};
Polygon.prototype.flip = function () {
var i, vertices = [];
2018-05-28 09:49:45 +08:00
this.normal.multiplyScalar(-1);
this.w *= -1;
for (i = this.vertices.length - 1; i >= 0; i--) {
vertices.push(this.vertices[i]);
}
this.vertices = vertices;
return this;
};
2018-05-28 09:49:45 +08:00
//划分?
Polygon.prototype.classifyVertex = function (vertex) {
var side_value = this.normal.dot(vertex) - this.w;
2018-05-28 09:49:45 +08:00
if (side_value < -EPSILON) {
return BACK;
}
else if (side_value > EPSILON) {
return FRONT;
}
else {
return COPLANAR;
}
};
2018-05-28 09:49:45 +08:00
//划分边?
Polygon.prototype.classifySide = function (polygon) {
var i, vertex, classification, num_positive = 0, num_negative = 0, vertice_count = polygon.vertices.length;
2018-05-28 09:49:45 +08:00
for (i = 0; i < vertice_count; i++) {
vertex = polygon.vertices[i];
classification = this.classifyVertex(vertex);
if (classification === FRONT) {
num_positive++;
}
else if (classification === BACK) {
num_negative++;
}
}
if (num_positive > 0 && num_negative === 0) {
return FRONT;
}
else if (num_positive === 0 && num_negative > 0) {
return BACK;
}
else if (num_positive === 0 && num_negative === 0) {
return COPLANAR;
}
else {
return SPANNING;
}
};
2018-05-28 09:49:45 +08:00
//分解 分离 区域?
Polygon.prototype.splitPolygon = function (polygon, coplanar_front, coplanar_back, front, back) {
var classification = this.classifySide(polygon);
2018-05-28 09:49:45 +08:00
if (classification === COPLANAR) {
(this.normal.dot(polygon.normal) > 0 ? coplanar_front : coplanar_back).push(polygon);
}
else if (classification === FRONT) {
front.push(polygon);
}
else if (classification === BACK) {
back.push(polygon);
}
else {
var vertice_count = void 0, i = void 0, j = void 0, ti = void 0, tj = void 0, vi = void 0, vj = void 0, t = void 0, v = void 0, f = [], b = [];
2018-05-28 09:49:45 +08:00
for (i = 0, vertice_count = polygon.vertices.length; i < vertice_count; i++) {
j = (i + 1) % vertice_count;
vi = polygon.vertices[i];
vj = polygon.vertices[j];
ti = this.classifyVertex(vi);
tj = this.classifyVertex(vj);
if (ti != BACK)
f.push(vi);
if (ti != FRONT)
b.push(vi);
if ((ti | tj) === SPANNING) {
t = (this.w - this.normal.dot(vi)) / this.normal.dot(vj.clone().subtract(vi));
v = vi.interpolate(vj, t);
f.push(v);
b.push(v);
}
}
if (f.length >= 3)
front.push(new Polygon(f).calculateProperties());
if (b.length >= 3)
back.push(new Polygon(b).calculateProperties());
}
};
return Polygon;
}());
2018-05-28 09:49:45 +08:00
exports.Polygon = Polygon;
var Vertex = /** @class */ (function () {
function Vertex(x, y, z, normal, uv) {
2018-05-28 09:49:45 +08:00
this.x = x;
this.y = y;
this.z = z;
this.normal = normal || new THREE.Vector3();
this.uv = uv || new THREE.Vector2();
}
Vertex.prototype.clone = function () {
2018-05-28 09:49:45 +08:00
return new Vertex(this.x, this.y, this.z, this.normal.clone(), this.uv.clone());
};
Vertex.prototype.add = function (vertex) {
2018-05-28 09:49:45 +08:00
this.x += vertex.x;
this.y += vertex.y;
this.z += vertex.z;
return this;
};
Vertex.prototype.subtract = function (vertex) {
2018-05-28 09:49:45 +08:00
this.x -= vertex.x;
this.y -= vertex.y;
this.z -= vertex.z;
return this;
};
Vertex.prototype.multiplyScalar = function (scalar) {
2018-05-28 09:49:45 +08:00
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
return this;
};
2018-05-28 09:49:45 +08:00
//×乘
Vertex.prototype.cross = function (vertex) {
var x = this.x, y = this.y, z = this.z;
2018-05-28 09:49:45 +08:00
this.x = y * vertex.z - z * vertex.y;
this.y = z * vertex.x - x * vertex.z;
this.z = x * vertex.y - y * vertex.x;
return this;
};
Vertex.prototype.normalize = function () {
var length = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
2018-05-28 09:49:45 +08:00
this.x /= length;
this.y /= length;
this.z /= length;
return this;
};
2018-05-28 09:49:45 +08:00
//点乘
Vertex.prototype.dot = function (vertex) {
2018-05-28 09:49:45 +08:00
return this.x * vertex.x + this.y * vertex.y + this.z * vertex.z;
};
2018-05-28 09:49:45 +08:00
//线性插值
Vertex.prototype.lerp = function (a, t) {
2018-05-28 09:49:45 +08:00
this.add(a.clone().subtract(this).multiplyScalar(t));
this.normal.add(a.normal.clone().sub(this.normal).multiplyScalar(t));
this.uv.add(a.uv.clone().sub(this.uv).multiplyScalar(t));
return this;
};
2018-05-28 09:49:45 +08:00
//插值
Vertex.prototype.interpolate = function (other, t) {
2018-05-28 09:49:45 +08:00
return this.clone().lerp(other, t);
};
Vertex.prototype.applyMatrix4 = function (m) {
2018-05-28 09:49:45 +08:00
// input: THREE.Matrix4 affine matrix
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
2018-05-28 09:49:45 +08:00
this.x = e[0] * x + e[4] * y + e[8] * z + e[12];
this.y = e[1] * x + e[5] * y + e[9] * z + e[13];
this.z = e[2] * x + e[6] * y + e[10] * z + e[14];
return this;
};
return Vertex;
}());
2018-05-28 09:49:45 +08:00
exports.Vertex = Vertex;
var Node = /** @class */ (function () {
function Node(polygons) {
var i, polygon_count, front = [], back = [];
2018-05-28 09:49:45 +08:00
this.polygons = [];
this.front = this.back = undefined;
if (!(polygons instanceof Array) || polygons.length === 0)
return;
this.divider = polygons[0].clone();
for (i = 0, polygon_count = polygons.length; i < polygon_count; i++) {
this.divider.splitPolygon(polygons[i], this.polygons, this.polygons, front, back);
}
if (front.length > 0) {
this.front = new Node(front);
}
if (back.length > 0) {
this.back = new Node(back);
}
}
//是凸的? 凸包?
Node.prototype.isConvex = function (polygons) {
var i, j;
2018-05-28 09:49:45 +08:00
for (i = 0; i < polygons.length; i++) {
for (j = 0; j < polygons.length; j++) {
if (i !== j && polygons[i].classifySide(polygons[j]) !== BACK) {
return false;
}
}
}
return true;
};
Node.prototype.build = function (polygons) {
var i, polygon_count, front = [], back = [];
2018-05-28 09:49:45 +08:00
if (!this.divider) {
this.divider = polygons[0].clone();
}
for (i = 0, polygon_count = polygons.length; i < polygon_count; i++) {
this.divider.splitPolygon(polygons[i], this.polygons, this.polygons, front, back);
}
if (front.length > 0) {
if (!this.front)
this.front = new Node();
this.front.build(front);
}
if (back.length > 0) {
if (!this.back)
this.back = new Node();
this.back.build(back);
}
};
Node.prototype.allPolygons = function () {
var polygons = this.polygons.slice();
2018-05-28 09:49:45 +08:00
if (this.front)
polygons = polygons.concat(this.front.allPolygons());
if (this.back)
polygons = polygons.concat(this.back.allPolygons());
return polygons;
};
Node.prototype.clone = function () {
var node = new Node();
2018-05-28 09:49:45 +08:00
node.divider = this.divider.clone();
node.polygons = this.polygons.map(function (polygon) {
return polygon.clone();
});
node.front = this.front && this.front.clone();
node.back = this.back && this.back.clone();
return node;
};
2018-05-28 09:49:45 +08:00
//反转
Node.prototype.invert = function () {
var i, polygon_count, temp;
2018-05-28 09:49:45 +08:00
for (i = 0, polygon_count = this.polygons.length; i < polygon_count; i++) {
this.polygons[i].flip();
}
this.divider.flip();
if (this.front)
this.front.invert();
if (this.back)
this.back.invert();
temp = this.front;
this.front = this.back;
this.back = temp;
return this;
};
2018-05-28 09:49:45 +08:00
//
Node.prototype.clipPolygons = function (polygons) {
var i, polygon_count, front, back;
2018-05-28 09:49:45 +08:00
if (!this.divider)
return polygons.slice();
front = [];
back = [];
for (i = 0, polygon_count = polygons.length; i < polygon_count; i++) {
this.divider.splitPolygon(polygons[i], front, back, front, back);
}
if (this.front)
front = this.front.clipPolygons(front);
if (this.back)
back = this.back.clipPolygons(back);
else
back = [];
return front.concat(back);
};
Node.prototype.clipTo = function (node) {
2018-05-28 09:49:45 +08:00
this.polygons = node.clipPolygons(this.polygons);
if (this.front)
this.front.clipTo(node);
if (this.back)
this.back.clipTo(node);
};
return Node;
}());
2018-05-28 09:49:45 +08:00
exports.Node = Node;
//# sourceMappingURL=ThreeCSG.js.map