Boolean Image v2
Create an operation to remove sections of a rectangle
by Nick Hulea
HTML
<script src="http://assets.paperjs.org/boolean/paper.js"></script>
<div id="container">
<button id="testStart" value="Start tests" onClick="runTests();">Start tests</button>
</div>
<svg class="hide" version="1.1" id="glyphsys" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
<path fill="none" d="M68.836,146.216c8.889,5.698,21.647,10.021,35.324,10.021c20.283,0,32.142-10.689,32.142-26.203
c0-14.122-8.203-22.557-28.949-30.305c-25.072-9.121-40.577-22.343-40.577-43.759c0-23.93,19.829-41.708,49.688-41.708
c15.495,0,27.112,3.646,33.719,7.516l-5.456,16.182c-4.787-2.959-15.031-7.293-28.949-7.293c-20.961,0-28.94,12.536-28.94,23.021
c0,14.354,9.344,21.425,30.536,29.627c25.981,10.03,38.971,22.565,38.971,45.123c0,23.717-17.313,44.444-53.557,44.444
c-14.809,0-30.991-4.546-39.194-10.039L68.836,146.216z" />
<path fill="none" d="M82.734,183.337v-66.265L33.15,27.158h23.17l22.009,43.104c5.792,11.811,10.66,21.321,15.528,32.207h0.462
c4.17-10.207,9.736-20.396,15.764-32.207l22.473-43.104h22.707l-52.131,89.669v66.51H82.734z" />
</svg>
<svg class="hide" version="1.1" id="glyphsacirc" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
<path fill="none" d="M107.585,161.74c-3.868,0-9.281-2.318-12.117-5.156c-3.351-3.35-4.898-6.961-6.186-11.342
c-10.312,6.961-22.688,16.498-30.421,16.498c-18.304,0-30.935-15.211-30.935-31.451c0-12.631,6.703-20.621,20.881-25.52
c15.468-5.157,34.287-12.118,39.958-16.757v-4.383c0-18.818-8.766-29.13-21.913-29.13c-4.898,0-8.765,1.805-11.601,4.898
c-3.093,3.609-5.413,9.281-7.476,17.015c-1.288,4.124-3.868,5.929-7.477,5.929c-4.64,0-11.084-4.898-11.084-11.085
...
CSS
body {
height: 100%;
overflow: auto;
font-family:'Helvetica Neue';
font-weight: 300;
}
#container {
display: block;
width: 1000px;
margin: 0 auto 50px;
}
h1, h3 {
font-weight: 300;
margin: 50px 0 20px;
}
footer {
display: block;
width: 1000px;
margin: 30px auto;
color: #999;
}
canvas {
cursor: crosshair;
width: 100%;
height: 440px;
margin: 5px 0;
}
.error {
color: #a00;
}
.hide {
display: none;
}
JavaScript
paper.install(window);
var operations = {
union: true,
intersection: true,
subtraction: true,
exclusion: true,
division: true
};
var hitOptions = {
segments: true,
stroke: true,
fill: true,
tolerance: 5
};
function runTests() {
var pathA, pathB, group;
var container = document.getElementById('container');
function runTest(testName, handler) {
var caption = document.createElement('h3');
var canvas = document.createElement('canvas');
caption.appendChild(document.createTextNode(testName));
container.appendChild(caption);
container.appendChild(canvas);
setTimeout(function () {
console.log('\n' + testName);
paper.setup(canvas);
var paths = handler();
testBooleanStatic(paths[0], paths[1]);
}, 0);
return caption;
}
runTest('Overlapping circles', function () {
return [
new Path.Circle(new Point(80, 110), 50),
new Path.Circle(new Point(150, 110), 70)];
});
runTest('Disjoint circles', function () {
return [
new Path.Circle(new Point(60, 110), 50),
new Path.Circle(new Point(170, 110), 50)];
});
runTest('Overlapping circles - enveloping', function () {
return [
new Path.Circle(new Point(110, 110), 100),
new Path.Circle(new Point(120, 110), 60)];
});
runTest('Polygon and square', function () {
return [
new Path.RegularPolygon(new Point(80, 110), 12, 80),
new Path.Rectangle(new Point(100, 80), [80, 80])];
});
runTest('Circle and square (overlaps exactly on existing segments)', function () {
return [
new Path.Circle(new Point(110, 110), 80),
new Path.Rectangle(new Point(110, 110), [80, 80])];
});
runTest('Circle and square (existing...