使用二元操作组合网格, THREE.REVERSION = 69
<!DOCTYPE html>
<html>
<head>
<title>Example 06.08 - Binary operations</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<script type="text/javascript" src="../libs/spin.js"></script>
<script type="text/javascript" src="../libs/ThreeBSP.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
// once everything is loaded, we run our Three.js stuff.
function init() {
var stats = initStats();
// create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(0x999999, 1.0);
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;
var sphere1 = createMesh(new THREE.CylinderGeometry(2, 2, 8, 30));
sphere1.position.x = -5;
// var sphere2 = createMesh(new THREE.CylinderGeometry(1, 1, 16, 30));
var sphere2 = createMesh(new THREE.CylinderGeometry(2, 2, 16, 30));
sphere2.position.set(-5, 0, 0);
sphere2.rotation.z = 0.5 * Math.PI;
var cube = createMesh(new THREE.BoxGeometry(5, 5, 5));
cube.position.x = -7;
var result;
// add the sphere to the scene
scene.add(sphere1);
scene.add(sphere2);
scene.add(cube);
// position and point the camera to the center of the scene
camera.position.x = 0;
camera.position.y = 20;
camera.position.z = 20;
camera.lookAt(new THREE.Vector3(0, 0, 0));
// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
// call the render function
var step = 0;
// setup the control gui
var controls = new function () {
this.sphere1PosX = sphere1.position.x;
this.sphere1PosY = sphere1.position.y;
this.sphere1PosZ = sphere1.position.z;
this.sphere1Scale = 1;
this.sphere2PosX = sphere2.position.x;
this.sphere2PosY = sphere2.position.y;
this.sphere2PosZ = sphere2.position.z;
this.sphere2Scale = 1;
this.cubePosX = cube.position.x;
this.cubePosY = cube.position.y;
this.cubePosZ = cube.position.z;
this.scaleX = 1;
this.scaleY = 1;
this.scaleZ = 1;
this.actionCube = "none"; // add, substract, intersect
this.actionSphere = "intersect";
this.showResult = function () {
redrawResult();
};
this.hideWireframes = false;
this.rotateResult = false;
};
var gui = new dat.GUI();
var guiSphere1 = gui.addFolder("Sphere1");
guiSphere1.add(controls, "sphere1PosX", -15, 15).onChange(function () {
sphere1.position.set(controls.sphere1PosX, controls.sphere1PosY, controls.sphere1PosZ)
});
guiSphere1.add(controls, "sphere1PosY", -15, 15).onChange(function () {
sphere1.position.set(controls.sphere1PosX, controls.sphere1PosY, controls.sphere1PosZ)
});
guiSphere1.add(controls, "sphere1PosZ", -15, 15).onChange(function () {
sphere1.position.set(controls.sphere1PosX, controls.sphere1PosY, controls.sphere1PosZ)
});
guiSphere1.add(controls, "sphere1Scale", 0, 10).onChange(function (e) {
sphere1.scale.set(e, e, e)
});
var guiSphere2 = gui.addFolder("Sphere2");
guiSphere2.add(controls, "sphere2PosX", -15, 15).onChange(function () {
sphere2.position.set(controls.sphere2PosX, controls.sphere2PosY, controls.sphere2PosZ)
});
guiSphere2.add(controls, "sphere2PosY", -15, 15).onChange(function () {
sphere2.position.set(controls.sphere2PosX, controls.sphere2PosY, controls.sphere2PosZ)
});
guiSphere2.add(controls, "sphere2PosZ", -15, 15).onChange(function () {
sphere2.position.set(controls.sphere2PosX, controls.sphere2PosY, controls.sphere2PosZ)
});
guiSphere2.add(controls, "sphere2Scale", 0, 10).onChange(function (e) {
sphere2.scale.set(e, e, e)
});
guiSphere2.add(controls, "actionSphere", ["subtract", "intersect", "union", "none"]);
var guiCube = gui.addFolder("cube");
guiCube.add(controls, "cubePosX", -15, 15).onChange(function () {
cube.position.set(controls.cubePosX, controls.cubePosY, controls.cubePosZ)
});
guiCube.add(controls, "cubePosY", -15, 15).onChange(function () {
cube.position.set(controls.cubePosX, controls.cubePosY, controls.cubePosZ)
});
guiCube.add(controls, "cubePosZ", -15, 15).onChange(function () {
cube.position.set(controls.cubePosX, controls.cubePosY, controls.cubePosZ)
});
guiCube.add(controls, "scaleX", 0, 10).onChange(function (e) {
cube.scale.x = e
});
guiCube.add(controls, "scaleY", 0, 10).onChange(function (e) {
cube.scale.y = e
});
guiCube.add(controls, "scaleZ", 0, 10).onChange(function (e) {
cube.scale.z = e
});
guiCube.add(controls, "actionCube", ["subtract", "intersect", "union", "none"]);
gui.add(controls, "showResult");
gui.add(controls, "rotateResult");
gui.add(controls, "hideWireframes").onChange(function () {
if (controls.hideWireframes) {
sphere1.material.visible = false;
sphere2.material.visible = false;
cube.material.visible = false;
} else {
sphere1.material.visible = true;
sphere2.material.visible = true;
cube.material.visible = true;
}
});
render();
var spinner;
function redrawResult() {
showSpinner();
// make the call async to avoid blocking the thread. Need
// to set timeout > 1, if not executed immediately.
setTimeout(function () {
scene.remove(result);
var sphere1BSP = new ThreeBSP(sphere1);
var sphere2BSP = new ThreeBSP(sphere2);
var cube2BSP = new ThreeBSP(cube);
var resultBSP;
// first do the sphere
switch (controls.actionSphere) {
case "subtract":
resultBSP = sphere1BSP.subtract(sphere2BSP);
break;
case "intersect":
resultBSP = sphere1BSP.intersect(sphere2BSP);
break;
case "union":
resultBSP = sphere1BSP.union(sphere2BSP);
break;
case "none": // noop;
}
// next do the cube
if (!resultBSP) resultBSP = sphere1BSP;
switch (controls.actionCube) {
case "subtract":
resultBSP = resultBSP.subtract(cube2BSP);
break;
case "intersect":
resultBSP = resultBSP.intersect(cube2BSP);
break;
case "union":
resultBSP = resultBSP.union(cube2BSP);
break;
case "none": // noop;
}
if (controls.actionCube === "none" && controls.actionSphere === "none") {
// do nothing
} else {
result = resultBSP.toMesh();
result.geometry.computeFaceNormals();
result.geometry.computeVertexNormals();
scene.add(result);
}
hideSpinner(spinner);
}, 200);
}
function createMesh(geom) {
// assign two materials
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial({transparency: true, opacity: 0.5, wireframeLinewidth: 0.5});
wireFrameMat.wireframe = true;
// create a multimaterial
var mesh = new THREE.Mesh(geom, wireFrameMat);
return mesh;
}
function showSpinner() {
var opts = {
lines: 13, // The number of lines to draw
length: 20, // The length of each line
width: 10, // The line thickness
radius: 30, // The radius of the inner circle
corners: 1, // Corner roundness (0..1)
rotate: 0, // The rotation offset
direction: 1, // 1: clockwise, -1: counterclockwise
color: '#000', // #rgb or #rrggbb or array of colors
speed: 1, // Rounds per second
trail: 60, // Afterglow percentage
shadow: false, // Whether to render a shadow
hwaccel: false, // Whether to use hardware acceleration
className: 'spinner', // The CSS class to assign to the spinner
zIndex: 2e9, // The z-index (defaults to 2000000000)
top: 'auto', // Top position relative to parent in px
left: 'auto' // Left position relative to parent in px
};
var target = document.getElementById('WebGL-output');
spinner = new Spinner(opts).spin(target);
return spinner;
}
function hideSpinner(spinner) {
spinner.stop();
}
function render() {
stats.update();
// sphere.rotation.y=step+=0.01;
// if (typeof ThreeBSP!='undefined') {console.log(ThreeBSP)};
// console.log(ThreeBSP);
if (controls.rotateResult && result) {
result.rotation.y += 0.04;
result.rotation.x+=0.04;
// result.rotation.z -= 0.005;
}
// render using requestAnimationFrame
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
};
window.onload = init();
</script>
</body>
</html>
// Generated by CoffeeScript 1.6.3
(function() {
var BACK, COPLANAR, EPSILON, FRONT, SPANNING, returning,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__slice = [].slice,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
EPSILON = 1e-5;
COPLANAR = 0;
FRONT = 1;
BACK = 2;
SPANNING = 3;
returning = function(value, fn) {
fn();
return value;
};
window.ThreeBSP = (function() {
function ThreeBSP(treeIsh, matrix) {
this.matrix = matrix;
this.intersect = __bind(this.intersect, this);
this.union = __bind(this.union, this);
this.subtract = __bind(this.subtract, this);
this.toGeometry = __bind(this.toGeometry, this);
this.toMesh = __bind(this.toMesh, this);
this.toTree = __bind(this.toTree, this);
if (this.matrix == null) {
this.matrix = new THREE.Matrix4();
}
this.tree = this.toTree(treeIsh);
}
ThreeBSP.prototype.toTree = function(treeIsh) {
var face, geometry, i, polygons, _fn, _i, _len, _ref,
_this = this;
if (treeIsh instanceof ThreeBSP.Node) {
return treeIsh;
}
polygons = [];
geometry = treeIsh instanceof THREE.Geometry ? treeIsh : treeIsh instanceof THREE.Mesh ? (treeIsh.updateMatrix(), this.matrix = treeIsh.matrix.clone(), treeIsh.geometry) : void 0;
_ref = geometry.faces;
_fn = function(face, i) {
var faceVertexUvs, idx, polygon, vIndex, vName, vertex, _j, _len1, _ref1, _ref2;
faceVertexUvs = (_ref1 = geometry.faceVertexUvs) != null ? _ref1[0][i] : void 0;
if (faceVertexUvs == null) {
faceVertexUvs = [new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2()];
}
polygon = new ThreeBSP.Polygon();
_ref2 = ['a', 'b', 'c', 'd'];
for (vIndex = _j = 0, _len1 = _ref2.length; _j < _len1; vIndex = ++_j) {
vName = _ref2[vIndex];
if ((idx = face[vName]) != null) {
vertex = geometry.vertices[idx];
vertex = new ThreeBSP.Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0], new THREE.Vector2(faceVertexUvs[vIndex].x, faceVertexUvs[vIndex].y));
vertex.applyMatrix4(_this.matrix);
polygon.vertices.push(vertex);
}
}
return polygons.push(polygon.calculateProperties());
};
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
face = _ref[i];
_fn(face, i);
}
return new ThreeBSP.Node(polygons);
};
ThreeBSP.prototype.toMesh = function(material) {
var geometry, mesh,
_this = this;
if (material == null) {
material = new THREE.MeshNormalMaterial();
}
geometry = this.toGeometry();
return returning((mesh = new THREE.Mesh(geometry, material)), function() {
mesh.position.getPositionFromMatrix(_this.matrix);
return mesh.rotation.setFromRotationMatrix(_this.matrix);
});
};
ThreeBSP.prototype.toGeometry = function() {
var geometry, matrix,
_this = this;
matrix = new THREE.Matrix4().getInverse(this.matrix);
return returning((geometry = new THREE.Geometry()), function() {
var face, idx, polyVerts, polygon, v, vertUvs, verts, _i, _len, _ref, _results;
_ref = _this.tree.allPolygons();
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
polygon = _ref[_i];
polyVerts = (function() {
var _j, _len1, _ref1, _results1;
_ref1 = polygon.vertices;
_results1 = [];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
v = _ref1[_j];
_results1.push(v.clone().applyMatrix4(matrix));
}
return _results1;
})();
_results.push((function() {
var _j, _ref1, _results1;
_results1 = [];
for (idx = _j = 2, _ref1 = polyVerts.length; 2 <= _ref1 ? _j < _ref1 : _j > _ref1; idx = 2 <= _ref1 ? ++_j : --_j) {
verts = [polyVerts[0], polyVerts[idx - 1], polyVerts[idx]];
vertUvs = (function() {
var _k, _len1, _ref2, _ref3, _results2;
_results2 = [];
for (_k = 0, _len1 = verts.length; _k < _len1; _k++) {
v = verts[_k];
_results2.push(new THREE.Vector2((_ref2 = v.uv) != null ? _ref2.x : void 0, (_ref3 = v.uv) != null ? _ref3.y : void 0));
}
return _results2;
})();
face = (function(func, args, ctor) {
ctor.prototype = func.prototype;
var child = new ctor, result = func.apply(child, args);
return Object(result) === result ? result : child;
})(THREE.Face3, __slice.call((function() {
var _k, _len1, _results2;
_results2 = [];
for (_k = 0, _len1 = verts.length; _k < _len1; _k++) {
v = verts[_k];
_results2.push(geometry.vertices.push(v) - 1);
}
return _results2;
})()).concat([polygon.normal.clone()]), function(){});
geometry.faces.push(face);
_results1.push(geometry.faceVertexUvs[0].push(vertUvs));
}
return _results1;
})());
}
return _results;
});
};
ThreeBSP.prototype.subtract = function(other) {
var them, us, _ref;
_ref = [this.tree.clone(), other.tree.clone()], us = _ref[0], them = _ref[1];
us.invert().clipTo(them);
them.clipTo(us).invert().clipTo(us).invert();
return new ThreeBSP(us.build(them.allPolygons()).invert(), this.matrix);
};
ThreeBSP.prototype.union = function(other) {
var them, us, _ref;
_ref = [this.tree.clone(), other.tree.clone()], us = _ref[0], them = _ref[1];
us.clipTo(them);
them.clipTo(us).invert().clipTo(us).invert();
return new ThreeBSP(us.build(them.allPolygons()), this.matrix);
};
ThreeBSP.prototype.intersect = function(other) {
var them, us, _ref;
_ref = [this.tree.clone(), other.tree.clone()], us = _ref[0], them = _ref[1];
them.clipTo(us.invert()).invert().clipTo(us.clipTo(them));
return new ThreeBSP(us.build(them.allPolygons()).invert(), this.matrix);
};
return ThreeBSP;
})();
ThreeBSP.Vertex = (function(_super) {
__extends(Vertex, _super);
function Vertex(x, y, z, normal, uv) {
this.normal = normal != null ? normal : new THREE.Vector3();
this.uv = uv != null ? uv : new THREE.Vector2();
this.interpolate = __bind(this.interpolate, this);
this.lerp = __bind(this.lerp, this);
Vertex.__super__.constructor.call(this, x, y, z);
}
Vertex.prototype.clone = function() {
return new ThreeBSP.Vertex(this.x, this.y, this.z, this.normal.clone(), this.uv.clone());
};
Vertex.prototype.lerp = function(v, alpha) {
var _this = this;
return returning(Vertex.__super__.lerp.apply(this, arguments), function() {
_this.uv.add(v.uv.clone().sub(_this.uv).multiplyScalar(alpha));
return _this.normal.lerp(v, alpha);
});
};
Vertex.prototype.interpolate = function() {
var args, _ref;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return (_ref = this.clone()).lerp.apply(_ref, args);
};
return Vertex;
})(THREE.Vector3);
ThreeBSP.Polygon = (function() {
function Polygon(vertices, normal, w) {
this.vertices = vertices != null ? vertices : [];
this.normal = normal;
this.w = w;
this.subdivide = __bind(this.subdivide, this);
this.tessellate = __bind(this.tessellate, this);
this.classifySide = __bind(this.classifySide, this);
this.classifyVertex = __bind(this.classifyVertex, this);
this.invert = __bind(this.invert, this);
this.clone = __bind(this.clone, this);
this.calculateProperties = __bind(this.calculateProperties, this);
if (this.vertices.length) {
this.calculateProperties();
}
}
Polygon.prototype.calculateProperties = function() {
var _this = this;
return returning(this, function() {
var a, b, c, _ref;
_ref = _this.vertices, a = _ref[0], b = _ref[1], c = _ref[2];
_this.normal = b.clone().sub(a).cross(c.clone().sub(a)).normalize();
return _this.w = _this.normal.clone().dot(a);
});
};
Polygon.prototype.clone = function() {
var v;
return new ThreeBSP.Polygon((function() {
var _i, _len, _ref, _results;
_ref = this.vertices;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
v = _ref[_i];
_results.push(v.clone());
}
return _results;
}).call(this), this.normal.clone(), this.w);
};
Polygon.prototype.invert = function() {
var _this = this;
return returning(this, function() {
_this.normal.multiplyScalar(-1);
_this.w *= -1;
return _this.vertices.reverse();
});
};
Polygon.prototype.classifyVertex = function(vertex) {
var side;
side = this.normal.dot(vertex) - this.w;
switch (false) {
case !(side < -EPSILON):
return BACK;
case !(side > EPSILON):
return FRONT;
default:
return COPLANAR;
}
};
Polygon.prototype.classifySide = function(polygon) {
var back, front, tally, v, _i, _len, _ref, _ref1,
_this = this;
_ref = [0, 0], front = _ref[0], back = _ref[1];
tally = function(v) {
switch (_this.classifyVertex(v)) {
case FRONT:
return front += 1;
case BACK:
return back += 1;
}
};
_ref1 = polygon.vertices;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
v = _ref1[_i];
tally(v);
}
if (front > 0 && back === 0) {
return FRONT;
}
if (front === 0 && back > 0) {
return BACK;
}
if ((front === back && back === 0)) {
return COPLANAR;
}
return SPANNING;
};
Polygon.prototype.tessellate = function(poly) {
var b, count, f, i, j, polys, t, ti, tj, v, vi, vj, _i, _len, _ref, _ref1, _ref2,
_this = this;
_ref = {
f: [],
b: [],
count: poly.vertices.length
}, f = _ref.f, b = _ref.b, count = _ref.count;
if (this.classifySide(poly) !== SPANNING) {
return [poly];
}
_ref1 = poly.vertices;
for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {
vi = _ref1[i];
vj = poly.vertices[(j = (i + 1) % count)];
_ref2 = (function() {
var _j, _len1, _ref2, _results;
_ref2 = [vi, vj];
_results = [];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
v = _ref2[_j];
_results.push(this.classifyVertex(v));
}
return _results;
}).call(this), ti = _ref2[0], tj = _ref2[1];
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().sub(vi));
v = vi.interpolate(vj, t);
f.push(v);
b.push(v);
}
}
return returning((polys = []), function() {
if (f.length >= 3) {
polys.push(new ThreeBSP.Polygon(f));
}
if (b.length >= 3) {
return polys.push(new ThreeBSP.Polygon(b));
}
});
};
Polygon.prototype.subdivide = function(polygon, coplanar_front, coplanar_back, front, back) {
var poly, side, _i, _len, _ref, _results;
_ref = this.tessellate(polygon);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
poly = _ref[_i];
side = this.classifySide(poly);
switch (side) {
case FRONT:
_results.push(front.push(poly));
break;
case BACK:
_results.push(back.push(poly));
break;
case COPLANAR:
if (this.normal.dot(poly.normal) > 0) {
_results.push(coplanar_front.push(poly));
} else {
_results.push(coplanar_back.push(poly));
}
break;
default:
throw new Error("BUG: Polygon of classification " + side + " in subdivision");
}
}
return _results;
};
return Polygon;
})();
ThreeBSP.Node = (function() {
Node.prototype.clone = function() {
var node,
_this = this;
return returning((node = new ThreeBSP.Node()), function() {
var p, _ref, _ref1, _ref2;
node.divider = (_ref = _this.divider) != null ? _ref.clone() : void 0;
node.polygons = (function() {
var _i, _len, _ref1, _results;
_ref1 = this.polygons;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
p = _ref1[_i];
_results.push(p.clone());
}
return _results;
}).call(_this);
node.front = (_ref1 = _this.front) != null ? _ref1.clone() : void 0;
return node.back = (_ref2 = _this.back) != null ? _ref2.clone() : void 0;
});
};
function Node(polygons) {
this.clipTo = __bind(this.clipTo, this);
this.clipPolygons = __bind(this.clipPolygons, this);
this.invert = __bind(this.invert, this);
this.allPolygons = __bind(this.allPolygons, this);
this.isConvex = __bind(this.isConvex, this);
this.build = __bind(this.build, this);
this.clone = __bind(this.clone, this);
this.polygons = [];
if ((polygons != null) && polygons.length) {
this.build(polygons);
}
}
Node.prototype.build = function(polygons) {
var _this = this;
return returning(this, function() {
var poly, polys, side, sides, _i, _len, _results;
sides = {
front: [],
back: []
};
if (_this.divider == null) {
_this.divider = polygons[0].clone();
}
for (_i = 0, _len = polygons.length; _i < _len; _i++) {
poly = polygons[_i];
_this.divider.subdivide(poly, _this.polygons, _this.polygons, sides.front, sides.back);
}
_results = [];
for (side in sides) {
if (!__hasProp.call(sides, side)) continue;
polys = sides[side];
if (polys.length) {
if (_this[side] == null) {
_this[side] = new ThreeBSP.Node();
}
_results.push(_this[side].build(polys));
} else {
_results.push(void 0);
}
}
return _results;
});
};
Node.prototype.isConvex = function(polys) {
var inner, outer, _i, _j, _len, _len1;
for (_i = 0, _len = polys.length; _i < _len; _i++) {
inner = polys[_i];
for (_j = 0, _len1 = polys.length; _j < _len1; _j++) {
outer = polys[_j];
if (inner !== outer && outer.classifySide(inner) !== BACK) {
return false;
}
}
}
return true;
};
Node.prototype.allPolygons = function() {
var _ref, _ref1;
return this.polygons.slice().concat(((_ref1 = this.front) != null ? _ref1.allPolygons() : void 0) || []).concat(((_ref = this.back) != null ? _ref.allPolygons() : void 0) || []);
};
Node.prototype.invert = function() {
var _this = this;
return returning(this, function() {
var flipper, poly, _i, _j, _len, _len1, _ref, _ref1, _ref2;
_ref = _this.polygons;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
poly = _ref[_i];
poly.invert();
}
_ref1 = [_this.divider, _this.front, _this.back];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
flipper = _ref1[_j];
if (flipper != null) {
flipper.invert();
}
}
return _ref2 = [_this.back, _this.front], _this.front = _ref2[0], _this.back = _ref2[1], _ref2;
});
};
Node.prototype.clipPolygons = function(polygons) {
var back, front, poly, _i, _len;
if (!this.divider) {
return polygons.slice();
}
front = [];
back = [];
for (_i = 0, _len = polygons.length; _i < _len; _i++) {
poly = polygons[_i];
this.divider.subdivide(poly, front, back, front, back);
}
if (this.front) {
front = this.front.clipPolygons(front);
}
if (this.back) {
back = this.back.clipPolygons(back);
}
return front.concat(this.back ? back : []);
};
Node.prototype.clipTo = function(node) {
var _this = this;
return returning(this, function() {
var _ref, _ref1;
_this.polygons = node.clipPolygons(_this.polygons);
if ((_ref = _this.front) != null) {
_ref.clipTo(node);
}
return (_ref1 = _this.back) != null ? _ref1.clipTo(node) : void 0;
});
};
return Node;
})();
}).call(this);