mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-07 13:22:07 -05:00
Merge branch 'master' of https://github.com/paperjs/paper.js
* 'master' of https://github.com/paperjs/paper.js: (90 commits) Start merging fat-line clipping code into Curve class. Fix white-spaces. Merge handling of flat curves. More getConvexHull() clean up. Remove unused variable dqmin. Further clean up clipFatLine() Some clean up in clipFatLine() Merge the two convergence checks to one. Simplify convergence checks. Rename p\d to part\d Rename v\dt to range\d Simplify handling of ranges and curve parts. Switch to using arrays rather than objects for parameter ranges. Reverse logic of v1t / _v1t naming and switch to using Numerical constants. Re-implement Curve.getLocation2() as "hub" for all the different intersection methods. Use break; instead of return; and untangle unnecessarily nested conditionals. Define private addLocation() to reduce code redundancy. Correctly handle calculation of CurveLocation point in getCurveIntersections(). Move Curve.getIntersection2 to private function and better name other private functions. Always use parameter in getCurveLineIntersection() by flipping curve1 / 2 values as well. ...
This commit is contained in:
commit
46a324722a
15 changed files with 2206 additions and 104 deletions
|
@ -27,7 +27,7 @@
|
|||
VERSION=0.8
|
||||
DATE=$(git log -1 --pretty=format:%ad)
|
||||
|
||||
COMMAND="./prepro.js -d '{ \"version\": $VERSION, \"date\": \"$DATE\", \"parser\": \"acorn\", \"svg\": true }' $3 $2"
|
||||
COMMAND="./prepro.js -d '{ \"version\": $VERSION, \"date\": \"$DATE\", \"parser\": \"acorn\", \"svg\": true, \"fatline\": false }' $3 $2"
|
||||
|
||||
case $1 in
|
||||
commented)
|
||||
|
|
9
fatline/COPYING
Normal file
9
fatline/COPYING
Normal file
|
@ -0,0 +1,9 @@
|
|||
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.
|
424
fatline/Intersect.js
Normal file
424
fatline/Intersect.js
Normal file
|
@ -0,0 +1,424 @@
|
|||
new function() {
|
||||
|
||||
var MAX_RECURSION = 20;
|
||||
var MAX_ITERATION = 20;
|
||||
|
||||
/**
|
||||
* This method is analogous to paperjs#PathItem.getIntersections, but calls
|
||||
* Curve.getIntersections2 instead.
|
||||
*/
|
||||
PathItem.prototype.getIntersections2 = 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 curve1 = curves1[i],
|
||||
values1 = curve1.getValues();
|
||||
for (var j = 0; j < length2; j++)
|
||||
Curve.getIntersections2(values1, values2[j], curve1, curves2[j],
|
||||
locations);
|
||||
}
|
||||
return locations;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method is analogous to paperjs#Curve.getIntersections
|
||||
*/
|
||||
Curve.getIntersections2 = function(v1, v2, curve1, curve2, locations) {
|
||||
var linear1 = Curve.isLinear(v1),
|
||||
linear2 = Curve.isLinear(v2);
|
||||
// Determine the correct intersection method based on values of linear1 & 2:
|
||||
(linear1 && linear2
|
||||
? getLineLineIntersection
|
||||
: linear1 || linear2
|
||||
? getCurveLineIntersections
|
||||
: getCurveIntersections)(v1, v2, curve1, curve2, locations);
|
||||
return locations;
|
||||
};
|
||||
|
||||
function addLocation(locations, curve1, parameter, point, curve2) {
|
||||
// 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)))
|
||||
locations.push(new CurveLocation(curve1, parameter, point, curve2));
|
||||
}
|
||||
|
||||
function getCurveIntersections(v1, v2, curve1, curve2, locations,
|
||||
range1, range2, recursion) {
|
||||
// NOTE: range1 and range1 are only used for recusion
|
||||
recursion = (recursion || 0) + 1;
|
||||
// Avoid endless recursion.
|
||||
// Perhaps we should fall back to a more expensive method after this, but
|
||||
// so far endless recursion happens only when there is no real intersection
|
||||
// and the infinite fatline continue to intersect with the other curve
|
||||
// outside its bounds!
|
||||
if (recursion > MAX_RECURSION)
|
||||
return;
|
||||
// Set up the parameter ranges.
|
||||
range1 = range1 || [ 0, 1 ];
|
||||
range2 = range2 || [ 0, 1 ];
|
||||
// Get the clipped parts from the original curve, to avoid cumulative errors
|
||||
var part1 = Curve.getPart(v1, range1[0], range1[1]),
|
||||
part2 = Curve.getPart(v2, range2[0], range2[1]),
|
||||
iteration = 0;
|
||||
// markCurve(part1, '#f0f', true);
|
||||
// markCurve(part2, '#0ff', false);
|
||||
// Loop until both parameter range converge. We have to handle the
|
||||
// degenerate case seperately, where fat-line clipping can become
|
||||
// numerically unstable when one of the curves has converged to a point and
|
||||
// the other hasn't.
|
||||
while (iteration++ < MAX_ITERATION
|
||||
&& (Math.abs(range1[1] - range1[0]) > /*#=*/ Numerical.TOLERANCE
|
||||
|| Math.abs(range2[1] - range2[0]) > /*#=*/ Numerical.TOLERANCE)) {
|
||||
// First we clip v2 with v1's fat-line
|
||||
var range,
|
||||
intersects1 = clipFatLine(part1, part2, range = range2.slice()),
|
||||
intersects2 = 0;
|
||||
// Stop if there are no possible intersections
|
||||
if (intersects1 === 0)
|
||||
break;
|
||||
if (intersects1 > 0) {
|
||||
// Get the clipped parts from the original v2, to avoid cumulative
|
||||
// errors ...and reuse some objects.
|
||||
range2 = range;
|
||||
part2 = Curve.getPart(v2, range2[0], range2[1]);
|
||||
// markCurve(part2, '#0ff', false);
|
||||
// Next we clip v1 with nuv2's fat-line
|
||||
intersects2 = clipFatLine(part2, part1, range = range1.slice());
|
||||
// Stop if there are no possible intersections
|
||||
if (intersects2 === 0)
|
||||
break;
|
||||
if (intersects1 > 0) {
|
||||
// Get the clipped parts from the original v2, to avoid
|
||||
// cumulative errors
|
||||
range1 = range;
|
||||
part1 = Curve.getPart(v1, range1[0], range1[1]);
|
||||
}
|
||||
// markCurve(part1, '#f0f', true);
|
||||
}
|
||||
// Get the clipped parts from the original v1
|
||||
// Check if there could be multiple intersections
|
||||
if (intersects1 < 0 || intersects2 < 0) {
|
||||
// Subdivide the curve which has converged the least from the
|
||||
// original range [0,1], which would be the curve with the largest
|
||||
// parameter range after clipping
|
||||
if (range1[1] - range1[0] > range2[1] - range2[0]) {
|
||||
// subdivide v1 and recurse
|
||||
var t = (range1[0] + range1[1]) / 2;
|
||||
getCurveIntersections(v1, v2, curve1, curve2, locations,
|
||||
[ range1[0], t ], range2, recursion);
|
||||
getCurveIntersections(v1, v2, curve1, curve2, locations,
|
||||
[ t, range1[1] ], range2, recursion);
|
||||
break;
|
||||
} else {
|
||||
// subdivide v2 and recurse
|
||||
var t = (range2[0] + range2[1]) / 2;
|
||||
getCurveIntersections(v1, v2, curve1, curve2, locations, range1,
|
||||
[ range2[0], t ], recursion);
|
||||
getCurveIntersections(v1, v2, curve1, curve2, locations, range1,
|
||||
[ t, range2[1] ], recursion);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We need to bailout of clipping and try a numerically stable method if
|
||||
// any of the following are true.
|
||||
// 1. One of the parameter ranges is converged to a point.
|
||||
// 2. Both of the parameter ranges have converged reasonably well
|
||||
// (according to Numerical.TOLERANCE).
|
||||
// 3. One of the parameter range is converged enough so that it is
|
||||
// *flat enough* to calculate line curve intersection implicitly.
|
||||
//
|
||||
// Check if one of the parameter range has converged completely to a
|
||||
// point. Now things could get only worse if we iterate more for the
|
||||
// other curve to converge if it hasn't yet happened so.
|
||||
var converged1 = Math.abs(range1[1] - range1[0]) < /*#=*/ Numerical.TOLERANCE,
|
||||
converged2 = Math.abs(range2[1] - range2[0]) < /*#=*/ Numerical.TOLERANCE;
|
||||
if (converged1 || converged2) {
|
||||
addLocation(locations, curve1, null, converged1
|
||||
? curve1.getPointAt(range1[0], true)
|
||||
: curve2.getPointAt(range2[0], true), curve2);
|
||||
break;
|
||||
}
|
||||
// see if either or both of the curves are flat enough to be treated
|
||||
// as lines.
|
||||
var flat1 = Curve.isFlatEnough(part1, /*#=*/ Numerical.TOLERANCE),
|
||||
flat2 = Curve.isFlatEnough(part2, /*#=*/ Numerical.TOLERANCE);
|
||||
if (flat1 || flat2) {
|
||||
(flat1 && flat2
|
||||
? getLineLineIntersection
|
||||
// Use curve line intersection method while specifying
|
||||
// which curve to be treated as line
|
||||
: getCurveLineIntersections)(part1, part2,
|
||||
curve1, curve2, locations, flat1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clip curve V2 with fat-line of v1
|
||||
* @param {Array} v1 section of the first curve, for which we will make a
|
||||
* fat-line
|
||||
* @param {Array} v2 section of the second curve; we will clip this curve with
|
||||
* the fat-line of v1
|
||||
* @param {Array} range2 the parameter range of v2
|
||||
* @return {Number} 0: no Intersection, 1: one intersection, -1: more than one
|
||||
* ntersection
|
||||
*/
|
||||
function clipFatLine(v1, v2, range2) {
|
||||
// P = first curve, Q = second curve
|
||||
var p0x = v1[0], p0y = v1[1], p1x = v1[2], p1y = v1[3],
|
||||
p2x = v1[4], p2y = v1[5], p3x = v1[6], p3y = v1[7],
|
||||
q0x = v2[0], q0y = v2[1], q1x = v2[2], q1y = v2[3],
|
||||
q2x = v2[4], q2y = v2[5], q3x = v2[6], q3y = v2[7],
|
||||
// Calculate the fat-line L for P is the baseline l and two
|
||||
// offsets which completely encloses the curve P.
|
||||
d1 = getSignedDistance(p0x, p0y, p3x, p3y, p1x, p1y) || 0,
|
||||
d2 = getSignedDistance(p0x, p0y, p3x, p3y, p2x, p2y) || 0,
|
||||
factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
|
||||
dmin = factor * Math.min(0, d1, d2),
|
||||
dmax = factor * Math.max(0, d1, d2),
|
||||
// Calculate non-parametric bezier curve D(ti, di(t)) - di(t) is the
|
||||
// distance of Q from the baseline l of the fat-line, ti is equally
|
||||
// spaced in [0, 1]
|
||||
dq0 = getSignedDistance(p0x, p0y, p3x, p3y, q0x, q0y),
|
||||
dq1 = getSignedDistance(p0x, p0y, p3x, p3y, q1x, q1y),
|
||||
dq2 = getSignedDistance(p0x, p0y, p3x, p3y, q2x, q2y),
|
||||
dq3 = getSignedDistance(p0x, p0y, p3x, p3y, q3x, q3y),
|
||||
// Find the minimum and maximum distances from l, this is useful for
|
||||
// checking whether the curves intersect with each other or not.
|
||||
mindist = Math.min(dq0, dq1, dq2, dq3),
|
||||
maxdist = Math.max(dq0, dq1, dq2, dq3);
|
||||
// If the fatlines don't overlap, we have no intersections!
|
||||
if (dmin > maxdist || dmax < mindist)
|
||||
return 0;
|
||||
var Dt = getConvexHull(dq0, dq1, dq2, dq3),
|
||||
tmp;
|
||||
if (dq3 < dq0) {
|
||||
tmp = dmin;
|
||||
dmin = dmax;
|
||||
dmax = tmp;
|
||||
}
|
||||
// Calculate the convex hull for non-parametric bezier curve D(ti, di(t))
|
||||
// Now we clip the convex hulls for D(ti, di(t)) with dmin and dmax
|
||||
// for the coorresponding t values (tmin, tmax): Portions of curve v2 before
|
||||
// tmin and after tmax can safely be clipped away
|
||||
var tmaxdmin = -Infinity,
|
||||
tmin = Infinity,
|
||||
tmax = -Infinity;
|
||||
for (var i = 0, l = Dt.length; i < l; i++) {
|
||||
var Dtl = Dt[i],
|
||||
dtlx1 = Dtl[0],
|
||||
dtly1 = Dtl[1],
|
||||
dtlx2 = Dtl[2],
|
||||
dtly2 = Dtl[3];
|
||||
if (dtly2 < dtly1) {
|
||||
tmp = dtly2;
|
||||
dtly2 = dtly1;
|
||||
dtly1 = tmp;
|
||||
tmp = dtlx2;
|
||||
dtlx2 = dtlx1;
|
||||
dtlx1 = tmp;
|
||||
}
|
||||
// We know that (dtlx2 - dtlx1) is never 0
|
||||
var inv = (dtly2 - dtly1) / (dtlx2 - dtlx1);
|
||||
if (dmin >= dtly1 && dmin <= dtly2) {
|
||||
var ixdx = dtlx1 + (dmin - dtly1) / inv;
|
||||
if (ixdx < tmin)
|
||||
tmin = ixdx;
|
||||
if (ixdx > tmaxdmin)
|
||||
tmaxdmin = ixdx;
|
||||
}
|
||||
if (dmax >= dtly1 && dmax <= dtly2) {
|
||||
var ixdx = dtlx1 + (dmax - dtly1) / inv;
|
||||
if (ixdx > tmax)
|
||||
tmax = ixdx;
|
||||
if (ixdx < tmin)
|
||||
tmin = 0;
|
||||
}
|
||||
}
|
||||
// Return the parameter values for v2 for which we can be sure that the
|
||||
// intersection with v1 lies within.
|
||||
if (tmin !== Infinity && tmax !== -Infinity) {
|
||||
var mindmin = Math.min(dmin, dmax),
|
||||
mindmax = Math.max(dmin, dmax);
|
||||
if (dq3 > mindmin && dq3 < mindmax)
|
||||
tmax = 1;
|
||||
if (dq0 > mindmin && dq0 < mindmax)
|
||||
tmin = 0;
|
||||
if (tmaxdmin > tmax)
|
||||
tmax = 1;
|
||||
// tmin and tmax are within the range (0, 1). We need to project it to
|
||||
// the original parameter range for v2.
|
||||
var v2tmin = range2[0],
|
||||
tdiff = range2[1] - v2tmin;
|
||||
range2[0] = v2tmin + tmin * tdiff;
|
||||
range2[1] = v2tmin + tmax * tdiff;
|
||||
// If the new parameter range fails to converge by atleast 20% of the
|
||||
// original range, possibly we have multiple intersections. We need to
|
||||
// subdivide one of the curves.
|
||||
if ((tdiff - (range2[1] - range2[0])) / tdiff >= 0.2)
|
||||
return 1;
|
||||
}
|
||||
// TODO: Try checking with a perpendicular fatline to see if the curves
|
||||
// overlap if it is any faster than this
|
||||
if (Curve.getBounds(v1).touches(Curve.getBounds(v2)))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the convex hull for the non-paramertic bezier curve D(ti, di(t)).
|
||||
* The ti is equally spaced across [0..1] — [0, 1/3, 2/3, 1] for
|
||||
* di(t), [dq0, dq1, dq2, dq3] respectively. In other words our CVs for the
|
||||
* curve are already sorted in the X axis in the increasing order. Calculating
|
||||
* convex-hull is much easier than a set of arbitrary points.
|
||||
*/
|
||||
function getConvexHull(dq0, dq1, dq2, dq3) {
|
||||
var distq1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1),
|
||||
distq2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2);
|
||||
// Check if [1/3, dq1] and [2/3, dq2] are on the same side of line
|
||||
// [0,dq0, 1,dq3]
|
||||
if (distq1 * distq2 < 0) {
|
||||
// dq1 and dq2 lie on different sides on [0, q0, 1, q3]. The hull is a
|
||||
// quadrilateral and line [0, q0, 1, q3] is NOT part of the hull so we
|
||||
// are pretty much done here.
|
||||
return [
|
||||
[ 0, dq0, 1 / 3, dq1 ],
|
||||
[ 1 / 3, dq1, 1, dq3 ],
|
||||
[ 2 / 3, dq2, 0, dq0 ],
|
||||
[ 1, dq3, 2 / 3, dq2 ]
|
||||
];
|
||||
}
|
||||
// dq1 and dq2 lie on the same sides on [0, q0, 1, q3]. The hull can be
|
||||
// a triangle or a quadrilateral and line [0, q0, 1, q3] is part of the
|
||||
// hull. Check if the hull is a triangle or a quadrilateral.
|
||||
var dqMaxX, dqMaxY, vqa1a2X, vqa1a2Y, vqa1MaxX, vqa1MaxY, vqa1MinX, vqa1MinY;
|
||||
if (Math.abs(distq1) > Math.abs(distq2)) {
|
||||
dqMaxX = 1 / 3;
|
||||
dqMaxY = dq1;
|
||||
// apex is dq3 and the other apex point is dq0 vector
|
||||
// dqapex->dqapex2 or base vector which is already part of the hull.
|
||||
vqa1a2X = 1;
|
||||
vqa1a2Y = dq3 - dq0;
|
||||
// vector dqapex->dqMax
|
||||
vqa1MaxX = 2 / 3;
|
||||
vqa1MaxY = dq3 - dq1;
|
||||
// vector dqapex->dqmin
|
||||
vqa1MinX = 1 / 3;
|
||||
vqa1MinY = dq3 - dq2;
|
||||
} else {
|
||||
dqMaxX = 2 / 3;
|
||||
dqMaxY = dq2;
|
||||
// apex is dq0 in this case, and the other apex point is dq3 vector
|
||||
// dqapex->dqapex2 or base vector which is already part of the hull.
|
||||
vqa1a2X = -1;
|
||||
vqa1a2Y = dq0 - dq3;
|
||||
// vector dqapex->dqMax
|
||||
vqa1MaxX = -2 / 3;
|
||||
vqa1MaxY = dq0 - dq2;
|
||||
// vector dqapex->dqmin
|
||||
vqa1MinX = -1 / 3;
|
||||
vqa1MinY = dq0 - dq1;
|
||||
}
|
||||
// Compare cross products of these vectors to determine, if
|
||||
// point is in triangles [ dq3, dqMax, dq0 ] or [ dq0, dqMax, dq3 ]
|
||||
var a1a2_a1Min = vqa1a2X * vqa1MinY - vqa1a2Y * vqa1MinX,
|
||||
a1Max_a1Min = vqa1MaxX * vqa1MinY - vqa1MaxY * vqa1MinX;
|
||||
return a1a2_a1Min * a1Max_a1Min < 0
|
||||
// Point [2/3, dq2] is inside the triangle, the hull is a triangle.
|
||||
? [
|
||||
[ 0, dq0, dqMaxX, dqMaxY ],
|
||||
[ dqMaxX, dqMaxY, 1, dq3 ],
|
||||
[ 1, dq3, 0, dq0 ]
|
||||
]
|
||||
// Convexhull is a quadrilateral and we need all lines in the
|
||||
// correct order where line [0, q0, 1, q3] is part of the hull.
|
||||
: [
|
||||
[ 0, dq0, 1 / 3, dq1 ],
|
||||
[ 1 / 3, dq1, 2 / 3, dq2 ],
|
||||
[ 2 / 3, dq2, 1, dq3 ],
|
||||
[ 1, dq3, 0, dq0 ]
|
||||
];
|
||||
}
|
||||
|
||||
// This is basically an "unrolled" version of #Line.getDistance() with sign
|
||||
// May be a static method could be better!
|
||||
function getSignedDistance(a1x, a1y, a2x, a2y, bx, by) {
|
||||
var m = (a2y - a1y) / (a2x - a1x),
|
||||
b = a1y - (m * a1x);
|
||||
return (by - (m * bx) - b) / Math.sqrt(m * m + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersections between curve and line becomes rather simple here mostly
|
||||
* because of Numerical class. We can rotate the curve and line so that the line
|
||||
* is on X axis, and solve the implicit equations for X axis and the curve.
|
||||
*/
|
||||
function getCurveLineIntersections(v1, v2, curve1, curve2, locations, flip) {
|
||||
if (flip === undefined)
|
||||
flip = Curve.isLinear(v1);
|
||||
var vc = flip ? v2 : v1,
|
||||
vl = flip ? v1 : v2,
|
||||
l1x = vl[0], l1y = vl[1],
|
||||
l2x = vl[6], l2y = vl[7],
|
||||
// Rotate both the curve and line around l1 so that line is on x axis
|
||||
lvx = l2x - l1x,
|
||||
lvy = l2y - l1y,
|
||||
// Angle with x axis (1, 0)
|
||||
angle = Math.atan2(-lvy, lvx),
|
||||
sin = Math.sin(angle),
|
||||
cos = Math.cos(angle),
|
||||
// (rl1x, rl1y) = (0, 0)
|
||||
rl2x = lvx * cos - lvy * sin,
|
||||
rl2y = lvy * cos + lvx * sin,
|
||||
vcr = [];
|
||||
|
||||
for(var i = 0; i < 8; i += 2) {
|
||||
var x = vc[i] - l1x,
|
||||
y = vc[i + 1] - l1y;
|
||||
vcr.push(
|
||||
x * cos - y * sin,
|
||||
y * cos + x * sin);
|
||||
}
|
||||
var roots = [],
|
||||
count = Curve.solveCubic(vcr, 1, 0, roots);
|
||||
// NOTE: count could theoretically be -1 for inifnite solutions, although
|
||||
// that should only happen with lines, in which case we should not be here.
|
||||
for (var i = 0; i < count; i++) {
|
||||
var t = roots[i];
|
||||
if (t >= 0 && t <= 1) {
|
||||
var point = Curve.evaluate(vcr, t, true, 0);
|
||||
// We do have a point on the infinite line. Check if it falls on the
|
||||
// line *segment*.
|
||||
if (point.x >= 0 && point.x <= rl2x)
|
||||
addLocation(locations,
|
||||
flip ? curve2 : curve1,
|
||||
// The actual intersection point
|
||||
t, Curve.evaluate(vc, t, true, 0),
|
||||
flip ? curve1 : curve2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getLineLineIntersection(v1, v2, curve1, curve2, locations) {
|
||||
var point = Line.intersect(
|
||||
v1[0], v1[1], v1[6], v1[7],
|
||||
v2[0], v2[1], v2[6], v2[7], false);
|
||||
// Passing null for parameter leads to lazy determination of parameter
|
||||
// values in CurveLocation#getParameter() only once they are requested.
|
||||
if (point)
|
||||
addLocation(locations, curve1, null, point, curve2);
|
||||
}
|
||||
|
||||
};
|
4
fatline/README.md
Normal file
4
fatline/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
|
||||
------
|
||||
Harikrishnan Gopalakrishnan
|
471
fatline/intersectStudy.html
Normal file
471
fatline/intersectStudy.html
Normal file
|
@ -0,0 +1,471 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Poly-bézier path Intersection Study</title>
|
||||
<script type="text/javascript" src="../lib/prepro.js"></script>
|
||||
<script type="text/javascript" src="../src/load.js"></script>
|
||||
<script type="text/javascript" src="Intersect.js"></script>
|
||||
<script type="text/javascript" src="intersectTests.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; margin: 30px auto; color: #999; }
|
||||
footer p, footer a { font-family: 'Helvetica Neue'; font-style: italic; font-weight: 300; }
|
||||
canvas { cursor: crosshair; width: 100%; height: 220px; margin: 5px 0;} canvas.big { height: 400px;}
|
||||
footer ul{ list-style: none; padding: 0; } footer ul li p, footer ul li a{ font-style: normal; }
|
||||
footer ul li a{ margin-left: 2em; } canvas.big2 { height: 300px;}
|
||||
footer ul li.caption p {font-weight: bold; opacity: 0.6; }
|
||||
.error { color: #a00; } .hide{ display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
<h1>Cubic bézier fat-line clipping study (using paperjs)</h1>
|
||||
<button id="testStart" value="Start tests" onClick="runTests();">Start tests</button>
|
||||
</div>
|
||||
<footer>
|
||||
<p>Fat-line clipping and other operations on cubic bézier curves.</p>
|
||||
<ul>
|
||||
<li class="caption"><p>References</p></li>
|
||||
<li><a href="http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf">T. W. Sederberg, T. Nishita – Curve intersection using bezier clipping.</a></li>
|
||||
</ul>
|
||||
<p>--<br />
|
||||
hari</p>
|
||||
</footer>
|
||||
|
||||
<svg class="hide" version="1.1" id="svgrandom2" 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">
|
||||
</svg>
|
||||
<svg class="hide" version="1.1" id="svgrandom1" 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 d="M121.938,15.632c-13.717-12.536 -86.488,106.314 -97.28853,96.70168c-10.79979,-9.61253 74.75206,22.03522 62.05339,14.94206c-12.69866,-7.09316 -39.33589,-120.29063 -50.13215,-122.55235c-10.79626,-2.26173 20.61549,120.92844 6.21122,120.91582c-14.40427,-0.01263 95.8736,-97.47028 79.15607,-110.0072z" />
|
||||
<path d="M112.56135,26.45534c-11.3324,-19.66938 2.46546,15.5079 -15.74899,1.46029c-18.21444,-14.04761 -66.32694,49.96681 -85.68888,45.03851c-19.36194,-4.9283 25.00762,66.13871 9.65758,51.54906c-15.35004,-14.58966 80.2128,-61.80948 76.57166,-81.27628c-3.64115,-19.4668 26.54102,2.89779 15.20863,-16.77158z" />
|
||||
</svg>
|
||||
<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>
|
828
fatline/intersectTests.js
Normal file
828
fatline/intersectTests.js
Normal file
|
@ -0,0 +1,828 @@
|
|||
|
||||
paper.install(window);
|
||||
|
||||
/**
|
||||
* http://stackoverflow.com/questions/6875625/does-javascript-provide-a-high-resolution-timer
|
||||
*/
|
||||
if (window.performance && window.performance.now) {
|
||||
console.log("Using high performance timer");
|
||||
getTimestamp = function() { return window.performance.now(); };
|
||||
} else {
|
||||
if (window.performance && window.performance.webkitNow) {
|
||||
console.log("Using webkit high performance timer");
|
||||
getTimestamp = function() { return window.performance.webkitNow(); };
|
||||
} else {
|
||||
console.log("Using low performance timer");
|
||||
getTimestamp = function() { return new Date().getTime(); };
|
||||
}
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
var caption, pathA, pathB, group, testdata = [], randomtestdata = [], testQueued = 0, testExecuted = 0;
|
||||
|
||||
var container = document.getElementById('container');
|
||||
|
||||
function runTest(testName, handler) {
|
||||
var caption = document.createElement('h3');
|
||||
var canvas = document.createElement('canvas');
|
||||
caption.appendChild(document.createTextNode(testName));
|
||||
container.appendChild(caption);
|
||||
container.appendChild(canvas);
|
||||
++testQueued;
|
||||
setTimeout(function() {
|
||||
console.log('\n' + testName);
|
||||
paper.setup(canvas);
|
||||
var paths = handler();
|
||||
var success = testIntersections(paths[0], paths[1], caption, testName, testdata);
|
||||
if (!success) {
|
||||
window.p1 = paths[0].exportSVG();
|
||||
window.p2 = paths[1].exportSVG();
|
||||
}
|
||||
testExecuted++;
|
||||
if (testExecuted === testQueued) {
|
||||
plotData();
|
||||
}
|
||||
}, 0);
|
||||
return caption;
|
||||
}
|
||||
|
||||
var caption = document.createElement('h3');
|
||||
caption.appendChild(document.createTextNode("Randomised tests (may take a while...)"));
|
||||
container.appendChild(caption);
|
||||
var canvas = document.createElement('CANVAS');
|
||||
container.appendChild(canvas);
|
||||
paper.setup(canvas);
|
||||
doRandomTests(randomtestdata);
|
||||
window.d = randomtestdata;
|
||||
container.removeChild(canvas);
|
||||
|
||||
runTest('random', function() {
|
||||
pathA = getRandomPath(20);
|
||||
pathB = getRandomPath(20);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('failcase 1', function() {
|
||||
group = paper.project.importSVG(document.getElementById('svgrandom1'));
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
pathA.style = pathB.style = null;
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Overlapping circles', function() {
|
||||
pathA = new Path.Circle(new Point(80, 110), 50);
|
||||
pathB = new Path.Circle(new Point(150, 110), 70);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Polygon and square', function() {
|
||||
pathA = new Path.RegularPolygon(new Point(80, 110), 12, 80);
|
||||
pathB = new Path.Rectangle(new Point(100, 80), [80, 80]);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Circle and square (overlaps exactly on existing segments)', function() {
|
||||
pathA = new Path.Circle(new Point(110, 110), 80);
|
||||
pathB = new Path.Rectangle(new Point(110, 110), [80, 80]);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Circle and square (existing segments overlaps on curves)', function() {
|
||||
pathA = new Path.Circle(new Point(110, 110), 80);
|
||||
pathB = new Path.Rectangle(new Point(110, 110), [100, 100]);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Square and square (one segment overlaps on a line)', function() {
|
||||
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]);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Rectangle and rectangle (overlaps exactly on existing curves)', function() {
|
||||
pathA = new Path.Rectangle(new Point(30.5, 50.5), [100, 150]);
|
||||
pathB = new Path.Rectangle(new Point(130.5, 60.5), [100, 150]);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Overlapping stars 1', function() {
|
||||
pathA = new Path.Star(new Point(80, 110), 10, 20, 80);
|
||||
pathB = new Path.Star(new Point(120, 110), 10, 30, 100);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Overlapping stars 2', function() {
|
||||
pathA = new Path.Star(new Point(110, 110), 20, 20, 80);
|
||||
pathB = new Path.Star(new Point(110, 110), 6, 30, 100);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Circle and banana (multiple intersections within same curve segment)', function() {
|
||||
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 ]);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Maximum possible intersections between 2 cubic bezier curve segments - 9', function() {
|
||||
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]);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('SVG gears', function() {
|
||||
group = paper.project.importSVG(document.getElementById('svggears'));
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('Glyphs imported from SVG', function() {
|
||||
group = paper.project.importSVG(document.getElementById('glyphsys'));
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('CompoundPaths 1', function() {
|
||||
group = paper.project.importSVG(document.getElementById('glyphsacirc'));
|
||||
pathA = group.children[0];
|
||||
pathB = group.children[1];
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('CompoundPaths 2 - holes', function() {
|
||||
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);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('CompoundPaths 3 !', function() {
|
||||
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);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('CompoundPaths 4 - holes and islands 1', function() {
|
||||
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);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('CompoundPaths 5 - holes and islands 2', function() {
|
||||
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);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('CompoundPaths 6 - holes and islands 3', function() {
|
||||
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);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
runTest('CompoundPaths 6 - holes and islands 4 (curves overlap exactly on existing curves)', function() {
|
||||
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]);
|
||||
return [pathA, pathB];
|
||||
});
|
||||
|
||||
|
||||
// Plot the run times
|
||||
function plotData() {
|
||||
prepareTest('Results - Random tests (Intersections/Curve vs Time)', container, 'big2');
|
||||
plotDataRandom(randomtestdata);
|
||||
|
||||
prepareTest('Results - Boolean tests (Time taken per test)', container, 'big');
|
||||
var x = 80.5, y = 15.5, width = 500, height = 190, i, txt, ny,
|
||||
yy = y + height, xx = x + width;
|
||||
var ppaperfill = new Path(), pfatfill = new Path();
|
||||
var ppaper = new Path(), pfat = new Path();
|
||||
var max = testdata.reduce(function(a, b) { return Math.max(a, b.paperTime + b.fatTime); }, 0) + 20;
|
||||
var vscale = height / max, hscale = width / testdata.length;
|
||||
var caxes = '#999', ctxt = '#222', ctxt2 = '#555', cpaper = '#268BD2', cpaperfill ='#B5E1FF',
|
||||
cfat = '#D33682', cfatfill = '#FFADD4';
|
||||
new Path.Line(x, yy, xx, yy).style.strokeColor = caxes;
|
||||
new Path.Line(x, yy, x, y).style.strokeColor = caxes;
|
||||
for (i = 0; i < 10 ; i++) {
|
||||
ny = yy - vscale * max * i / 10;
|
||||
new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes;
|
||||
txt = new PointText([x-10, ny]);
|
||||
txt.justification = 'right';
|
||||
txt.fillColor = (i%2)? ctxt: ctxt2;
|
||||
txt.content = (max * i / 10).toFixed(1) + ((!i)? ' ms' : '');
|
||||
}
|
||||
ppaperfill.add(new Segment(x, yy));
|
||||
pfatfill.add(new Segment(x, yy));
|
||||
var vx = x, clr = ctxt;
|
||||
var coords = [], avgPaper = 0, avgFat = 0,
|
||||
maxSpeedup = -Infinity, minSpeedup = Infinity, avgSpeedup = 0;
|
||||
testdata.map(function(data) {
|
||||
avgPaper += data.paperTime;
|
||||
ny = yy - (data.paperTime + data.fatTime) * vscale;
|
||||
ppaper.add(new Segment([vx, ny]));
|
||||
ppaperfill.add(new Segment([vx, ny]));
|
||||
var np = new Point(vx, ny);
|
||||
np._data = data;
|
||||
np._datatype = 'paper';
|
||||
coords.push(np);
|
||||
avgFat += data.fatTime;
|
||||
ny = yy - (data.fatTime) * vscale;
|
||||
pfat.add(new Segment([vx, ny]));
|
||||
pfatfill.add(new Segment([vx, ny]));
|
||||
np = new Point(vx, ny);
|
||||
np._data = data;
|
||||
np._datatype = 'fat';
|
||||
coords.push(np);
|
||||
|
||||
var speedup = data.paperTime / data.fatTime;
|
||||
if (speedup > maxSpeedup) maxSpeedup = speedup;
|
||||
if (speedup < minSpeedup) minSpeedup = speedup;
|
||||
avgSpeedup += speedup;
|
||||
|
||||
new Path.Line(vx, yy, vx, yy + 5).style.strokeColor = caxes;
|
||||
txt = new PointText([vx, yy+18]);
|
||||
txt.justification = 'left';
|
||||
txt.fillColor = clr;
|
||||
txt.content = data.name;
|
||||
txt.rotate(30, new Point(vx, yy+10));
|
||||
|
||||
if (!data.success) {
|
||||
var p = new Path.Line(vx, y, vx, yy);
|
||||
p.style.strokeWidth = 5;
|
||||
p.style.strokeColor = '#f00';
|
||||
}
|
||||
|
||||
clr = (clr === ctxt)? ctxt2 : ctxt;
|
||||
vx += hscale;
|
||||
});
|
||||
ppaper.style.strokeWidth = 2;
|
||||
ppaper.style.strokeColor = cpaper;
|
||||
ppaperfill.add(new Segment(vx-hscale, yy));
|
||||
ppaperfill.closed = true;
|
||||
ppaperfill.style.fillColor = cpaperfill;
|
||||
pfat.style.strokeWidth = 2;
|
||||
pfat.style.strokeColor = cfat;
|
||||
pfatfill.add(new Segment(vx-hscale, yy));
|
||||
pfatfill.closed = true;
|
||||
pfatfill.style.fillColor = cfatfill;
|
||||
|
||||
avgPaper/= testdata.length;
|
||||
avgFat/= testdata.length;
|
||||
avgSpeedup = Math.round(avgSpeedup / testdata.length);
|
||||
maxSpeedup = Math.round(maxSpeedup);
|
||||
minSpeedup = Math.round(minSpeedup);
|
||||
ny = Math.round(yy - avgPaper * vscale) + 0.5;
|
||||
new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper;
|
||||
txt = new PointText([xx, ny]);
|
||||
txt.justification = 'right';
|
||||
txt.fillColor = cpaper;
|
||||
txt.content = avgPaper.toFixed(1);
|
||||
ny = Math.round(yy - avgFat * vscale) + 0.5;
|
||||
new Path.Line(x, ny, xx, ny).style.strokeColor = cfat;
|
||||
txt = new PointText([xx, ny]);
|
||||
txt.justification = 'right';
|
||||
txt.fillColor = cfat;
|
||||
txt.content = avgFat.toFixed(1);
|
||||
|
||||
txt = new PointText([610, 75]);
|
||||
txt.justification = 'center';
|
||||
txt.fillColor = '#000';
|
||||
txt.content = 'fatline vs subdiv';
|
||||
new Path.Rectangle([600, 90], [20, 100]).style = { fillColor: '#ccc', strokeColor: '#000' };
|
||||
ny = 190 - (avgSpeedup - minSpeedup) * 100.0 / (maxSpeedup - minSpeedup);
|
||||
new Path.Line([600, ny], [620, ny]).style = { strokeWidth: 2, strokeColor: '#000' };
|
||||
txt = new PointText([630, 95]);
|
||||
txt.fillColor = '#000';
|
||||
txt.content = maxSpeedup;
|
||||
txt = new PointText([630, 195]);
|
||||
txt.fillColor = '#000';
|
||||
txt.content = minSpeedup;
|
||||
txt = new PointText([630, ny+5]);
|
||||
txt.fillColor = '#000';
|
||||
txt.content = avgSpeedup + ' times';
|
||||
view.draw();
|
||||
|
||||
var tool = new Tool();
|
||||
tool.onMouseMove = function(e) {
|
||||
var len = coords.length;
|
||||
var data = null, dist = Infinity, dst, pnt = null, type = 'paper';
|
||||
while (len--) {
|
||||
dst = e.point.getDistance(coords[len], true);
|
||||
if (dst < dist) {
|
||||
pnt = coords[len];
|
||||
data = coords[len]._data;
|
||||
type = coords[len]._datatype;
|
||||
dist = dst;
|
||||
}
|
||||
}
|
||||
if (dist > 500) { return; }
|
||||
if (pnt && data) {
|
||||
var p = new Path.Line(pnt.x+0.5, y, pnt.x+0.5, yy);
|
||||
p.style.strokeColor = '#000';
|
||||
p.removeOnMove();
|
||||
p = new Path.Circle(pnt, 3);
|
||||
p.style.fillColor = (type === 'fat')? '#D33682' :'#268BD2';
|
||||
p.removeOnMove();
|
||||
var txt = new PointText([ 500, 20 ]);
|
||||
txt.content = 'subdiv : ' + data.paperTime.toFixed(1) + ' ms';
|
||||
txt.fillColor = '#222';
|
||||
txt.removeOnMove();
|
||||
txt = new PointText([ 500, 36 ]);
|
||||
txt.content = 'fatline : ' + data.fatTime.toFixed(1) + ' ms';
|
||||
txt.fillColor = '#222';
|
||||
txt.removeOnMove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function prepareTest(testName, parentNode, _big) {
|
||||
console.log('\n' + testName);
|
||||
var caption = document.createElement('h3');
|
||||
caption.appendChild(document.createTextNode(testName));
|
||||
var canvas = document.createElement('CANVAS');
|
||||
canvas.className += ' ' + _big;
|
||||
parentNode.appendChild(caption);
|
||||
parentNode.appendChild(canvas);
|
||||
paper.setup(canvas);
|
||||
return caption;
|
||||
}
|
||||
}
|
||||
|
||||
var pathStyleIx = {
|
||||
fillColor: new Color(0.8, 0, 0),
|
||||
strokeColor: new Color(0, 0, 0)
|
||||
};
|
||||
|
||||
var pathStyleNormal = {
|
||||
strokeColor: new Color(0, 0, 0),
|
||||
// fillColor: new Color(0, 0, 0, 0.1),
|
||||
strokeWidth: 1
|
||||
};
|
||||
|
||||
var pathStyleBoolean = {
|
||||
strokeColor: new Color(0,0,0,0.4),
|
||||
fillColor: new Color(0, 0, 0, 0.0),
|
||||
strokeWidth: 1
|
||||
};
|
||||
|
||||
|
||||
// Better if path1 and path2 fit nicely inside a 200x200 pixels rect
|
||||
function testIntersections(path1, path2, caption, testname, testdata, nomark) {
|
||||
var i, l, maxCount = 10, count = maxCount, st, t1, t2,
|
||||
ixsPaper, ixsFatline, success = false, maxdiff = -Infinity;
|
||||
try {
|
||||
path1.style = path2.style = pathStyleNormal;
|
||||
|
||||
if (!nomark) console.time('paperjs x ' + maxCount);
|
||||
st = getTimestamp();
|
||||
while (count--) {
|
||||
ixsPaper = path1.getIntersections(path2);
|
||||
}
|
||||
t1 = (getTimestamp() - st) / maxCount;
|
||||
if (!nomark) console.timeEnd('paperjs x ' + maxCount);
|
||||
|
||||
count = maxCount;
|
||||
if (!nomark) console.time('fatline x ' + maxCount);
|
||||
st = getTimestamp();
|
||||
while (count--) {
|
||||
ixsFatline = path1.getIntersections2(path2);
|
||||
}
|
||||
t2 = (getTimestamp() - st) / maxCount;
|
||||
if (!nomark) console.timeEnd('fatline x ' + maxCount);
|
||||
|
||||
var found = 0, tol = 0.1;
|
||||
if (ixsFatline.length === ixsPaper.length) {
|
||||
for (i=0, l=ixsFatline.length; i<l; i++) {
|
||||
pa = ixsFatline[i].point;
|
||||
for (j = 0; j < ixsPaper.length; j++) {
|
||||
if (!ixsPaper[j]._found) {
|
||||
pb = ixsPaper[j].point;
|
||||
if (Math.abs(pa.x - pb.x) < tol && Math.abs(pa.y - pb.y) < tol) {
|
||||
++found;
|
||||
ixsPaper[j]._found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
success = ixsPaper.length === found;
|
||||
|
||||
window.pap = ixsPaper;
|
||||
window.fat = ixsFatline;
|
||||
|
||||
if (!nomark) {
|
||||
markIntersections(ixsPaper, '#00f', 'paperjs');
|
||||
markIntersections(ixsFatline, '#f00', 'fatline');
|
||||
}
|
||||
} catch(e) {
|
||||
console.timeEnd('paperjs x ' + maxCount);
|
||||
console.timeEnd('fatline x ' + maxCount);
|
||||
t1 = t2 = 0;
|
||||
console.error(e.name + ": " + e.message);
|
||||
if (caption) { caption.className += ' error'; }
|
||||
} finally {
|
||||
view.draw();
|
||||
testdata.push({
|
||||
name: testname,
|
||||
ratio: ixsFatline.length / (path1.curves.length + path2.curves.length),
|
||||
paperTime: t1,
|
||||
fatTime: t2,
|
||||
success: success
|
||||
});
|
||||
console.log(found);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
function doRandomTests(testdata) {
|
||||
var p1 = new Path(), p2 = new Path(), ixspaper, ixsfat;
|
||||
var seg = 5, maxseg = 30, maxiter = 10;
|
||||
var i, j, halfseg = (maxseg / 2) | 0;
|
||||
var p, hi, ho, st, t1, t2, success;
|
||||
while (seg <= maxseg) {
|
||||
for (i = 0; i < maxiter; i++) {
|
||||
p1.removeSegments();
|
||||
p2.removeSegments();
|
||||
for (j = 0; j < seg; j++) {
|
||||
p = new Point.random().multiply([100, 100]);
|
||||
v = new Point.random().multiply([20, 20]);
|
||||
p1.add(new Segment(p, v, v.multiply(-1)));
|
||||
p1.closed = true;
|
||||
p = new Point.random().multiply([100, 100]);
|
||||
v = new Point.random().multiply([20, 20]);
|
||||
p2.add(new Segment(p, v, v.multiply(-1)));
|
||||
p2.closed = true;
|
||||
}
|
||||
st = getTimestamp();
|
||||
ixspaper = p1.getIntersections(p2);
|
||||
t1 = (getTimestamp() - st);
|
||||
st = getTimestamp();
|
||||
ixsfat = p1.getIntersections2(p2);
|
||||
t2 = (getTimestamp() - st);
|
||||
// Check against paperjs output
|
||||
// tol - tolerence for computed points with in 1/10 th of a pixel
|
||||
var found = 0, tol = 0.1;
|
||||
if (ixsfat.length === ixspaper.length) {
|
||||
for (i=0, l=ixsfat.length; i<l; i++) {
|
||||
pa = ixsfat[i].point;
|
||||
for (j = 0; j < ixspaper.length; j++) {
|
||||
if (!ixspaper[j]._found) {
|
||||
pb = ixspaper[j].point;
|
||||
if (Math.abs(pa.x - pb.x) < tol && Math.abs(pa.y - pb.y) < tol) {
|
||||
++found;
|
||||
ixspaper[j]._found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
success = ixspaper.length === found;
|
||||
testdata.push({
|
||||
curves: p1.curves.length + p2.curves.length,
|
||||
ixsfat: ixsfat.length,
|
||||
ixspaper: ixspaper.length,
|
||||
ratio: ixsfat.length / (seg),
|
||||
paperTime: t1,
|
||||
fatTime: t2,
|
||||
speedup: t1 / t2,
|
||||
success: success
|
||||
});
|
||||
}
|
||||
++seg;
|
||||
if (seg === halfseg) maxiter = (maxiter / 2) | 0;
|
||||
}
|
||||
}
|
||||
|
||||
function getRandomPath(seg) {
|
||||
seg = seg || 3;
|
||||
var p = new Path(), pnt, hi, ho, v;
|
||||
for (j = 0; j < seg; j++) {
|
||||
pnt = new Point.random().multiply([130, 130]);
|
||||
v = new Point.random().multiply([20, 20]);
|
||||
p.add(new Segment(pnt, v, v.multiply(-1)));
|
||||
p.closed = true;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
function markIntersections(ixs, c, txt) {
|
||||
for (i = 0, len = ixs.length; i < len; i++) {
|
||||
// force calculate the parameter for debugging
|
||||
var a = ixs[i].parameter;
|
||||
// markPoint(ixs[i].point, ixs[i].parameter);
|
||||
markPoint(ixs[i].point, ' ', c, null, false);
|
||||
// console.log(txt , ixs[i].parameter)
|
||||
}
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// 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 markCurve(crv, c, flag) {
|
||||
if (!crv) return;
|
||||
c = c || '#000';
|
||||
if (flag) {
|
||||
if (window.__p1) window.__p1.remove();
|
||||
window.__p1 = new Path(
|
||||
new Segment([crv[0], crv[1]], null, [crv[2] - crv[0], crv[3] - crv[1]]),
|
||||
new Segment([crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null)
|
||||
);
|
||||
window.__p1.style.strokeColor = c;
|
||||
// window.__p1.fullySelected = true;
|
||||
} else {
|
||||
if (window.__p2) window.__p2.remove();
|
||||
window.__p2 = new Path(
|
||||
new Segment([crv[0], crv[1]], null, [crv[2] - crv[0], crv[3] - crv[1]]),
|
||||
new Segment([crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null)
|
||||
);
|
||||
window.__p2.style.strokeColor = c;
|
||||
// window.__p2.fullySelected = true;
|
||||
}
|
||||
view.draw();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Plot the run times
|
||||
function plotDataRandom(testdata) {
|
||||
var x = 80.5, y = 15.5, width = 500, height = 190, i, txt, ny,
|
||||
yy = y + height, xx = x + width;
|
||||
var ppaper = new Path(), pfat = new Path();
|
||||
var max = testdata.reduce(function(a, b) { return Math.max(a, b.paperTime, b.fatTime); }, 0) + 20;
|
||||
testdata.sort(function(a,b) { return a.ratio - b.ratio; });
|
||||
var vscale = height / max, hscale = width / testdata.length;
|
||||
var caxes = '#999', ctxt = '#222', cpaper = '#268BD2', cfat = '#D33682';
|
||||
new Path.Line(x, yy, xx, yy).style.strokeColor = caxes;
|
||||
new Path.Line(x, yy, x, y).style.strokeColor = caxes;
|
||||
for (i = 0; i < 10 ; i++) {
|
||||
ny = yy - vscale * max * i / 10;
|
||||
new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes;
|
||||
txt = new PointText([x-10, ny]);
|
||||
txt.justification = 'right';
|
||||
txt.fillColor = ctxt;
|
||||
txt.content = (max * i / 10).toFixed(1) + ((!i)? ' ms' : '');
|
||||
}
|
||||
txt = new PointText([xx + 20, yy + 18 ]);
|
||||
txt.justification = 'left';
|
||||
txt.fillColor = ctxt;
|
||||
txt.content = 'ixs / curve';
|
||||
txt = new PointText([xx + 20, yy + 40]);
|
||||
txt.justification = 'left';
|
||||
txt.fillColor = '#999';
|
||||
txt.content = '(Total Curves)';
|
||||
var vx = x, step = 15, count = 0;
|
||||
var avgPaper = 0, avgFat = 0;
|
||||
testdata.map(function(data) {
|
||||
avgPaper += data.paperTime;
|
||||
ny = yy - (data.paperTime + data.fatTime) * vscale;
|
||||
ppaper.add(new Segment([vx, ny]));
|
||||
avgFat += data.fatTime;
|
||||
ny = yy - (data.fatTime) * vscale;
|
||||
pfat.add(new Segment([vx, ny]));
|
||||
|
||||
new Path.Line(vx, yy, vx, yy + 5 + ((count%2)? step:0)).style.strokeColor = caxes;
|
||||
txt = new PointText([vx, yy+18 + ((count%2)? step:0) ]);
|
||||
txt.justification = 'center';
|
||||
txt.fillColor = ctxt;
|
||||
txt.content = data.ratio.toFixed(1);
|
||||
txt = new PointText([vx -5, yy+40 ]);
|
||||
txt.justification = 'left';
|
||||
txt.fillColor = '#999';
|
||||
txt.content = data.curves;
|
||||
txt.rotate(90, [vx-5, yy+40 ]);
|
||||
|
||||
if (!data.success) {
|
||||
var p = new Path.Line(vx, y, vx, yy);
|
||||
p.style.strokeWidth = 5;
|
||||
p.style.strokeColor = '#f00';
|
||||
}
|
||||
++count;
|
||||
vx += hscale;
|
||||
});
|
||||
ppaper.smooth();
|
||||
ppaper.style.strokeWidth = 2;
|
||||
ppaper.style.strokeColor = cpaper;
|
||||
pfat.smooth();
|
||||
pfat.style.strokeWidth = 2;
|
||||
pfat.style.strokeColor = cfat;
|
||||
|
||||
avgPaper/= testdata.length;
|
||||
avgFat/= testdata.length;
|
||||
ny = Math.round(yy - avgPaper * vscale) + 0.5;
|
||||
new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper;
|
||||
txt = new PointText([xx, ny]);
|
||||
txt.justification = 'right';
|
||||
txt.fillColor = cpaper;
|
||||
txt.content = avgPaper.toFixed(1);
|
||||
ny = Math.round(yy - avgFat * vscale) + 0.5;
|
||||
new Path.Line(x, ny, xx, ny).style.strokeColor = cfat;
|
||||
txt = new PointText([xx, ny]);
|
||||
txt.justification = 'right';
|
||||
txt.fillColor = cfat;
|
||||
txt.content = avgFat.toFixed(1);
|
||||
|
||||
view.draw();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function drawFatline(v1) {
|
||||
function signum(num) {
|
||||
return (num > 0)? 1 : (num < 0)? -1 : 0;
|
||||
}
|
||||
var l = new Line([v1[0], v1[1]], [v1[6], v1[7]], false);
|
||||
var p1 = new Point(v1[2], v1[3]), p2 = new Point(v1[4], v1[5]);
|
||||
var d1 = l.getSide(p1) * l.getDistance(p1) || 0;
|
||||
var d2 = l.getSide(p2) * l.getDistance(p2) || 0;
|
||||
var dmin, dmax;
|
||||
if (d1 * d2 > 0) {
|
||||
// 3/4 * min{0, d1, d2}
|
||||
dmin = 0.75 * Math.min(0, d1, d2);
|
||||
dmax = 0.75 * Math.max(0, d1, d2);
|
||||
} else {
|
||||
// 4/9 * min{0, d1, d2}
|
||||
dmin = 4 * Math.min(0, d1, d2) / 9.0;
|
||||
dmax = 4 * Math.max(0, d1, d2) / 9.0;
|
||||
}
|
||||
var ll = new Path.Line(v1[0], v1[1], v1[6], v1[7]);
|
||||
window.__p3.push(ll);
|
||||
window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9, 0.8);
|
||||
var lp1 = ll.segments[0].point;
|
||||
var lp2 = ll.segments[1].point;
|
||||
var pm = l.vector, pm1 = pm.rotate(signum(dmin) * -90), pm2 = pm.rotate(signum(dmax) * -90);
|
||||
var p11 = lp1.add(pm1.normalize(Math.abs(dmin)));
|
||||
var p12 = lp2.add(pm1.normalize(Math.abs(dmin)));
|
||||
var p21 = lp1.add(pm2.normalize(Math.abs(dmax)));
|
||||
var p22 = lp2.add(pm2.normalize(Math.abs(dmax)));
|
||||
window.__p3.push(new Path.Line(p11, p12));
|
||||
window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9);
|
||||
window.__p3.push(new Path.Line(p21, p22));
|
||||
window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9);
|
||||
}
|
||||
|
||||
function plotD_vs_t(x, y, arr, arr2, v, dmin, dmax, tmin, tmax, yscale, tvalue) {
|
||||
yscale = yscale || 1;
|
||||
new Path.Line(x, y-100, x, y+100).style.strokeColor = '#aaa';
|
||||
new Path.Line(x, y, x + 200, y).style.strokeColor = '#aaa';
|
||||
|
||||
var clr = (tvalue)? '#a00' : '#00a';
|
||||
if (window.__p3) window.__p3.map(function(a) {a.remove();});
|
||||
|
||||
window.__p3 = [];
|
||||
|
||||
drawFatline(v);
|
||||
|
||||
window.__p3.push(new Path.Line(x, y + dmin * yscale, x + 200, y + dmin * yscale));
|
||||
window.__p3[window.__p3.length-1].style.strokeColor = '#000';
|
||||
window.__p3.push(new Path.Line(x, y + dmax * yscale, x + 200, y + dmax * yscale));
|
||||
window.__p3[window.__p3.length-1].style.strokeColor = '#000';
|
||||
window.__p3.push(new Path.Line(x + tmin * 190, y-100, x + tmin * 190, y+100));
|
||||
window.__p3[window.__p3.length-1].style.strokeColor = clr;
|
||||
window.__p3.push(new Path.Line(x + tmax * 190, y-100, x + tmax * 190, y+100));
|
||||
window.__p3[window.__p3.length-1].style.strokeColor = clr;
|
||||
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
window.__p3.push(new Path.Line(new Point(x + arr[i][0] * 190, y + arr[i][1] * yscale),
|
||||
new Point(x + arr[i][2] * 190, y + arr[i][3] * yscale)));
|
||||
window.__p3[window.__p3.length-1].style.strokeColor = '#999';
|
||||
}
|
||||
var pnt = [];
|
||||
var arr2x = [ 0.0, 0.333333333, 0.6666666666, 1.0 ];
|
||||
for (var i = 0; i < arr2.length; i++) {
|
||||
pnt.push(new Point(x + arr2x[i] * 190, y + arr2[i] * yscale));
|
||||
window.__p3.push(new Path.Circle(pnt[pnt.length-1], 2));
|
||||
window.__p3[window.__p3.length-1].style.fillColor = '#000';
|
||||
}
|
||||
// var pth = new Path(pnt[0], pnt[1], pnt[2], pnt[3]);
|
||||
// pth.closed = true;
|
||||
window.__p3.push(new Path(
|
||||
new Segment(pnt[0], null, pnt[1].subtract(pnt[0])),
|
||||
new Segment(pnt[3], pnt[2].subtract(pnt[3]), null)));
|
||||
window.__p3[window.__p3.length-1].style.strokeColor = clr;
|
||||
view.draw();
|
||||
}
|
|
@ -126,6 +126,7 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{
|
|||
var to = Point.readNamed(arguments, 'to');
|
||||
this.width = to.x - point.x;
|
||||
this.height = to.y - point.y;
|
||||
// Check if horizontal or vertical order needs to be reversed.
|
||||
if (this.width < 0) {
|
||||
this.x = to.x;
|
||||
this.width = -this.width;
|
||||
|
|
|
@ -2234,19 +2234,22 @@ var Item = this.Item = Base.extend(Callback, {
|
|||
// transformation state is stored.
|
||||
// Pass on the transformation to the content, and apply it there too,
|
||||
// by passing true for the 2nd hidden parameter.
|
||||
if (this._transformContent(this._matrix, true)) {
|
||||
var matrix = this._matrix;
|
||||
if (this._transformContent(matrix, true)) {
|
||||
// When the matrix could be applied, we also need to transform
|
||||
// color styles with matrices (only gradients so far):
|
||||
var style = this._style,
|
||||
// pass true for dontMerge so we don't recursively transform
|
||||
// styles on groups' children.
|
||||
fillColor = style.getFillColor(true),
|
||||
strokeColor = style.getStrokeColor(true);
|
||||
if (fillColor)
|
||||
fillColor.transform(this._matrix);
|
||||
fillColor.transform(matrix);
|
||||
if (strokeColor)
|
||||
strokeColor.transform(this._matrix);
|
||||
strokeColor.transform(matrix);
|
||||
// Reset the internal matrix to the identity transformation if it
|
||||
// was possible to apply it.
|
||||
this._matrix.reset();
|
||||
matrix.reset();
|
||||
}
|
||||
if (!_dontNotify)
|
||||
this._changed(/*#=*/ Change.GEOMETRY);
|
||||
|
|
|
@ -45,25 +45,25 @@ var PlacedSymbol = this.PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
|
|||
* fillColor: 'white',
|
||||
* strokeColor: 'black'
|
||||
* });
|
||||
*
|
||||
*
|
||||
* // Create a symbol from the path:
|
||||
* var symbol = new Symbol(path);
|
||||
*
|
||||
* // Remove the path:
|
||||
* path.remove();
|
||||
*
|
||||
*
|
||||
* // Place 100 instances of the symbol:
|
||||
* for (var i = 0; i < 100; i++) {
|
||||
* // Place an instance of the symbol in the project:
|
||||
* var instance = new PlacedSymbol(symbol);
|
||||
*
|
||||
*
|
||||
* // Move the instance to a random position within the view:
|
||||
* instance.position = Point.random() * view.size;
|
||||
*
|
||||
*
|
||||
* // Rotate the instance by a random amount between
|
||||
* // 0 and 360 degrees:
|
||||
* instance.rotate(Math.random() * 360);
|
||||
*
|
||||
*
|
||||
* // Scale the instance between 0.25 and 1:
|
||||
* instance.scale(0.25 + Math.random() * 0.75);
|
||||
* }
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
|
||||
// Define options for compile-time preprocessing.
|
||||
var options = {
|
||||
parser: 'acorn',
|
||||
version: 'dev',
|
||||
browser: true,
|
||||
stats: true,
|
||||
svg: true,
|
||||
version: 'dev',
|
||||
parser: 'acorn',
|
||||
fatline: true,
|
||||
debug: false
|
||||
};
|
||||
|
||||
|
|
|
@ -20,11 +20,12 @@ var fs = require('fs'),
|
|||
json = require('../../package.json');
|
||||
|
||||
var options = {
|
||||
server: true,
|
||||
svg: true,
|
||||
parser: 'acorn',
|
||||
// Use 'dev' for on-the fly compilation of separate files ,but update after.
|
||||
version: 'dev'
|
||||
version: 'dev',
|
||||
server: true,
|
||||
svg: true,
|
||||
fatline: false
|
||||
};
|
||||
|
||||
// Create a document and a window using jsdom, e.g. for exportSVG()
|
||||
|
@ -80,9 +81,9 @@ var context = vm.createContext({
|
|||
DOMParser: DOMParser,
|
||||
Image: Canvas.Image,
|
||||
window: win,
|
||||
document: doc,
|
||||
navigator: win.navigator,
|
||||
console: console
|
||||
document: doc,
|
||||
navigator: win.navigator,
|
||||
console: console
|
||||
});
|
||||
|
||||
// Load Paper.js library files:
|
||||
|
|
|
@ -709,82 +709,6 @@ statics: {
|
|||
+ t * t * t * v3,
|
||||
padding);
|
||||
}
|
||||
},
|
||||
|
||||
// We need to provide the original left curve reference to the
|
||||
// #getIntersections() calls as it is required to create the resulting
|
||||
// CurveLocation objects.
|
||||
getIntersections: function(v1, v2, curve1, curve2, locations) {
|
||||
var bounds1 = this.getBounds(v1),
|
||||
bounds2 = this.getBounds(v2);
|
||||
/*#*/ if (options.debug) {
|
||||
new Path.Rectangle({
|
||||
rectangle: bounds1,
|
||||
strokeColor: 'green',
|
||||
strokeWidth: 0.1
|
||||
});
|
||||
new Path.Rectangle({
|
||||
rectangle: bounds2,
|
||||
strokeColor: 'red',
|
||||
strokeWidth: 0.1
|
||||
});
|
||||
/*#*/ }
|
||||
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 the curve was flat in a previous iteration, we don't need to
|
||||
// recalculate since it does not need further subdivision then.
|
||||
if ((this.isLinear(v1)
|
||||
|| this.isFlatEnough(v1, /*#=*/ Numerical.TOLERANCE))
|
||||
&& (this.isLinear(v2)
|
||||
|| this.isFlatEnough(v2, /*#=*/ Numerical.TOLERANCE))) {
|
||||
/*#*/ if (options.debug) {
|
||||
new Path.Line({
|
||||
from: [v1[0], v1[1]],
|
||||
to: [v1[6], v1[7]],
|
||||
strokeColor: 'green',
|
||||
strokeWidth: 0.1
|
||||
});
|
||||
new Path.Line({
|
||||
from: [v2[0], v2[1]],
|
||||
to: [v2[6], v2[7]],
|
||||
strokeColor: 'red',
|
||||
strokeWidth: 0.1
|
||||
});
|
||||
/*#*/ }
|
||||
// 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));
|
||||
// Use static version without creation of Line objects, but it
|
||||
// doesn't seem to yield measurable speed improvements!
|
||||
var point = Line.intersect(
|
||||
v1[0], v1[1], v1[6], v1[7],
|
||||
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.
|
||||
locations.push(new CurveLocation(curve1, null, point,
|
||||
curve2));
|
||||
}
|
||||
} else {
|
||||
// Subdivide both curves, and see if they intersect.
|
||||
// If one of the curves is flat already, no further subdivion
|
||||
// is required.
|
||||
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], curve1, curve2,
|
||||
locations);
|
||||
}
|
||||
}
|
||||
return locations;
|
||||
}
|
||||
}}, Base.each(['getBounds', 'getStrokeBounds', 'getHandleBounds', 'getRoughBounds'],
|
||||
// Note: Although Curve.getBounds() exists, we are using Path.getBounds() to
|
||||
|
@ -1099,4 +1023,440 @@ new function() { // Scope for methods that require numerical integration
|
|||
a, b, 16, /*#=*/ Numerical.TOLERANCE);
|
||||
}
|
||||
};
|
||||
}, new function() { // Scope for Curve intersection
|
||||
function addLocation(locations, curve1, parameter, point, curve2) {
|
||||
// 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)))
|
||||
locations.push(new CurveLocation(curve1, parameter, point, curve2));
|
||||
}
|
||||
|
||||
function getCurveIntersections(v1, v2, curve1, curve2, locations,
|
||||
range1, range2, recursion) {
|
||||
/*#*/ if (options.fatline) {
|
||||
// NOTE: range1 and range1 are only used for recusion
|
||||
recursion = (recursion || 0) + 1;
|
||||
// Avoid endless recursion.
|
||||
// Perhaps we should fall back to a more expensive method after this,
|
||||
// but so far endless recursion happens only when there is no real
|
||||
// intersection and the infinite fatline continue to intersect with the
|
||||
// other curve outside its bounds!
|
||||
if (recursion > 20)
|
||||
return;
|
||||
// Set up the parameter ranges.
|
||||
range1 = range1 || [ 0, 1 ];
|
||||
range2 = range2 || [ 0, 1 ];
|
||||
// Get the clipped parts from the original curve, to avoid cumulative
|
||||
// errors
|
||||
var part1 = Curve.getPart(v1, range1[0], range1[1]),
|
||||
part2 = Curve.getPart(v2, range2[0], range2[1]),
|
||||
iteration = 0;
|
||||
// markCurve(part1, '#f0f', true);
|
||||
// markCurve(part2, '#0ff', false);
|
||||
// Loop until both parameter range converge. We have to handle the
|
||||
// degenerate case seperately, where fat-line clipping can become
|
||||
// numerically unstable when one of the curves has converged to a point
|
||||
// and the other hasn't.
|
||||
while (iteration++ < 20
|
||||
&& (Math.abs(range1[1] - range1[0]) > /*#=*/ Numerical.TOLERANCE
|
||||
|| Math.abs(range2[1] - range2[0]) > /*#=*/ Numerical.TOLERANCE)) {
|
||||
// First we clip v2 with v1's fat-line
|
||||
var range,
|
||||
intersects1 = clipFatLine(part1, part2, range = range2.slice()),
|
||||
intersects2 = 0;
|
||||
// Stop if there are no possible intersections
|
||||
if (intersects1 === 0)
|
||||
break;
|
||||
if (intersects1 > 0) {
|
||||
// Get the clipped parts from the original v2, to avoid
|
||||
// cumulative errors
|
||||
range2 = range;
|
||||
part2 = Curve.getPart(v2, range2[0], range2[1]);
|
||||
// markCurve(part2, '#0ff', false);
|
||||
// Next we clip v1 with nuv2's fat-line
|
||||
intersects2 = clipFatLine(part2, part1, range = range1.slice());
|
||||
// Stop if there are no possible intersections
|
||||
if (intersects2 === 0)
|
||||
break;
|
||||
if (intersects1 > 0) {
|
||||
// Get the clipped parts from the original v2, to avoid
|
||||
// cumulative errors
|
||||
range1 = range;
|
||||
part1 = Curve.getPart(v1, range1[0], range1[1]);
|
||||
}
|
||||
// markCurve(part1, '#f0f', true);
|
||||
}
|
||||
// Get the clipped parts from the original v1
|
||||
// Check if there could be multiple intersections
|
||||
if (intersects1 < 0 || intersects2 < 0) {
|
||||
// Subdivide the curve which has converged the least from the
|
||||
// original range [0,1], which would be the curve with the
|
||||
// largest parameter range after clipping
|
||||
if (range1[1] - range1[0] > range2[1] - range2[0]) {
|
||||
// subdivide v1 and recurse
|
||||
var t = (range1[0] + range1[1]) / 2;
|
||||
getCurveIntersections(v1, v2, curve1, curve2, locations,
|
||||
[ range1[0], t ], range2, recursion);
|
||||
getCurveIntersections(v1, v2, curve1, curve2, locations,
|
||||
[ t, range1[1] ], range2, recursion);
|
||||
break;
|
||||
} else {
|
||||
// subdivide v2 and recurse
|
||||
var t = (range2[0] + range2[1]) / 2;
|
||||
getCurveIntersections(v1, v2, curve1, curve2, locations,
|
||||
range1, [ range2[0], t ], recursion);
|
||||
getCurveIntersections(v1, v2, curve1, curve2, locations,
|
||||
range1, [ t, range2[1] ], recursion);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We need to bailout of clipping and try a numerically stable
|
||||
// method if any of the following are true.
|
||||
// 1. One of the parameter ranges is converged to a point.
|
||||
// 2. Both of the parameter ranges have converged reasonably well
|
||||
// (according to Numerical.TOLERANCE).
|
||||
// 3. One of the parameter range is converged enough so that it is
|
||||
// *flat enough* to calculate line curve intersection implicitly
|
||||
//
|
||||
// Check if one of the parameter range has converged completely to a
|
||||
// point. Now things could get only worse if we iterate more for the
|
||||
// other curve to converge if it hasn't yet happened so.
|
||||
var converged1 = Math.abs(range1[1] - range1[0]) < /*#=*/ Numerical.TOLERANCE,
|
||||
converged2 = Math.abs(range2[1] - range2[0]) < /*#=*/ Numerical.TOLERANCE;
|
||||
if (converged1 || converged2) {
|
||||
addLocation(locations, curve1, null, converged1
|
||||
? curve1.getPointAt(range1[0], true)
|
||||
: curve2.getPointAt(range2[0], true), curve2);
|
||||
break;
|
||||
}
|
||||
// see if either or both of the curves are flat enough to be treated
|
||||
// as lines.
|
||||
var flat1 = Curve.isFlatEnough(part1, /*#=*/ Numerical.TOLERANCE),
|
||||
flat2 = Curve.isFlatEnough(part2, /*#=*/ Numerical.TOLERANCE);
|
||||
if (flat1 || flat2) {
|
||||
(flat1 && flat2
|
||||
? getLineLineIntersection
|
||||
// Use curve line intersection method while specifying
|
||||
// which curve to be treated as line
|
||||
: getCurveLineIntersections)(part1, part2,
|
||||
curve1, curve2, locations, flat1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*#*/ } else { // !options.fatline
|
||||
var bounds1 = Curve.getBounds(v1),
|
||||
bounds2 = Curve.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 the curve was flat in a previous iteration, we don't need to
|
||||
// recalculate since it does not need further subdivision then.
|
||||
if ((Curve.isLinear(v1)
|
||||
|| Curve.isFlatEnough(v1, /*#=*/ Numerical.TOLERANCE))
|
||||
&& (Curve.isLinear(v2)
|
||||
|| Curve.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));
|
||||
// Use static version without creation of Line objects, but it
|
||||
// doesn't seem to yield measurable speed improvements!
|
||||
var point = Line.intersect(
|
||||
v1[0], v1[1], v1[6], v1[7],
|
||||
v2[0], v2[1], v2[6], v2[7], false);
|
||||
if (point)
|
||||
addLocation(locations, curve1, null, point, curve2);
|
||||
} else {
|
||||
// Subdivide both curves, and see if they intersect.
|
||||
// If one of the curves is flat already, no further subdivion
|
||||
// is required.
|
||||
var v1s = Curve.subdivide(v1),
|
||||
v2s = Curve.subdivide(v2);
|
||||
for (var i = 0; i < 2; i++)
|
||||
for (var j = 0; j < 2; j++)
|
||||
Curve.getIntersections(v1s[i], v2s[j], curve1, curve2,
|
||||
locations);
|
||||
}
|
||||
}
|
||||
return locations;
|
||||
/*#*/ } // !options.fatline
|
||||
}
|
||||
|
||||
/*#*/ if (options.fatline) {
|
||||
/**
|
||||
* Clip curve V2 with fat-line of v1
|
||||
* @param {Array} v1 section of the first curve, for which we will make a
|
||||
* fat-line
|
||||
* @param {Array} v2 section of the second curve; we will clip this curve
|
||||
* with the fat-line of v1
|
||||
* @param {Array} range2 the parameter range of v2
|
||||
* @return {Number} 0: no Intersection, 1: one intersection, -1: more than
|
||||
* one ntersection
|
||||
*/
|
||||
function clipFatLine(v1, v2, range2) {
|
||||
// P = first curve, Q = second curve
|
||||
var p0x = v1[0], p0y = v1[1], p1x = v1[2], p1y = v1[3],
|
||||
p2x = v1[4], p2y = v1[5], p3x = v1[6], p3y = v1[7],
|
||||
q0x = v2[0], q0y = v2[1], q1x = v2[2], q1y = v2[3],
|
||||
q2x = v2[4], q2y = v2[5], q3x = v2[6], q3y = v2[7],
|
||||
// Calculate the fat-line L for P is the baseline l and two
|
||||
// offsets which completely encloses the curve P.
|
||||
d1 = getSignedDistance(p0x, p0y, p3x, p3y, p1x, p1y) || 0,
|
||||
d2 = getSignedDistance(p0x, p0y, p3x, p3y, p2x, p2y) || 0,
|
||||
factor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,
|
||||
dmin = factor * Math.min(0, d1, d2),
|
||||
dmax = factor * Math.max(0, d1, d2),
|
||||
// Calculate non-parametric bezier curve D(ti, di(t)) - di(t) is the
|
||||
// distance of Q from the baseline l of the fat-line, ti is equally
|
||||
// spaced in [0, 1]
|
||||
dq0 = getSignedDistance(p0x, p0y, p3x, p3y, q0x, q0y),
|
||||
dq1 = getSignedDistance(p0x, p0y, p3x, p3y, q1x, q1y),
|
||||
dq2 = getSignedDistance(p0x, p0y, p3x, p3y, q2x, q2y),
|
||||
dq3 = getSignedDistance(p0x, p0y, p3x, p3y, q3x, q3y),
|
||||
// Find the minimum and maximum distances from l, this is useful for
|
||||
// checking whether the curves intersect with each other or not.
|
||||
mindist = Math.min(dq0, dq1, dq2, dq3),
|
||||
maxdist = Math.max(dq0, dq1, dq2, dq3);
|
||||
// If the fatlines don't overlap, we have no intersections!
|
||||
if (dmin > maxdist || dmax < mindist)
|
||||
return 0;
|
||||
var Dt = getConvexHull(dq0, dq1, dq2, dq3),
|
||||
tmp;
|
||||
if (dq3 < dq0) {
|
||||
tmp = dmin;
|
||||
dmin = dmax;
|
||||
dmax = tmp;
|
||||
}
|
||||
// Calculate the convex hull for non-parametric bezier curve D(ti, di(t))
|
||||
// Now we clip the convex hulls for D(ti, di(t)) with dmin and dmax
|
||||
// for the coorresponding t values (tmin, tmax): Portions of curve v2
|
||||
// before tmin and after tmax can safely be clipped away.
|
||||
var tmaxdmin = -Infinity,
|
||||
tmin = Infinity,
|
||||
tmax = -Infinity;
|
||||
for (var i = 0, l = Dt.length; i < l; i++) {
|
||||
var Dtl = Dt[i],
|
||||
dtlx1 = Dtl[0],
|
||||
dtly1 = Dtl[1],
|
||||
dtlx2 = Dtl[2],
|
||||
dtly2 = Dtl[3];
|
||||
if (dtly2 < dtly1) {
|
||||
tmp = dtly2;
|
||||
dtly2 = dtly1;
|
||||
dtly1 = tmp;
|
||||
tmp = dtlx2;
|
||||
dtlx2 = dtlx1;
|
||||
dtlx1 = tmp;
|
||||
}
|
||||
// We know that (dtlx2 - dtlx1) is never 0
|
||||
var inv = (dtly2 - dtly1) / (dtlx2 - dtlx1);
|
||||
if (dmin >= dtly1 && dmin <= dtly2) {
|
||||
var ixdx = dtlx1 + (dmin - dtly1) / inv;
|
||||
if (ixdx < tmin)
|
||||
tmin = ixdx;
|
||||
if (ixdx > tmaxdmin)
|
||||
tmaxdmin = ixdx;
|
||||
}
|
||||
if (dmax >= dtly1 && dmax <= dtly2) {
|
||||
var ixdx = dtlx1 + (dmax - dtly1) / inv;
|
||||
if (ixdx > tmax)
|
||||
tmax = ixdx;
|
||||
if (ixdx < tmin)
|
||||
tmin = 0;
|
||||
}
|
||||
}
|
||||
// Return the parameter values for v2 for which we can be sure that the
|
||||
// intersection with v1 lies within.
|
||||
if (tmin !== Infinity && tmax !== -Infinity) {
|
||||
var mindmin = Math.min(dmin, dmax),
|
||||
mindmax = Math.max(dmin, dmax);
|
||||
if (dq3 > mindmin && dq3 < mindmax)
|
||||
tmax = 1;
|
||||
if (dq0 > mindmin && dq0 < mindmax)
|
||||
tmin = 0;
|
||||
if (tmaxdmin > tmax)
|
||||
tmax = 1;
|
||||
// tmin and tmax are within the range (0, 1). We need to project it
|
||||
// to the original parameter range for v2.
|
||||
var v2tmin = range2[0],
|
||||
tdiff = range2[1] - v2tmin;
|
||||
range2[0] = v2tmin + tmin * tdiff;
|
||||
range2[1] = v2tmin + tmax * tdiff;
|
||||
// If the new parameter range fails to converge by atleast 20% of
|
||||
// the original range, possibly we have multiple intersections.
|
||||
// We need to subdivide one of the curves.
|
||||
if ((tdiff - (range2[1] - range2[0])) / tdiff >= 0.2)
|
||||
return 1;
|
||||
}
|
||||
// TODO: Try checking with a perpendicular fatline to see if the curves
|
||||
// overlap if it is any faster than this
|
||||
if (Curve.getBounds(v1).touches(Curve.getBounds(v2)))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the convex hull for the non-paramertic bezier curve D(ti, di(t))
|
||||
* The ti is equally spaced across [0..1] — [0, 1/3, 2/3, 1] for
|
||||
* di(t), [dq0, dq1, dq2, dq3] respectively. In other words our CVs for the
|
||||
* curve are already sorted in the X axis in the increasing order.
|
||||
* Calculating convex-hull is much easier than a set of arbitrary points.
|
||||
*/
|
||||
function getConvexHull(dq0, dq1, dq2, dq3) {
|
||||
var distq1 = getSignedDistance(0, dq0, 1, dq3, 1 / 3, dq1),
|
||||
distq2 = getSignedDistance(0, dq0, 1, dq3, 2 / 3, dq2);
|
||||
// Check if [1/3, dq1] and [2/3, dq2] are on the same side of line
|
||||
// [0,dq0, 1,dq3]
|
||||
if (distq1 * distq2 < 0) {
|
||||
// dq1 and dq2 lie on different sides on [0, q0, 1, q3]. The hull is
|
||||
// a quadrilateral and line [0, q0, 1, q3] is NOT part of the hull
|
||||
// so we are pretty much done here.
|
||||
return [
|
||||
[ 0, dq0, 1 / 3, dq1 ],
|
||||
[ 1 / 3, dq1, 1, dq3 ],
|
||||
[ 2 / 3, dq2, 0, dq0 ],
|
||||
[ 1, dq3, 2 / 3, dq2 ]
|
||||
];
|
||||
}
|
||||
// dq1 and dq2 lie on the same sides on [0, q0, 1, q3]. The hull can be
|
||||
// a triangle or a quadrilateral and line [0, q0, 1, q3] is part of the
|
||||
// hull. Check if the hull is a triangle or a quadrilateral.
|
||||
var dqMaxX, dqMaxY, vqa1a2X, vqa1a2Y, vqa1MaxX, vqa1MaxY, vqa1MinX, vqa1MinY;
|
||||
if (Math.abs(distq1) > Math.abs(distq2)) {
|
||||
dqMaxX = 1 / 3;
|
||||
dqMaxY = dq1;
|
||||
// apex is dq3 and the other apex point is dq0 vector
|
||||
// dqapex->dqapex2 or base vector which is already part of the hull.
|
||||
vqa1a2X = 1;
|
||||
vqa1a2Y = dq3 - dq0;
|
||||
// vector dqapex->dqMax
|
||||
vqa1MaxX = 2 / 3;
|
||||
vqa1MaxY = dq3 - dq1;
|
||||
// vector dqapex->dqmin
|
||||
vqa1MinX = 1 / 3;
|
||||
vqa1MinY = dq3 - dq2;
|
||||
} else {
|
||||
dqMaxX = 2 / 3;
|
||||
dqMaxY = dq2;
|
||||
// apex is dq0 in this case, and the other apex point is dq3 vector
|
||||
// dqapex->dqapex2 or base vector which is already part of the hull.
|
||||
vqa1a2X = -1;
|
||||
vqa1a2Y = dq0 - dq3;
|
||||
// vector dqapex->dqMax
|
||||
vqa1MaxX = -2 / 3;
|
||||
vqa1MaxY = dq0 - dq2;
|
||||
// vector dqapex->dqmin
|
||||
vqa1MinX = -1 / 3;
|
||||
vqa1MinY = dq0 - dq1;
|
||||
}
|
||||
// Compare cross products of these vectors to determine, if
|
||||
// point is in triangles [ dq3, dqMax, dq0 ] or [ dq0, dqMax, dq3 ]
|
||||
var a1a2_a1Min = vqa1a2X * vqa1MinY - vqa1a2Y * vqa1MinX,
|
||||
a1Max_a1Min = vqa1MaxX * vqa1MinY - vqa1MaxY * vqa1MinX;
|
||||
return a1a2_a1Min * a1Max_a1Min < 0
|
||||
// Point [2/3, dq2] is inside the triangle, hull is a triangle.
|
||||
? [
|
||||
[ 0, dq0, dqMaxX, dqMaxY ],
|
||||
[ dqMaxX, dqMaxY, 1, dq3 ],
|
||||
[ 1, dq3, 0, dq0 ]
|
||||
]
|
||||
// Convexhull is a quadrilateral and we need all lines in the
|
||||
// correct order where line [0, q0, 1, q3] is part of the hull.
|
||||
: [
|
||||
[ 0, dq0, 1 / 3, dq1 ],
|
||||
[ 1 / 3, dq1, 2 / 3, dq2 ],
|
||||
[ 2 / 3, dq2, 1, dq3 ],
|
||||
[ 1, dq3, 0, dq0 ]
|
||||
];
|
||||
}
|
||||
|
||||
// This is basically an "unrolled" version of #Line.getDistance() with sign
|
||||
// May be a static method could be better!
|
||||
function getSignedDistance(a1x, a1y, a2x, a2y, bx, by) {
|
||||
var m = (a2y - a1y) / (a2x - a1x),
|
||||
b = a1y - (m * a1x);
|
||||
return (by - (m * bx) - b) / Math.sqrt(m * m + 1);
|
||||
}
|
||||
/*#*/ } // options.fatline
|
||||
|
||||
/**
|
||||
* Intersections between curve and line becomes rather simple here mostly
|
||||
* because of Numerical class. We can rotate the curve and line so that the
|
||||
* line is on the X axis, and solve the implicit equations for the X axis
|
||||
* and the curve.
|
||||
*/
|
||||
function getCurveLineIntersections(v1, v2, curve1, curve2, locations, flip) {
|
||||
if (flip === undefined)
|
||||
flip = Curve.isLinear(v1);
|
||||
var vc = flip ? v2 : v1,
|
||||
vl = flip ? v1 : v2,
|
||||
l1x = vl[0], l1y = vl[1],
|
||||
l2x = vl[6], l2y = vl[7],
|
||||
// Rotate both curve and line around l1 so that line is on x axis
|
||||
lvx = l2x - l1x,
|
||||
lvy = l2y - l1y,
|
||||
// Angle with x axis (1, 0)
|
||||
angle = Math.atan2(-lvy, lvx),
|
||||
sin = Math.sin(angle),
|
||||
cos = Math.cos(angle),
|
||||
// (rl1x, rl1y) = (0, 0)
|
||||
rl2x = lvx * cos - lvy * sin,
|
||||
rl2y = lvy * cos + lvx * sin,
|
||||
vcr = [];
|
||||
|
||||
for(var i = 0; i < 8; i += 2) {
|
||||
var x = vc[i] - l1x,
|
||||
y = vc[i + 1] - l1y;
|
||||
vcr.push(
|
||||
x * cos - y * sin,
|
||||
y * cos + x * sin);
|
||||
}
|
||||
var roots = [],
|
||||
count = Curve.solveCubic(vcr, 1, 0, roots);
|
||||
// NOTE: count could be -1 for inifnite solutions, but that should only
|
||||
// happen with lines, in which case we should not be here.
|
||||
for (var i = 0; i < count; i++) {
|
||||
var t = roots[i];
|
||||
if (t >= 0 && t <= 1) {
|
||||
var point = Curve.evaluate(vcr, t, true, 0);
|
||||
// We do have a point on the infinite line. Check if it falls on
|
||||
// the line *segment*.
|
||||
if (point.x >= 0 && point.x <= rl2x)
|
||||
addLocation(locations,
|
||||
flip ? curve2 : curve1,
|
||||
// The actual intersection point
|
||||
t, Curve.evaluate(vc, t, true, 0),
|
||||
flip ? curve1 : curve2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getLineLineIntersection(v1, v2, curve1, curve2, locations) {
|
||||
var point = Line.intersect(
|
||||
v1[0], v1[1], v1[6], v1[7],
|
||||
v2[0], v2[1], v2[6], v2[7], false);
|
||||
// Passing null for parameter leads to lazy determination of parameter
|
||||
// values in CurveLocation#getParameter() only once they are requested.
|
||||
if (point)
|
||||
addLocation(locations, curve1, null, point, curve2);
|
||||
}
|
||||
|
||||
return { statics: {
|
||||
// We need to provide the original left curve reference to the
|
||||
// #getIntersections() calls as it is required to create the resulting
|
||||
// CurveLocation objects.
|
||||
getIntersections: function(v1, v2, curve1, curve2, locations) {
|
||||
var linear1 = Curve.isLinear(v1),
|
||||
linear2 = Curve.isLinear(v2);
|
||||
// Determine the correct intersection method based on values of
|
||||
// linear1 & 2:
|
||||
(linear1 && linear2
|
||||
? getLineLineIntersection
|
||||
: linear1 || linear2
|
||||
? getCurveLineIntersections
|
||||
: getCurveIntersections)(v1, v2, curve1, curve2, locations);
|
||||
return locations;
|
||||
}
|
||||
}};
|
||||
});
|
||||
|
|
|
@ -80,16 +80,16 @@ var Segment = this.Segment = Base.extend(/** @lends Segment# */{
|
|||
* @param {Number} x the x coordinate of the segment point
|
||||
* @param {Number} y the y coordinate of the segment point
|
||||
* @param {Number} inX the x coordinate of the the handle point relative
|
||||
* to the anchor point of the segment that describes the in tangent
|
||||
* to the anchor point of the segment that describes the in tangent
|
||||
* of the segment.
|
||||
* @param {Number} inY the y coordinate of the the handle point relative
|
||||
* to the anchor point of the segment that describes the in tangent
|
||||
* to the anchor point of the segment that describes the in tangent
|
||||
* of the segment.
|
||||
* @param {Number} outX the x coordinate of the the handle point relative
|
||||
* to the anchor point of the segment that describes the out tangent
|
||||
* to the anchor point of the segment that describes the out tangent
|
||||
* of the segment.
|
||||
* @param {Number} outY the y coordinate of the the handle point relative
|
||||
* to the anchor point of the segment that describes the out tangent
|
||||
* to the anchor point of the segment that describes the out tangent
|
||||
* of the segment.
|
||||
*
|
||||
* @example {@paperscript}
|
||||
|
|
|
@ -36,25 +36,25 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
|
|||
* fillColor: 'white',
|
||||
* strokeColor: 'black'
|
||||
* };
|
||||
*
|
||||
*
|
||||
* // Create a symbol from the path:
|
||||
* var symbol = new Symbol(path);
|
||||
*
|
||||
* // Remove the path:
|
||||
* path.remove();
|
||||
*
|
||||
*
|
||||
* // Place 100 instances of the symbol:
|
||||
* for (var i = 0; i < 100; i++) {
|
||||
* // Place an instance of the symbol in the project:
|
||||
* var instance = symbol.place();
|
||||
*
|
||||
*
|
||||
* // Move the instance to a random position within the view:
|
||||
* instance.position = Point.random() * view.size;
|
||||
*
|
||||
*
|
||||
* // Rotate the instance by a random amount between
|
||||
* // 0 and 360 degrees:
|
||||
* instance.rotate(Math.random() * 360);
|
||||
*
|
||||
*
|
||||
* // Scale the instance between 0.25 and 1:
|
||||
* instance.scale(0.25 + Math.random() * 0.75);
|
||||
* }
|
||||
|
|
|
@ -484,7 +484,7 @@ new function() {
|
|||
// When url() comes from a style property, '#'' seems to be missing on
|
||||
// WebKit, so let's make it optional here:
|
||||
var match = value && value.match(/\((?:#|)([^)']+)/);
|
||||
return match && definitions[match[1]];
|
||||
return match && definitions[match[1]];
|
||||
}
|
||||
|
||||
function importSVG(node, clearDefs) {
|
||||
|
|
Loading…
Reference in a new issue