|
(function() { |
|
var clip_paths, clip_type, cpr, height, path, paths2string, solution_paths, solutions, subj_paths, succeeded, svg, width, _i, _j, _len, _len2, _ref, _ref2; |
|
|
|
width = 960; |
|
|
|
height = 500; |
|
|
|
/* create the SVG |
|
*/ |
|
|
|
svg = d3.select('body').append('svg').attr('width', width).attr('height', height); |
|
|
|
/* define subject and clip paths |
|
*/ |
|
|
|
subj_paths = [ |
|
[ |
|
{ |
|
X: 10, |
|
Y: 10 |
|
}, { |
|
X: 110, |
|
Y: 10 |
|
}, { |
|
X: 110, |
|
Y: 110 |
|
}, { |
|
X: 10, |
|
Y: 110 |
|
} |
|
], [ |
|
{ |
|
X: 20, |
|
Y: 20 |
|
}, { |
|
X: 20, |
|
Y: 100 |
|
}, { |
|
X: 100, |
|
Y: 100 |
|
}, { |
|
X: 100, |
|
Y: 20 |
|
} |
|
] |
|
]; |
|
|
|
clip_paths = [ |
|
[ |
|
{ |
|
X: 50, |
|
Y: 50 |
|
}, { |
|
X: 150, |
|
Y: 50 |
|
}, { |
|
X: 150, |
|
Y: 150 |
|
}, { |
|
X: 50, |
|
Y: 150 |
|
} |
|
], [ |
|
{ |
|
X: 60, |
|
Y: 60 |
|
}, { |
|
X: 60, |
|
Y: 140 |
|
}, { |
|
X: 140, |
|
Y: 140 |
|
}, { |
|
X: 140, |
|
Y: 60 |
|
} |
|
] |
|
]; |
|
|
|
/* create and instruct Clipper to work with the provided paths |
|
*/ |
|
|
|
cpr = new ClipperLib.Clipper(); |
|
|
|
/* true for closed paths |
|
*/ |
|
|
|
cpr.AddPaths(subj_paths, ClipperLib.PolyType.ptSubject, true); |
|
|
|
cpr.AddPaths(clip_paths, ClipperLib.PolyType.ptClip, true); |
|
|
|
/* perform a UNION, a DIFFERENCE, a XOR and an INTERSECTION |
|
*/ |
|
|
|
solutions = []; |
|
|
|
_ref = [ClipperLib.ClipType.ctUnion, ClipperLib.ClipType.ctDifference, ClipperLib.ClipType.ctXor, ClipperLib.ClipType.ctIntersection]; |
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) { |
|
clip_type = _ref[_i]; |
|
solution_paths = new ClipperLib.Paths(); |
|
succeeded = cpr.Execute(clip_type, solution_paths, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero); |
|
if (!succeeded) throw new Error('Clipper operation failed!'); |
|
solutions.push(solution_paths); |
|
} |
|
|
|
/* Converts Paths to SVG path string |
|
*/ |
|
|
|
/* and scales down the coordinates |
|
*/ |
|
|
|
/* from http://jsclipper.sourceforge.net/6.1.3.1/index.html?p=starter_boolean.html |
|
*/ |
|
|
|
paths2string = function(paths, scale) { |
|
var i, p, path, svgpath, _j, _len2, _len3; |
|
svgpath = ''; |
|
if (!(scale != null)) scale = 1; |
|
for (_j = 0, _len2 = paths.length; _j < _len2; _j++) { |
|
path = paths[_j]; |
|
for (i = 0, _len3 = path.length; i < _len3; i++) { |
|
p = path[i]; |
|
if (i === 0) { |
|
svgpath += 'M'; |
|
} else { |
|
svgpath += 'L'; |
|
} |
|
svgpath += p.X / scale + ", " + p.Y / scale; |
|
} |
|
svgpath += 'Z'; |
|
} |
|
if (svgpath === '') svgpath = 'M0,0'; |
|
return svgpath; |
|
}; |
|
|
|
/* display all the solutions in SVG |
|
*/ |
|
|
|
svg.selectAll('path').data(solutions).enter().append('path').attr('d', function(d) { |
|
return paths2string(d); |
|
}).attr('transform', function(d, i) { |
|
return "translate(" + (width / 2 + (i - 2) * 200 + 50) + "," + (height / 2 + 25) + ")"; |
|
}); |
|
|
|
/* display the original paths as reference |
|
*/ |
|
|
|
_ref2 = [subj_paths, clip_paths]; |
|
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { |
|
path = _ref2[_j]; |
|
svg.append('path').attr('class', 'original').attr('d', paths2string(path)).attr('transform', "translate(" + (width / 2 - 75) + ",50)"); |
|
} |
|
|
|
}).call(this); |