mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 02:38:43 -05:00
Remove separate boolean folder now.
This commit is contained in:
parent
90e3dd201a
commit
26cb5791bc
10 changed files with 0 additions and 2387 deletions
|
@ -1,3 +0,0 @@
|
|||
|
||||
set tags+=./tags
|
||||
|
1
boolean/.gitignore
vendored
1
boolean/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
tags
|
|
@ -1,696 +0,0 @@
|
|||
|
||||
|
||||
/*!
|
||||
*
|
||||
* Vector boolean operations on paperjs objects
|
||||
* This is mostly written for clarity (I hope it is clear) and compatibility,
|
||||
* not optimised for performance, and has to be tested heavily for stability.
|
||||
* (Looking up to Java's Area path boolean algorithms for stability,
|
||||
* but the code is too complex —mainly because the operations are stored and
|
||||
* enumerable, such as quadraticCurveTo, cubicCurveTo etc.; and is largely
|
||||
* undocumented to directly adapt from)
|
||||
*
|
||||
* Supported
|
||||
* - paperjs Path and CompoundPath objects
|
||||
* - Boolean Union
|
||||
* - Boolean Intersection
|
||||
* - Boolean Subtraction
|
||||
* - Resolving a self-intersecting Path
|
||||
*
|
||||
* Not supported yet ( which I would like to see supported )
|
||||
* - Boolean operations on self-intersecting Paths, these has to be resolved first
|
||||
* - Paths are clones of each other that ovelap exactly on top of each other!
|
||||
*
|
||||
* ------
|
||||
* Harikrishnan Gopalakrishnan
|
||||
* http://hkrish.com/playground/paperjs/booleanStudy.html
|
||||
*
|
||||
* ------
|
||||
* Paperjs
|
||||
* Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
|
||||
* http://paperjs.org/license/
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* BooleanOps defines the boolean operator functions to use.
|
||||
* A boolean operator is a function f( link:Link, isInsidePath1:Boolean, isInsidePath2:Boolean ) :
|
||||
* should return a Boolean value indicating whether to keep the link or not.
|
||||
* return true - keep the path
|
||||
* return false - discard the path
|
||||
*/
|
||||
var BooleanOps = {
|
||||
Union: function( lnk, isInsidePath1, isInsidePath2 ){
|
||||
if( isInsidePath1 || isInsidePath2 ){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
Intersection: function( lnk, isInsidePath1, isInsidePath2 ){
|
||||
if( !isInsidePath1 && !isInsidePath2 ){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// path1 - path2
|
||||
Subtraction: function( lnk, isInsidePath1, isInsidePath2 ){
|
||||
var lnkid = lnk.id;
|
||||
if( lnkid === 1 && isInsidePath2 ){
|
||||
return false;
|
||||
} else if( lnkid === 2 && !isInsidePath1 ){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The datastructure for boolean computation:
|
||||
* Graph - List of Links
|
||||
* Link - Connects 2 Nodes, represents a Curve
|
||||
* Node - Connects 2 Links, represents a Segment
|
||||
*/
|
||||
|
||||
var NORMAL_NODE = 1;
|
||||
var INTERSECTION_NODE = 2;
|
||||
var IntersectionID = 1;
|
||||
var UNIQUE_ID = 1;
|
||||
|
||||
/**
|
||||
* Nodes in the graph are analogous to Segment objects
|
||||
* with additional linkage information to track intersections etc.
|
||||
* (enough to do a complete graph traversal)
|
||||
* @param {Point} _point
|
||||
* @param {Point} _handleIn
|
||||
* @param {Point} _handleOut
|
||||
* @param {Any} _id
|
||||
*/
|
||||
function Node( _point, _handleIn, _handleOut, _id, isBaseContour ){
|
||||
this.id = _id;
|
||||
this.isBaseContour = isBaseContour;
|
||||
this.type = NORMAL_NODE;
|
||||
this.point = _point;
|
||||
this.handleIn = _handleIn; // handleIn
|
||||
this.handleOut = _handleOut; // handleOut
|
||||
this.linkIn = null; // aka linkIn
|
||||
this.linkOut = null; // linkOut
|
||||
this.uniqueID = ++UNIQUE_ID;
|
||||
|
||||
// In case of an intersection this will be a merged node.
|
||||
// And we need space to save the "other Node's" parameters before merging.
|
||||
this.idB = null;
|
||||
this.isBaseContourB = false;
|
||||
// this.pointB = this.point; // point should be the same
|
||||
this.handleBIn = null;
|
||||
this.handleBOut = null;
|
||||
this.linkBIn = null;
|
||||
this.linkBOut = null;
|
||||
|
||||
this._segment = null;
|
||||
|
||||
this.getSegment = function( recalculate ){
|
||||
if( this.type === INTERSECTION_NODE && recalculate ){
|
||||
// point this.linkIn and this.linkOut to those active ones
|
||||
// also point this.handleIn and this.handleOut to correct in and out handles
|
||||
// If a link is null, make sure the corresponding handle is also null
|
||||
this.handleIn = (this.linkIn)? this.handleIn : null;
|
||||
this.handleOut = (this.linkOut)? this.handleOut : null;
|
||||
this.handleBIn = (this.linkBIn)? this.handleBIn : null;
|
||||
this.handleBOut = (this.linkBOut)? this.handleBOut : null;
|
||||
// Select the valid links
|
||||
this.linkIn = this.linkIn || this.linkBIn; // linkIn
|
||||
this.linkOut = this.linkOut || this.linkBOut; // linkOut
|
||||
// Also update the references in links to point to "this" Node
|
||||
if( !this.linkIn || !this.linkOut ){
|
||||
// markPoint( this.point, this._intersectionID );
|
||||
throw { name: 'Boolean Error', message: 'No matching link found at ixID: ' +
|
||||
this._intersectionID + " point: " + this.point.toString() };
|
||||
}
|
||||
this.linkIn.nodeOut = this; // linkIn.nodeEnd
|
||||
this.linkOut.nodeIn = this; // linkOut.nodeStart
|
||||
this.handleIn = this.handleIn || this.handleBIn;
|
||||
this.handleOut = this.handleOut || this.handleBOut;
|
||||
this.isBaseContour = this.isBaseContour | this.isBaseContourB;
|
||||
}
|
||||
this._segment = this._segment || new Segment( this.point, this.handleIn, this.handleOut );
|
||||
return this._segment;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Links in the graph are analogous to CUrve objects
|
||||
* @param {Node} _nodeIn
|
||||
* @param {Node} _nodeOut
|
||||
* @param {Any} _id
|
||||
*/
|
||||
function Link( _nodeIn, _nodeOut, _id, isBaseContour, _winding ) {
|
||||
this.id = _id;
|
||||
this.isBaseContour = isBaseContour;
|
||||
this.winding = _winding;
|
||||
this.nodeIn = _nodeIn; // nodeStart
|
||||
this.nodeOut = _nodeOut; // nodeEnd
|
||||
this.nodeIn.linkOut = this; // nodeStart.linkOut
|
||||
this.nodeOut.linkIn = this; // nodeEnd.linkIn
|
||||
this._curve = null;
|
||||
this.intersections = [];
|
||||
|
||||
// for reusing the paperjs function we need to (temperorily) build a Curve object from this Link
|
||||
// for performance reasons we cache it.
|
||||
this.getCurve = function() {
|
||||
this._curve = this._curve || new Curve( this.nodeIn.getSegment(), this.nodeOut.getSegment() );
|
||||
return this._curve;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* makes a graph. Only works on paths, for compound paths we need to
|
||||
* make graphs for each of the child paths and merge them.
|
||||
* @param {Path} path
|
||||
* @param {Integer} id
|
||||
* @return {Array} Links
|
||||
*/
|
||||
function makeGraph( path, id, isBaseContour ){
|
||||
var graph = [];
|
||||
var segs = path.segments, prevNode = null, firstNode = null, nuLink, nuNode,
|
||||
winding = path.clockwise;
|
||||
for( i = 0, l = segs.length; i < l; i++ ){
|
||||
// var nuSeg = segs[i].clone();
|
||||
var nuSeg = segs[i];
|
||||
nuNode = new Node( nuSeg.point, nuSeg.handleIn, nuSeg.handleOut, id, isBaseContour );
|
||||
if( prevNode ) {
|
||||
nuLink = new Link( prevNode, nuNode, id, isBaseContour, winding );
|
||||
graph.push( nuLink );
|
||||
}
|
||||
prevNode = nuNode;
|
||||
if( !firstNode ){
|
||||
firstNode = nuNode;
|
||||
}
|
||||
}
|
||||
// the path is closed
|
||||
nuLink = new Link( prevNode, firstNode, id, isBaseContour, winding );
|
||||
graph.push( nuLink );
|
||||
return graph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the Union of two paths
|
||||
* Boolean API.
|
||||
* @param {Path} path1
|
||||
* @param {Path} path2
|
||||
* @return {CompoundPath} union of path1 & path2
|
||||
*/
|
||||
function boolUnion( path1, path2 ){
|
||||
return computeBoolean( path1, path2, BooleanOps.Union );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the Intersection between two paths
|
||||
* Boolean API.
|
||||
* @param {Path} path1
|
||||
* @param {Path} path2
|
||||
* @return {CompoundPath} Intersection of path1 & path2
|
||||
*/
|
||||
function boolIntersection( path1, path2 ){
|
||||
return computeBoolean( path1, path2, BooleanOps.Intersection );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates path1—path2
|
||||
* Boolean API.
|
||||
* @param {Path} path1
|
||||
* @param {Path} path2
|
||||
* @return {CompoundPath} path1 <minus> path2
|
||||
*/
|
||||
function boolSubtract( path1, path2 ){
|
||||
return computeBoolean( path1, path2, BooleanOps.Subtraction );
|
||||
}
|
||||
|
||||
/**
|
||||
* To deal with a HTML canvas requirement where CompoundPaths' child contours
|
||||
* has to be of different winding direction for correctly filling holes.
|
||||
* But if some individual countours are disjoint, i.e. islands, we have to
|
||||
* reorient them so that
|
||||
* the holes have opposit winding direction ( already handled by paperjs )
|
||||
* islands has to have same winding direction ( as the first child of the path )
|
||||
*
|
||||
* Does NOT handle selfIntersecting CompoundPaths.
|
||||
*
|
||||
* @param {CompoundPath} path - Input CompoundPath, Note: This path could be modified if need be.
|
||||
* @return {boolean} the winding direction of the base contour( true if clockwise )
|
||||
*/
|
||||
function reorientCompoundPath( path ){
|
||||
if( !(path instanceof CompoundPath) ){ return path.clockwise; }
|
||||
var children = path.children, len = children.length, baseWinding;
|
||||
var bounds = new Array( len );
|
||||
var tmparray = new Array( len );
|
||||
baseWinding = children[0].clockwise;
|
||||
// Omit the first path
|
||||
for (i = 0; i < len; i++) {
|
||||
bounds[i] = children[i].bounds;
|
||||
tmparray[i] = 0;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
var p1 = children[i];
|
||||
for (j = 0; j < len; j++) {
|
||||
var p2 = children[j];
|
||||
if( i !== j && bounds[i].contains( bounds[j] ) ){
|
||||
tmparray[j]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 1; i < len; i++) {
|
||||
if ( tmparray[i] % 2 === 0 ) {
|
||||
children[i].clockwise = baseWinding;
|
||||
}
|
||||
}
|
||||
return baseWinding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actual function that computes the boolean
|
||||
* @param {Path} _path1 (cannot be self-intersecting at the moment)
|
||||
* @param {Path} _path2 (cannot be self-intersecting at the moment)
|
||||
* @param {BooleanOps type} operator
|
||||
* @return {CompoundPath} boolean result
|
||||
*/
|
||||
function computeBoolean( _path1, _path2, operator ){
|
||||
IntersectionID = 1;
|
||||
UNIQUE_ID = 1;
|
||||
|
||||
// We work on duplicate paths since the algorithm may modify the original paths
|
||||
var path1 = _path1.clone();
|
||||
var path2 = _path2.clone();
|
||||
|
||||
var i, j, k, l, lnk, crv, node, nuNode, leftLink, rightLink;
|
||||
var path1Clockwise = true, path2Clockwise = true;
|
||||
|
||||
// If one of the operands is empty, resolve self-intersections on the second operand
|
||||
var childCount1 = (_path1 instanceof CompoundPath)? _path1.children.length : _path1.curves.length;
|
||||
var childCount2 = (_path2 instanceof CompoundPath)? _path2.children.length : _path2.curves.length;
|
||||
var resolveSelfIntersections = !childCount1 | !childCount2;
|
||||
|
||||
// Reorient the compound paths, i.e. make all the islands wind in the same direction
|
||||
// and holes in the opposit direction.
|
||||
// Do this only if we are not resolving selfIntersections:
|
||||
// Resolving self-intersections work on compound paths, but, we might get different results!
|
||||
if( !resolveSelfIntersections ){
|
||||
path1Clockwise = reorientCompoundPath( path1 );
|
||||
path2Clockwise = reorientCompoundPath( path2 );
|
||||
}
|
||||
|
||||
// Cache the bounding rectangle of paths
|
||||
// so we can make the test for containment quite a bit faster
|
||||
path1._bounds = (childCount1)? path1.bounds : null;
|
||||
path2._bounds = (childCount2)? path2.bounds : null;
|
||||
|
||||
// Prepare the graphs. Graphs are list of Links that retains
|
||||
// full connectivity information. The order of links in a graph is not important
|
||||
// That allows us to sort and merge graphs and 'splice' links with their splits easily.
|
||||
// Also, this is the place to resolve self-intersecting paths
|
||||
var graph = [], path1Children, path2Children, base;
|
||||
if( path1 instanceof CompoundPath ){
|
||||
path1Children = path1.children;
|
||||
for (i = 0, base = true, l = path1Children.length; i < l; i++, base = false) {
|
||||
path1Children[i].closed = true;
|
||||
graph = graph.concat( makeGraph( path1Children[i], 1, base ) );
|
||||
}
|
||||
} else {
|
||||
path1.closed = true;
|
||||
path1Clockwise = path1.clockwise;
|
||||
// path1.clockwise = true;
|
||||
graph = graph.concat( makeGraph( path1, 1, true ) );
|
||||
}
|
||||
|
||||
// if operator === BooleanOps.Subtraction, then reverse path2
|
||||
// so that the nodes and links will link correctly
|
||||
var reverse = ( operator === BooleanOps.Subtraction )? true: false;
|
||||
path2Clockwise = (reverse)? !path2Clockwise : path2Clockwise;
|
||||
if( path2 instanceof CompoundPath ){
|
||||
path2Children = path2.children;
|
||||
for (i = 0, base = true, l = path2Children.length; i < l; i++, base = false) {
|
||||
path2Children[i].closed = true;
|
||||
if( reverse ){path2Children[i].reverse(); }
|
||||
graph = graph.concat( makeGraph( path2Children[i], 2, base ) );
|
||||
}
|
||||
} else {
|
||||
path2.closed = true;
|
||||
// path2.clockwise = true;
|
||||
if( reverse ){ path2.reverse(); }
|
||||
path2Clockwise = path2.clockwise;
|
||||
graph = graph.concat( makeGraph( path2, 2, true ) );
|
||||
}
|
||||
|
||||
window.g = graph;
|
||||
|
||||
// Sort function to sort intersections according to the 'parameter'(t) in a link (curve)
|
||||
function ixSort( a, b ){ return a.parameter - b.parameter; }
|
||||
|
||||
/*
|
||||
* Pass 1:
|
||||
* Calculate the intersections for all graphs
|
||||
*/
|
||||
var ix, loc, loc2, ixCount = 0;
|
||||
for ( i = graph.length - 1; i >= 0; i--) {
|
||||
var c1 = graph[i].getCurve();
|
||||
var v1 = c1.getValues();
|
||||
for ( j = i -1; j >= 0; j-- ) {
|
||||
if( !resolveSelfIntersections && graph[j].id === graph[i].id ){ continue; }
|
||||
var c2 = graph[j].getCurve();
|
||||
var v2 = c2.getValues();
|
||||
loc = [];
|
||||
Curve.getIntersections( v1, v2, c1, loc );
|
||||
if( loc.length ){
|
||||
for (k = 0, l=loc.length; k<l; k++) {
|
||||
// Ignore segment overlaps if both curve are part of same contour
|
||||
// This is a degenerate case while resolving self-intersections,
|
||||
// after paperjs rev#8d35d92
|
||||
if( graph[j].id === graph[i].id &&
|
||||
( loc[k].parameter === 0.0 || loc[k].parameter === 1.0) ) {
|
||||
continue;
|
||||
}
|
||||
// markPoint( loc[k].point, loc[k]._id )
|
||||
// console.log( loc[k].point, loc[k]._id )
|
||||
graph[i].intersections.push( loc[k] );
|
||||
loc2 = new CurveLocation( c2, null, loc[k].point );
|
||||
loc2._id = loc[k]._id;
|
||||
graph[j].intersections.push( loc2 );
|
||||
loc[k]._ixpair = loc2;
|
||||
loc2._ixpair = loc[k];
|
||||
++ixCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Avoid duplicate intersections when a curve that belongs to one contour
|
||||
* passes through a segment on another contour
|
||||
*/
|
||||
len = graph.length;
|
||||
while( len-- ){
|
||||
ix = graph[len].intersections;
|
||||
for (i =0, l=ix.length; i<l; i++) {
|
||||
// In case of an over lap over the first segment on a link we
|
||||
// look for duplicates and mark them INVALID
|
||||
loc = ix[i];
|
||||
if ( loc.parameter === 0.0 ){
|
||||
j = graph.length;
|
||||
while( j-- ) {
|
||||
var ix2 = graph[j].intersections;
|
||||
k = ix2.length;
|
||||
while ( k-- ) {
|
||||
loc2 = ix2[k];
|
||||
if( !loc2.INVALID && loc._id !== loc2._id && loc2.parameter !== 1.0 &&
|
||||
loc2.point.equals( loc.point ) ) {
|
||||
loc2.INVALID = loc2._ixpair.INVALID = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // if( loc.parameter === 0.0 )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass 2:
|
||||
* Walk the graph, sort the intersections on each individual link.
|
||||
* for each link that intersects with another one, replace it with new split links.
|
||||
*/
|
||||
var ixPoint, ixHandleI, ixHandleOut, param, isLinear, parts, left, right;
|
||||
var values, nix, niy,nox, noy, niho, nohi, nihox, nihoy, nohix, nohiy;
|
||||
for ( i = graph.length - 1; i >= 0; i--) {
|
||||
if( graph[i].intersections.length ){
|
||||
ix = graph[i].intersections;
|
||||
// Sort the intersections if there is more than one
|
||||
if( graph[i].intersections.length > 1 ){ ix.sort( ixSort ); }
|
||||
// Remove the graph link, this link has to be split and replaced with the splits
|
||||
lnk = graph.splice( i, 1 )[0];
|
||||
|
||||
nix = lnk.nodeIn.point.x; niy = lnk.nodeIn.point.y;
|
||||
nox = lnk.nodeOut.point.x; noy = lnk.nodeOut.point.y;
|
||||
niho = lnk.nodeIn.handleOut; nohi = lnk.nodeOut.handleIn;
|
||||
nihox = nihoy = nohix = nohiy = 0;
|
||||
isLinear = true;
|
||||
if( niho ){ nihox = niho.x; nihoy = niho.y; isLinear = false; }
|
||||
if( nohi ){ nohix = nohi.x; nohiy = nohi.y; isLinear = false; }
|
||||
values = [ nix, niy, nihox + nix, nihoy + niy,
|
||||
nohix + nox, nohiy + noy, nox, noy ];
|
||||
|
||||
for (j =0, l=ix.length; j<l && lnk; j++) {
|
||||
if( ix[j].INVALID ){ continue; }
|
||||
param = ix[j].parameter;
|
||||
// param = crv.getParameterOf( ix[j].point );
|
||||
if( param === 0.0 || param === 1.0) {
|
||||
// Intersection falls on an existing node
|
||||
// there is no need to split the link
|
||||
nuNode = ( param === 0.0 )? lnk.nodeIn : lnk.nodeOut;
|
||||
nuNode.type = INTERSECTION_NODE;
|
||||
nuNode._intersectionID = ix[j]._id;
|
||||
if( param === 1.0 ){
|
||||
leftLink = null;
|
||||
rightLink = lnk;
|
||||
} else {
|
||||
leftLink = lnk;
|
||||
rightLink = null;
|
||||
}
|
||||
} else {
|
||||
parts = Curve.subdivide(values, param);
|
||||
left = parts[0];
|
||||
right = parts[1];
|
||||
// Make new link and convert handles from absolute to relative
|
||||
ixPoint = new Point( left[6], left[7] );
|
||||
if( !isLinear ){
|
||||
ixHandleIn = new Point(left[4] - ixPoint.x, left[5] - ixPoint.y);
|
||||
ixHandleOut = new Point(right[2] - ixPoint.x, right[3] - ixPoint.y);
|
||||
} else {
|
||||
ixHandleIn = ixHandleOut = null;
|
||||
right[2] = right[0];
|
||||
right[3] = right[1];
|
||||
}
|
||||
nuNode = new Node( ixPoint, ixHandleIn, ixHandleOut, lnk.id, lnk.isBaseContour );
|
||||
nuNode.type = INTERSECTION_NODE;
|
||||
nuNode._intersectionID = ix[j]._id;
|
||||
// clear the cached Segment on original end nodes and Update their handles
|
||||
lnk.nodeIn._segment = null;
|
||||
lnk.nodeOut._segment = null;
|
||||
if( !isLinear ){
|
||||
var tmppnt = lnk.nodeIn.point;
|
||||
lnk.nodeIn.handleOut = new Point( left[2] - tmppnt.x, left[3] - tmppnt.y );
|
||||
tmppnt = lnk.nodeOut.point;
|
||||
lnk.nodeOut.handleIn = new Point( right[4] - tmppnt.x, right[5] - tmppnt.y );
|
||||
}
|
||||
// Make new links after the split
|
||||
leftLink = new Link( lnk.nodeIn, nuNode, lnk.id, lnk.isBaseContour, lnk.winding );
|
||||
rightLink = new Link( nuNode, lnk.nodeOut, lnk.id, lnk.isBaseContour, lnk.winding );
|
||||
|
||||
values = right;
|
||||
}
|
||||
// Add the first split link back to the graph, since we sorted the intersections
|
||||
// already, this link should contain no more intersections to the left.
|
||||
if( leftLink ){
|
||||
graph.splice( i, 0, leftLink );
|
||||
}
|
||||
// continue with the second split link, to see if
|
||||
// there are more intersections to deal with
|
||||
lnk = rightLink;
|
||||
// Interpolate the rest of the parameters
|
||||
if( lnk ) {
|
||||
var one_minus_param = (1.0 - param);
|
||||
for (k =j + 1, l=ix.length; k<l; k++) {
|
||||
ix[k]._parameter = ( ix[k].parameter - param ) / one_minus_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add the last split link back to the graph
|
||||
if( lnk ){
|
||||
graph.splice( i, 0, lnk );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass 3:
|
||||
* Merge matching intersection Node Pairs (type is INTERSECTION_NODE &&
|
||||
* a._intersectionID == b._intersectionID )
|
||||
*
|
||||
* Mark each Link(Curve) according to whether it is
|
||||
* case 1. inside Path1 ( and only Path1 )
|
||||
* 2. inside Path2 ( and only Path2 )
|
||||
* 3. outside (normal case)
|
||||
*
|
||||
* Take a test function "operator" which will discard links
|
||||
* according to the above
|
||||
* * Union -> discard cases 1 and 2
|
||||
* * Intersection -> discard case 3
|
||||
* * Path1-Path2 -> discard cases 2, 3[Path2]
|
||||
*/
|
||||
|
||||
// step 1: discard invalid links according to the boolean operator
|
||||
for ( i = graph.length - 1; i >= 0; i-- ) {
|
||||
var insidePath1 = false, insidePath2 = false, contains;
|
||||
lnk = graph[i];
|
||||
// if( lnk.SKIP_OPERATOR ) { continue; }
|
||||
if( !lnk.INVALID ) {
|
||||
crv = lnk.getCurve();
|
||||
// var midPoint = new Point(lnk.nodeIn.point);
|
||||
var midPoint = crv.getPoint( 0.5 );
|
||||
// If on a base curve, consider points on the curve and inside,
|
||||
// if not —for example a hole, points on the curve falls outside
|
||||
if( lnk.id !== 1 ){
|
||||
contains = path1.contains( midPoint );
|
||||
insidePath1 = (lnk.winding === path1Clockwise)? contains :
|
||||
contains && !testOnCurve( path1, midPoint );
|
||||
}
|
||||
if( lnk.id !== 2 ){
|
||||
contains = path2.contains( midPoint );
|
||||
insidePath2 = (lnk.winding === path2Clockwise)? contains :
|
||||
contains && !testOnCurve( path2, midPoint );
|
||||
}
|
||||
}
|
||||
if( lnk.INVALID || !operator( lnk, insidePath1, insidePath2 ) ){
|
||||
// lnk = graph.splice( i, 1 )[0];
|
||||
lnk.INVALID = true;
|
||||
lnk.nodeIn.linkOut = null;
|
||||
lnk.nodeOut.linkIn = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// step 2: Match nodes according to their _intersectionID and merge them together
|
||||
var len = graph.length;
|
||||
while( len-- ){
|
||||
node = graph[len].nodeIn;
|
||||
if( node.type === INTERSECTION_NODE ){
|
||||
var otherNode = null;
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
var tmpnode = graph[i].nodeIn;
|
||||
if( tmpnode._intersectionID === node._intersectionID &&
|
||||
tmpnode.uniqueID !== node.uniqueID ) {
|
||||
otherNode = tmpnode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( otherNode ) {
|
||||
//Check if it is a self-intersecting Node
|
||||
if( node.id === otherNode.id ){
|
||||
// Swap the outgoing links, this will resolve a knot and create two paths,
|
||||
// the portion of the original path on one side of a self crossing is counter-clockwise,
|
||||
// so one of the resulting paths will also be counter-clockwise
|
||||
var tmp = otherNode.linkOut;
|
||||
otherNode.linkOut = node.linkOut;
|
||||
node.linkOut = tmp;
|
||||
tmp = otherNode.handleOut;
|
||||
otherNode.handleOut = node.handleOut;
|
||||
node.handleOut = tmp;
|
||||
node.type = otherNode.type = NORMAL_NODE;
|
||||
node._intersectionID = null;
|
||||
node._segment = otherNode._segment = null;
|
||||
} else {
|
||||
// Merge the nodes together, by adding this node's information to the other node
|
||||
otherNode.idB = node.id;
|
||||
otherNode.isBaseContourB = node.isBaseContour;
|
||||
otherNode.handleBIn = node.handleIn;
|
||||
otherNode.handleBOut = node.handleOut;
|
||||
otherNode.linkBIn = node.linkIn;
|
||||
otherNode.linkBOut = node.linkOut;
|
||||
otherNode._segment = null;
|
||||
if( node.linkIn ){ node.linkIn.nodeOut = otherNode; }
|
||||
if( node.linkOut ){ node.linkOut.nodeIn = otherNode; }
|
||||
// Clear this node's intersectionID, so that we won't iterate over it again
|
||||
node._intersectionID = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Final step: Retrieve the resulting paths from the graph
|
||||
var boolResult = new CompoundPath();
|
||||
var firstNode = true, nextNode, foundBasePath = false;
|
||||
while( firstNode ){
|
||||
firstNode = nextNode = null;
|
||||
len = graph.length;
|
||||
while( len-- ){
|
||||
lnk = graph[len];
|
||||
if( !lnk.INVALID && !lnk.nodeIn.visited && !firstNode ){
|
||||
if( !foundBasePath && lnk.isBaseContour ){
|
||||
firstNode = lnk.nodeIn;
|
||||
foundBasePath = true;
|
||||
break;
|
||||
} else if(foundBasePath){
|
||||
firstNode = lnk.nodeIn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( firstNode ){
|
||||
var path = new Path();
|
||||
path.add( firstNode.getSegment( true ) );
|
||||
firstNode.visited = true;
|
||||
nextNode = firstNode.linkOut.nodeOut;
|
||||
var linkCount = graph.length + 1;
|
||||
while( firstNode.uniqueID !== nextNode.uniqueID && linkCount-- ){
|
||||
path.add( nextNode.getSegment( true ) );
|
||||
nextNode.visited = true;
|
||||
if( !nextNode.linkOut ){
|
||||
throw { name: 'Boolean Error', message: 'No link found at node id: ' + nextNode.id };
|
||||
}
|
||||
nextNode = nextNode.linkOut.nodeOut;
|
||||
}
|
||||
path.closed = true;
|
||||
// path.clockwise = true;
|
||||
if( path.segments.length > 1 && linkCount >= 0 ){ // avoid stray segments and incomplete paths
|
||||
if( path.segments.length === 2 ){
|
||||
}
|
||||
if( path.segments.length > 2 || !path.curves[0].isLinear() ){
|
||||
boolResult.addChild( path );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
boolResult = boolResult.reduce();
|
||||
|
||||
// Remove the paths we duplicated
|
||||
path1.remove();
|
||||
path2.remove();
|
||||
|
||||
return boolResult;
|
||||
}
|
||||
|
||||
|
||||
// var getLineIntersections = function(v1, v2, curve, locations) {
|
||||
// var result, a1x, a2x, b1x, b2x, a1y, a2y, b1y, b2y;
|
||||
// a1x = v1[0]; a1y = v1[1];
|
||||
// a2x = v1[6]; a2y = v1[7];
|
||||
// b1x = v2[0]; b1y = v2[1];
|
||||
// b2x = v2[6]; b2y = v2[7];
|
||||
// var ua_t = (b2x - b1x) * (a1y - b1y) - (b2y - b1y) * (a1x - b1x);
|
||||
// var ub_t = (a2x - a1x) * (a1y - b1y) - (a2y - a1y) * (a1x - b1x);
|
||||
// var u_b = (b2y - b1y) * (a2x - a1x) - (b2x - b1x) * (a2y - a1y);
|
||||
// if ( u_b !== 0 ) {
|
||||
// var ua = ua_t / u_b;
|
||||
// var ub = ub_t / u_b;
|
||||
// if ( 0 <= ua && ua <= 1 && 0 <= ub && ub <= 1 ) {
|
||||
// locations.push( new CurveLocation(curve, null, new Point(a1x + ua * (a2x - a1x), a1y + ua * (a2y - a1y))) );
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
function testOnCurve( path, point ){
|
||||
var res = 0;
|
||||
var crv = path.getCurves();
|
||||
var i = 0;
|
||||
var bounds = path._bounds;
|
||||
if( bounds && bounds.contains( point ) ){
|
||||
for( i = 0; i < crv.length && !res; i++ ){
|
||||
var crvi = crv[i];
|
||||
if( crvi.bounds.contains( point ) && crvi.getParameterOf( point ) ){
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -1,332 +0,0 @@
|
|||
|
||||
|
||||
function sortIx( a, b ) { return b.parameter - a.parameter; }
|
||||
|
||||
function splitPath( _ixs, other ) {
|
||||
other = other || false;
|
||||
var i, j, k, l, len, ixs, ix, path, crv, vals;
|
||||
var ixPoint, nuSeg;
|
||||
var paths = {}, lastPathId = null;
|
||||
for (i = 0, l = _ixs.length; i < l; i++) {
|
||||
ix = ( other )? _ixs[i].getIntersection() : _ixs[i];
|
||||
if( !paths[ix.path.id] ){
|
||||
paths[ix.path.id] = ix.path;
|
||||
}
|
||||
if( !ix.curve._ixParams ){ix.curve._ixParams = []; }
|
||||
ix.curve._ixParams.push( { parameter: ix.parameter, pair: ix.getIntersection() } );
|
||||
}
|
||||
for (k in paths) {
|
||||
if( !paths.hasOwnProperty( k ) ){ continue; }
|
||||
path = paths[k];
|
||||
var lastNode = path.lastSegment, firstNode = path.firstSegment;
|
||||
var nextNode = null, left = null, right = null, parts = null, isLinear;
|
||||
var handleIn, handleOut;
|
||||
while( nextNode !== firstNode){
|
||||
nextNode = ( nextNode )? nextNode.previous: lastNode;
|
||||
if( nextNode.curve._ixParams ){
|
||||
ixs = nextNode.curve._ixParams;
|
||||
ixs.sort( sortIx );
|
||||
crv = nextNode.getCurve();
|
||||
isLinear = crv.isLinear();
|
||||
crv = vals = null;
|
||||
for (i = 0, l = ixs.length; i < l; i++) {
|
||||
ix = ixs[i];
|
||||
crv = nextNode.getCurve();
|
||||
if( !vals ) vals = crv.getValues();
|
||||
if( ix.parameter === 0.0 || ix.parameter === 1.0 ){
|
||||
// Intersection is on an existing node
|
||||
// no need to create a new segment,
|
||||
// we just link the corresponding intersections together
|
||||
nuSeg = ( ix.parameter === 0.0 )? crv.segment1 : crv.segment2;
|
||||
nuSeg._ixPair = ix.pair;
|
||||
nuSeg._ixPair._segment = nuSeg;
|
||||
} else {
|
||||
parts = Curve.subdivide( vals, ix.parameter );
|
||||
left = parts[0];
|
||||
right = parts[1];
|
||||
handleIn = handleOut = null;
|
||||
ixPoint = new Point( right[0], right[1] );
|
||||
if( !isLinear ){
|
||||
crv.segment1.handleOut = new Point( left[2] - left[0], left[3] - left[1] );
|
||||
crv.segment2.handleIn = new Point( right[4] - right[6], right[5] - right[7] );
|
||||
handleIn = new Point( left[4] - ixPoint.x, left[5] - ixPoint.y );
|
||||
handleOut = new Point( right[2] - ixPoint.x, right[3] - ixPoint.y );
|
||||
}
|
||||
nuSeg = new Segment( ixPoint, handleIn, handleOut );
|
||||
nuSeg._ixPair = ix.pair;
|
||||
nuSeg._ixPair._segment = nuSeg;
|
||||
path.insert( nextNode.index + 1, nuSeg );
|
||||
}
|
||||
for (j = i + 1; j < l; j++) {
|
||||
ixs[j].parameter = ixs[j].parameter / ix.parameter;
|
||||
}
|
||||
vals = left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To deal with a HTML canvas requirement where CompoundPaths' child contours
|
||||
* has to be of different winding direction for correctly filling holes.
|
||||
* But if some individual countours are disjoint, i.e. islands, we have to
|
||||
* reorient them so that
|
||||
* the holes have opposit winding direction ( already handled by paperjs )
|
||||
* islands has to have same winding direction ( as the first child of the path )
|
||||
*
|
||||
* Does NOT handle selfIntersecting CompoundPaths.
|
||||
*
|
||||
* @param {CompoundPath} path - Input CompoundPath, Note: This path could be modified if need be.
|
||||
* @return {boolean} the winding direction of the base contour( true if clockwise )
|
||||
*/
|
||||
function reorientCompoundPath( path ){
|
||||
if( !(path instanceof CompoundPath) ){
|
||||
path.closed = true;
|
||||
return path.clockwise;
|
||||
}
|
||||
var children = path.children, len = children.length, baseWinding;
|
||||
var bounds = new Array( len );
|
||||
var tmparray = new Array( len );
|
||||
baseWinding = children[0].clockwise;
|
||||
// Omit the first path
|
||||
for (i = 0; i < len; i++) {
|
||||
children[i].closed = true;
|
||||
bounds[i] = children[i].bounds;
|
||||
tmparray[i] = 0;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
var p1 = children[i];
|
||||
for (j = 0; j < len; j++) {
|
||||
var p2 = children[j];
|
||||
if( i !== j && bounds[i].contains( bounds[j] ) ){
|
||||
tmparray[j]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 1; i < len; i++) {
|
||||
if ( tmparray[i] % 2 === 0 ) {
|
||||
children[i].clockwise = baseWinding;
|
||||
}
|
||||
}
|
||||
return baseWinding;
|
||||
}
|
||||
|
||||
function reversePath( path ){
|
||||
var baseWinding;
|
||||
if( path instanceof CompoundPath ){
|
||||
var children = path.children, i, len;
|
||||
for (i = 0, len = children.length; i < len; i++) {
|
||||
children[i].reverse();
|
||||
children[i]._curves = null;
|
||||
}
|
||||
baseWinding = children[0].clockwise;
|
||||
} else {
|
||||
path.reverse();
|
||||
baseWinding = path.clockwise;
|
||||
path._curves = null;
|
||||
}
|
||||
return baseWinding;
|
||||
}
|
||||
|
||||
function computeBoolean( path1, path2, operator, _splitCache ){
|
||||
var _path1, _path2, path1Clockwise, path2Clockwise;
|
||||
var ixs, path1Id, path2Id;
|
||||
// We do not modify the operands themselves
|
||||
// The result might not belong to the same type
|
||||
// i.e. subtraction( A:Path, B:Path ):CompoundPath etc.
|
||||
_path1 = path1.clone();
|
||||
_path2 = path2.clone();
|
||||
_path1.style = _path2.style = null;
|
||||
_path1.selected = _path2.selected = false;
|
||||
path1Clockwise = reorientCompoundPath( _path1 );
|
||||
path2Clockwise = reorientCompoundPath( _path2 );
|
||||
path1Id = _path1.id;
|
||||
path2Id = _path2.id;
|
||||
// Calculate all the intersections
|
||||
ixs = ( _splitCache && _splitCache.intersections )?
|
||||
_splitCache.intersections : _path1.getIntersections( _path2 );
|
||||
// if we have a empty _splitCache object as an operand,
|
||||
// skip calculating boolean and cache the intersections
|
||||
if( _splitCache && !_splitCache.intersections ){
|
||||
_splitCache.intersections = ixs;
|
||||
return;
|
||||
}
|
||||
splitPath( ixs );
|
||||
splitPath( ixs, true );
|
||||
path1Id = _path1.id;
|
||||
path2Id = _path2.id;
|
||||
// Do operator specific calculations before we begin
|
||||
if( operator.name === "subtraction" ) {
|
||||
path2Clockwise = reversePath( _path2 );
|
||||
}
|
||||
|
||||
var i, j, len, path, crv;
|
||||
var paths = [];
|
||||
if( _path1 instanceof CompoundPath ){
|
||||
paths = paths.concat( _path1.children );
|
||||
} else {
|
||||
paths = [ _path1 ];
|
||||
}
|
||||
if( _path2 instanceof CompoundPath ){
|
||||
paths = paths.concat( _path2.children );
|
||||
} else {
|
||||
paths.push( _path2 );
|
||||
}
|
||||
// step 1: discard invalid links according to the boolean operator
|
||||
var lastNode, firstNode, nextNode, midPoint, insidePath1, insidePath2;
|
||||
var thisId, thisWinding, contains, subtractionOp = (operator.name === 'subtraction');
|
||||
for (i = 0, len = paths.length; i < len; i++) {
|
||||
insidePath1 = insidePath2 = false;
|
||||
path = paths[i];
|
||||
thisId = ( path.parent instanceof CompoundPath )? path.parent.id : path.id;
|
||||
thisWinding = path.clockwise;
|
||||
lastNode = path.lastSegment;
|
||||
firstNode = path.firstSegment;
|
||||
nextNode = null;
|
||||
while( nextNode !== firstNode){
|
||||
nextNode = ( nextNode )? nextNode.previous: lastNode;
|
||||
crv = nextNode.curve;
|
||||
midPoint = crv.getPoint( 0.5 );
|
||||
if( thisId !== path1Id ){
|
||||
contains = _path1.contains( midPoint );
|
||||
insidePath1 = (thisWinding === path1Clockwise || subtractionOp )? contains :
|
||||
contains && !testOnCurve( _path1, midPoint );
|
||||
}
|
||||
if( thisId !== path2Id ){
|
||||
contains = _path2.contains( midPoint );
|
||||
insidePath2 = (thisWinding === path2Clockwise )? contains :
|
||||
contains && !testOnCurve( _path2, midPoint );
|
||||
}
|
||||
if( !operator( thisId === path1Id, insidePath1, insidePath2 ) ){
|
||||
crv._INVALID = true;
|
||||
// markPoint( midPoint, '+' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Final step: Retrieve the resulting paths from the graph
|
||||
var boolResult = new CompoundPath();
|
||||
var node, nuNode, nuPath, nodeList = [], handle;
|
||||
for (i = 0, len = paths.length; i < len; i++) {
|
||||
nodeList = nodeList.concat( paths[i].segments );
|
||||
}
|
||||
for (i = 0, len = nodeList.length; i < len; i++) {
|
||||
node = nodeList[i];
|
||||
if( node.curve._INVALID || node._visited ){ continue; }
|
||||
path = node.path;
|
||||
thisId = ( path.parent instanceof CompoundPath )? path.parent.id : path.id;
|
||||
thisWinding = path.clockwise;
|
||||
nuPath = new Path();
|
||||
firstNode = null;
|
||||
firstNode_ix = null;
|
||||
if( node.previous.curve._INVALID ) {
|
||||
node.handleIn = ( node._ixPair )?
|
||||
node._ixPair.getIntersection()._segment.handleIn : [ 0, 0 ];
|
||||
}
|
||||
while( node && !node._visited && ( node !== firstNode && node !== firstNode_ix ) ){
|
||||
node._visited = true;
|
||||
firstNode = ( firstNode )? firstNode: node;
|
||||
firstNode_ix = ( !firstNode_ix && firstNode._ixPair )?
|
||||
firstNode._ixPair.getIntersection()._segment: firstNode_ix;
|
||||
// node._ixPair is this node's intersection CurveLocation object
|
||||
// node._ixPair.getIntersection() is the other CurveLocation object this node intersects with
|
||||
nextNode = ( node._ixPair && node.curve._INVALID )? node._ixPair.getIntersection()._segment : node;
|
||||
if( node._ixPair ) {
|
||||
nextNode._visited = true;
|
||||
nuNode = new Segment( node.point, node.handleIn, nextNode.handleOut );
|
||||
nuPath.add( nuNode );
|
||||
node = nextNode;
|
||||
path = node.path;
|
||||
thisWinding = path.clockwise;
|
||||
} else {
|
||||
nuPath.add( node );
|
||||
}
|
||||
node = node.next;
|
||||
}
|
||||
if( nuPath.segments.length > 1 ) {
|
||||
// avoid stray segments and incomplete paths
|
||||
if( nuPath.segments.length > 2 || !nuPath.curves[0].isLinear() ){
|
||||
nuPath.closed = true;
|
||||
boolResult.addChild( nuPath, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
// Delete the proxies
|
||||
_path1.remove();
|
||||
_path2.remove();
|
||||
// And then, we are done.
|
||||
return boolResult.reduce();
|
||||
}
|
||||
|
||||
// Bottleneck no: 2
|
||||
function testOnCurve( path, point ){
|
||||
var res = 0;
|
||||
var crv = path.getCurves();
|
||||
var i = 0;
|
||||
var bounds = path.bounds;
|
||||
if( bounds && bounds.contains( point ) ){
|
||||
for( i = 0; i < crv.length && !res; i++ ){
|
||||
var crvi = crv[i];
|
||||
if( crvi.bounds.contains( point ) && crvi.getParameterOf( point ) ){
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* A boolean operator is a binary operator function of the form
|
||||
* f( isPath1:boolean, isInsidePath1:Boolean, isInsidePath2:Boolean ) :Boolean
|
||||
*
|
||||
* Boolean operator determines whether a curve segment in the operands is part
|
||||
* of the boolean result, and will be called for each curve segment in the graph after
|
||||
* all the intersections between the operands are calculated and curves in the operands
|
||||
* are split at intersections.
|
||||
*
|
||||
* These functions should have a name ( "union", "subtraction" etc. below ), if we need to
|
||||
* do operator specific operations on paths inside the computeBoolean function.
|
||||
* for example: if the name of the operator is "subtraction" then we need to reverse the second
|
||||
* operand. Subtraction is neither associative nor commutative.
|
||||
*
|
||||
* The boolean operator should return a Boolean value indicating whether to keep the curve or not.
|
||||
* return true - keep the curve
|
||||
* return false - discard the curve
|
||||
*/
|
||||
|
||||
function unite( path1, path2, _cache ){
|
||||
var unionOp = function union( isPath1, isInsidePath1, isInsidePath2 ){
|
||||
return ( isInsidePath1 || isInsidePath2 )? false : true;
|
||||
};
|
||||
return computeBoolean( path1, path2, unionOp, _cache );
|
||||
}
|
||||
|
||||
function intersect( path1, path2, _cache ){
|
||||
var intersectionOp = function intersection( isPath1, isInsidePath1, isInsidePath2 ){
|
||||
return ( !isInsidePath1 && !isInsidePath2 )? false : true;
|
||||
};
|
||||
return computeBoolean( path1, path2, intersectionOp, _cache );
|
||||
}
|
||||
|
||||
function subtract( path1, path2, _cache ){
|
||||
var subtractionOp = function subtraction( isPath1, isInsidePath1, isInsidePath2 ){
|
||||
return ( (isPath1 && isInsidePath2) || (!isPath1 && !isInsidePath1) )? false : true;
|
||||
};
|
||||
return computeBoolean( path1, path2, subtractionOp, _cache );
|
||||
}
|
||||
|
||||
// a.k.a. eXclusiveOR
|
||||
function exclude( path1, path2 ){
|
||||
var res1 = subtract( path1, path2 );
|
||||
var res2 = subtract( path2, path1 );
|
||||
var res = new Group( [res1, res2] );
|
||||
return res;
|
||||
}
|
||||
|
||||
function divide( path1, path2 ){
|
||||
var res1 = subtract( path1, path2 );
|
||||
var res2 = intersect( path1, path2 );
|
||||
var res = new Group( [res1, res2] );
|
||||
return res;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Harikrishnan Gopalakrishnan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,31 +0,0 @@
|
|||
|
||||
Vector boolean operations on paperjs objects.
|
||||
This is mostly written for clarity (I hope it is clear) and compatibility,
|
||||
not optimised for performance, and has to be tested heavily for stability.
|
||||
|
||||
(Looking up to Java's Area path boolean algorithms for stability,
|
||||
but the code is too complex —mainly because the operations are stored and
|
||||
enumerable, such as quadraticCurveTo, cubicCurveTo etc.; and is largely
|
||||
undocumented to directly adapt from)
|
||||
|
||||
Supported
|
||||
- paperjs Path and CompoundPath objects
|
||||
- Boolean Union
|
||||
- Boolean Intersection
|
||||
- Boolean Subtraction
|
||||
- Resolving a self-intersecting Path
|
||||
|
||||
Not supported yet ( which I would like to see supported )
|
||||
- Boolean operations between self-intersecting Paths
|
||||
- Paths are clones of each other that ovelap exactly on top of each other!
|
||||
|
||||
This is meant to be integrated into the paperjs library in the near future.
|
||||
|
||||
------
|
||||
Harikrishnan Gopalakrishnan
|
||||
http://hkrish.com/playground/paperjs/booleanStudy.html
|
||||
|
||||
------
|
||||
Paperjs
|
||||
Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
|
||||
http://paperjs.org/license/
|
|
@ -1,457 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Boolean Study</title>
|
||||
<script type="text/javascript" src="../dist/paper.js"></script>
|
||||
<script type="text/javascript" src="Boolean2.js"></script>
|
||||
<script type="text/javascript" src="booleanTests.js"></script>
|
||||
<style>
|
||||
body { height: 100%; overflow: auto; }
|
||||
#container { display: block; width: 1000px; margin: 0 auto 50px; }
|
||||
h1, h3 { font-family: 'Helvetica Neue'; font-weight: 300; margin: 50px 0 20px; }
|
||||
footer{display: block; width: 1000px; height: 100px; margin: 30px auto; color: #999; }
|
||||
footer p { font-family: 'Helvetica Neue'; font-style: italic; font-weight: 300; }
|
||||
canvas { cursor: crosshair; width: 100%; height: 440px; margin: 5px 0;}
|
||||
.error { color: #a00; } .hide{ display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
<h1>paperjs - Boolean Tests</h1>
|
||||
<button id="testStart" value="Start tests" onClick="runTests();">Start tests</button>
|
||||
</div>
|
||||
<footer>
|
||||
<p>Vector boolean operations on paperjs objects. <br />
|
||||
Still under development, mostly written for clarity and compatibility,
|
||||
not optimised for performance, and has to be tested heavily.</p>
|
||||
<p>--<br />
|
||||
hari</p>
|
||||
</footer>
|
||||
|
||||
<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
|
||||
c0-3.609,3.094-6.703,7.991-10.312c6.961-5.156,23.976-14.952,38.67-18.045c7.733,0,15.466,2.321,21.139,6.961
|
||||
c9.024,7.733,11.601,18.045,11.601,31.708v47.693c0,11.6,4.64,15.467,9.024,15.467c3.094,0,6.7-1.289,9.279-2.836l2.577,6.703
|
||||
L107.585,161.74z M88.766,96.778c-5.415,2.835-17.788,8.248-23.202,10.828c-10.054,4.639-15.725,9.537-15.725,19.076
|
||||
c0,13.146,10.31,19.592,18.303,19.592c6.701,0,15.725-4.383,20.623-9.279V96.778z"/>
|
||||
<circle fill="none" cx="112.681" cy="105.821" r="52.076"/>
|
||||
</svg>
|
||||
<svg class="hide" version="1.1" id="svggears" 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="M127.11,135.58c0.899,0.19,2.568,0.312,3.713,0.269l1.001-0.038c1.145-0.043,2.215-1.005,2.381-2.138
|
||||
l0.588-5.705c0.071-1.142-0.778-2.305-1.888-2.585l-0.956-0.242c-1.11-0.279-2.77-0.509-3.689-0.509s-1.724-0.936-1.785-2.077
|
||||
l-0.674-6.489c-0.181-1.13,0.407-2.211,1.305-2.401c0.899-0.191,2.475-0.76,3.5-1.266l0.901-0.441
|
||||
c1.026-0.505,1.617-1.819,1.311-2.923l-1.762-5.453c-0.397-1.072-1.644-1.791-2.771-1.597l-1.005,0.176
|
||||
c-1.127,0.194-2.737,0.66-3.578,1.034c-0.84,0.375-1.954-0.152-2.475-1.172l-3.263-5.647c-0.625-0.958-0.525-2.186,0.221-2.728
|
||||
c0.744-0.542,1.954-1.704,2.687-2.582l0.641-0.769c0.734-0.879,0.735-2.318,0.004-3.198l-3.842-4.259
|
||||
c-0.8-0.817-2.232-0.964-3.184-0.327l-0.823,0.552c-0.95,0.637-2.232,1.718-2.849,2.402c-0.615,0.685-1.849,0.655-2.737-0.064
|
||||
l-5.276-3.833c-0.96-0.623-1.37-1.785-0.908-2.583c0.459-0.797,1.092-2.35,1.403-3.451l0.275-0.974
|
||||
c0.313-1.101-0.271-2.417-1.296-2.925l-5.237-2.329c-1.064-0.42-2.433,0.027-3.042,0.996l-0.536,0.853
|
||||
c-0.609,0.968-1.34,2.476-1.624,3.35c-0.285,0.874-1.421,1.346-2.525,1.047l-6.383-1.349c-1.13-0.18-1.976-1.075-1.879-1.989
|
||||
c0.096-0.914,0.042-2.588-0.121-3.72l-0.141-0.983c-0.163-1.132-1.229-2.122-2.371-2.199c0,0-1.201-0.081-2.866-0.081
|
||||
c-1.669,0-2.876,0.081-2.876,0.081c-1.141,0.077-2.208,1.067-2.371,2.199l-0.141,0.982c-0.163,1.132-0.217,2.807-0.121,3.721
|
||||
c0.096,0.914-0.75,1.81-1.879,1.99l-6.383,1.35c-1.105,0.298-2.241-0.173-2.525-1.046c-0.284-0.874-1.015-2.381-1.624-3.35
|
||||
l-0.537-0.854c-0.609-0.969-1.978-1.417-3.041-0.996l-5.238,2.331c-1.024,0.508-1.608,1.825-1.295,2.925l0.275,0.973
|
||||
c0.313,1.1,0.945,2.653,1.406,3.452c0.46,0.798,0.052,1.96-0.907,2.583l-5.278,3.834c-0.889,0.72-2.122,0.75-2.737,0.065
|
||||
c-0.616-0.684-1.897-1.765-2.848-2.402L36.61,82.52c-0.951-0.637-2.384-0.49-3.185,0.327l-3.841,4.26
|
||||
c-0.73,0.881-0.729,2.32,0.004,3.199l0.641,0.768c0.733,0.878,1.943,2.041,2.688,2.582c0.746,0.542,0.845,1.77,0.221,2.729
|
||||
l-3.263,5.649c-0.52,1.019-1.633,1.547-2.473,1.173c-0.841-0.374-2.45-0.84-3.577-1.035l-1.006-0.175
|
||||
c-1.127-0.196-2.375,0.522-2.771,1.596l-1.762,5.455c-0.306,1.102,0.285,2.417,1.312,2.921l0.899,0.441
|
||||
c1.027,0.505,2.602,1.074,3.5,1.265c0.899,0.191,1.487,1.271,1.306,2.401c0,0-0.784,4.917-0.784,8.558c0,0.003,0,0.003,0,0.003
|
||||
c0,0.004-0.751,0.007-1.671,0.007s-2.579,0.23-3.688,0.509l-0.959,0.242c-1.109,0.28-1.958,1.443-1.887,2.586l0.59,5.706
|
||||
c0.166,1.132,1.237,2.093,2.38,2.137l1.001,0.037c1.144,0.043,2.814-0.078,3.713-0.269c0.898-0.19,1.877,0.557,2.175,1.662
|
||||
l2.015,6.205c0.412,1.067,0.062,2.246-0.778,2.621c-0.84,0.373-2.263,1.258-3.163,1.965l-0.796,0.626
|
||||
c-0.9,0.706-1.2,2.114-0.667,3.126l2.872,4.963c0.615,0.966,1.986,1.406,3.049,0.981l0.926-0.372
|
||||
c1.062-0.425,2.541-1.218,3.287-1.758c0.746-0.542,1.945-0.258,2.665,0.631l4.365,4.848c0.808,0.81,0.966,2.031,0.35,2.716
|
||||
s-1.557,2.071-2.091,3.083l-0.463,0.877c-0.534,1.012-0.239,2.424,0.655,3.137l4.633,3.378c0.951,0.637,2.38,0.486,3.178-0.334
|
||||
l0.708-0.729c0.797-0.821,1.826-2.145,2.287-2.943c0.46-0.797,1.67-1.023,2.689-0.502l5.959,2.653
|
||||
c1.067,0.412,1.708,1.462,1.425,2.335c-0.283,0.875-0.578,2.522-0.654,3.665l-0.068,1.012c-0.076,1.141,0.768,2.307,1.876,2.589
|
||||
l5.611,1.181c1.128,0.189,2.374-0.535,2.769-1.609l0.343-0.933c0.395-1.074,0.796-2.701,0.892-3.614
|
||||
c0.097-0.914,1.108-1.589,2.249-1.499c0,0,1.458,0.114,3.26,0.114c1.805,0,3.271-0.115,3.271-0.115
|
||||
c1.141-0.09,2.152,0.584,2.248,1.497c0.097,0.914,0.498,2.541,0.892,3.614l0.344,0.935c0.394,1.073,1.64,1.798,2.769,1.608
|
||||
l5.61-1.182c1.108-0.282,1.953-1.448,1.876-2.59l-0.067-1.009c-0.077-1.143-0.372-2.791-0.656-3.665s0.358-1.926,1.425-2.337
|
||||
l5.958-2.656c1.019-0.521,2.228-0.296,2.689,0.501c0.46,0.799,1.489,2.122,2.287,2.943l0.708,0.729
|
||||
c0.799,0.82,2.227,0.97,3.178,0.334l4.632-3.379c0.895-0.714,1.188-2.125,0.655-3.137l-0.462-0.877
|
||||
c-0.534-1.011-1.477-2.398-2.092-3.082c-0.617-0.686-0.46-1.907,0.349-2.718l4.364-4.848c0.719-0.89,1.918-1.175,2.663-0.634
|
||||
c0.745,0.543,2.224,1.333,3.286,1.758l0.927,0.373c1.063,0.425,2.435-0.017,3.05-0.981l2.87-4.963
|
||||
c0.532-1.014,0.231-2.42-0.668-3.127l-0.795-0.625c-0.899-0.706-2.323-1.591-3.164-1.966c-0.84-0.374-1.19-1.554-0.778-2.621
|
||||
l2.013-6.206C125.234,136.137,126.212,135.39,127.11,135.58z"/>
|
||||
<path fill="none" d="M175.403,87.286c0.899,0.19,2.568,0.311,3.713,0.268l1.002-0.038c1.145-0.042,2.215-1.005,2.381-2.137
|
||||
l0.587-5.705c0.072-1.141-0.777-2.305-1.888-2.585l-0.956-0.242c-1.109-0.279-2.769-0.509-3.689-0.509
|
||||
c-0.919,0-1.723-0.935-1.785-2.077l-0.673-6.489c-0.181-1.13,0.406-2.211,1.305-2.401c0.898-0.192,2.474-0.76,3.5-1.266l0.901-0.442
|
||||
c1.025-0.504,1.616-1.819,1.311-2.922l-1.763-5.453c-0.396-1.073-1.644-1.792-2.771-1.596l-1.004,0.175
|
||||
c-1.127,0.195-2.738,0.66-3.579,1.035c-0.839,0.375-1.954-0.152-2.474-1.171l-3.264-5.648c-0.624-0.958-0.524-2.186,0.221-2.728
|
||||
c0.744-0.542,1.954-1.704,2.688-2.582l0.64-0.769c0.734-0.879,0.735-2.318,0.005-3.198l-3.842-4.26
|
||||
c-0.801-0.816-2.233-0.964-3.184-0.327l-0.823,0.552c-0.951,0.637-2.233,1.718-2.849,2.402s-1.849,0.655-2.737-0.064l-5.277-3.833
|
||||
c-0.96-0.623-1.37-1.785-0.908-2.583c0.46-0.797,1.092-2.35,1.404-3.451l0.275-0.974c0.312-1.101-0.271-2.417-1.296-2.925
|
||||
l-5.237-2.329c-1.063-0.42-2.434,0.027-3.042,0.996l-0.536,0.853c-0.608,0.968-1.34,2.476-1.624,3.35
|
||||
c-0.285,0.875-1.421,1.346-2.524,1.048l-6.384-1.349c-1.13-0.18-1.976-1.075-1.879-1.989c0.096-0.914,0.042-2.588-0.121-3.72
|
||||
l-0.142-0.983c-0.162-1.132-1.229-2.122-2.369-2.199c0,0-1.202-0.081-2.867-0.081c-1.669,0-2.876,0.082-2.876,0.082
|
||||
c-1.142,0.077-2.209,1.066-2.371,2.199l-0.142,0.982c-0.161,1.132-0.217,2.807-0.121,3.721c0.097,0.914-0.749,1.81-1.879,1.99
|
||||
l-6.384,1.351c-1.105,0.298-2.24-0.173-2.524-1.046c-0.284-0.874-1.016-2.381-1.623-3.35l-0.538-0.854
|
||||
c-0.607-0.969-1.978-1.417-3.04-0.996l-5.238,2.33c-1.024,0.509-1.608,1.825-1.295,2.926l0.275,0.973
|
||||
c0.313,1.1,0.945,2.653,1.406,3.452c0.46,0.797,0.052,1.96-0.907,2.583l-5.278,3.834c-0.889,0.72-2.122,0.75-2.737,0.065
|
||||
c-0.616-0.684-1.897-1.765-2.848-2.402l-0.823-0.553c-0.951-0.637-2.384-0.49-3.185,0.327l-3.841,4.261
|
||||
c-0.73,0.881-0.729,2.32,0.004,3.199l0.641,0.768c0.733,0.878,1.943,2.041,2.688,2.582c0.746,0.542,0.845,1.77,0.221,2.729
|
||||
l-3.263,5.649c-0.52,1.019-1.633,1.547-2.473,1.173c-0.841-0.374-2.45-0.84-3.577-1.035l-1.006-0.175
|
||||
c-1.127-0.196-2.375,0.522-2.771,1.595l-1.762,5.455c-0.306,1.102,0.285,2.417,1.312,2.921l0.899,0.442
|
||||
c1.027,0.504,2.602,1.074,3.5,1.265c0.899,0.19,1.487,1.271,1.306,2.401c0,0-0.784,4.917-0.784,8.557c0,0.003,0,0.003,0,0.003
|
||||
c0,0.003-0.751,0.007-1.671,0.007s-2.579,0.23-3.688,0.509L66.496,77.1c-1.109,0.28-1.958,1.442-1.887,2.585l0.59,5.706
|
||||
c0.166,1.132,1.237,2.094,2.38,2.136l1.001,0.038c1.144,0.043,2.814-0.078,3.713-0.269c0.898-0.19,1.877,0.556,2.175,1.661
|
||||
l2.015,6.206c0.412,1.067,0.062,2.247-0.778,2.621c-0.84,0.373-2.263,1.258-3.163,1.964l-0.796,0.625
|
||||
c-0.9,0.706-1.2,2.114-0.667,3.128l2.872,4.962c0.615,0.966,1.986,1.405,3.049,0.981l0.926-0.372
|
||||
c1.062-0.426,2.541-1.217,3.287-1.758c0.746-0.542,1.945-0.258,2.665,0.63l4.365,4.848c0.808,0.81,0.966,2.031,0.35,2.718
|
||||
c-0.616,0.684-1.557,2.069-2.091,3.083l-0.463,0.877c-0.534,1.011-0.239,2.424,0.655,3.137l4.633,3.376
|
||||
c0.951,0.637,2.38,0.487,3.178-0.334l0.708-0.729c0.797-0.82,1.826-2.144,2.287-2.941c0.46-0.799,1.67-1.025,2.689-0.503
|
||||
l5.959,2.653c1.066,0.412,1.708,1.462,1.426,2.336c-0.285,0.874-0.579,2.522-0.655,3.664l-0.068,1.011
|
||||
c-0.076,1.142,0.769,2.308,1.877,2.59l5.611,1.182c1.129,0.188,2.374-0.536,2.769-1.61l0.343-0.933
|
||||
c0.396-1.074,0.797-2.701,0.892-3.614c0.097-0.915,1.108-1.59,2.249-1.5c0,0,1.458,0.114,3.26,0.114
|
||||
c1.805,0,3.271-0.114,3.271-0.114c1.142-0.09,2.152,0.583,2.249,1.498c0.096,0.912,0.497,2.54,0.893,3.614l0.343,0.933
|
||||
c0.395,1.074,1.641,1.798,2.769,1.61l5.61-1.182c1.109-0.283,1.954-1.449,1.876-2.59l-0.066-1.009
|
||||
c-0.076-1.144-0.373-2.792-0.655-3.666c-0.284-0.875,0.356-1.927,1.424-2.337l5.96-2.656c1.018-0.521,2.228-0.296,2.688,0.502
|
||||
c0.459,0.798,1.488,2.121,2.286,2.941l0.709,0.731c0.798,0.82,2.227,0.968,3.177,0.334l4.633-3.379
|
||||
c0.895-0.716,1.188-2.126,0.654-3.137l-0.462-0.877c-0.533-1.011-1.477-2.399-2.092-3.083c-0.616-0.687-0.46-1.908,0.349-2.718
|
||||
l4.364-4.847c0.719-0.891,1.918-1.176,2.664-0.635c0.744,0.542,2.223,1.334,3.286,1.758l0.927,0.372
|
||||
c1.062,0.426,2.434-0.016,3.049-0.979l2.87-4.965c0.532-1.013,0.232-2.419-0.668-3.125l-0.795-0.626
|
||||
c-0.899-0.706-2.323-1.592-3.163-1.966s-1.191-1.554-0.778-2.621l2.012-6.206C173.528,87.844,174.506,87.095,175.403,87.286z"/>
|
||||
</svg>
|
||||
|
||||
<svg class="hide" version="1.1" id="svggreenland" 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="M172.189,76.894c-0.651,0.691-2.171,0.642-3.206,0.797c-0.596,0.087-1.085,0.335-1.678,0.422
|
||||
c-0.75,0.111-1.668-0.134-2.337,0.133c0.275,0.186,0.555,0.276,0.84,0.27c-0.22,0.446-1.029,0.344-1.575,0.335
|
||||
c-0.67-0.016-1.193,0.186-1.808,0.273c-1.274,0.18-2.74-0.13-4.092-0.149c-0.53-0.006-0.801,0.35-1.287,0.434
|
||||
c-0.604,0.102-1.296,0.062-1.979,0.006c-1.745-0.139-3.273-0.006-4.852,0.183c1.095,0.127,1.975-0.118,2.954-0.205
|
||||
c0.875-0.074,1.857,0.074,2.797,0.164c2.257,0.217,4.241-0.288,6.573,0.174c-1.358,0.654-2.937,0.788-4.729,0.806
|
||||
c-1.193,0.009-2.533-0.254-3.695-0.195c-0.8,0.041-1.38,0.397-2.155,0.471c0.794,0.137-0.183,0.409-0.418,0.617
|
||||
c0.657-0.022,0.958,0.263,1.605,0.056c-0.821,0.133,0.258-0.456,0.543-0.515c0.555-0.115,1.19-0.103,1.811-0.093
|
||||
c1.169,0.019,2.533-0.635,3.882,0.105c-1.253,0.515-2.348,0.654-3.956,0.624c-0.887-0.019-0.89,0.313-1.451,0.573
|
||||
c-0.195,0.09,0.167,0.192,0.09,0.307c-0.111,0.18-0.279,0.326-0.499,0.434c0.666,0.049,0.921-0.366,1.792-0.192
|
||||
c-0.195,0.292-0.385,0-0.707,0.084c-0.267,0.068-0.348,0.282-0.614,0.35c-0.418,0.108-0.8-0.019-0.911,0.341
|
||||
c-0.121,0.387-0.871,0.248-1.37,0.189c-0.556-0.068-1.032,0.118-1.491,0.202c1.026,0.074-0.258,0.362-0.416,0.434
|
||||
c0.232-0.087,0.496-0.05,0.791,0.108c-0.248,0.09-0.837,0.359-0.731,0.645c0.167,0.446-0.58,0.381-0.971,0.409
|
||||
c0.254,0.019,0.505,0.037,0.76,0.056c-0.593,0.26-1.163,0.558-1.51,1.001c0.181,0,1.371,0.042,1.148,0.226
|
||||
c0.434-0.215,0.578-0.676,1.108-0.846c0.533-0.17,1.125,0.043,1.764,0.118c0.134,0.015,0.327,0.024,0.541,0.035
|
||||
c-0.269-0.055-0.539-0.119-0.808-0.211c0.633-0.081,2.053-0.068,2.729,0.406c-0.084-0.005-0.168-0.01-0.251-0.014
|
||||
c0.397,0.09,0.74,0.225,0.911,0.448c-1.447,0.09-3.175-0.465-4.479-0.108c0.449-0.041,1.104,0.031,1.603,0.245
|
||||
c-0.146-0.021-1.364-0.031-0.359,0.109c-0.462,0.059-1.002-0.075-1.482-0.056c0.794,0.103,1.56,0.105,2.362,0.245
|
||||
c-0.028,0.006-0.062,0.004-0.092,0.008c0.447-0.001,0.89,0.038,1.187,0.203c0.366,0.201,0.831,0.416,1.166,0.208
|
||||
c0.679-0.421,3.045,0.068,2.154,0.946c-0.449,0.45-2.089,0.09-2.88-0.034c-1.259-0.192-2.747-0.434-3.776-0.14
|
||||
c0.229-0.043,0.483-0.019,0.757,0.081c-0.238,0.155-0.595,0.158-0.979,0.127c0.132,0.02,0.264,0.043,0.401,0.09
|
||||
c-0.552,0.155-1.259,0.515-1.996,0.366c-0.413-0.083-0.8-0.496-1.24-0.462c-0.189,0.016-0.819,0.363-0.905,0.478
|
||||
c0.288,0.019,0.579,0.17,0.769,0.378c0.124-0.394,1.33-0.146,0.686-0.056c0.214-0.074,0.462-0.056,0.744,0.056
|
||||
c-0.224,0.034-0.44,0.077-0.648,0.136c0.22-0.05,0.462-0.068,0.723-0.056c-0.446,0.232-1.303-0.14-1.702,0.136
|
||||
c0.558-0.012,1.28-0.152,1.916,0.161c-0.05,0.103-0.103,0.202-0.161,0.298c0.549,0.09,0.908-0.152,1.451-0.081
|
||||
c0.515,0.068,1.051,0.369,1.54,0.325c-0.533-0.09-1.075-0.332-1.611-0.406c0.312-0.056,0.667-0.029,1.029,0.011
|
||||
c-0.197-0.048-0.394-0.088-0.593-0.147c0.245,0.011,0.498,0.082,0.75,0.162c0.436,0.052,0.877,0.117,1.274,0.095
|
||||
c0.657-0.037,1.256,0.493,0.432,0.484c-0.475-0.006-0.901,0.084-1.343,0.156c0.807,0.056,1.61,0.223,2.347,0.646
|
||||
c-0.087,0.053-0.174,0.108-0.26,0.161c0.629,0.245,0.691,0.85,0.437,1.11c-0.264,0.272-0.877,0.232-1.383,0.108
|
||||
c0.224-0.527-1.984-0.351-2.428-0.487c-0.89-0.276-2.093-0.915-2.855-0.651c0.54,0.083,1.11,0.118,1.628,0.462
|
||||
c-0.518-0.1-0.974-0.034-1.473-0.081c1.293,0.251,2.602,0.121,3.879,0.865c-0.71,0.217-1.659,0.071-2.385,0.282
|
||||
c-0.691,0.192-1.199-0.279-1.912-0.307c0.703,0.056,1.156,0.571,1.891,0.443c0.713-0.133,1.314-0.313,2.161-0.226
|
||||
c-0.158,0.22-0.499,0.511,0.04,0.784c-0.254,0.152-0.62,0.183-0.979,0.199c0.735,0.081,1.38-0.295,2.151-0.043
|
||||
c0.775,0.254,1.266-0.009,1.947-0.031c0.016,0.316,0.53,0.468,0.865,0.447c-0.57,0.257-0.998,0.629-1.82,0.573
|
||||
c-0.288-0.019-0.583,0.006-0.88-0.081c-0.264-0.074-0.574-0.394-0.847-0.394c-0.896,0-1.798-0.034-2.691-0.019
|
||||
c-0.471,0.006-0.861-0.341-1.271-0.304c0.285,0.078,0.561,0.229,0.74,0.422c-0.396,0.22-1.026,0.297-1.618,0.22
|
||||
c0.279,0.021,0.546,0.102,0.8,0.248c-0.077,0.316-0.552,0.226-0.896,0.297c1.094,0.223,1.37,0.208,1.562,0.989
|
||||
c0.778-0.118-0.81-0.937,0.316-0.946c1.007-0.006,2.198,0.381,3.249,0.403c0.062,0.291-0.338,0.394-0.412,0.632
|
||||
c-0.105,0.35,0.248,0.391-0.45,0.431c-0.85,0.049-1.637-0.143-2.35,0.111c-1.736,0.62-3.37,0.103-5.513-0.508
|
||||
c0.062-0.468,1.072-0.267,1.597-0.158c0.955,0.198,1.711,0.313,2.521,0.108c-0.971,0.016-1.699,0.003-2.737-0.205
|
||||
c-0.698-0.143-1.612-0.359-2.093-0.065c-0.372,0.229-0.633,0.642-1.374,0.294c-0.471-0.223-1.413-0.859-1.882-0.667
|
||||
c0.623,0.391,1.634,0.66,2.325,0.939c-0.545,0.043-1.178-0.003-1.612,0.192c-0.428,0.189-0.669,0.403-1.265,0.431
|
||||
c-0.645,0.028-1.392-0.18-2.068-0.22c-0.514-0.031-1.19-0.524-1.611-0.304c0.747,0.146,1.491,0.412,2.204,0.397
|
||||
c-0.264,0.313-0.555,0.381-1.172,0.267c-0.53-0.103-0.939,0.068-1.43,0.053c0.478-0.009,0.694,0.406,0.311,0.496
|
||||
c0.425,0.034,0.502-0.254,0.771-0.378c0.372-0.167,1.11-0.021,1.572-0.124c0.666-0.149,1.305-0.037,2.086,0.105
|
||||
c0.487,0.09,0.943-0.009,1.442,0.174c-0.189,0.341-0.747,0.307-1.231,0.347c-0.471,0.037-0.809,0.245-1.283,0.279
|
||||
s-1.001-0.205-1.485-0.205c-0.539,0-1.051,0.053-1.603,0.025c0.766,0.254,1.389,0,2.143,0.173c-0.189,0.078-0.403,0.127-0.636,0.149
|
||||
c0.354,0,0.716,0.009,1.051-0.025c-0.059,0.093-0.124,0.183-0.192,0.273c0.623-0.214,3.061-1.014,3.91,0.013
|
||||
c0.459,0.558-2.288,0.465-2.604,0.456c0.385,0.118,0.707,0.041,1.054,0.05c0.022,0.201-0.077,0.372-0.267,0.471
|
||||
c0.784-0.078,1.032-0.704,2.034-0.471c0.589,0.139,1.628,0.583,2.124,0.396c0.117,0.385,0.84,0.254,1.383,0.533
|
||||
c0.452,0.233,1.02,0.031,1.568,0.335c-0.418,0.041-1.256,0.208-1.243,0.592c0.372-0.117,0.753-0.354,1.274-0.223
|
||||
c-0.239,0.034-0.359,0.161-0.229,0.372c0.396-0.307,0.942-0.332,1.554-0.322c-0.85,0.137-1.414,0.369-1.237,1.092
|
||||
c0.518-0.41,0.914-0.559,1.845-0.372c-0.438,0.065-0.409,0.13,0.077,0.198c-0.183,0.071-0.385,0.121-0.604,0.148
|
||||
c0.248-0.037,0.446,0.057,0.521,0.273c-0.409-0.162-0.883,0.186-1.19,0.244c0.329,0.01,0.639-0.024,0.955-0.049
|
||||
c-0.071,0.084-0.143,0.167-0.214,0.248c0.217-0.034,0.449-0.028,0.701,0.024c-0.264,0.099-0.248,0.524-0.701,0.372
|
||||
c0.248,0.043,0.496,0.111,0.738,0.199c-0.276-0.016-0.425,0.117-0.403,0.322c0.868-0.105-0.028,0.924-0.509,0.369
|
||||
c-0.275-0.314-1.534,0.223-1.146-0.816c-0.747-0.31-0.195,0.57-0.376,0.757c-0.278,0.298-1.444,0.081-1.925-0.024
|
||||
c-0.858-0.193-1.705-0.326-1.876-1.095c-0.093-0.419-1.014-1.023-1.553-0.986c-0.939,0.065-1.777-0.495-2.731-0.558
|
||||
c-0.348-0.021-0.754-0.171-1.082-0.148c-0.248,0.018-0.366,0.158-0.599,0.188c-0.564,0.068-1.541-0.58-2.14-0.788
|
||||
c-0.8-0.282-1.516-0.359-2.354-0.639c0.354,0.109,0.524,0.307,0.376,0.496c0.449-0.012,0.917-0.015,1.407,0.075
|
||||
c-0.934-0.09,0.937,0.403,1.2,0.443c-0.075,0.153-0.278,0.237-0.534,0.288c0.245,0.006,1.548,0.002,0.757,0.184
|
||||
c0.701,0,1.442,0.102,2.143,0.107c0.422,0.007,0.8-0.102,1.253-0.018c0.26,0.049,0.731,0.17,0.868,0.406
|
||||
c0.251,0.418-0.546,0.053-0.571,0.226c-0.08,0.593-2.188,0.7-2.954,0.714c-0.406,0.006-0.952,0.102-1.396-0.152
|
||||
c-0.282-0.164-0.57-0.416-0.884-0.344c0.131,0.188,0.369,0.338,0.627,0.396c-0.425,0.123-1.135,0.096-1.678-0.025
|
||||
c1.433,0.348,0.391,0.599,0.065,0.949c-0.329,0.354-1.427,0.375-2.071,0.338c0.438,0.223,1.417,0.034,1.742-0.068
|
||||
c0.276-0.087,0.276,0.229,0.596,0.254c0.338,0.025,0.636-0.021,0.945-0.049c0.02-0.002,0.045-0.006,0.065-0.008
|
||||
c-0.244-0.02-0.489-0.062-0.735-0.154c0.267-0.064,0.189-0.347,0.465-0.394c0.192-0.028,0.379-0.059,0.562-0.096
|
||||
c0.567-0.14,0.964-0.456,1.581-0.549c0.651-0.097,1.321-0.022,1.926-0.204c0.356-0.112,0.747-0.225,1.188-0.218
|
||||
c-0.01,0.075-0.016,0.149-0.021,0.224c0.399-0.047,1.215,0.471,0.576,0.521c0.14,0.074,0.276,0.149,0.412,0.224
|
||||
c-1.078,0.362-2.378,0.285-3.615,0.381c-0.026,0.002-0.054,0.007-0.079,0.01c0.418,0.01,0.821,0.079,1.152,0.275
|
||||
c-0.362,0.311-0.967,0.177-1.525,0.224c-0.412,0.034-0.738,0.198-1.061,0.338c-0.521,0.229-1.854,0.285-2.576,0.204
|
||||
c0.57,0.205,1.581,0.208,2.064,0.134c0.556-0.084,0.894,0.255,1.297-0.158c0.515-0.54,1.624-0.226,2.468-0.369
|
||||
c0.645-0.111,1.196-0.437,1.978-0.322c-0.046,0.093-0.103,0.183-0.161,0.272c0.636-0.136,1.15-0.17,1.922,0.09
|
||||
c0.646,0.221,1.256,0.112,1.892,0.252c0.726,0.158,1.56,0.18,2.214,0.114c0.381-0.04,0.995-0.204,1.426,0.087
|
||||
c-0.446,0.312-1.785,0.44-2.455,0.478c0.227-0.022,0.449,0.024,0.673,0.14c-0.285,0.143-0.683-0.053-1.014-0.14
|
||||
c0.297,0.425-0.928,0.276-1.203,0.257c0.526-0.002,0.756,0.292,0.384,0.479c-0.248,0.12-0.924-0.041-1.277-0.06
|
||||
c0.825,0.118-0.006,0.385-0.241,0.403c-0.298,0.019-0.633,0.006-0.952-0.053c0.66,0.428-0.558,0.27,0.27,0.372
|
||||
c-0.391,0.111-1.022-0.235-1.265,0.071c0.58-0.065,0.369,0.235,0.134,0.272c-0.354,0.056-0.636-0.226-0.354,0.192
|
||||
c-0.369-0.093-1.34,0.09-0.586,0.071c-0.577,0.103-0.847,0.512-1.504,0.512c-0.311,0-0.348,0.226-0.604,0.285
|
||||
c-0.341,0.077-0.757-0.016-1.095,0.077c-0.465,0.127-0.961,0.041-1.398,0.174c-0.27,0.084-1.011,0.245-1.357-0.021
|
||||
c0.105,0.227-0.087,0.35-0.4,0.248c-0.351-0.111-0.493,0.049-0.729,0.124c-0.44,0.136-1.001,0.278-1.594,0.046
|
||||
c0.348,0.472-0.893,0.373-1.222,0.289c-0.167-0.041-0.797-0.416-0.787-0.158c0.013,0.304-0.366,0.152-0.651,0.195
|
||||
c0.261,0.003,0.506,0.137,0.633,0.328c-0.288,0.016-0.536,0.094-0.871-0.018c-0.304-0.1-0.533-0.299-0.856-0.311
|
||||
c0.264,0.077,0.493,0.201,0.683,0.375c-0.704,0.117-1.464,0.062-2.227,0.064c-0.412,0-1.066-0.328-0.439-0.368
|
||||
c-0.63-0.151-0.992,0.013-1.327-0.562c-0.323,0.242-0.493-0.133-0.694-0.372c0.074,0.255-0.354,0.202-0.158,0.472
|
||||
c0.13,0.18,0.61,0.248,0.809,0.391c-0.158,0.09-0.359,0.115-0.604,0.071c0.335,0.136,0.772,0.09,0.952,0.419
|
||||
c-0.406-0.068-0.202,0.217-0.242,0.384c-0.05,0.211-0.8,0.047-1.042,0.128c-0.359,0.12-1.032,0.223-1.305,0.387
|
||||
c-0.227,0.133-0.164,0.412-0.63,0.313c0.189,0.257,0.056,0.552-0.372,0.421c0.348,0.273-0.102,0.271-0.037,0.521
|
||||
c0.078,0.316-1.433,0.174-0.766,0.502c-0.483-0.13-0.385,0.242-0.198,0.469c-0.409-0.192-0.683,0.318-0.878,0.418
|
||||
c0.214-0.496-0.108,0.162-0.301-0.371c-0.198,0.099-0.217,0.285,0.078,0.465c-0.245,0.033-1.575,0.977-1.733,0.303
|
||||
c-0.223,0.104-0.201,0.283,0.127,0.443c-0.31-0.002-0.647-0.033-0.977-0.129c-0.412-0.121-0.546-0.49-0.831-0.268
|
||||
c0.519,0.121,0.363,0.4,0.654,0.654c-0.48,0.078-0.617-0.021-0.905,0.273c-0.217,0.223-0.713,0.086-0.971,0.26
|
||||
c0.022-0.186-0.167-0.354-0.446-0.418c0.189,0.514-0.893,0.232-1.014,0.582c-0.248-0.167-0.27-0.35-0.118-0.465
|
||||
c-0.592-0.037,0.1,0.555-0.415,0.509c-0.378-0.031-1.156-0.362-1.38-0.183c-0.14-0.521,0.862-0.971,1.451-1.002
|
||||
c-0.734-0.006-1.538-0.18-2.264-0.164c0.242,0.105,0.484,0.168,0.723,0.186c-0.254,0.094-0.121,0.403-0.412,0.443
|
||||
c-0.359,0.047,0.124,0.184,0.024,0.305c-0.164,0.201-0.781,0.402-1.048-0.072c-0.214,0.292,0.366,0.416,0.686,0.516
|
||||
c-0.04,0.533-0.596,0.25-0.815,0.536c-0.108-0.394-0.248-0.202-0.645-0.211c0.13,0.077,0.26,0.155,0.391,0.232
|
||||
c-0.559,0.028-1.104-0.151-1.702-0.304c0.394,0.26,0.062,0.465-0.252,0.422c-0.204-0.028-0.319-0.32-0.555-0.335
|
||||
c-0.298-0.016-0.177,0.344-0.425,0.375c-0.312,0.04-0.766-0.271-0.691,0.146c0.264,0.043,0.527,0.1,0.797,0.164
|
||||
c-0.087,0.044-0.17,0.09-0.251,0.14c0.118,0.081,0.235,0.158,0.359,0.233c-0.499-0.105-0.431,0.31-0.865,0.257
|
||||
c0.744,0.22-0.248,0.384-0.474,0.315c-0.184-0.052-0.503-0.275-0.673-0.229c-0.235,0.064-0.942-0.068-0.992,0.161
|
||||
c-0.034,0.151,0.13,0.251-0.164,0.282c0.496,0.394,1.454,0.586,1.116,1.092c0.235,0.009,0.424,0.114,0.523,0.287
|
||||
c-0.388,0.094-0.84-0.148-1.243-0.009c-0.412,0.143-1.179-0.121-1.398,0.211c0.593,0.369,1.141,0.188,1.693,0.226
|
||||
c0.688,0.047,0.483,0.481,0.096,0.531c0.475,0.084,0.311,0.354,0.499,0.576c-0.478-0.117-0.865,0.016-1.339-0.084
|
||||
c-0.369-0.074-1.015-0.341-1.179-0.07c0.443-0.078,1.671,0.136,2.006,0.579c-0.121,0.024-0.598-0.111-0.636-0.003
|
||||
c-0.056,0.174-0.154,0.205-0.443,0.047c0.841,0.514-0.245,0.027-0.399-0.044c0.217,0.248,0.148,0.298-0.211,0.155
|
||||
c0.26,0.086,0.512,0.198,0.75,0.334c-0.347-0.129-0.694-0.275-1.051-0.355c0.121,0.046,1.203,0.514,1.116,0.586
|
||||
c-0.227,0.191-1.398-0.426-1.718-0.518c0.025,0.455,0.884,0.176,0.958,0.691c0.038,0.272-0.853-0.137-1.048-0.137
|
||||
c0.251,0.059,0.493,0.198,0.627,0.378c-0.289,0.084-1.029-0.103-1.309-0.356c-0.059,0.567,1.082,0.186,1.212,0.67
|
||||
c-0.188-0.062-0.567,0.148-0.757,0.18c-0.468,0.077-0.026,0.05-0.098,0.125c0.011,0.001,0.022,0.003,0.033,0.005
|
||||
c-0.028,0.011-0.061,0.019-0.089,0.028c-0.042,0.02-0.102,0.042-0.2,0.071c-0.013,0.004-0.03,0.003-0.043,0.007
|
||||
c-0.189,0.055-0.389,0.098-0.621,0.095c-0.002,0-0.004,0.001-0.006,0.001c-0.001,0-0.001,0-0.002,0
|
||||
c-0.008-0.066,0.012-0.113,0.042-0.151c0.004-0.005,0.007-0.009,0.011-0.013c0.067-0.072,0.194-0.1,0.346-0.1
|
||||
c0.008,0,0.015,0,0.022,0c0.072,0.001,0.147,0.006,0.224,0.015c-0.401-0.165-0.707-0.12-1.088-0.173
|
||||
c0.434,0.08,0.444,0.117,0.028,0.108c0.093,0.074,0.14,0.148,0.137,0.226c-0.028,0.097-0.22,0.104-0.348,0.104
|
||||
c-0.334-0.004-0.753-0.06-1.116-0.171c0.323,0.186,0.946,0.452,1.281,0.431c0.347-0.025,0.946,0.304,0.319,0.214
|
||||
c0.229,0.09,0.461,0.174,0.694,0.245c-0.526,0.152-1.298-0.267-1.906-0.312c0.391,0.173,1.206,0.263,1.514,0.526
|
||||
c0.391,0.338-0.208,0.647-0.404,0.788c0.199-0.051,0.406-0.097,0.617-0.134c0.193,0.192,0.134,0.304-0.148,0.267
|
||||
c0.815,0.552-0.936,0.311-1.209,0.312c0.416,0.174,0.927,0.332,1.219,0.156c-0.232,0.08-0.211,0.328-0.453,0.396
|
||||
c-0.313,0.09-0.955-0.028-1.342-0.084c0.418,0.248,0.843,0.154,1.215,0.154c0.49,0.721-1.001,0.487-1.532,0.443
|
||||
c0.214,0.051,1.376,0.1,0.726,0.246c0.189,0.006,0.375,0,0.549-0.021c-0.105,0.281-0.778,0.111-1.128,0.111
|
||||
c0.325,0.043,0.654,0.086,0.989,0.154c-0.478,0.279-1.386-0.003-2.028,0.025c0.667,0.167,1.504,0.27,2.071,0.176
|
||||
c-0.292,0.097-0.232,0.379-0.608,0.406c-0.353,0.028-0.763-0.024-1.163-0.117c0.558,0.201,1.079,0.174,1.628,0.312
|
||||
c-0.381,0.149-0.999,0.004-1.488-0.046c0.428,0.103,0.815,0.056,1.247,0.18c0.118,0.391-0.524,0.248-0.872,0.224
|
||||
c0.462,0.108,0.81,0.09,1.129-0.047c-0.087,0.236-0.425,0.242-0.766,0.201c0.211,0.037,0.419,0.06,0.624,0.065
|
||||
c-0.323,0.103-0.72,0.155-1.15,0.068c0.822,0.208-0.453,0.241-0.806-0.202c-0.118,0.279-0.719,0.143-1.101,0.047
|
||||
c0.558,0.227,1.085,0.205,1.637,0.335c-0.043,0.161-0.165,0.294-0.338,0.378c0.267-0.053,0.481-0.167,0.766-0.201
|
||||
c-0.505,0.115,0.13,0.124,0.391,0.379c-0.217-0.022-0.4,0.009-0.54,0.09c0.202-0.041,0.394,0.046,0.53,0.223
|
||||
c-0.133,0.082-0.307,0.092-0.497,0.073c0.019,0.006,0.034,0.014,0.052,0.021c0.018,0.006,0.033,0.013,0.05,0.02
|
||||
c0.043,0.018,0.088,0.035,0.123,0.055c0.062,0.035,0.113,0.074,0.142,0.121c-0.288,0.006-0.599-0.103-0.902-0.177
|
||||
c0.018,0.024,0.017,0.04,0.029,0.062c0.021,0.039,0.044,0.078,0.05,0.107c0.003,0.015-0.003,0.025-0.004,0.039
|
||||
c-0.002,0.026-0.008,0.051-0.026,0.067c-0.012,0.013-0.029,0.021-0.047,0.029c-0.016,0.006-0.031,0.012-0.05,0.015
|
||||
c-0.074,0.018-0.166,0.022-0.287,0.002c-0.179-0.03-0.482-0.072-0.512-0.131c-0.014-0.005-0.031-0.01-0.043-0.014
|
||||
c0.02-0.007,0.039-0.014,0.058-0.021c0.026-0.021,0.083-0.042,0.19-0.066c0.004-0.001,0.008-0.003,0.012-0.004
|
||||
c-0.025,0.001-0.052-0.007-0.078-0.008c-0.13-0.003-0.261-0.03-0.395-0.077c-0.064-0.021-0.128-0.038-0.194-0.07
|
||||
c0.002-0.003,0.011-0.005,0.014-0.008c0.083-0.127,0.242-0.171,0.479-0.125c-0.18-0.021-0.36-0.043-0.542-0.068
|
||||
c0.105-0.117,0.13-0.267,0.077-0.443c0.019,0.229-0.146,0.258-0.44,0.068c0.217,0.385-0.192,0.291-0.416,0.443
|
||||
c-0.09,0.062-0.608,0.719-0.558,0.155c0,0.229-0.251,0.304-0.478,0c-0.083,0.173-0.322,0.157-0.574-0.022
|
||||
c0.422-0.387,1.079-0.582,1.495-1.001c-0.58,0.14-1.048,0.617-1.532,0.868c-0.102-0.344,0.391-0.469,0.567-0.676
|
||||
c0.177-0.205,0.167-0.506,0.434-0.66c-0.617,0.064-0.657,0.619-1.367,0.602c0.037-0.164,0.155-0.298,0.329-0.379
|
||||
c-0.267,0.078-0.474,0.215-0.741,0.291c0.102-0.21,0.307-0.368,0.617-0.424c-0.49-0.034-0.698,0.207-0.887,0.446
|
||||
c-0.161-0.388-0.62-0.14-0.177-0.378c-0.344-0.028-0.391,0.264-0.775,0.176c0.223-0.105,0.458-0.204,0.729-0.266
|
||||
c-0.67,0,0.177-0.336,0.344-0.41c0.232-0.107,0.793,0.004,0.347-0.347c-0.298,0.232-0.592,0.592-1.153,0.577
|
||||
c0.074-0.057,0.146-0.115,0.214-0.178c-0.527-0.143-0.54,0.391-1.045,0.202c0.174-0.155,0.468-0.202,0.713-0.292
|
||||
c-0.214-0.016-0.396,0.016-0.542,0.09c0.502-0.502,1.913-0.198,2.173-0.89c-0.235,0.146-0.378,0.316-0.62-0.046
|
||||
c0.013,0.529-0.8,0.505-1.249,0.713c-0.133-0.396,0.595-0.289,0.713-0.559c-0.124-0.049-0.245-0.102-0.369-0.154
|
||||
c0.056-0.078,0.121-0.152,0.189-0.224c-0.329-0.021-0.416,0.251-0.803,0.134c0.673,0.086,0.056,0.536-0.434,0.402
|
||||
c0.515,0.118,0.369,0.199,0.149,0.268c-0.403-0.521-1.026,0.127-1.42,0.09c0.341,0.318-0.105,0.381-0.44,0.22
|
||||
c0.062-0.068,0.13-0.134,0.199-0.198c-0.729-0.072-1.371,0.009-2.025,0.064c0.338,0.103,0.614,0.047,0.893,0.025
|
||||
c-0.104,0.152-0.501,0.197-0.927,0.2c0.03,0.008,0.058,0.01,0.089,0.02c-0.021,0.331-0.626,0.413-1.032,0.024
|
||||
c0.086-0.024,0.177-0.047,0.271-0.064c-0.145-0.009-0.279-0.019-0.376-0.025c0.351-0.198,0.834-0.266,1.228-0.424
|
||||
c-0.48,0-0.939,0.037-1.414,0.046c0.248-0.136,1.293,0.044,1.088-0.378c-0.248,0.074-0.527,0.183-0.856-0.111
|
||||
c0.248-0.1,0.341-0.332,0.688-0.336c-0.769-0.105-0.527,0.496-1.008,0.469c0.041-0.074,0.084-0.148,0.127-0.223
|
||||
c-0.183,0.07-0.577,0.176-0.71-0.156c0.242,0.022,0.412-0.03,0.505-0.154c-0.478-0.111-1.166-0.254-1.43-0.025
|
||||
c0.162-0.391,0.992-0.355,1.529-0.399c-0.381,0-0.397-0.031-0.053-0.09c-0.698-0.028-1.197,0.44-2.046,0.046
|
||||
c0.211-0.257,0.937-0.133,1.336-0.201c-0.298-0.006-0.567,0.037-0.88,0c0.031-0.164,0.146-0.297,0.319-0.378
|
||||
c-0.14,0.093-0.323,0.136-0.549,0.134c-0.09-0.299,0.409-0.496,0.704-0.556c-0.729-0.211-0.589,0.475-1.101,0.512
|
||||
c0.019-0.084,0.041-0.165,0.059-0.245c-0.502,0.307-0.056-0.285,0.136-0.365c0.232-0.094,0.521-0.174,0.837-0.171
|
||||
c-0.229,0.013-0.394-0.087-0.44-0.267c-0.282,0.068-0.264,0.328-0.54,0.4c-0.254,0.067-0.629-0.047-0.846,0.067
|
||||
c0.201-0.13,0.3-0.183-0.143-0.245c0.205-0.154,0.636,0.037,0.853-0.111c-0.22-0.037-0.431-0.053-0.629-0.043
|
||||
c0.059-0.146,0.226-0.236,0.487-0.202c-0.292-0.05-2.301-0.232-2.208-0.71c0.077-0.406,0.685-0.57,0.958-0.871
|
||||
c-0.242,0.18-0.543,0.351-0.967,0.356c0.118-0.226,0.347-0.394,0.601-0.533c-0.394-0.028-0.493,0.224-0.707,0.356
|
||||
c0.037-0.174,0.108-0.328,0.21-0.468c-0.093,0.148-0.759,0.059-0.685-0.174c0.056-0.177,0.694-0.292,0.912-0.362
|
||||
c-0.356,0.006-0.716,0.006-1.061,0.031c-0.164,0.009-1.029,0.241-0.453-0.053c-0.127,0.102-0.793,0.012-0.626-0.187
|
||||
c0.094-0.113,0.33-0.133,0.597-0.134c-0.282-0.027-0.575-0.185-0.848-0.17c0.289-0.14,0.71-0.143,1.039-0.245
|
||||
c-0.27,0.03-0.552,0.046-0.84,0.046c-0.075-0.402,0.905-0.201,1.23-0.312c-0.421,0.025-1.593-0.133-1.448,0.335
|
||||
c-0.292-0.181-1.138-0.403-0.561-0.49c-0.794,0.128,0.403-0.151,0.499-0.177c0.261-0.074,0.434-0.22,0.694-0.291
|
||||
c-0.322,0.056-0.672,0.27-1.134,0.09c0.155-0.164,0.006-0.307-0.351-0.379c0.713,0.115,1.401-0.055,1.907-0.223
|
||||
c0.229-0.074,1.342-0.146,1.625,0c-0.279-0.381-0.793-0.111-1.113-0.155c0.139-0.105,0.267-0.214,0.381-0.335
|
||||
c-0.53,0.41-1.848,0.915-2.998,0.533c0.133-0.086,0.31-0.13,0.527-0.133c-0.223-0.016-0.443-0.028-0.667-0.043
|
||||
c0.602-0.137,1.6,0.201,2.003-0.156c-0.837-0.17,0.242-0.331,0.508-0.322c0.413,0.02,0.937,0.09,1.051-0.191
|
||||
c-0.239,0.108-1.38-0.021-0.726-0.134c-0.254-0.074-0.508-0.158-0.763-0.245c0.124-0.019,1.42-0.009,0.533-0.133
|
||||
c0.512-0.174,0.632,0.198,1.073,0.468c0.384,0.235,0.89,0.295,1.296,0.4c-0.211-0.45-1.594-0.466-0.89-0.89
|
||||
c-0.639,0.183-0.149-0.336-0.006-0.4c-0.409,0.124-0.887,0.543-1.532-0.04c-0.051-0.046-0.101-0.101-0.147-0.157
|
||||
c0.017,0.036,0.039,0.062,0.051,0.107c0.118,0.434-0.676,0.754-1.255,0.691c0.046-0.152,0.18-0.267,0.388-0.313
|
||||
c-1.377-0.351-1.001,1.349-2.18,1.293c-0.13-0.158-0.422-1.106-0.304-1.209c0.228-0.192,0.685-0.334,1.137-0.45
|
||||
c0.052-0.052,0.101-0.107,0.141-0.167c-0.508-0.217-0.713,0.178-1.003,0.358c-0.086,0.012-0.336,0.032-0.402-0.166
|
||||
c-0.003-0.1,0.078-0.143,0.239-0.127c-0.508-0.4-0.239-0.639,0.006-0.834c-0.133,0.08-0.285,0.148-0.45,0.207
|
||||
c0.025-0.074,0.043-0.151,0.053-0.232c-0.478-0.167-0.493,0.187-0.729,0.279c0.17-0.102,0.006-0.387,0.205-0.465
|
||||
c0.223-0.053,0.431-0.117,0.623-0.198c0.282-0.171,0.642-0.181,0.847-0.415c0.57-0.648,1.993,0.002,2.93-0.134
|
||||
c-0.307,0.021-0.403-0.034-0.282-0.161c-0.518,0.09-1.231-0.174-1.767-0.068c-0.422,0.08-0.871,0.183-1.116,0.409
|
||||
c-0.22,0.204-0.44,0.335-0.843,0.394c-0.198,0.021-0.394,0.05-0.586,0.08c0.155-0.244,0.071-0.307-0.245-0.186
|
||||
c0.133-0.133,0.242-0.281,0.323-0.443c-0.149,0.152-0.289,0.443-0.757,0.279c0.1-0.087,0.853-0.341,0.109-0.279
|
||||
c0.214-0.024,0.263-0.143,0.133-0.325c-0.105,0.27-0.524,0.44-1.088,0.187c0.245,0.002,0.428-0.051,0.542-0.165
|
||||
c-0.164,0.068-0.372,0.084-0.623,0.046c0.372-0.176,0.803-0.27,1.349-0.263c0.074,0,0.713,0.105,0.766,0.067
|
||||
c0.205-0.145,0.267-0.291,0.62-0.331c0.316-0.037,0.822,0.204,0.552-0.195c-0.341,0.093-0.781,0.127-1.066,0.272
|
||||
c-0.397,0.199-0.22-0.053-0.654-0.086c-0.598-0.044-0.952,0.535-1.711,0.186c0.147-0.038,0.276-0.092,0.412-0.141
|
||||
c-0.218,0.074-0.467,0.123-0.809-0.045c0.223,0.012,0.415-0.01,0.577-0.068c-0.217-0.01-0.44-0.035-0.673-0.072
|
||||
c0.552-0.22,1.392-0.22,1.742-0.604c0.06-0.064,0.154-0.1,0.244-0.139c-0.177,0.053-0.348,0.11-0.495,0.185
|
||||
c-0.453,0.229-1.066,0.604-1.916,0.372c0.183-0.301,0.75-0.301,1.203-0.372c-0.065,0.003-1.724,0.103-1.352-0.183
|
||||
c0.174-0.133,0.26-0.348,0.54-0.409c0.121-0.028,1.039,0.03,0.279,0.03c0.502,0.1,1.805,0.031,2.118-0.093
|
||||
c-0.48,0.075-1.733,0.174-2.375-0.232c0.505-0.167,1.268-0.037,1.789-0.187c-0.332-0.018-0.583,0.094-0.974-0.024
|
||||
c0.27-0.062,0.664,0,0.803-0.186c-0.22-0.013-0.446-0.034-0.679-0.068c0.388,0.062,0.626-0.065,0.986-0.044
|
||||
c0.313,0.021,0.691,0.165,0.905,0.044c-0.487-0.077-0.543-0.149-0.177-0.211c-0.479-0.224-1.15-0.11-1.735,0.039
|
||||
c-0.602-0.031-1.167-0.001-1.843-0.179c0.422,0,0.828-0.019,1.228-0.047c-0.341-0.03-0.651,0.016-1.045-0.164
|
||||
c0.319,0.01,0.623-0.012,0.868-0.093c-0.363,0.068-0.769,0.108-1.265-0.046c0.236-0.189,0.747-0.109,1.104-0.187
|
||||
c-0.952-0.022,0.307-0.118,0.391-0.124c0.394-0.031,0.8-0.043,1.19-0.074c0.698-0.057,1.432-0.062,2.127-0.115
|
||||
c0.744-0.056,0.716,0.059,1.429,0.435c0.487,0.257,1.584-0.06,1.959-0.1c-0.912-0.177-1.56,0.48-2.496-0.394
|
||||
c0.307-0.016,0.589-0.062,0.84-0.143c-1.101,0.227-2.552-0.01-3.667,0.214c-0.465,0.097-1.054-0.053-1.513,0.028
|
||||
c-0.391,0.07-0.707,0.211-1.104,0.272c-0.419-0.442,0.312-0.668,0.651-0.776c-0.118,0.022-0.228,0.054-0.373,0.051
|
||||
c-0.418-0.438,0.602-0.273,0.149-0.604c-0.676-0.452,1.547,0.294,0.471-0.325c0.341,0.13,1.023-0.065,0.267-0.047
|
||||
c0.217-0.115,0.533-0.137,0.815-0.189c-0.211,0.013-0.44-0.009-0.691-0.068c0.325-0.059,0.717-0.004,1.117,0.063
|
||||
c-0.134-0.035-0.268-0.071-0.407-0.132c-0.44-0.188-0.607-0.281-1.042-0.281c0.645-0.134,1.56,0.096,2.365,0.257
|
||||
c-0.27-0.111-0.542-0.198-0.815-0.257c0.453-0.14,1.163,0.183,1.73,0.257c0.524,0.068,1.011,0.047,1.466,0.013
|
||||
c0.899-0.074,2.089,0.455,2.948,0.312c-0.933-0.059-1.962-0.439-2.933-0.604c0.229-0.115,0.62-0.02,0.945,0
|
||||
c-0.242-0.068-0.483-0.121-0.722-0.165c0.304-0.03,0.164-0.263,0.366-0.356c0.217-0.1,0.537-0.102,0.75-0.201
|
||||
c-0.648,0.009-1.101,0.279-1.86,0.139c0.273,0.141,0.527,0.195,0.756,0.162c-0.058,0.177-0.311,0.24-0.614,0.265
|
||||
c-0.239,0.245-0.831,0.291-1.302,0.321c0.629-0.273-0.14-0.065-0.45-0.164c0.495-0.035,0.987-0.077,1.458-0.143
|
||||
c-0.29,0.005-0.588-0.004-0.794,0.021c-0.465,0.053-1.705-0.254-1.885,0.027c0.043-0.164,0.223-0.264,0.493-0.258
|
||||
c-0.604-0.096-1.001,0.105-1.55,0.094c0.319-0.143,0.76-0.18,1.16-0.251c0.149-0.024,1.268-0.261,0.462-0.261
|
||||
c0.298-0.146,0.757-0.183,1.203-0.164c-0.239-0.021-0.465-0.031-0.685-0.021c0.276-0.199,0.877,0.016,1.184-0.143
|
||||
c-0.136,0.07-0.294,0.123-0.468,0.164c0.413-0.084,1.023,0.031,1.52,0.062c0.493,0.033,0.722-0.305,1.292-0.156
|
||||
c-0.48-0.325,0.038-0.396,0.267-0.465c-0.422,0.016-0.695,0.221-1.191,0.14c0.016-0.245,0.465-0.214,0.416-0.465
|
||||
c-0.053-0.276,0.093-0.503,0.546-0.422c-0.056,0.062-0.118,0.124-0.18,0.187c0.351-0.02,0.859-0.174,1.185,0.257
|
||||
c0.103-0.114,0.27-0.167,0.505-0.164c-0.248-0.09-0.49-0.143-0.726-0.165c0.143-0.182,0.558-0.083,0.797-0.186
|
||||
c-0.289-0.04-0.549-0.328-0.784-0.328c-0.53,0-0.62,0.348-1.296,0.214c0.313-0.429,0.996-0.837,1.947-0.723
|
||||
c-0.468-0.187-0.89,0-1.265,0c-0.288-0.446,0.527-0.288,0.924-0.232c-0.279-0.149-0.527-0.195-0.744-0.143
|
||||
c0.21-0.276,0.669-0.229,1.184-0.208c-0.053-0.189-0.273-0.332-0.549-0.35c0.121-0.125,0.48-0.141,0.478-0.336
|
||||
c-0.855-0.024-1.46,0.255-2.356,0.171c0.177-0.05,0.363-0.09,0.558-0.12c-0.536-0.255-0.735,0.023-0.995,0.12
|
||||
c-0.103,0.034-0.483-0.062-0.62-0.081c-0.837-0.107-1.206-0.006-2.142-0.449c-1.026-0.48-1.888-0.344-2.8-0.49
|
||||
c-0.664-0.105-1.333-0.449-2.015-0.709c0.375-0.438,1.395-0.41,2.375-0.242c1.054,0.18,1.771-0.115,2.924,0.238
|
||||
c1.169,0.359,1.885,0.524,2.979,0.695c0.31,0.046,1.101,0.27,1.194,0.07c0.068-0.136-0.022-0.301,0.108-0.418
|
||||
c-0.214,0.232-0.604,0.388-1.234,0.148c0.862,0.057-0.264-0.167-0.524-0.272c0.356-0.031,0.902-0.04,1.361,0.099
|
||||
c-0.17-0.077-0.338-0.16-0.505-0.244c0.208-0.031,0.44-0.031,0.691,0c-0.446-0.1-1.417-0.074-1.808-0.273
|
||||
c0.425-0.006,0.679-0.13,1.209,0.016c0.307,0.087,0.521-0.198,0.124-0.267c-0.366-0.059-0.732-0.062-1.07-0.077
|
||||
c-0.502-0.021-1.029-0.232-1.569-0.342c0.478-0.365,1.932,0.416,2.394,0c-0.195,0.022-1.625-0.09-0.877-0.272
|
||||
c-0.54,0.024-1.333,0.295-2.065-0.024c0.298-0.124,0.623-0.227,1.023-0.261c0.496,0.105,0.567,0.019,0.21-0.257
|
||||
c-0.623,0.077-1.091,0.716-2.049,0.369c0.524-0.081,0.685-0.432,1.203-0.518c0.474-0.081,1.24,0.074,1.562-0.149
|
||||
c-1.429-0.248-2.508,0.241-3.854,0.173c0.732-0.489,2.639-0.039,3.11-0.719c-0.691-0.14-0.979,0.258-1.603,0.217
|
||||
c-0.36-0.024-0.742-0.059-1.126-0.096c-0.247,0.165-0.59,0.278-0.979,0.326c-0.31,0.012-0.694-0.233-0.418-0.336
|
||||
c0.273-0.105,0.819-0.005,1.229-0.006c-0.281-0.027-0.563-0.055-0.836-0.08c0.155-0.255,0.775-0.54,1.101-0.695
|
||||
c-0.48,0.059-0.989,0.316-1.321,0.496c-0.239-0.624-1.838-1.352-0.651-1.386c-0.366,0-0.744-0.081-0.626,0.248
|
||||
c0.105,0.301,0.478,0.372,0.766,0.648c0.8,0.772-1.299,0.363-0.53,0.812c-0.229,0.051-0.499-0.009-0.812-0.173
|
||||
c0.105,0.443,0.837,0.458,0.273,0.713c-0.208,0.093-0.468,0.146-0.75,0.171c-0.617,0.053-1.46-0.007-2.278-0.338
|
||||
c0.781,0.452-0.18,0.281-0.509,0.055c-0.288-0.197-0.53-0.449-0.905-0.502c0.217-0.325,0.999-0.456,1.578-0.508
|
||||
c0.905-0.086,1.299-0.332,1.764-0.753c-0.806,0.27-1.079,0.937-2.564,0.521c0.096-0.276,0.632-0.372,0.983-0.483
|
||||
c0.369-0.118,0.458-0.431,0.945-0.459c-0.75-0.292-1.42,0.173-2.22-0.199c0.682-0.369,2.186,0.09,3.06-0.099
|
||||
c-0.508-0.056-0.992-0.078-1.522-0.173c0.391-0.118,0.515-0.413,0.893-0.543c-0.13,0.105-0.35,0.112-0.654,0.025
|
||||
c0.521-0.034,0.534-0.48-0.31-0.669c-0.555-0.127-0.834,0.056-1.513-0.149c0.561,0.146,0.542-0.202,0.871-0.273
|
||||
c-0.921-0.124,0.13-0.381,0.48-0.27c-0.316-0.257-2.539-0.682-1.851-0.794c-1.011-0.074,0.57-0.074,0.632-0.099
|
||||
c-0.583-0.04-0.632-0.344-0.254-0.372c-0.217-0.021-1.374-0.282-0.626-0.344c-0.264-0.003-0.552-0.046-0.862-0.124
|
||||
c0.192-0.086,0.31-0.226,0.341-0.396c-0.753,0.189-1.5,0.44-2.57,0.322c0.676-0.251,1.689-0.217,2.4-0.446
|
||||
c-0.22,0.049-0.487,0.015-0.81-0.1c0.326-0.034,0.741,0.013,0.921-0.148c-0.326,0.037-0.682,0.062-1.141-0.1
|
||||
c0.487,0.059,1.082,0.031,1.188-0.22c-0.334,0.115-1.395-0.599-1.758-0.273c-0.322-0.341,0.264-0.26,0.406-0.397
|
||||
c-0.986-0.505-2.021-0.316-3.042-0.648c0.031-0.074,0.068-0.146,0.108-0.217c-0.536,0.04-0.756-0.419-0.567-0.54
|
||||
c-0.391-0.016-0.437,0.235-0.955,0.108c0.31-0.121,1.067-0.021,0.896-0.425c-0.196-0.456-1.231-0.282-0.53-0.496
|
||||
c-0.36-0.009-0.608,0.081-0.974,0.068c-0.292-0.013-1.284-0.344-0.583-0.366c-0.602-0.115-0.868,0.093-1.476-0.028
|
||||
c0.019-0.083,0.04-0.164,0.071-0.242c-0.195,0.041-0.413,0.068-0.651,0.081c-0.285-0.443-1.531-0.186-1.95-0.245
|
||||
c-0.028-0.09-0.062-0.18-0.096-0.27c-0.989-0.146-1.771-0.074-2.747-0.202c-0.685-0.09-1.699-0.276-1.829,0.065
|
||||
c-0.558-0.84-2.917,0.115-3.153,0.108c-0.459-0.443-0.949-0.335-1.321-0.251c-0.164,0.037,0.074,0.242-0.198,0.22
|
||||
c-0.211-0.041-0.372-0.041-0.493-0.003c-0.118,0.108-0.974-0.053-0.955,0.031c0.068,0.307-0.297,0.434-1.066,0.167
|
||||
c0.013-0.162,0.112-0.279,0.294-0.354c-1.184-0.344-1.336,0.511-2.074,0.257c-1.172-0.409-1.02-0.227-1.758-0.149
|
||||
c0.478,0.034,1.101,0.369,1.628,0.487c-0.471,0.254-1.823-0.108-2.635-0.124c-0.375-0.006-0.732,0.003-1.153-0.043
|
||||
c-0.289-0.031-1.185-0.121-0.577-0.239c-0.676-0.019-1.892-0.22-2.834-0.595c0.363-0.273,1.457-0.484,2.254-0.471
|
||||
c0.422,0.006,1.95,0.248,1.367-0.289c-1.314,0.115-2.796,0.115-4.57-0.161c-0.099-0.347,0.471-0.536,1.004-0.54
|
||||
c-1.652-0.359-1.107,1.11-3.32,0.217c0.239-0.012,0.458-0.041,0.651-0.081c-0.335,0.028-0.868-0.115-1.166-0.056
|
||||
c-1.752-1.2,11.112-0.13,11.815-0.596c-0.989,0.236-2.545-0.031-3.773,0.006c-0.769,0.022-1.656,0.189-2.855-0.223
|
||||
c0.942-0.18,2.151-0.214,3.308-0.242c0.862-0.022,2.468,0.403,3.128,0.27c-0.387,0.043-1.02-0.384-0.595-0.372
|
||||
c0.394,0.009,1.008,0.019,1.144-0.143c-1.06-0.701-2.031-0.496-2.48-0.354c-0.679,0.214-1.312,0.428-2.443,0.323
|
||||
c-0.344-0.031-1.476-0.515-1.364-0.245c0.115,0.282,0.031,0.313-0.406,0.341c-0.915,0.059-2.059-0.006-3.317-0.254
|
||||
c0.562-0.1,1.46-0.043,1.628-0.381c-0.443,0.22-1.436,0.322-2.496,0.056c0.552-0.068,1.07-0.17,1.492-0.326
|
||||
c-1.299-0.077-1.907,0.372-3.401,0.137c0.14-0.078,0.292-0.149,0.45-0.217c-0.484,0.053-1.219,0.053-1.95-0.108
|
||||
c-0.766-0.167-1.609-0.505-2.322-0.595c0.394,0.065,1.705-0.251,0.546-0.406c0.483-0.031,0.363-0.391,0.837-0.428
|
||||
c0.515-0.041,1.091-0.031,1.557-0.105c0.71-0.118,1.578-0.013,2.344-0.065c0.375-0.028,0.45-0.273,0.818-0.326
|
||||
C33.521,84,34.023,84,34.432,83.938c0.502-0.078,1.131-0.065,1.671-0.115c0.149-0.013,1.423-0.103,0.223-0.224
|
||||
c0.782-0.254,2.019-0.195,3.026-0.294c0.769-0.074,1.299-0.242,2.254-0.183c1.714,0.108,2.576-0.137,3.789-0.381
|
||||
c0.502-0.103,1.107-0.205,1.237-0.518c0.096-0.229-0.4-0.611-0.319-0.85c0.108-0.654,1.63-0.663,2.774-0.626
|
||||
c-1.813-0.232-2.799,0.326-4.393,0.285c-0.669-0.016-1.445-0.183-2.034-0.124c-0.562,0.056-1.495-0.304-1.984-0.264
|
||||
c-0.478-0.651,0.707-0.759,1.215-0.874c0.939-0.211,1.885-0.406,2.905-0.564c1.218-0.189,2.009-0.664,3.271-0.828
|
||||
c0.443-0.059,0.927-0.5,1.78-0.133c0.599,0.257,1.197,0.617,1.789,0.846c-0.434-0.257-1.488-0.741-1.358-0.983
|
||||
c0.18-0.329,1.057-0.217,1.727-0.18c1.29,0.071,3.181,0.502,3.919,0.115c-0.226-0.112-0.456-0.223-0.682-0.338
|
||||
c-0.006-0.375,0.735-0.282,0.977-0.505c-1.885-0.211-0.899-1.014-0.323-1.085c0.933-0.108,2.146,0.022,3.274,0.084
|
||||
c0.456,0.025,1.026-0.103,1.724,0.273c0.645,0.347,0.877,0.425,1.404,0.449c1.188,0.053,2.834,0.583,3.91,0.549
|
||||
c-0.75-0.139-1.584-0.391-2.35-0.545c-0.502-0.103-0.936-0.037-1.491-0.22c-0.512-0.167-1.107-0.484-1.59-0.586
|
||||
c-0.524-0.112-0.868-0.037-1.417-0.17c1.625-0.388,3.764-0.357,5.714-0.484c0.726-0.046,1.553,0.046,2.254-0.025
|
||||
c0.285-0.028,2.453-0.257,1.364-0.201c0.406-0.034,3.808-0.534,4.502,0.511c0.44,0.67-0.552,0.744-0.326,1.314
|
||||
c0.719,0.1,1.098-0.474,1.578-0.614c0.341-0.096,0.18-0.487,0.502-0.577c0.02-0.005,0.053-0.002,0.077-0.006
|
||||
c-0.391-0.095-0.782-0.217-1.159-0.394c0.09-0.48,1.156-0.478,2.22-0.037c1.07,0.449,1.609,0.012,2.729,0.545
|
||||
c-0.38,0.046-0.896,0.1-1.48,0.114c0.773,0.073,1.555,0.147,2.367,0.292c0.974,0.177,2.136,0.639,2.799,0.44
|
||||
c-1.11-0.381-2.009-0.394-3.131-0.778c1.396,0.223,2.865,0.363,3.714,0.034c-0.735-0.108-1.727-0.208-2.583-0.521
|
||||
c-0.53-0.192-0.775-0.607-1.355-0.831c1.268-0.152,2.691-0.217,4.347,0.034c1.234,0.186,2.669,0.319,3.975,0.642
|
||||
c1.386,0.347,2.437,0.223,3.835,0.577c1.681,0.428,3.138,0.66,4.25,0.369c-0.245-0.009-1.358-0.037-0.676-0.304
|
||||
c-0.279-0.021-0.558-0.043-0.84-0.068c0.162-0.229,0.642-0.195,0.989-0.27c-1.014-0.065-0.319-0.49-0.078-0.533
|
||||
c0.403-0.078,0.943-0.013,1.46,0.046c1.243,0.143,2.505,0.248,3.575,0.183c-1.268-0.202-2.322-0.109-3.59-0.304
|
||||
c0.871-0.226-0.54-0.257-0.803-0.294c-0.372-0.056-0.75-0.115-1.129-0.177c-0.75-0.121-1.513-0.26-2.3-0.44
|
||||
c0.549-0.335,1.833-0.093,2.722-0.105c0.986-0.013,1.975-0.022,2.942-0.053c0.787-0.028,1.671-0.087,2.639,0.121
|
||||
c0.328,0.068,1.605,1.12,1.203,0.273c-0.184-0.074-0.369-0.14-0.553-0.201c0.553-0.298,2.019-0.01,2.979,0.205
|
||||
c0.484,0.105,1.058,0.242,1.575,0.515c0.307,0.161,0.797-0.217-0.08-0.316c0.812-0.326-1.768-0.549-2.09-0.558
|
||||
c-0.952-0.025-1.973-0.14-2.93-0.174c-2.385-0.083-4.664-0.04-7.072-0.146c1.193,0.195-0.208,0.155-0.357,0.158
|
||||
c-0.425,0.012-0.865,0.009-1.299,0.009c-0.694,0.006-1.429,0.037-2.332-0.236c0.45-0.136,1.193,0.041,1.798,0.068
|
||||
c-0.542-0.17-1.029-0.223-1.436-0.202c0.607-0.416,2.031-0.096,3.138-0.009c0.93,0.068,1.82,0.093,2.759,0.177
|
||||
c-1.128-0.198-2.139-0.22-3.333-0.505c1.188,0.146,1.987-0.127,3.119-0.043c1.091,0.081,2.127,0.093,3.19,0.143
|
||||
c-0.828-0.133-1.503-0.034-2.399-0.27c0.759,0,1.615,0.103,2.279,0c-0.341-0.031-0.67-0.041-0.98-0.034
|
||||
c0.45-0.229,1.315-0.192,2.043-0.143c0.304,0.021,2.347,0.288,1.33,0.446c1.182-0.272,3.141,0.341,4.526,0.301
|
||||
c0.607-0.019,1.193-0.037,1.96,0.189c0.492,0.146,1.345,0.449,1.494,0.152c-0.394,0.083-1.005-0.323-1.473-0.372
|
||||
c0.401-0.112,0.879-0.146,1.375-0.157c-0.121-0.016-0.232-0.019-0.361-0.045c1.327-0.115,2.958,0.103,4.12-0.205
|
||||
c-0.468,0.056-3.969,0.174-4.384-0.642c1.069,0.102,1.879-0.087,2.803-0.158c0.881-0.068,2.127,0.403,2.974,0.294
|
||||
c-0.356-0.152-0.691-0.242-1.008-0.27c1.058-0.425,2.933-0.065,4.328-0.121c0.428-0.016,1.141-0.177,1.562-0.115
|
||||
c0.49,0.071,0.995,0.409,1.398,0.236c-0.205-0.068-0.406-0.137-0.611-0.205c2.06-0.18,4.366-0.021,6.595,0.034
|
||||
c1.116,0.031,2.168-0.034,3.262-0.034c0.536,0,1.169,0.211,1.718,0.239c0.499,0.025,0.821-0.173,1.407,0
|
||||
c-0.285-0.012-0.558,0-0.815,0.034c0.268,0.046,2.44,0.121,1.219,0c2.047,0.059,4.037-0.356,6.402,0.438
|
||||
c-2.982,0.387-6.321,0.239-9.556,0.239c-1.463,0-2.877,0.074-4.244,0.201c-1.354,0.127-2.97-0.133-4.412-0.133
|
||||
c0.624,0.062,1.185,0.009,1.895,0.27c-2.372,0-4.731,0.037-6.889,0.304c1.004,0.083-0.04,0.264-0.224,0.304
|
||||
c1.073,0.006,1.848-0.356,2.964-0.341c0.165,0,1.216,0.242,1.287,0.167c0.267-0.273,0.651-0.264,1.185-0.273
|
||||
c2.183-0.043,4.188-0.093,6.253-0.279c2.385-0.214,5.008,0.016,7.531,0.016c2.03,0,3.983-0.664,6.399,0.167
|
||||
c-0.788,0.26-1.606,0.49-2.555,0.54c1.634,0.046,2.861-0.716,4.712-0.27c-0.09,0.105-0.186,0.208-0.288,0.304
|
||||
c1.86-0.202,4.071-0.425,6.337,0.372c-0.523,0.334-1.51,0.304-2.16,0.499c-0.899,0.27-1.963,0.229-3.032,0.235
|
||||
c-2.195,0.006-4.186,0.344-6.378,0.351c-2.267,0.009-4.632-0.155-6.803,0.006c-0.964,0.071-2.031-0.018-3.087-0.091
|
||||
c0.244,0.057,0.49,0.132,0.74,0.252c-1.352,0.335-3.004,0.282-4.585,0.304c-0.71,0.012-2.744-0.074-2.469,0.741
|
||||
c2.999-0.41,6.204-0.537,9.302-0.837c1.621-0.158,3.423-0.093,5.168-0.062c0.965,0.016,2.81-0.338,3.96,0.257
|
||||
c-0.06,0.778-1.675,0.614-2.453,0.695c-0.979,0.099-2.402-0.031-3.075,0.421c0.288,0.009,0.592,0.065,0.911,0.167
|
||||
c-0.238,0.031-0.489,0.041-0.753,0.034c1.299,0.183,2.434-0.285,3.581-0.381c1.165-0.093,2.191-0.344,3.407-0.36
|
||||
c1.008-0.012,0.97-0.716,1.808-0.862c0.731-0.127,1.634-0.102,2.421-0.149c0.375-0.021,2.05,0.016,2.013,0.741
|
||||
c-0.025,0.459-0.577,0.738-0.955,0.936c-0.651,0.344-1.485,0.478-2.155,0.8c-0.827,0.396-1.581,0.877-2.561,1.101
|
||||
c1.048-0.031,0.006,0.279-0.158,0.372c0.881-0.229,1.488-0.524,2.248-0.875c0.713-0.326,1.845-0.425,2.657-0.679
|
||||
c1.829-0.571,3.674-1.058,5.751-1.321c-0.372,0.071-0.741,0.22-0.707,0.607c0.75-0.053,1.352-0.335,2.121-0.359
|
||||
c0.492-0.019,1.014,0.158,1.528,0.226c0.902,0.121,2.067,0.022,2.666-0.338c-0.998,0.065,0.232-0.257,0.636-0.236
|
||||
c-0.14-0.111-0.276-0.226-0.412-0.338c2.285-0.186,4.585-0.356,7.034-0.167C168.128,76.345,170.205,76.751,172.189,76.894z"/>
|
||||
<circle fill="none" cx="99.197" cy="100.656" r="82.295"/>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -1,429 +0,0 @@
|
|||
|
||||
paper.install(window);
|
||||
|
||||
|
||||
|
||||
function runTests() {
|
||||
var caption, pathA, pathB, group;
|
||||
|
||||
var container = document.getElementById( 'container' );
|
||||
|
||||
caption = prepareTest( 'Overlapping circles', container );
|
||||
pathA = new Path.Circle(new Point(80, 110), 50);
|
||||
pathB = new Path.Circle(new Point(150, 110), 70);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Disjoint circles', container );
|
||||
pathA = new Path.Circle(new Point(60, 110), 50);
|
||||
pathB = new Path.Circle(new Point(170, 110), 50);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Overlapping circles - enveloping', container );
|
||||
pathA = new Path.Circle(new Point(110, 110), 100);
|
||||
pathB = new Path.Circle(new Point(120, 110), 60);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Polygon and square', container );
|
||||
pathA = new Path.RegularPolygon(new Point(80, 110), 12, 80);
|
||||
pathB = new Path.Rectangle(new Point(100, 80), [80, 80] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Circle and square (overlaps exactly on existing segments)', container );
|
||||
pathA = new Path.Circle(new Point(110, 110), 80);
|
||||
pathB = new Path.Rectangle(new Point(110, 110), [80, 80] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Circle and square (existing segments overlaps on curves)', container );
|
||||
pathA = new Path.Circle(new Point(110, 110), 80);
|
||||
pathB = new Path.Rectangle(new Point(110, 110), [100, 100] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Square and square (one segment overlaps on a line)', container );
|
||||
pathA = new Path.Rectangle(new Point(80, 125), [50, 50] );
|
||||
pathA.rotate( 45 );
|
||||
pathB = new Path.Rectangle(new Point(pathA.segments[2].point.x, 110), [80, 80] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Rectangle and rectangle (overlaps exactly on existing curves)', container );
|
||||
pathA = new Path.Rectangle(new Point(30.5, 50.5), [100, 150]);
|
||||
pathB = new Path.Rectangle(new Point(130.5, 60.5), [100, 150]);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Circle and banana (multiple intersections within same curve segment)', container );
|
||||
pathA = new Path.Circle(new Point(80, 110), 80);
|
||||
pathB = new Path.Circle(new Point(130, 110), 80 );
|
||||
pathB.segments[3].point = pathB.segments[3].point.add( [ 0, -120 ] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Overlapping stars 1', container );
|
||||
pathA = new Path.Star(new Point(80, 110), 10, 20, 80);
|
||||
pathB = new Path.Star(new Point(120, 110), 10, 30, 100);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Overlapping stars 2', container );
|
||||
pathA = new Path.Star(new Point(110, 110), 20, 20, 80);
|
||||
pathB = new Path.Star(new Point(110, 110), 6, 30, 100);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
// caption = prepareTest( 'Circles overlap exactly over each other', container );
|
||||
// pathA = new Path.Circle(new Point(110, 110), 100);
|
||||
// pathB = new Path.Circle(new Point(110, 110), 100 );
|
||||
// // pathB.translate([0.5,0])
|
||||
// testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Maximum possible intersections between 2 cubic bezier curve segments - 9', container );
|
||||
pathA = new Path();
|
||||
pathA.add( new Segment( [173, 44], [-281, 268], [-86, 152] ) );
|
||||
pathA.add( new Segment( [47, 93], [-89, 100], [240, -239] ) );
|
||||
pathA.closed = true;
|
||||
pathB = pathA.clone();
|
||||
pathB.rotate( -90 );
|
||||
pathA.translate( [-10,0] );
|
||||
pathB.translate( [10,0] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
annotatePath( pathA, null, '#008' );
|
||||
annotatePath( pathB, null, '#800' );
|
||||
view.draw();
|
||||
|
||||
caption = prepareTest( 'SVG gears', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'svggears' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Glyphs imported from SVG', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsys' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 1', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 2 - holes', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = new CompoundPath();
|
||||
group.children[1].clockwise = true;
|
||||
pathB.addChild(group.children[1]);
|
||||
var npath = new Path.Circle([110, 110], 30);
|
||||
pathB.addChild( npath );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 3 !', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'svggreenland' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
pathB.scale( 0.5, 1 ).translate( [25.5, 0] );
|
||||
// pathA.scale( 2 );
|
||||
// pathB.scale( 2 );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 4 - holes and islands 1', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = new CompoundPath();
|
||||
group.children[1].clockwise = true;
|
||||
pathB.addChild(group.children[1]);
|
||||
var npath = new Path.Circle([40, 80], 20);
|
||||
pathB.addChild( npath );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 5 - holes and islands 2', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = new CompoundPath();
|
||||
group.children[1].clockwise = true;
|
||||
pathB.addChild(group.children[1]);
|
||||
var npath = new Path.Circle([40, 80], 20);
|
||||
pathB.addChild( npath );
|
||||
npath = new Path.Circle([120, 110], 30);
|
||||
pathB.addChild( npath );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 6 - holes and islands 3', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = new CompoundPath();
|
||||
var npath = new Path.Circle([110, 110], 100);
|
||||
pathB.addChild( npath );
|
||||
npath = new Path.Circle([110, 110], 60);
|
||||
pathB.addChild( npath );
|
||||
npath = new Path.Circle([110, 110], 30);
|
||||
pathB.addChild( npath );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 6 - holes and islands 4 (curves overlap exactly on existing curves)', container );
|
||||
pathA = new Path.Rectangle(new Point(50.5, 50.5), [100, 120]);
|
||||
pathB = new CompoundPath();
|
||||
pathB.addChild( new Path.Rectangle(new Point(140.5, 30.5), [100, 150]) );
|
||||
pathB.addChild( new Path.Rectangle(new Point(150.5, 65.5), [50, 100]) );
|
||||
// pathB = new Path.Rectangle(new Point(150.5, 80.5), [80, 80] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
|
||||
// // To resolve self intersection on a single path,
|
||||
// // pass an empty second operand and do a Union operation
|
||||
// caption = prepareTest( 'Self-intersecting paths 1 - Resolve self-intersection on single path', container );
|
||||
// pathA = new Path.Star(new Point(110, 110), 10, 20, 80);
|
||||
// pathA.smooth();
|
||||
// pathB = new Path();
|
||||
// testBooleanStatic( pathA, pathB, caption, false, true, true, true );
|
||||
|
||||
// caption = prepareTest( 'Self-intersecting paths 2 - Resolve self-intersecting CompoundPath', container );
|
||||
// pathA = new CompoundPath();
|
||||
// pathA.addChild( new Path.Circle([100, 110], 60) );
|
||||
// pathA.addChild( new Path.Circle([160, 110], 30) );
|
||||
// pathB = new Path();
|
||||
// testBooleanStatic( pathA, pathB, caption, false, true, true, true );
|
||||
|
||||
|
||||
// var tool = new Tool();
|
||||
// tool.onMouseMove = function( e ){
|
||||
// var hi = project.hitTest( e.point );
|
||||
// if( hi ){
|
||||
// var item = hi.item;
|
||||
// if( item instanceof PathItem ){
|
||||
// var txt = new PointText( e.point.add([0, -10]) );
|
||||
// txt.justification = 'center';
|
||||
// txt.content = item.id;
|
||||
// txt.fillColor = '#000';
|
||||
// txt.removeOnMove();
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
window.a = pathA;
|
||||
window.b = pathB;
|
||||
|
||||
// // pathA.selected = true;
|
||||
// // pathA.fullySelected = true;
|
||||
// // pathB.selected = true;
|
||||
// pathA.style = pathStyleBoolean;
|
||||
// pathB.style = pathStyleBoolean;
|
||||
|
||||
// // reorientCompoundPath( pathB )
|
||||
|
||||
// // var ixs = pathA.getIntersections( pathB );
|
||||
// // ixs.map( function(a){ console.log( "( " + a.path.id + " , " + a.curve.index + " , "+ a.parameter +" )" );
|
||||
// // markPoint( a.point, " " ) } );
|
||||
// // ixs.map( function(a){ markPoint( a.point, " " ); } );
|
||||
|
||||
// // splitPath( ixs, true );
|
||||
// // splitPath( ixs );
|
||||
|
||||
// // annotatePath( pathB )
|
||||
// // pathB.translate( [ 300, 0 ] );
|
||||
// // pathB.segments.filter( function(a){ return a._ixPair; } ).map(
|
||||
// // function(a){ a._ixPair.getIntersection()._segment.selected = true; });
|
||||
|
||||
// console.time('unite');
|
||||
// var nup = unite( pathA, pathB );
|
||||
// console.timeEnd('unite');
|
||||
// // nup.style = booleanStyle;
|
||||
// window.p = nup;
|
||||
|
||||
// view.draw();
|
||||
|
||||
|
||||
function prepareTest( testName, parentNode ){
|
||||
console.log( '\n' + testName );
|
||||
var caption = document.createElement('h3');
|
||||
caption.appendChild( document.createTextNode( testName ) );
|
||||
var canvas = document.createElement('CANVAS');
|
||||
parentNode.appendChild( caption );
|
||||
parentNode.appendChild( canvas );
|
||||
paper.setup( canvas );
|
||||
return caption;
|
||||
}
|
||||
}
|
||||
|
||||
var booleanStyle = {
|
||||
fillColor: new Color( 1, 0, 0, 0.5 ),
|
||||
strokeColor: new Color( 0, 0, 0 ),
|
||||
strokeWidth: 1.5
|
||||
};
|
||||
|
||||
var pathStyleNormal = {
|
||||
strokeColor: new Color( 0, 0, 0 ),
|
||||
fillColor: new Color( 0, 0, 0, 0.1 ),
|
||||
strokeWidth: 1
|
||||
};
|
||||
|
||||
var pathStyleBoolean = {
|
||||
strokeColor: new Color( 0.8 ),
|
||||
fillColor: new Color( 0, 0, 0, 0.0 ),
|
||||
strokeWidth: 1
|
||||
};
|
||||
|
||||
// Better if path1 and path2 fit nicely inside a 200x200 pixels rect
|
||||
function testBooleanStatic( path1, path2, caption, noUnion, noIntersection, noSubtraction, _disperse ) {
|
||||
// try{
|
||||
path1.style = path2.style = pathStyleNormal;
|
||||
|
||||
if( !noUnion ) {
|
||||
var _p1U = path1.clone().translate( [250, 0] );
|
||||
var _p2U = path2.clone().translate( [250, 0] );
|
||||
_p1U.style = _p2U.style = pathStyleBoolean;
|
||||
console.time( 'Union' );
|
||||
var boolPathU = unite( _p1U, _p2U );
|
||||
console.timeEnd( 'Union' );
|
||||
boolPathU.style = booleanStyle;
|
||||
if( _disperse ){ disperse( boolPathU ); }
|
||||
}
|
||||
|
||||
if( !noIntersection ) {
|
||||
var _p1I = path1.clone().translate( [500, 0] );
|
||||
var _p2I = path2.clone().translate( [500, 0] );
|
||||
_p1I.style = _p2I.style = pathStyleBoolean;
|
||||
console.time( 'Intersection' );
|
||||
var boolPathI = intersect( _p1I, _p2I );
|
||||
console.timeEnd( 'Intersection' );
|
||||
boolPathI.style = booleanStyle;
|
||||
}
|
||||
|
||||
if( !noSubtraction ) {
|
||||
var _p1S = path1.clone().translate( [750, 0] );
|
||||
var _p2S = path2.clone().translate( [750, 0] );
|
||||
_p1S.style = _p2S.style = pathStyleBoolean;
|
||||
console.time( 'Subtraction' );
|
||||
var boolPathS = subtract( _p1S, _p2S );
|
||||
console.timeEnd( 'Subtraction' );
|
||||
boolPathS.style = booleanStyle;
|
||||
}
|
||||
|
||||
if( !noSubtraction ) {
|
||||
var _p1E = path1.clone().translate( [250, 220] );
|
||||
var _p2E = path2.clone().translate( [250, 220] );
|
||||
_p1E.style = _p2E.style = pathStyleBoolean;
|
||||
console.time( 'Exclusion' );
|
||||
var boolPathE = exclude( _p1E, _p2E );
|
||||
console.timeEnd( 'Exclusion' );
|
||||
boolPathE.style = booleanStyle;
|
||||
}
|
||||
|
||||
if( !noSubtraction && !noIntersection) {
|
||||
var _p1D = path1.clone().translate( [500, 220] );
|
||||
var _p2D = path2.clone().translate( [500, 220] );
|
||||
_p1D.style = _p2D.style = pathStyleBoolean;
|
||||
console.time( 'Division' );
|
||||
var boolPathD = divide( _p1D, _p2D );
|
||||
console.timeEnd( 'Division' );
|
||||
disperse( boolPathD );
|
||||
boolPathD.style = booleanStyle;
|
||||
}
|
||||
// } catch( e ){
|
||||
// console.error( e.name + ": " + e.message );
|
||||
// if( caption ) { caption.className += ' error'; }
|
||||
// // paper.project.view.element.className += ' hide';
|
||||
// } finally {
|
||||
console.timeEnd( 'Union' );
|
||||
console.timeEnd( 'Intersection' );
|
||||
console.timeEnd( 'Subtraction' );
|
||||
view.draw();
|
||||
// }
|
||||
}
|
||||
|
||||
function disperse( path, distance ){
|
||||
distance = distance || 10;
|
||||
if( ! path instanceof CompoundPath || ! path instanceof Group ){ return; }
|
||||
var center = path.bounds.center;
|
||||
var children = path.children, i ,len;
|
||||
for (i = 0, len = children.length; i < len; i++) {
|
||||
var cCenter = children[i].bounds.center;
|
||||
var vec = cCenter.subtract( center );
|
||||
vec = ( vec.isClose( [0,0], 0.5 ) )? vec : vec.normalize( distance );
|
||||
children[i].translate( vec );
|
||||
}
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// On screen debug helpers
|
||||
function markPoint( pnt, t, c, tc, remove ) {
|
||||
if( !pnt ) return;
|
||||
c = c || '#000';
|
||||
if( remove === undefined ){ remove = true; }
|
||||
var cir = new Path.Circle( pnt, 2 );
|
||||
cir.style.fillColor = c;
|
||||
cir.style.strokeColor = tc;
|
||||
if( t !== undefined || t !== null ){
|
||||
var text = new PointText( pnt.add([0, -3]) );
|
||||
text.justification = 'center';
|
||||
text.fillColor = c;
|
||||
text.content = t;
|
||||
if( remove ){
|
||||
text.removeOnMove();
|
||||
}
|
||||
}
|
||||
if( remove ) {
|
||||
cir.removeOnMove();
|
||||
}
|
||||
}
|
||||
|
||||
function annotatePath( path, t, c, tc, remove ) {
|
||||
if( !path ) return;
|
||||
var crvs = path.curves;
|
||||
for (i = crvs.length - 1; i >= 0; i--) {
|
||||
annotateCurve( crvs[i], t, c, tc, remove );
|
||||
}
|
||||
var segs = path.segments;
|
||||
for (i = segs.length - 1; i >= 0; i--) {
|
||||
annotateSegment( segs[i], t, c, tc, remove, true );
|
||||
}
|
||||
}
|
||||
|
||||
function annotateSegment( s, t, c, tc, remove, skipCurves ) {
|
||||
if( !s ) return;
|
||||
c = c || '#000';
|
||||
tc = tc || '#ccc';
|
||||
t = t || s.index;
|
||||
if( remove === undefined ){ remove = true; }
|
||||
var crv = s.curve;
|
||||
var t1 = crv.getNormal( 0 ).normalize( 10 );
|
||||
var p = s.point.clone().add( t1 );
|
||||
var cir = new Path.Circle( s.point, 2 );
|
||||
cir.style.fillColor = c;
|
||||
cir.style.strokeColor = tc;
|
||||
var text = new PointText( p );
|
||||
text.justification = 'center';
|
||||
text.fillColor = c;
|
||||
text.content = t;
|
||||
if( remove ) {
|
||||
cir.removeOnMove();
|
||||
text.removeOnMove();
|
||||
}
|
||||
if( !skipCurves ) {
|
||||
annotateCurve( s.curveIn, null, c, tc, remove );
|
||||
annotateCurve( s.curveOut, null, c, tc, remove );
|
||||
}
|
||||
}
|
||||
|
||||
function annotateCurve( crv, t, c, tc, remove ) {
|
||||
if( !crv ) return;
|
||||
c = c || '#000';
|
||||
tc = tc || '#ccc';
|
||||
t = t || crv.index;
|
||||
if( remove === undefined ){ remove = true; }
|
||||
var p = crv.getPoint( 0.57 );
|
||||
var t1 = crv.getTangent( 0.57 ).normalize( -10 );
|
||||
var p2 = p.clone().add( t1 );
|
||||
var l = new Path.Line( p, p2 ).rotate( 30, p );
|
||||
var l2 = new Path.Line( p, p2 ).rotate( -30, p );
|
||||
p = crv.getPoint( 0.43 );
|
||||
var cir = new Path.Circle( p, 8 );
|
||||
var text = new PointText( p.subtract( [0, -4] ) );
|
||||
text.justification = 'center';
|
||||
text.fillColor = tc;
|
||||
text.content = t;
|
||||
l.style.strokeColor = l2.style.strokeColor = c;
|
||||
cir.style.fillColor = c;
|
||||
if( remove ) {
|
||||
l.removeOnMove();
|
||||
l2.removeOnMove();
|
||||
cir.removeOnMove();
|
||||
text.removeOnMove();
|
||||
}
|
||||
}
|
|
@ -1,366 +0,0 @@
|
|||
|
||||
paper.install(window);
|
||||
|
||||
|
||||
|
||||
function runTests() {
|
||||
var caption, pathA, pathB, group;
|
||||
|
||||
var container = document.getElementById( 'container' );
|
||||
|
||||
caption = prepareTest( 'Overlapping circles', container );
|
||||
pathA = new Path.Circle(new Point(80, 110), 50);
|
||||
pathB = new Path.Circle(new Point(150, 110), 70);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Disjoint circles', container );
|
||||
pathA = new Path.Circle(new Point(60, 110), 50);
|
||||
pathB = new Path.Circle(new Point(170, 110), 50);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Overlapping circles - enveloping', container );
|
||||
pathA = new Path.Circle(new Point(110, 110), 100);
|
||||
pathB = new Path.Circle(new Point(120, 110), 60);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Polygon and square', container );
|
||||
pathA = new Path.RegularPolygon(new Point(80, 110), 12, 80);
|
||||
pathB = new Path.Rectangle(new Point(100, 80), [80, 80] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Circle and square (overlaps exactly on existing segments)', container );
|
||||
pathA = new Path.Circle(new Point(110, 110), 80);
|
||||
pathB = new Path.Rectangle(new Point(110, 110), [80, 80] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Circle and square (existing segments overlaps on curves)', container );
|
||||
pathA = new Path.Circle(new Point(110, 110), 80);
|
||||
pathB = new Path.Rectangle(new Point(110, 110), [100, 100] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Square and square (one segment overlaps on a line)', container );
|
||||
pathA = new Path.Rectangle(new Point(80, 125), [50, 50] );
|
||||
pathA.rotate( 45 );
|
||||
pathB = new Path.Rectangle(new Point(pathA.segments[2].point.x, 110), [80, 80] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Rectangle and rectangle (overlaps exactly on existing curves)', container );
|
||||
pathA = new Path.Rectangle(new Point(30.5, 50.5), [100, 150]);
|
||||
pathB = new Path.Rectangle(new Point(130.5, 60.5), [100, 150]);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Circle and banana (multiple intersections within same curve segment)', container );
|
||||
pathA = new Path.Circle(new Point(80, 110), 80);
|
||||
pathB = new Path.Circle(new Point(130, 110), 80 );
|
||||
pathB.segments[3].point = pathB.segments[3].point.add( [ 0, -120 ] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Overlapping stars 1', container );
|
||||
pathA = new Path.Star(new Point(80, 110), 10, 20, 80);
|
||||
pathB = new Path.Star(new Point(120, 110), 10, 30, 100);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Overlapping stars 2', container );
|
||||
pathA = new Path.Star(new Point(110, 110), 20, 20, 80);
|
||||
pathB = new Path.Star(new Point(110, 110), 6, 30, 100);
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
// caption = prepareTest( 'Circles overlap exactly over each other', container );
|
||||
// pathA = new Path.Circle(new Point(110, 110), 100);
|
||||
// pathB = new Path.Circle(new Point(110, 110), 100 );
|
||||
// // pathB.translate([0.5,0])
|
||||
// testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Maximum possible intersections between 2 cubic bezier curve segments - 9', container );
|
||||
pathA = new Path();
|
||||
pathA.add( new Segment( [173, 44], [-281, 268], [-86, 152] ) );
|
||||
pathA.add( new Segment( [47, 93], [-89, 100], [240, -239] ) );
|
||||
pathA.closed = true;
|
||||
pathB = pathA.clone();
|
||||
pathB.rotate( -90 );
|
||||
pathA.translate( [-10,0] );
|
||||
pathB.translate( [10,0] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
annotatePath( pathA, null, '#008' );
|
||||
annotatePath( pathB, null, '#800' );
|
||||
view.draw();
|
||||
|
||||
caption = prepareTest( 'SVG gears', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'svggears' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'Glyphs imported from SVG', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsys' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 1', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 2 - holes', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = new CompoundPath();
|
||||
group.children[1].clockwise = true;
|
||||
pathB.addChild(group.children[1]);
|
||||
var npath = new Path.Circle([110, 110], 30);
|
||||
pathB.addChild( npath );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 3 !', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'svggreenland' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
pathB.scale( 0.5, 1 ).translate( [25.5, 0] );
|
||||
// pathA.scale( 2 );
|
||||
// pathB.scale( 2 );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 4 - holes and islands 1', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = new CompoundPath();
|
||||
group.children[1].clockwise = true;
|
||||
pathB.addChild(group.children[1]);
|
||||
var npath = new Path.Circle([40, 80], 20);
|
||||
pathB.addChild( npath );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 5 - holes and islands 2', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = new CompoundPath();
|
||||
group.children[1].clockwise = true;
|
||||
pathB.addChild(group.children[1]);
|
||||
var npath = new Path.Circle([40, 80], 20);
|
||||
pathB.addChild( npath );
|
||||
npath = new Path.Circle([120, 110], 30);
|
||||
pathB.addChild( npath );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 6 - holes and islands 3', container );
|
||||
group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) );
|
||||
pathA = group.children[0];
|
||||
pathB = new CompoundPath();
|
||||
var npath = new Path.Circle([110, 110], 100);
|
||||
pathB.addChild( npath );
|
||||
npath = new Path.Circle([110, 110], 60);
|
||||
pathB.addChild( npath );
|
||||
npath = new Path.Circle([110, 110], 30);
|
||||
pathB.addChild( npath );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
caption = prepareTest( 'CompoundPaths 6 - holes and islands 4 (curves overlap exactly on existing curves)', container );
|
||||
pathA = new Path.Rectangle(new Point(50.5, 50.5), [100, 120]);
|
||||
pathB = new CompoundPath();
|
||||
pathB.addChild( new Path.Rectangle(new Point(140.5, 30.5), [100, 150]) );
|
||||
pathB.addChild( new Path.Rectangle(new Point(150.5, 60.5), [50, 100]) );
|
||||
// pathB = new Path.Rectangle(new Point(150.5, 80.5), [80, 80] );
|
||||
testBooleanStatic( pathA, pathB, caption );
|
||||
|
||||
|
||||
// To resolve self intersection on a single path,
|
||||
// pass an empty second operand and do a Union operation
|
||||
caption = prepareTest( 'Self-intersecting paths 1 - Resolve self-intersection on single path', container );
|
||||
pathA = new Path.Star(new Point(110, 110), 10, 20, 80);
|
||||
pathA.smooth();
|
||||
pathB = new Path();
|
||||
testBooleanStatic( pathA, pathB, caption, false, true, true, true );
|
||||
|
||||
caption = prepareTest( 'Self-intersecting paths 2 - Resolve self-intersecting CompoundPath', container );
|
||||
pathA = new CompoundPath();
|
||||
pathA.addChild( new Path.Circle([100, 110], 60) );
|
||||
pathA.addChild( new Path.Circle([160, 110], 30) );
|
||||
pathB = new Path();
|
||||
testBooleanStatic( pathA, pathB, caption, false, true, true, true );
|
||||
|
||||
window.a = pathA;
|
||||
window.b = pathB;
|
||||
|
||||
|
||||
function prepareTest( testName, parentNode ){
|
||||
console.log( '\n' + testName );
|
||||
var caption = document.createElement('h3');
|
||||
caption.appendChild( document.createTextNode( testName ) );
|
||||
var canvas = document.createElement('CANVAS');
|
||||
parentNode.appendChild( caption );
|
||||
parentNode.appendChild( canvas );
|
||||
paper.setup( canvas );
|
||||
return caption;
|
||||
}
|
||||
}
|
||||
|
||||
var booleanStyle = {
|
||||
fillColor: new Color( 1, 0, 0, 0.5 ),
|
||||
strokeColor: new Color( 0, 0, 0 ),
|
||||
strokeWidth: 1.5
|
||||
};
|
||||
|
||||
var pathStyleNormal = {
|
||||
strokeColor: new Color( 0, 0, 0 ),
|
||||
fillColor: new Color( 0, 0, 0, 0.1 ),
|
||||
strokeWidth: 1
|
||||
};
|
||||
|
||||
var pathStyleBoolean = {
|
||||
strokeColor: new Color( 0.8 ),
|
||||
fillColor: new Color( 0, 0, 0, 0.0 ),
|
||||
strokeWidth: 1
|
||||
};
|
||||
|
||||
// Better if path1 and path2 fit nicely inside a 200x200 pixels rect
|
||||
function testBooleanStatic( path1, path2, caption, noUnion, noIntersection, noSubtraction, _disperse ) {
|
||||
// try{
|
||||
path1.style = path2.style = pathStyleNormal;
|
||||
|
||||
if( !noUnion ) {
|
||||
var _p1U = path1.clone().translate( [250, 0] );
|
||||
var _p2U = path2.clone().translate( [250, 0] );
|
||||
_p1U.style = _p2U.style = pathStyleBoolean;
|
||||
console.time( 'Union' );
|
||||
var boolPathU = _p1U.unite( _p2U );
|
||||
console.timeEnd( 'Union' );
|
||||
boolPathU.style = booleanStyle;
|
||||
if( _disperse ){ disperse( boolPathU ); }
|
||||
window.p = boolPathU;
|
||||
}
|
||||
|
||||
if( !noIntersection ) {
|
||||
var _p1I = path1.clone().translate( [500, 0] );
|
||||
var _p2I = path2.clone().translate( [500, 0] );
|
||||
_p1I.style = _p2I.style = pathStyleBoolean;
|
||||
console.time( 'Intersection' );
|
||||
var boolPathI = _p1I.intersect( _p2I );
|
||||
console.timeEnd( 'Intersection' );
|
||||
if( _disperse ){ disperse( boolPathI ); }
|
||||
boolPathI.style = booleanStyle;
|
||||
}
|
||||
|
||||
if( !noSubtraction ) {
|
||||
var _p1S = path1.clone().translate( [750, 0] );
|
||||
var _p2S = path2.clone().translate( [750, 0] );
|
||||
_p1S.style = _p2S.style = pathStyleBoolean;
|
||||
console.time( 'Subtraction' );
|
||||
var boolPathS = _p1S.subtract( _p2S );
|
||||
console.timeEnd( 'Subtraction' );
|
||||
if( _disperse ){ disperse( boolPathS ); }
|
||||
boolPathS.style = booleanStyle;
|
||||
}
|
||||
// } catch( e ){
|
||||
// console.error( e.name + ": " + e.message );
|
||||
// if( caption ) { caption.className += ' error'; }
|
||||
// // paper.project.view.element.className += ' hide';
|
||||
// } finally {
|
||||
console.timeEnd( 'Union' );
|
||||
console.timeEnd( 'Intersection' );
|
||||
console.timeEnd( 'Subtraction' );
|
||||
view.draw();
|
||||
// }
|
||||
}
|
||||
|
||||
function disperse( path, distance ){
|
||||
distance = distance || 10;
|
||||
if( ! path instanceof CompoundPath ){ return; }
|
||||
var center = path.bounds.center;
|
||||
var children = path.children, i ,len;
|
||||
for (i = 0, len = children.length; i < len; i++) {
|
||||
var cCenter = children[i].bounds.center;
|
||||
var vec = cCenter.subtract( center );
|
||||
vec = ( vec.isClose( [0,0], 0.5 ) )? vec : vec.normalize( distance );
|
||||
children[i].translate( vec );
|
||||
}
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// On screen debug helpers
|
||||
function markPoint( pnt, t, c, tc, remove ) {
|
||||
if( !pnt ) return;
|
||||
c = c || '#000';
|
||||
if( remove === undefined ){ remove = true; }
|
||||
var cir = new Path.Circle( pnt, 2 );
|
||||
cir.style.fillColor = c;
|
||||
cir.style.strokeColor = tc;
|
||||
if( t !== undefined || t !== null ){
|
||||
var text = new PointText( pnt.add([0, -3]) );
|
||||
text.justification = 'center';
|
||||
text.fillColor = c;
|
||||
text.content = t;
|
||||
if( remove ){
|
||||
text.removeOnMove();
|
||||
}
|
||||
}
|
||||
if( remove ) {
|
||||
cir.removeOnMove();
|
||||
}
|
||||
}
|
||||
|
||||
function annotatePath( path, t, c, tc, remove ) {
|
||||
if( !path ) return;
|
||||
var crvs = path.curves;
|
||||
for (i = crvs.length - 1; i >= 0; i--) {
|
||||
annotateCurve( crvs[i], t, c, tc, remove );
|
||||
}
|
||||
var segs = path.segments;
|
||||
for (i = segs.length - 1; i >= 0; i--) {
|
||||
annotateSegment( segs[i], t, c, tc, remove, true );
|
||||
}
|
||||
}
|
||||
|
||||
function annotateSegment( s, t, c, tc, remove, skipCurves ) {
|
||||
if( !s ) return;
|
||||
c = c || '#000';
|
||||
tc = tc || '#ccc';
|
||||
t = t || s.index;
|
||||
if( remove === undefined ){ remove = true; }
|
||||
var crv = s.curve;
|
||||
var t1 = crv.getNormal( 0 ).normalize( 10 );
|
||||
var p = s.point.clone().add( t1 );
|
||||
var cir = new Path.Circle( s.point, 2 );
|
||||
cir.style.fillColor = c;
|
||||
cir.style.strokeColor = tc;
|
||||
var text = new PointText( p );
|
||||
text.justification = 'center';
|
||||
text.fillColor = c;
|
||||
text.content = t;
|
||||
if( remove ) {
|
||||
cir.removeOnMove();
|
||||
text.removeOnMove();
|
||||
}
|
||||
if( !skipCurves ) {
|
||||
annotateCurve( s.curveIn, null, c, tc, remove );
|
||||
annotateCurve( s.curveOut, null, c, tc, remove );
|
||||
}
|
||||
}
|
||||
|
||||
function annotateCurve( crv, t, c, tc, remove ) {
|
||||
if( !crv ) return;
|
||||
c = c || '#000';
|
||||
tc = tc || '#ccc';
|
||||
t = t || crv.index;
|
||||
if( remove === undefined ){ remove = true; }
|
||||
var p = crv.getPoint( 0.57 );
|
||||
var t1 = crv.getTangent( 0.57 ).normalize( -10 );
|
||||
var p2 = p.clone().add( t1 );
|
||||
var l = new Path.Line( p, p2 ).rotate( 30, p );
|
||||
var l2 = new Path.Line( p, p2 ).rotate( -30, p );
|
||||
p = crv.getPoint( 0.43 );
|
||||
var cir = new Path.Circle( p, 8 );
|
||||
var text = new PointText( p.subtract( [0, -4] ) );
|
||||
text.justification = 'center';
|
||||
text.fillColor = tc;
|
||||
text.content = t;
|
||||
l.style.strokeColor = l2.style.strokeColor = c;
|
||||
cir.style.fillColor = c;
|
||||
if( remove ) {
|
||||
l.removeOnMove();
|
||||
l2.removeOnMove();
|
||||
cir.removeOnMove();
|
||||
text.removeOnMove();
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
|
||||
paper.PathItem.prototype.getIntersections = function(path) {
|
||||
// First check the bounds of the two paths. If they don't intersect,
|
||||
// we don't need to iterate through their curves.
|
||||
if (!this.getBounds().touches(path.getBounds()))
|
||||
return [];
|
||||
var locations = [],
|
||||
curves1 = this.getCurves(),
|
||||
curves2 = path.getCurves(),
|
||||
length2 = curves2.length,
|
||||
values2 = [];
|
||||
for (var i = 0; i < length2; i++)
|
||||
values2[i] = curves2[i].getValues();
|
||||
for (var i = 0, l = curves1.length; i < l; i++) {
|
||||
var curve = curves1[i],
|
||||
values1 = curve.getValues();
|
||||
for (var j = 0; j < length2; j++)
|
||||
Curve.getIntersections(values1, values2[j], curve, curves2[j], locations);
|
||||
}
|
||||
return locations;
|
||||
};
|
||||
|
||||
|
||||
paper.Curve.getIntersections = function(v1, v2, curve, curve2, locations) {
|
||||
var bounds1 = this.getBounds(v1),
|
||||
bounds2 = this.getBounds(v2);
|
||||
if (bounds1.touches(bounds2)) {
|
||||
// See if both curves are flat enough to be treated as lines, either
|
||||
// because they have no control points at all, or are "flat enough"
|
||||
if ((this.isLinear(v1)
|
||||
|| this.isFlatEnough(v1, /*#=*/ Numerical.TOLERANCE))
|
||||
&& (this.isLinear(v2)
|
||||
|| this.isFlatEnough(v2, /*#=*/ Numerical.TOLERANCE))) {
|
||||
// See if the parametric equations of the lines interesct.
|
||||
var point = new Line(v1[0], v1[1], v1[6], v1[7], false)
|
||||
.intersect(new Line(v2[0], v2[1], v2[6], v2[7], false));
|
||||
if (point) {
|
||||
// Avoid duplicates when hitting segments (closed paths too)
|
||||
var first = locations[0],
|
||||
last = locations[locations.length - 1];
|
||||
if ((!first || !point.equals(first._point))
|
||||
&& (!last || !point.equals(last._point))){
|
||||
// Passing null for parameter leads to lazy determination
|
||||
// of parameter values in CurveLocation#getParameter()
|
||||
// only once they are requested.
|
||||
var cloc = new CurveLocation(curve, null, point);
|
||||
var cloc2 = new CurveLocation(curve2, null, point)
|
||||
cloc2._ixPair = cloc;
|
||||
cloc._ixPair = cloc2;
|
||||
locations.push( cloc );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Subdivide both curves, and see if they intersect.
|
||||
var v1s = this.subdivide(v1),
|
||||
v2s = this.subdivide(v2);
|
||||
for (var i = 0; i < 2; i++)
|
||||
for (var j = 0; j < 2; j++)
|
||||
this.getIntersections(v1s[i], v2s[j], curve, curve2, locations);
|
||||
}
|
||||
}
|
||||
return locations;
|
||||
};
|
Loading…
Reference in a new issue