From 5d1bc7152143cb629a18c770fb8136a1b721954b Mon Sep 17 00:00:00 2001 From: Joost Nieuwenhuijse Date: Sat, 21 Jan 2012 21:13:54 +0100 Subject: [PATCH] Added csg.cutByPlane() and CSG.Plane.fromNormalAndPoint() --- csg.js | 46 +++++++++++++++++++++++++++++++++++++++++++++- index.html | 20 ++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/csg.js b/csg.js index bf44224..d1fe3a9 100644 --- a/csg.js +++ b/csg.js @@ -371,7 +371,43 @@ CSG.prototype = { this.cachedBoundingBox = [minpoint, maxpoint]; } return this.cachedBoundingBox; - } + }, + + // Cut the solid by a plane. Returns the solid on the back side of the plane + cutByPlane: function(plane) { + // Ideally we would like to do an intersection with a polygon of inifinite size + // but this is not supported by our implementation. As a workaround, we will create + // a cube, with one face on the plane, and a size larger enough so that the entire + // solid fits in the cube. + + // find the max distance of any vertex to the center of the plane: + var planecenter = plane.normal.times(plane.w); + var maxdistance = 0; + this.polygons.map(function(polygon){ + polygon.vertices.map(function(vertex){ + var distance = vertex.pos.distanceToSquared(planecenter); + if(distance > maxdistance) maxdistance = distance; + }); + }); + maxdistance = Math.sqrt(maxdistance); + maxdistance *= 1.01; // make sure it's really larger + + // Now build a polygon on the plane, at any point farther than maxdistance from the plane center: + var vertices = []; + var orthobasis = new CSG.OrthoNormalBasis(plane); + vertices.push(new CSG.Vertex(orthobasis.to3D(new CSG.Vector2D(maxdistance,maxdistance)))); + vertices.push(new CSG.Vertex(orthobasis.to3D(new CSG.Vector2D(-maxdistance,maxdistance)))); + vertices.push(new CSG.Vertex(orthobasis.to3D(new CSG.Vector2D(-maxdistance,-maxdistance)))); + vertices.push(new CSG.Vertex(orthobasis.to3D(new CSG.Vector2D(maxdistance,-maxdistance)))); + var polygon = new CSG.Polygon(vertices, null, plane.flipped()); + + // and extrude the polygon into a cube, backwards of the plane: + var cube = polygon.extrude(plane.normal.times(-maxdistance)); + + // Now we can do the intersection: + return this.intersect(cube); + }, + }; // Parse an option from the options object @@ -938,6 +974,14 @@ CSG.Plane.fromPoints = function(a, b, c) { return CSG.Plane.fromVector3Ds(a, b, c); }; +CSG.Plane.fromNormalAndPoint = function(normal, point) { + normal = new CSG.Vector3D(normal); + point = new CSG.Vector3D(point); + normal = normal.unit(); + var w = point.dot(normal); + return new CSG.Plane(normal, w); +}; + CSG.Plane.prototype = { flipped: function() { return new CSG.Plane(this.normal.negated(), -this.w); diff --git a/index.html b/index.html index f0cca01..a684e22 100644 --- a/index.html +++ b/index.html @@ -276,6 +276,26 @@ var plane = CSG.Plane.fromPoints([5,0,0], [5, 1, 0], [3, 1, 7]); var cube5 = cube.mirrored(plane); +

Cutting by a plane

+A solid can be cut by a plane; only the part on the back side is kept: + +
+var cube = CSG.cube({radius: 10});
+
+// create a plane by specifying 3 points:
+var plane1 = CSG.Plane.fromPoints([5,0,0], [7, 1, 0], [3, 1, 7]);
+
+// or by specifying a normal and a point on the plane:
+var plane2 = CSG.Plane.fromNormalAndPoint([3, 1, 2], [5, 0, 0]);
+
+// and cut by the plane:
+var part1 = cube.cutByPlane(plane2);
+
+// or if we need the other half of the cube:
+var part2 = cube.cutByPlane(plane2.flipped());
+
+ +

Expansion and contraction

Expansion can be seen as the 3D convolution of an object with a sphere. Contraction is the reverse: the area outside the solid