Added csg.cutByPlane() and CSG.Plane.fromNormalAndPoint()

This commit is contained in:
Joost Nieuwenhuijse 2012-01-21 21:13:54 +01:00
parent 1eac51e260
commit 5d1bc71521
2 changed files with 65 additions and 1 deletions

46
csg.js
View file

@ -371,7 +371,43 @@ CSG.prototype = {
this.cachedBoundingBox = [minpoint, maxpoint]; this.cachedBoundingBox = [minpoint, maxpoint];
} }
return this.cachedBoundingBox; 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 // 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); 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 = { CSG.Plane.prototype = {
flipped: function() { flipped: function() {
return new CSG.Plane(this.normal.negated(), -this.w); return new CSG.Plane(this.normal.negated(), -this.w);

View file

@ -276,6 +276,26 @@ var plane = CSG.Plane.fromPoints([5,0,0], [5, 1, 0], [3, 1, 7]);
var cube5 = cube.mirrored(plane); var cube5 = cube.mirrored(plane);
</pre> </pre>
<h2>Cutting by a plane</h2>
A solid can be cut by a plane; only the part on the back side is kept:
<pre>
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());
</pre>
<h2>Expansion and contraction</h2> <h2>Expansion and contraction</h2>
Expansion can be seen Expansion can be seen
as the 3D convolution of an object with a sphere. Contraction is the reverse: the area outside the solid as the 3D convolution of an object with a sphere. Contraction is the reverse: the area outside the solid