mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-07 13:22:07 -05:00
Prebuilt module for commit 3965dd9b77
This commit is contained in:
parent
df790ce2e9
commit
329d629583
9 changed files with 1501 additions and 1224 deletions
480
dist/docs/assets/js/paper.js
vendored
480
dist/docs/assets/js/paper.js
vendored
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Date: Tue Feb 9 10:07:28 2016 +0100
|
||||
* Date: Tue Feb 9 14:13:30 2016 +0100
|
||||
*
|
||||
***
|
||||
*
|
||||
|
@ -7764,39 +7764,6 @@ var Path = PathItem.extend({
|
|||
this.setSelected(true);
|
||||
},
|
||||
|
||||
flatten: function(maxDistance) {
|
||||
var iterator = new PathIterator(this, 64, 0.1),
|
||||
pos = 0,
|
||||
step = iterator.length / Math.ceil(iterator.length / maxDistance),
|
||||
end = iterator.length + (this._closed ? -step : step) / 2;
|
||||
var segments = [];
|
||||
while (pos <= end) {
|
||||
segments.push(new Segment(iterator.getPointAt(pos)));
|
||||
pos += step;
|
||||
}
|
||||
this.setSegments(segments);
|
||||
},
|
||||
|
||||
reduce: function(options) {
|
||||
var curves = this.getCurves(),
|
||||
simplify = options && options.simplify,
|
||||
tolerance = simplify ? 2e-7 : 0;
|
||||
for (var i = curves.length - 1; i >= 0; i--) {
|
||||
var curve = curves[i];
|
||||
if (!curve.hasHandles() && (curve.getLength() < tolerance
|
||||
|| simplify && curve.isCollinear(curve.getNext())))
|
||||
curve.remove();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
simplify: function(tolerance) {
|
||||
if (this._segments.length > 2) {
|
||||
var fitter = new PathFitter(this, tolerance || 2.5);
|
||||
this.setSegments(fitter.fit());
|
||||
}
|
||||
},
|
||||
|
||||
splitAt: function(location) {
|
||||
var index = location && location.index,
|
||||
time = location && location.time,
|
||||
|
@ -7836,21 +7803,6 @@ var Path = PathItem.extend({
|
|||
return location ? this.splitAt(location) : null;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
this._segments.reverse();
|
||||
for (var i = 0, l = this._segments.length; i < l; i++) {
|
||||
var segment = this._segments[i];
|
||||
var handleIn = segment._handleIn;
|
||||
segment._handleIn = segment._handleOut;
|
||||
segment._handleOut = handleIn;
|
||||
segment._index = i;
|
||||
}
|
||||
this._curves = null;
|
||||
if (this._clockwise !== undefined)
|
||||
this._clockwise = !this._clockwise;
|
||||
this._changed(9);
|
||||
},
|
||||
|
||||
join: function(path) {
|
||||
if (path) {
|
||||
var segments = path._segments,
|
||||
|
@ -7890,6 +7842,159 @@ var Path = PathItem.extend({
|
|||
return this;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
this._segments.reverse();
|
||||
for (var i = 0, l = this._segments.length; i < l; i++) {
|
||||
var segment = this._segments[i];
|
||||
var handleIn = segment._handleIn;
|
||||
segment._handleIn = segment._handleOut;
|
||||
segment._handleOut = handleIn;
|
||||
segment._index = i;
|
||||
}
|
||||
this._curves = null;
|
||||
if (this._clockwise !== undefined)
|
||||
this._clockwise = !this._clockwise;
|
||||
this._changed(9);
|
||||
},
|
||||
|
||||
flatten: function(maxDistance) {
|
||||
var iterator = new PathIterator(this, 64, 0.1),
|
||||
pos = 0,
|
||||
step = iterator.length / Math.ceil(iterator.length / maxDistance),
|
||||
end = iterator.length + (this._closed ? -step : step) / 2;
|
||||
var segments = [];
|
||||
while (pos <= end) {
|
||||
segments.push(new Segment(iterator.getPointAt(pos)));
|
||||
pos += step;
|
||||
}
|
||||
this.setSegments(segments);
|
||||
},
|
||||
|
||||
reduce: function(options) {
|
||||
var curves = this.getCurves(),
|
||||
simplify = options && options.simplify,
|
||||
tolerance = simplify ? 2e-7 : 0;
|
||||
for (var i = curves.length - 1; i >= 0; i--) {
|
||||
var curve = curves[i];
|
||||
if (!curve.hasHandles() && (curve.getLength() < tolerance
|
||||
|| simplify && curve.isCollinear(curve.getNext())))
|
||||
curve.remove();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
simplify: function(tolerance) {
|
||||
var segments = new PathFitter(this).fit(tolerance || 2.5);
|
||||
if (segments)
|
||||
this.setSegments(segments);
|
||||
return !!segments;
|
||||
},
|
||||
|
||||
smooth: function(options) {
|
||||
function getIndex(value, _default) {
|
||||
var index = value && value.index;
|
||||
if (index != null) {
|
||||
var path = value.path;
|
||||
if (path && path !== that)
|
||||
throw new Error(value._class + ' ' + index + ' of ' + path
|
||||
+ ' is not part of ' + that);
|
||||
if (_default && value instanceof Curve)
|
||||
index++;
|
||||
} else {
|
||||
index = typeof value === 'number' ? value : _default;
|
||||
}
|
||||
return Math.min(index < 0 && closed
|
||||
? index % length
|
||||
: index < 0 ? index + length : index, length - 1);
|
||||
}
|
||||
|
||||
var that = this,
|
||||
opts = options || {},
|
||||
type = opts.type || 'asymmetric',
|
||||
segments = this._segments,
|
||||
length = segments.length,
|
||||
closed = this._closed,
|
||||
loop = closed && opts.from === undefined && opts.to === undefined,
|
||||
from = getIndex(opts.from, 0),
|
||||
to = getIndex(opts.to, length - 1);
|
||||
if (from > to) {
|
||||
if (closed) {
|
||||
from -= length;
|
||||
} else {
|
||||
var tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
}
|
||||
if (/^(?:asymmetric|continuous)$/.test(type)) {
|
||||
var asymmetric = type === 'asymmetric',
|
||||
min = Math.min,
|
||||
amount = to - from + 1,
|
||||
n = amount - 1,
|
||||
padding = loop ? min(amount, 4) : 1,
|
||||
paddingLeft = padding,
|
||||
paddingRight = padding,
|
||||
knots = [];
|
||||
if (!closed) {
|
||||
paddingLeft = min(1, from);
|
||||
paddingRight = min(1, length - to - 1);
|
||||
}
|
||||
n += paddingLeft + paddingRight;
|
||||
if (n <= 1)
|
||||
return;
|
||||
for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
|
||||
knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
|
||||
}
|
||||
|
||||
var x = knots[0]._x + 2 * knots[1]._x,
|
||||
y = knots[0]._y + 2 * knots[1]._y,
|
||||
f = 2,
|
||||
n_1 = n - 1,
|
||||
rx = [x],
|
||||
ry = [y],
|
||||
rf = [f],
|
||||
px = [],
|
||||
py = [];
|
||||
for (var i = 1; i < n; i++) {
|
||||
var internal = i < n_1,
|
||||
a = internal ? 1 : asymmetric ? 1 : 2,
|
||||
b = internal ? 4 : asymmetric ? 2 : 7,
|
||||
u = internal ? 4 : asymmetric ? 3 : 8,
|
||||
v = internal ? 2 : asymmetric ? 0 : 1,
|
||||
m = a / f;
|
||||
f = rf[i] = b - m;
|
||||
x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
|
||||
y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
|
||||
}
|
||||
|
||||
px[n_1] = rx[n_1] / rf[n_1];
|
||||
py[n_1] = ry[n_1] / rf[n_1];
|
||||
for (var i = n - 2; i >= 0; i--) {
|
||||
px[i] = (rx[i] - px[i + 1]) / rf[i];
|
||||
py[i] = (ry[i] - py[i + 1]) / rf[i];
|
||||
}
|
||||
px[n] = (3 * knots[n]._x - px[n_1]) / 2;
|
||||
py[n] = (3 * knots[n]._y - py[n_1]) / 2;
|
||||
|
||||
for (var i = paddingLeft, max = n - paddingRight, j = from;
|
||||
i <= max; i++, j++) {
|
||||
var segment = segments[j < 0 ? j + length : j],
|
||||
pt = segment._point,
|
||||
hx = px[i] - pt._x,
|
||||
hy = py[i] - pt._y;
|
||||
if (loop || i < max)
|
||||
segment.setHandleOut(hx, hy);
|
||||
if (loop || i > paddingLeft)
|
||||
segment.setHandleIn(-hx, -hy);
|
||||
}
|
||||
} else {
|
||||
for (var i = from; i <= to; i++) {
|
||||
segments[i < 0 ? i + length : i].smooth(opts,
|
||||
!loop && i === from, !loop && i === to);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
toShape: function(insert) {
|
||||
if (!this._closed)
|
||||
return null;
|
||||
|
@ -8172,111 +8277,6 @@ var Path = PathItem.extend({
|
|||
|
||||
getNearestPoint: function() {
|
||||
return this.getNearestLocation.apply(this, arguments).getPoint();
|
||||
},
|
||||
|
||||
smooth: function(options) {
|
||||
function getIndex(value, _default) {
|
||||
var index = value && value.index;
|
||||
if (index != null) {
|
||||
var path = value.path;
|
||||
if (path && path !== that)
|
||||
throw new Error(value._class + ' ' + index + ' of ' + path
|
||||
+ ' is not part of ' + that);
|
||||
if (_default && value instanceof Curve)
|
||||
index++;
|
||||
} else {
|
||||
index = typeof value === 'number' ? value : _default;
|
||||
}
|
||||
return Math.min(index < 0 && closed
|
||||
? index % length
|
||||
: index < 0 ? index + length : index, length - 1);
|
||||
}
|
||||
|
||||
var that = this,
|
||||
opts = options || {},
|
||||
type = opts.type || 'asymmetric',
|
||||
segments = this._segments,
|
||||
length = segments.length,
|
||||
closed = this._closed,
|
||||
loop = closed && opts.from === undefined && opts.to === undefined,
|
||||
from = getIndex(opts.from, 0),
|
||||
to = getIndex(opts.to, length - 1);
|
||||
if (from > to) {
|
||||
if (closed) {
|
||||
from -= length;
|
||||
} else {
|
||||
var tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
}
|
||||
if (/^(?:asymmetric|continuous)$/.test(type)) {
|
||||
var asymmetric = type === 'asymmetric',
|
||||
min = Math.min,
|
||||
amount = to - from + 1,
|
||||
n = amount - 1,
|
||||
padding = loop ? min(amount, 4) : 1,
|
||||
paddingLeft = padding,
|
||||
paddingRight = padding,
|
||||
knots = [];
|
||||
if (!closed) {
|
||||
paddingLeft = min(1, from);
|
||||
paddingRight = min(1, length - to - 1);
|
||||
}
|
||||
n += paddingLeft + paddingRight;
|
||||
if (n <= 1)
|
||||
return;
|
||||
for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
|
||||
knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
|
||||
}
|
||||
|
||||
var x = knots[0]._x + 2 * knots[1]._x,
|
||||
y = knots[0]._y + 2 * knots[1]._y,
|
||||
f = 2,
|
||||
n_1 = n - 1,
|
||||
rx = [x],
|
||||
ry = [y],
|
||||
rf = [f],
|
||||
px = [],
|
||||
py = [];
|
||||
for (var i = 1; i < n; i++) {
|
||||
var internal = i < n_1,
|
||||
a = internal ? 1 : asymmetric ? 1 : 2,
|
||||
b = internal ? 4 : asymmetric ? 2 : 7,
|
||||
u = internal ? 4 : asymmetric ? 3 : 8,
|
||||
v = internal ? 2 : asymmetric ? 0 : 1,
|
||||
m = a / f;
|
||||
f = rf[i] = b - m;
|
||||
x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
|
||||
y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
|
||||
}
|
||||
|
||||
px[n_1] = rx[n_1] / rf[n_1];
|
||||
py[n_1] = ry[n_1] / rf[n_1];
|
||||
for (var i = n - 2; i >= 0; i--) {
|
||||
px[i] = (rx[i] - px[i + 1]) / rf[i];
|
||||
py[i] = (ry[i] - py[i + 1]) / rf[i];
|
||||
}
|
||||
px[n] = (3 * knots[n]._x - px[n_1]) / 2;
|
||||
py[n] = (3 * knots[n]._y - py[n_1]) / 2;
|
||||
|
||||
for (var i = paddingLeft, max = n - paddingRight, j = from;
|
||||
i <= max; i++, j++) {
|
||||
var segment = segments[j < 0 ? j + length : j],
|
||||
pt = segment._point,
|
||||
hx = px[i] - pt._x,
|
||||
hy = py[i] - pt._y;
|
||||
if (loop || i < max)
|
||||
segment.setHandleOut(hx, hy);
|
||||
if (loop || i > paddingLeft)
|
||||
segment.setHandleIn(-hx, -hy);
|
||||
}
|
||||
} else {
|
||||
for (var i = from; i <= to; i++) {
|
||||
segments[i < 0 ? i + length : i].smooth(opts,
|
||||
!loop && i === from, !loop && i === to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
new function() {
|
||||
|
@ -9040,12 +9040,6 @@ var CompoundPath = PathItem.extend({
|
|||
return items;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
var children = this._children;
|
||||
for (var i = 0, l = children.length; i < l; i++)
|
||||
children[i].reverse();
|
||||
},
|
||||
|
||||
reduce: function reduce(options) {
|
||||
var children = this._children;
|
||||
for (var i = children.length - 1; i >= 0; i--) {
|
||||
|
@ -9063,12 +9057,6 @@ var CompoundPath = PathItem.extend({
|
|||
return reduce.base.call(this);
|
||||
},
|
||||
|
||||
smooth: function(options) {
|
||||
var children = this._children;
|
||||
for (var i = 0, l = children.length; i < l; i++)
|
||||
children[i].smooth(options);
|
||||
},
|
||||
|
||||
isClockwise: function() {
|
||||
var child = this.getFirstChild();
|
||||
return child && child.isClockwise();
|
||||
|
@ -9176,40 +9164,46 @@ new function() {
|
|||
return children[children.length - 1];
|
||||
}
|
||||
|
||||
var fields = {
|
||||
moveTo: function() {
|
||||
var current = getCurrentPath(this),
|
||||
path = current && current.isEmpty() ? current
|
||||
: new Path(Item.NO_INSERT);
|
||||
if (path !== current)
|
||||
this.addChild(path);
|
||||
path.moveTo.apply(path, arguments);
|
||||
},
|
||||
return Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',
|
||||
'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',
|
||||
'arcBy'],
|
||||
function(key) {
|
||||
this[key] = function() {
|
||||
var path = getCurrentPath(this, true);
|
||||
path[key].apply(path, arguments);
|
||||
};
|
||||
}, {
|
||||
moveTo: function() {
|
||||
var current = getCurrentPath(this),
|
||||
path = current && current.isEmpty() ? current
|
||||
: new Path(Item.NO_INSERT);
|
||||
if (path !== current)
|
||||
this.addChild(path);
|
||||
path.moveTo.apply(path, arguments);
|
||||
},
|
||||
|
||||
moveBy: function() {
|
||||
var current = getCurrentPath(this, true),
|
||||
last = current && current.getLastSegment(),
|
||||
point = Point.read(arguments);
|
||||
this.moveTo(last ? point.add(last._point) : point);
|
||||
},
|
||||
moveBy: function() {
|
||||
var current = getCurrentPath(this, true),
|
||||
last = current && current.getLastSegment(),
|
||||
point = Point.read(arguments);
|
||||
this.moveTo(last ? point.add(last._point) : point);
|
||||
},
|
||||
|
||||
closePath: function(join) {
|
||||
getCurrentPath(this, true).closePath(join);
|
||||
}
|
||||
};
|
||||
|
||||
Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo', 'arcTo',
|
||||
'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy', 'arcBy'],
|
||||
function(key) {
|
||||
fields[key] = function() {
|
||||
var path = getCurrentPath(this, true);
|
||||
path[key].apply(path, arguments);
|
||||
};
|
||||
closePath: function(join) {
|
||||
getCurrentPath(this, true).closePath(join);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return fields;
|
||||
});
|
||||
}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {
|
||||
this[key] = function(param) {
|
||||
var children = this._children,
|
||||
res;
|
||||
for (var i = 0, l = children.length; i < l; i++) {
|
||||
res = children[i][key](param) || res;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}, {}));
|
||||
|
||||
PathItem.inject(new function() {
|
||||
var operators = {
|
||||
|
@ -9972,63 +9966,61 @@ var PathIterator = Base.extend({
|
|||
);
|
||||
|
||||
var PathFitter = Base.extend({
|
||||
initialize: function(path, error) {
|
||||
initialize: function(path) {
|
||||
var points = this.points = [],
|
||||
segments = path._segments,
|
||||
prev;
|
||||
for (var i = 0, l = segments.length; i < l; i++) {
|
||||
var point = segments[i].point.clone();
|
||||
closed = path._closed;
|
||||
for (var i = 0, prev, l = segments.length; i < l; i++) {
|
||||
var point = segments[i].point;
|
||||
if (!prev || !prev.equals(point)) {
|
||||
points.push(point);
|
||||
prev = point;
|
||||
points.push(prev = point.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if (path._closed) {
|
||||
this.closed = true;
|
||||
if (closed) {
|
||||
points.unshift(points[points.length - 1]);
|
||||
points.push(points[1]);
|
||||
}
|
||||
|
||||
this.error = error;
|
||||
this.closed = closed;
|
||||
},
|
||||
|
||||
fit: function() {
|
||||
fit: function(error) {
|
||||
var points = this.points,
|
||||
length = points.length,
|
||||
segments = this.segments = length > 0
|
||||
? [new Segment(points[0])] : [];
|
||||
if (length > 1)
|
||||
this.fitCubic(0, length - 1,
|
||||
points[1].subtract(points[0]).normalize(),
|
||||
points[length - 2].subtract(points[length - 1]).normalize());
|
||||
|
||||
if (this.closed) {
|
||||
segments.shift();
|
||||
segments.pop();
|
||||
segments = null;
|
||||
if (length > 0) {
|
||||
segments = [new Segment(points[0])];
|
||||
if (length > 1) {
|
||||
this.fitCubic(segments, error, 0, length - 1,
|
||||
points[1].subtract(points[0]),
|
||||
points[length - 2].subtract(points[length - 1]));
|
||||
if (this.closed) {
|
||||
segments.shift();
|
||||
segments.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return segments;
|
||||
},
|
||||
|
||||
fitCubic: function(first, last, tan1, tan2) {
|
||||
if (last - first == 1) {
|
||||
var pt1 = this.points[first],
|
||||
pt2 = this.points[last],
|
||||
fitCubic: function(segments, error, first, last, tan1, tan2) {
|
||||
var points = this.points;
|
||||
if (last - first === 1) {
|
||||
var pt1 = points[first],
|
||||
pt2 = points[last],
|
||||
dist = pt1.getDistance(pt2) / 3;
|
||||
this.addCurve([pt1, pt1.add(tan1.normalize(dist)),
|
||||
this.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),
|
||||
pt2.add(tan2.normalize(dist)), pt2]);
|
||||
return;
|
||||
}
|
||||
var uPrime = this.chordLengthParameterize(first, last),
|
||||
maxError = Math.max(this.error, this.error * this.error),
|
||||
maxError = Math.max(error, error * error),
|
||||
split,
|
||||
parametersInOrder = true;
|
||||
for (var i = 0; i <= 4; i++) {
|
||||
var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
|
||||
var max = this.findMaxError(first, last, curve, uPrime);
|
||||
if (max.error < this.error && parametersInOrder) {
|
||||
this.addCurve(curve);
|
||||
if (max.error < error && parametersInOrder) {
|
||||
this.addCurve(segments, curve);
|
||||
return;
|
||||
}
|
||||
split = max.index;
|
||||
|
@ -10037,23 +10029,23 @@ var PathFitter = Base.extend({
|
|||
parametersInOrder = this.reparameterize(first, last, uPrime, curve);
|
||||
maxError = max.error;
|
||||
}
|
||||
var tanCenter = this.points[split - 1].subtract(this.points[split + 1])
|
||||
.normalize();
|
||||
this.fitCubic(first, split, tan1, tanCenter);
|
||||
this.fitCubic(split, last, tanCenter.negate(), tan2);
|
||||
var tanCenter = points[split - 1].subtract(points[split + 1]);
|
||||
this.fitCubic(segments, error, first, split, tan1, tanCenter);
|
||||
this.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);
|
||||
},
|
||||
|
||||
addCurve: function(curve) {
|
||||
var prev = this.segments[this.segments.length - 1];
|
||||
addCurve: function(segments, curve) {
|
||||
var prev = segments[segments.length - 1];
|
||||
prev.setHandleOut(curve[1].subtract(curve[0]));
|
||||
this.segments.push(
|
||||
new Segment(curve[3], curve[2].subtract(curve[3])));
|
||||
segments.push(new Segment(curve[3], curve[2].subtract(curve[3])));
|
||||
},
|
||||
|
||||
generateBezier: function(first, last, uPrime, tan1, tan2) {
|
||||
var epsilon = 1e-12,
|
||||
pt1 = this.points[first],
|
||||
pt2 = this.points[last],
|
||||
abs = Math.abs,
|
||||
points = this.points,
|
||||
pt1 = points[first],
|
||||
pt2 = points[last],
|
||||
C = [[0, 0], [0, 0]],
|
||||
X = [0, 0];
|
||||
|
||||
|
@ -10067,7 +10059,7 @@ var PathFitter = Base.extend({
|
|||
b3 = u * u * u,
|
||||
a1 = tan1.normalize(b1),
|
||||
a2 = tan2.normalize(b2),
|
||||
tmp = this.points[first + i]
|
||||
tmp = points[first + i]
|
||||
.subtract(pt1.multiply(b0 + b1))
|
||||
.subtract(pt2.multiply(b2 + b3));
|
||||
C[0][0] += a1.dot(a1);
|
||||
|
@ -10080,7 +10072,7 @@ var PathFitter = Base.extend({
|
|||
|
||||
var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],
|
||||
alpha1, alpha2;
|
||||
if (Math.abs(detC0C1) > epsilon) {
|
||||
if (abs(detC0C1) > epsilon) {
|
||||
var detC0X = C[0][0] * X[1] - C[1][0] * X[0],
|
||||
detXC1 = X[0] * C[1][1] - X[1] * C[0][1];
|
||||
alpha1 = detXC1 / detC0C1;
|
||||
|
@ -10088,9 +10080,9 @@ var PathFitter = Base.extend({
|
|||
} else {
|
||||
var c0 = C[0][0] + C[0][1],
|
||||
c1 = C[1][0] + C[1][1];
|
||||
if (Math.abs(c0) > epsilon) {
|
||||
if (abs(c0) > epsilon) {
|
||||
alpha1 = alpha2 = X[0] / c0;
|
||||
} else if (Math.abs(c1) > epsilon) {
|
||||
} else if (abs(c1) > epsilon) {
|
||||
alpha1 = alpha2 = X[1] / c1;
|
||||
} else {
|
||||
alpha1 = alpha2 = 0;
|
||||
|
@ -10113,8 +10105,10 @@ var PathFitter = Base.extend({
|
|||
}
|
||||
}
|
||||
|
||||
return [pt1, pt1.add(handle1 || tan1.normalize(alpha1)),
|
||||
pt2.add(handle2 || tan2.normalize(alpha2)), pt2];
|
||||
return [pt1,
|
||||
pt1.add(handle1 || tan1.normalize(alpha1)),
|
||||
pt2.add(handle2 || tan2.normalize(alpha2)),
|
||||
pt2];
|
||||
},
|
||||
|
||||
reparameterize: function(first, last, u, curve) {
|
||||
|
|
220
dist/docs/classes/CompoundPath.html
vendored
220
dist/docs/classes/CompoundPath.html
vendored
|
@ -355,31 +355,6 @@ path.fillColor = 'black';
|
|||
|
||||
|
||||
|
||||
<!-- ============================== methods ================================ -->
|
||||
<div class="reference-members">
|
||||
<h2>Methods</h2>
|
||||
|
||||
|
||||
<div id="reverse" class="member">
|
||||
<div class="member-link">
|
||||
<a name="reverse" href="#reverse"><tt><b>reverse</b>()</tt></a>
|
||||
</div>
|
||||
<div class="member-description hidden">
|
||||
<div class="member-text">
|
||||
<p>Reverses the orientation of all nested paths.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6619,6 +6594,81 @@ function onFrame(event) {
|
|||
</div>
|
||||
|
||||
|
||||
<div id="reverse" class="member">
|
||||
<div class="member-link">
|
||||
<a name="reverse" href="#reverse"><tt><b>reverse</b>()</tt></a>
|
||||
</div>
|
||||
<div class="member-description hidden">
|
||||
<div class="member-text">
|
||||
<p>Reverses the orientation of the path item. When called on <a href="../classes/CompoundPath.html"><tt>CompoundPath</tt></a> items, each of the nested paths is reversed. On <a href="../classes/Path.html"><tt>Path</tt></a> items, the sequence of <a href="../classes/Path.html#segments"><tt>path.segments</tt></a> is reversed.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="flatten-maxDistance" class="member">
|
||||
<div class="member-link">
|
||||
<a name="flatten-maxDistance" href="#flatten-maxDistance"><tt><b>flatten</b>(maxDistance)</tt></a>
|
||||
</div>
|
||||
<div class="member-description hidden">
|
||||
<div class="member-text">
|
||||
<p>Converts the curves in a path to straight lines with an even distribution of points. The distance between the produced segments is as close as possible to the value specified by the <code>maxDistance</code> parameter.</p>
|
||||
|
||||
|
||||
<ul class="member-list">
|
||||
<h4>Parameters:</h4>
|
||||
|
||||
<li>
|
||||
<tt>maxDistance:</tt>
|
||||
<tt>Number</tt>
|
||||
— the maximum distance between the points
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<h4>Example:<span class="description">Flattening a circle shaped path:</span></h4>
|
||||
|
||||
<div class="paperscript split">
|
||||
|
||||
<div class="buttons">
|
||||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-56">
|
||||
// Create a circle shaped path at { x: 80, y: 50 }
|
||||
// with a radius of 35:
|
||||
var path = new Path.Circle({
|
||||
center: new Size(80, 50),
|
||||
radius: 35
|
||||
});
|
||||
|
||||
// Select the path, so we can inspect its segments:
|
||||
path.selected = true;
|
||||
|
||||
// Create a copy of the path and move it 150 points to the right:
|
||||
var copy = path.clone();
|
||||
copy.position.x += 150;
|
||||
|
||||
// Convert its curves to points, with a max distance of 20:
|
||||
copy.flatten(20);
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="100" id="canvas-56"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="smooth" class="member">
|
||||
<div class="member-link">
|
||||
<a name="smooth" href="#smooth"><tt><b>smooth</b>([options])</tt></a>
|
||||
|
@ -6686,7 +6736,7 @@ function onFrame(event) {
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-56">
|
||||
<script type="text/paperscript" canvas="canvas-57">
|
||||
// Create a rectangular path with its top-left point at
|
||||
// {x: 30, y: 25} and a size of {width: 50, height: 50}:
|
||||
var path = new Path.Rectangle({
|
||||
|
@ -6705,7 +6755,7 @@ copy.position.x += 100;
|
|||
// Smooth the segments of the copy:
|
||||
copy.smooth({ type: 'continuous' });
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="100" id="canvas-56"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="100" id="canvas-57"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -6717,7 +6767,7 @@ copy.smooth({ type: 'continuous' });
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-57">
|
||||
<script type="text/paperscript" canvas="canvas-58">
|
||||
var path = new Path();
|
||||
path.strokeColor = 'black';
|
||||
|
||||
|
@ -6742,7 +6792,7 @@ copy.fullySelected = true;
|
|||
// Smooth the path using centripetal Catmull-Rom splines:
|
||||
copy.smooth({ type: 'catmull-rom', factor: 0.5 });
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="220" id="canvas-57"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="220" id="canvas-58"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -6754,7 +6804,7 @@ copy.smooth({ type: 'catmull-rom', factor: 0.5 });
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-58">
|
||||
<script type="text/paperscript" canvas="canvas-59">
|
||||
// Create 5 rectangles, next to each other:
|
||||
var paths = [];
|
||||
for (var i = 0; i < 5; i++) {
|
||||
|
@ -6784,7 +6834,87 @@ paths[3].smooth({ type: 'continuous', from: 0, to: 2 });
|
|||
// Smooth a range, using negative indices:
|
||||
paths[4].smooth({ type: 'continuous', from: -1, to: 1 });
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="110" id="canvas-58"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="110" id="canvas-59"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="simplify" class="member">
|
||||
<div class="member-link">
|
||||
<a name="simplify" href="#simplify"><tt><b>simplify</b>([tolerance])</tt></a>
|
||||
</div>
|
||||
<div class="member-description hidden">
|
||||
<div class="member-text">
|
||||
<p>Fits a sequence of as few curves as possible through the path’s anchor points, ignoring the path items’s curve-handles, with an allowed maximum error. When called on <a href="../classes/CompoundPath.html"><tt>CompoundPath</tt></a> items, each of the nested paths is simplified. On <a href="../classes/Path.html"><tt>Path</tt></a> items, the <a href="../classes/Path.html#segments"><tt>path.segments</tt></a> array is processed and replaced by the resulting sequence of fitted curves.</p>
|
||||
<p>This method can be used to process and simplify the point data received from a mouse or touch device.</p>
|
||||
|
||||
|
||||
<ul class="member-list">
|
||||
<h4>Parameters:</h4>
|
||||
|
||||
<li>
|
||||
<tt>tolerance:</tt>
|
||||
<tt>Number</tt>
|
||||
— the allowed maximum error when fitting the curves through the segment points
|
||||
— optional, default: <tt>2.5</tt>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<ul class="member-list">
|
||||
<h4>Returns:</h4>
|
||||
|
||||
<li>
|
||||
<tt><tt>Boolean</tt></tt> — <tt>true</tt> if the method was capable of fitting curves through the path’s segment points, <tt>false</tt> otherwise
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<h4>Example:<span class="description">Click and drag below to draw to draw a line, when you release the mouse, the is made smooth using path.simplify():</span></h4>
|
||||
|
||||
<div class="paperscript split">
|
||||
|
||||
<div class="buttons">
|
||||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-60">
|
||||
var path;
|
||||
function onMouseDown(event) {
|
||||
// If we already made a path before, deselect it:
|
||||
if (path) {
|
||||
path.selected = false;
|
||||
}
|
||||
|
||||
// Create a new path and add the position of the mouse
|
||||
// as its first segment. Select it, so we can see the
|
||||
// segment points:
|
||||
path = new Path({
|
||||
segments: [event.point],
|
||||
strokeColor: 'black',
|
||||
selected: true
|
||||
});
|
||||
}
|
||||
|
||||
function onMouseDrag(event) {
|
||||
// On every drag event, add a segment to the path
|
||||
// at the position of the mouse:
|
||||
path.add(event.point);
|
||||
}
|
||||
|
||||
function onMouseUp(event) {
|
||||
// When the mouse is released, simplify the path:
|
||||
path.simplify();
|
||||
path.selected = true;
|
||||
}
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="300" id="canvas-60"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -7020,7 +7150,7 @@ paths[4].smooth({ type: 'continuous', from: -1, to: 1 });
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-59">
|
||||
<script type="text/paperscript" canvas="canvas-61">
|
||||
var myPath;
|
||||
function onMouseMove(event) {
|
||||
// If we created a path before, remove it:
|
||||
|
@ -7041,7 +7171,7 @@ function onMouseMove(event) {
|
|||
myPath.selected = true;
|
||||
}
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="300" id="canvas-59"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="300" id="canvas-61"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -7088,7 +7218,7 @@ function onMouseMove(event) {
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-60">
|
||||
<script type="text/paperscript" canvas="canvas-62">
|
||||
var path = new Path();
|
||||
path.strokeColor = 'black';
|
||||
|
||||
|
@ -7108,7 +7238,7 @@ path.arcTo(throughPoint, toPoint);
|
|||
var circle = new Path.Circle(throughPoint, 3);
|
||||
circle.fillColor = 'red';
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="100" id="canvas-60"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="100" id="canvas-62"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -7120,7 +7250,7 @@ circle.fillColor = 'red';
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-61">
|
||||
<script type="text/paperscript" canvas="canvas-63">
|
||||
var myPath;
|
||||
function onMouseDrag(event) {
|
||||
// If we created a path before, remove it:
|
||||
|
@ -7148,7 +7278,7 @@ function onMouseUp(event) {
|
|||
myPath.fillColor = 'black';
|
||||
}
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="300" id="canvas-61"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="300" id="canvas-63"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -7195,7 +7325,7 @@ function onMouseUp(event) {
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-62">
|
||||
<script type="text/paperscript" canvas="canvas-64">
|
||||
var path = new Path();
|
||||
path.strokeColor = 'black';
|
||||
|
||||
|
@ -7210,7 +7340,7 @@ path2.add(new Point(180, 25));
|
|||
// we pass `false` as the second argument to arcTo:
|
||||
path2.arcTo(new Point(280, 25), false);
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="100" id="canvas-62"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="100" id="canvas-64"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -7222,7 +7352,7 @@ path2.arcTo(new Point(280, 25), false);
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-63">
|
||||
<script type="text/paperscript" canvas="canvas-65">
|
||||
var myPath;
|
||||
|
||||
// The mouse has to move at least 20 points before
|
||||
|
@ -7243,7 +7373,7 @@ function onMouseDrag(event) {
|
|||
myPath.arcTo(event.point);
|
||||
}
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="300" id="canvas-63"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="300" id="canvas-65"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -7350,7 +7480,7 @@ function onMouseDrag(event) {
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-64">
|
||||
<script type="text/paperscript" canvas="canvas-66">
|
||||
var path = new Path();
|
||||
path.strokeColor = 'black';
|
||||
|
||||
|
@ -7364,7 +7494,7 @@ path.lineBy(50, 0);
|
|||
// 0 in x direction and 50 in y direction, becomes {x: 75, y: 75}
|
||||
path.lineBy(0, 50);
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="100" id="canvas-64"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="100" id="canvas-66"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -7376,7 +7506,7 @@ path.lineBy(0, 50);
|
|||
<div class="button run">Run</div>
|
||||
</div>
|
||||
|
||||
<script type="text/paperscript" canvas="canvas-65">
|
||||
<script type="text/paperscript" canvas="canvas-67">
|
||||
var path = new Path();
|
||||
path.strokeColor = 'black';
|
||||
|
||||
|
@ -7402,7 +7532,7 @@ path.smooth();
|
|||
// the construction of the path:
|
||||
// path.selected = true;
|
||||
</script>
|
||||
<div class="canvas"><canvas width="516" height="300" id="canvas-65"></canvas></div>
|
||||
<div class="canvas"><canvas width="516" height="300" id="canvas-67"></canvas></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
2
dist/docs/classes/Curve.html
vendored
2
dist/docs/classes/Curve.html
vendored
|
@ -1557,7 +1557,7 @@
|
|||
</div>
|
||||
<div class="member-description hidden">
|
||||
<div class="member-text">
|
||||
<p>Returns the curve-time parameter of the specified point if it lies on the curve, <code>null</code> otherwise.</p>
|
||||
<p>Returns the curve-time parameter of the specified point if it lies on the curve, <code>null</code> otherwise. Note that if there is more than one possible solution in a self-intersecting curve, the first found result is returned.</p>
|
||||
|
||||
|
||||
<ul class="member-list">
|
||||
|
|
638
dist/docs/classes/Path.html
vendored
638
dist/docs/classes/Path.html
vendored
File diff suppressed because it is too large
Load diff
407
dist/docs/classes/PathItem.html
vendored
407
dist/docs/classes/PathItem.html
vendored
File diff suppressed because it is too large
Load diff
480
dist/paper-core.js
vendored
480
dist/paper-core.js
vendored
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Date: Tue Feb 9 10:07:28 2016 +0100
|
||||
* Date: Tue Feb 9 14:13:30 2016 +0100
|
||||
*
|
||||
***
|
||||
*
|
||||
|
@ -7764,39 +7764,6 @@ var Path = PathItem.extend({
|
|||
this.setSelected(true);
|
||||
},
|
||||
|
||||
flatten: function(maxDistance) {
|
||||
var iterator = new PathIterator(this, 64, 0.1),
|
||||
pos = 0,
|
||||
step = iterator.length / Math.ceil(iterator.length / maxDistance),
|
||||
end = iterator.length + (this._closed ? -step : step) / 2;
|
||||
var segments = [];
|
||||
while (pos <= end) {
|
||||
segments.push(new Segment(iterator.getPointAt(pos)));
|
||||
pos += step;
|
||||
}
|
||||
this.setSegments(segments);
|
||||
},
|
||||
|
||||
reduce: function(options) {
|
||||
var curves = this.getCurves(),
|
||||
simplify = options && options.simplify,
|
||||
tolerance = simplify ? 2e-7 : 0;
|
||||
for (var i = curves.length - 1; i >= 0; i--) {
|
||||
var curve = curves[i];
|
||||
if (!curve.hasHandles() && (curve.getLength() < tolerance
|
||||
|| simplify && curve.isCollinear(curve.getNext())))
|
||||
curve.remove();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
simplify: function(tolerance) {
|
||||
if (this._segments.length > 2) {
|
||||
var fitter = new PathFitter(this, tolerance || 2.5);
|
||||
this.setSegments(fitter.fit());
|
||||
}
|
||||
},
|
||||
|
||||
splitAt: function(location) {
|
||||
var index = location && location.index,
|
||||
time = location && location.time,
|
||||
|
@ -7836,21 +7803,6 @@ var Path = PathItem.extend({
|
|||
return location ? this.splitAt(location) : null;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
this._segments.reverse();
|
||||
for (var i = 0, l = this._segments.length; i < l; i++) {
|
||||
var segment = this._segments[i];
|
||||
var handleIn = segment._handleIn;
|
||||
segment._handleIn = segment._handleOut;
|
||||
segment._handleOut = handleIn;
|
||||
segment._index = i;
|
||||
}
|
||||
this._curves = null;
|
||||
if (this._clockwise !== undefined)
|
||||
this._clockwise = !this._clockwise;
|
||||
this._changed(9);
|
||||
},
|
||||
|
||||
join: function(path) {
|
||||
if (path) {
|
||||
var segments = path._segments,
|
||||
|
@ -7890,6 +7842,159 @@ var Path = PathItem.extend({
|
|||
return this;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
this._segments.reverse();
|
||||
for (var i = 0, l = this._segments.length; i < l; i++) {
|
||||
var segment = this._segments[i];
|
||||
var handleIn = segment._handleIn;
|
||||
segment._handleIn = segment._handleOut;
|
||||
segment._handleOut = handleIn;
|
||||
segment._index = i;
|
||||
}
|
||||
this._curves = null;
|
||||
if (this._clockwise !== undefined)
|
||||
this._clockwise = !this._clockwise;
|
||||
this._changed(9);
|
||||
},
|
||||
|
||||
flatten: function(maxDistance) {
|
||||
var iterator = new PathIterator(this, 64, 0.1),
|
||||
pos = 0,
|
||||
step = iterator.length / Math.ceil(iterator.length / maxDistance),
|
||||
end = iterator.length + (this._closed ? -step : step) / 2;
|
||||
var segments = [];
|
||||
while (pos <= end) {
|
||||
segments.push(new Segment(iterator.getPointAt(pos)));
|
||||
pos += step;
|
||||
}
|
||||
this.setSegments(segments);
|
||||
},
|
||||
|
||||
reduce: function(options) {
|
||||
var curves = this.getCurves(),
|
||||
simplify = options && options.simplify,
|
||||
tolerance = simplify ? 2e-7 : 0;
|
||||
for (var i = curves.length - 1; i >= 0; i--) {
|
||||
var curve = curves[i];
|
||||
if (!curve.hasHandles() && (curve.getLength() < tolerance
|
||||
|| simplify && curve.isCollinear(curve.getNext())))
|
||||
curve.remove();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
simplify: function(tolerance) {
|
||||
var segments = new PathFitter(this).fit(tolerance || 2.5);
|
||||
if (segments)
|
||||
this.setSegments(segments);
|
||||
return !!segments;
|
||||
},
|
||||
|
||||
smooth: function(options) {
|
||||
function getIndex(value, _default) {
|
||||
var index = value && value.index;
|
||||
if (index != null) {
|
||||
var path = value.path;
|
||||
if (path && path !== that)
|
||||
throw new Error(value._class + ' ' + index + ' of ' + path
|
||||
+ ' is not part of ' + that);
|
||||
if (_default && value instanceof Curve)
|
||||
index++;
|
||||
} else {
|
||||
index = typeof value === 'number' ? value : _default;
|
||||
}
|
||||
return Math.min(index < 0 && closed
|
||||
? index % length
|
||||
: index < 0 ? index + length : index, length - 1);
|
||||
}
|
||||
|
||||
var that = this,
|
||||
opts = options || {},
|
||||
type = opts.type || 'asymmetric',
|
||||
segments = this._segments,
|
||||
length = segments.length,
|
||||
closed = this._closed,
|
||||
loop = closed && opts.from === undefined && opts.to === undefined,
|
||||
from = getIndex(opts.from, 0),
|
||||
to = getIndex(opts.to, length - 1);
|
||||
if (from > to) {
|
||||
if (closed) {
|
||||
from -= length;
|
||||
} else {
|
||||
var tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
}
|
||||
if (/^(?:asymmetric|continuous)$/.test(type)) {
|
||||
var asymmetric = type === 'asymmetric',
|
||||
min = Math.min,
|
||||
amount = to - from + 1,
|
||||
n = amount - 1,
|
||||
padding = loop ? min(amount, 4) : 1,
|
||||
paddingLeft = padding,
|
||||
paddingRight = padding,
|
||||
knots = [];
|
||||
if (!closed) {
|
||||
paddingLeft = min(1, from);
|
||||
paddingRight = min(1, length - to - 1);
|
||||
}
|
||||
n += paddingLeft + paddingRight;
|
||||
if (n <= 1)
|
||||
return;
|
||||
for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
|
||||
knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
|
||||
}
|
||||
|
||||
var x = knots[0]._x + 2 * knots[1]._x,
|
||||
y = knots[0]._y + 2 * knots[1]._y,
|
||||
f = 2,
|
||||
n_1 = n - 1,
|
||||
rx = [x],
|
||||
ry = [y],
|
||||
rf = [f],
|
||||
px = [],
|
||||
py = [];
|
||||
for (var i = 1; i < n; i++) {
|
||||
var internal = i < n_1,
|
||||
a = internal ? 1 : asymmetric ? 1 : 2,
|
||||
b = internal ? 4 : asymmetric ? 2 : 7,
|
||||
u = internal ? 4 : asymmetric ? 3 : 8,
|
||||
v = internal ? 2 : asymmetric ? 0 : 1,
|
||||
m = a / f;
|
||||
f = rf[i] = b - m;
|
||||
x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
|
||||
y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
|
||||
}
|
||||
|
||||
px[n_1] = rx[n_1] / rf[n_1];
|
||||
py[n_1] = ry[n_1] / rf[n_1];
|
||||
for (var i = n - 2; i >= 0; i--) {
|
||||
px[i] = (rx[i] - px[i + 1]) / rf[i];
|
||||
py[i] = (ry[i] - py[i + 1]) / rf[i];
|
||||
}
|
||||
px[n] = (3 * knots[n]._x - px[n_1]) / 2;
|
||||
py[n] = (3 * knots[n]._y - py[n_1]) / 2;
|
||||
|
||||
for (var i = paddingLeft, max = n - paddingRight, j = from;
|
||||
i <= max; i++, j++) {
|
||||
var segment = segments[j < 0 ? j + length : j],
|
||||
pt = segment._point,
|
||||
hx = px[i] - pt._x,
|
||||
hy = py[i] - pt._y;
|
||||
if (loop || i < max)
|
||||
segment.setHandleOut(hx, hy);
|
||||
if (loop || i > paddingLeft)
|
||||
segment.setHandleIn(-hx, -hy);
|
||||
}
|
||||
} else {
|
||||
for (var i = from; i <= to; i++) {
|
||||
segments[i < 0 ? i + length : i].smooth(opts,
|
||||
!loop && i === from, !loop && i === to);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
toShape: function(insert) {
|
||||
if (!this._closed)
|
||||
return null;
|
||||
|
@ -8172,111 +8277,6 @@ var Path = PathItem.extend({
|
|||
|
||||
getNearestPoint: function() {
|
||||
return this.getNearestLocation.apply(this, arguments).getPoint();
|
||||
},
|
||||
|
||||
smooth: function(options) {
|
||||
function getIndex(value, _default) {
|
||||
var index = value && value.index;
|
||||
if (index != null) {
|
||||
var path = value.path;
|
||||
if (path && path !== that)
|
||||
throw new Error(value._class + ' ' + index + ' of ' + path
|
||||
+ ' is not part of ' + that);
|
||||
if (_default && value instanceof Curve)
|
||||
index++;
|
||||
} else {
|
||||
index = typeof value === 'number' ? value : _default;
|
||||
}
|
||||
return Math.min(index < 0 && closed
|
||||
? index % length
|
||||
: index < 0 ? index + length : index, length - 1);
|
||||
}
|
||||
|
||||
var that = this,
|
||||
opts = options || {},
|
||||
type = opts.type || 'asymmetric',
|
||||
segments = this._segments,
|
||||
length = segments.length,
|
||||
closed = this._closed,
|
||||
loop = closed && opts.from === undefined && opts.to === undefined,
|
||||
from = getIndex(opts.from, 0),
|
||||
to = getIndex(opts.to, length - 1);
|
||||
if (from > to) {
|
||||
if (closed) {
|
||||
from -= length;
|
||||
} else {
|
||||
var tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
}
|
||||
if (/^(?:asymmetric|continuous)$/.test(type)) {
|
||||
var asymmetric = type === 'asymmetric',
|
||||
min = Math.min,
|
||||
amount = to - from + 1,
|
||||
n = amount - 1,
|
||||
padding = loop ? min(amount, 4) : 1,
|
||||
paddingLeft = padding,
|
||||
paddingRight = padding,
|
||||
knots = [];
|
||||
if (!closed) {
|
||||
paddingLeft = min(1, from);
|
||||
paddingRight = min(1, length - to - 1);
|
||||
}
|
||||
n += paddingLeft + paddingRight;
|
||||
if (n <= 1)
|
||||
return;
|
||||
for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
|
||||
knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
|
||||
}
|
||||
|
||||
var x = knots[0]._x + 2 * knots[1]._x,
|
||||
y = knots[0]._y + 2 * knots[1]._y,
|
||||
f = 2,
|
||||
n_1 = n - 1,
|
||||
rx = [x],
|
||||
ry = [y],
|
||||
rf = [f],
|
||||
px = [],
|
||||
py = [];
|
||||
for (var i = 1; i < n; i++) {
|
||||
var internal = i < n_1,
|
||||
a = internal ? 1 : asymmetric ? 1 : 2,
|
||||
b = internal ? 4 : asymmetric ? 2 : 7,
|
||||
u = internal ? 4 : asymmetric ? 3 : 8,
|
||||
v = internal ? 2 : asymmetric ? 0 : 1,
|
||||
m = a / f;
|
||||
f = rf[i] = b - m;
|
||||
x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
|
||||
y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
|
||||
}
|
||||
|
||||
px[n_1] = rx[n_1] / rf[n_1];
|
||||
py[n_1] = ry[n_1] / rf[n_1];
|
||||
for (var i = n - 2; i >= 0; i--) {
|
||||
px[i] = (rx[i] - px[i + 1]) / rf[i];
|
||||
py[i] = (ry[i] - py[i + 1]) / rf[i];
|
||||
}
|
||||
px[n] = (3 * knots[n]._x - px[n_1]) / 2;
|
||||
py[n] = (3 * knots[n]._y - py[n_1]) / 2;
|
||||
|
||||
for (var i = paddingLeft, max = n - paddingRight, j = from;
|
||||
i <= max; i++, j++) {
|
||||
var segment = segments[j < 0 ? j + length : j],
|
||||
pt = segment._point,
|
||||
hx = px[i] - pt._x,
|
||||
hy = py[i] - pt._y;
|
||||
if (loop || i < max)
|
||||
segment.setHandleOut(hx, hy);
|
||||
if (loop || i > paddingLeft)
|
||||
segment.setHandleIn(-hx, -hy);
|
||||
}
|
||||
} else {
|
||||
for (var i = from; i <= to; i++) {
|
||||
segments[i < 0 ? i + length : i].smooth(opts,
|
||||
!loop && i === from, !loop && i === to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
new function() {
|
||||
|
@ -9040,12 +9040,6 @@ var CompoundPath = PathItem.extend({
|
|||
return items;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
var children = this._children;
|
||||
for (var i = 0, l = children.length; i < l; i++)
|
||||
children[i].reverse();
|
||||
},
|
||||
|
||||
reduce: function reduce(options) {
|
||||
var children = this._children;
|
||||
for (var i = children.length - 1; i >= 0; i--) {
|
||||
|
@ -9063,12 +9057,6 @@ var CompoundPath = PathItem.extend({
|
|||
return reduce.base.call(this);
|
||||
},
|
||||
|
||||
smooth: function(options) {
|
||||
var children = this._children;
|
||||
for (var i = 0, l = children.length; i < l; i++)
|
||||
children[i].smooth(options);
|
||||
},
|
||||
|
||||
isClockwise: function() {
|
||||
var child = this.getFirstChild();
|
||||
return child && child.isClockwise();
|
||||
|
@ -9176,40 +9164,46 @@ new function() {
|
|||
return children[children.length - 1];
|
||||
}
|
||||
|
||||
var fields = {
|
||||
moveTo: function() {
|
||||
var current = getCurrentPath(this),
|
||||
path = current && current.isEmpty() ? current
|
||||
: new Path(Item.NO_INSERT);
|
||||
if (path !== current)
|
||||
this.addChild(path);
|
||||
path.moveTo.apply(path, arguments);
|
||||
},
|
||||
return Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',
|
||||
'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',
|
||||
'arcBy'],
|
||||
function(key) {
|
||||
this[key] = function() {
|
||||
var path = getCurrentPath(this, true);
|
||||
path[key].apply(path, arguments);
|
||||
};
|
||||
}, {
|
||||
moveTo: function() {
|
||||
var current = getCurrentPath(this),
|
||||
path = current && current.isEmpty() ? current
|
||||
: new Path(Item.NO_INSERT);
|
||||
if (path !== current)
|
||||
this.addChild(path);
|
||||
path.moveTo.apply(path, arguments);
|
||||
},
|
||||
|
||||
moveBy: function() {
|
||||
var current = getCurrentPath(this, true),
|
||||
last = current && current.getLastSegment(),
|
||||
point = Point.read(arguments);
|
||||
this.moveTo(last ? point.add(last._point) : point);
|
||||
},
|
||||
moveBy: function() {
|
||||
var current = getCurrentPath(this, true),
|
||||
last = current && current.getLastSegment(),
|
||||
point = Point.read(arguments);
|
||||
this.moveTo(last ? point.add(last._point) : point);
|
||||
},
|
||||
|
||||
closePath: function(join) {
|
||||
getCurrentPath(this, true).closePath(join);
|
||||
}
|
||||
};
|
||||
|
||||
Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo', 'arcTo',
|
||||
'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy', 'arcBy'],
|
||||
function(key) {
|
||||
fields[key] = function() {
|
||||
var path = getCurrentPath(this, true);
|
||||
path[key].apply(path, arguments);
|
||||
};
|
||||
closePath: function(join) {
|
||||
getCurrentPath(this, true).closePath(join);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return fields;
|
||||
});
|
||||
}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {
|
||||
this[key] = function(param) {
|
||||
var children = this._children,
|
||||
res;
|
||||
for (var i = 0, l = children.length; i < l; i++) {
|
||||
res = children[i][key](param) || res;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}, {}));
|
||||
|
||||
PathItem.inject(new function() {
|
||||
var operators = {
|
||||
|
@ -9972,63 +9966,61 @@ var PathIterator = Base.extend({
|
|||
);
|
||||
|
||||
var PathFitter = Base.extend({
|
||||
initialize: function(path, error) {
|
||||
initialize: function(path) {
|
||||
var points = this.points = [],
|
||||
segments = path._segments,
|
||||
prev;
|
||||
for (var i = 0, l = segments.length; i < l; i++) {
|
||||
var point = segments[i].point.clone();
|
||||
closed = path._closed;
|
||||
for (var i = 0, prev, l = segments.length; i < l; i++) {
|
||||
var point = segments[i].point;
|
||||
if (!prev || !prev.equals(point)) {
|
||||
points.push(point);
|
||||
prev = point;
|
||||
points.push(prev = point.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if (path._closed) {
|
||||
this.closed = true;
|
||||
if (closed) {
|
||||
points.unshift(points[points.length - 1]);
|
||||
points.push(points[1]);
|
||||
}
|
||||
|
||||
this.error = error;
|
||||
this.closed = closed;
|
||||
},
|
||||
|
||||
fit: function() {
|
||||
fit: function(error) {
|
||||
var points = this.points,
|
||||
length = points.length,
|
||||
segments = this.segments = length > 0
|
||||
? [new Segment(points[0])] : [];
|
||||
if (length > 1)
|
||||
this.fitCubic(0, length - 1,
|
||||
points[1].subtract(points[0]).normalize(),
|
||||
points[length - 2].subtract(points[length - 1]).normalize());
|
||||
|
||||
if (this.closed) {
|
||||
segments.shift();
|
||||
segments.pop();
|
||||
segments = null;
|
||||
if (length > 0) {
|
||||
segments = [new Segment(points[0])];
|
||||
if (length > 1) {
|
||||
this.fitCubic(segments, error, 0, length - 1,
|
||||
points[1].subtract(points[0]),
|
||||
points[length - 2].subtract(points[length - 1]));
|
||||
if (this.closed) {
|
||||
segments.shift();
|
||||
segments.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return segments;
|
||||
},
|
||||
|
||||
fitCubic: function(first, last, tan1, tan2) {
|
||||
if (last - first == 1) {
|
||||
var pt1 = this.points[first],
|
||||
pt2 = this.points[last],
|
||||
fitCubic: function(segments, error, first, last, tan1, tan2) {
|
||||
var points = this.points;
|
||||
if (last - first === 1) {
|
||||
var pt1 = points[first],
|
||||
pt2 = points[last],
|
||||
dist = pt1.getDistance(pt2) / 3;
|
||||
this.addCurve([pt1, pt1.add(tan1.normalize(dist)),
|
||||
this.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),
|
||||
pt2.add(tan2.normalize(dist)), pt2]);
|
||||
return;
|
||||
}
|
||||
var uPrime = this.chordLengthParameterize(first, last),
|
||||
maxError = Math.max(this.error, this.error * this.error),
|
||||
maxError = Math.max(error, error * error),
|
||||
split,
|
||||
parametersInOrder = true;
|
||||
for (var i = 0; i <= 4; i++) {
|
||||
var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
|
||||
var max = this.findMaxError(first, last, curve, uPrime);
|
||||
if (max.error < this.error && parametersInOrder) {
|
||||
this.addCurve(curve);
|
||||
if (max.error < error && parametersInOrder) {
|
||||
this.addCurve(segments, curve);
|
||||
return;
|
||||
}
|
||||
split = max.index;
|
||||
|
@ -10037,23 +10029,23 @@ var PathFitter = Base.extend({
|
|||
parametersInOrder = this.reparameterize(first, last, uPrime, curve);
|
||||
maxError = max.error;
|
||||
}
|
||||
var tanCenter = this.points[split - 1].subtract(this.points[split + 1])
|
||||
.normalize();
|
||||
this.fitCubic(first, split, tan1, tanCenter);
|
||||
this.fitCubic(split, last, tanCenter.negate(), tan2);
|
||||
var tanCenter = points[split - 1].subtract(points[split + 1]);
|
||||
this.fitCubic(segments, error, first, split, tan1, tanCenter);
|
||||
this.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);
|
||||
},
|
||||
|
||||
addCurve: function(curve) {
|
||||
var prev = this.segments[this.segments.length - 1];
|
||||
addCurve: function(segments, curve) {
|
||||
var prev = segments[segments.length - 1];
|
||||
prev.setHandleOut(curve[1].subtract(curve[0]));
|
||||
this.segments.push(
|
||||
new Segment(curve[3], curve[2].subtract(curve[3])));
|
||||
segments.push(new Segment(curve[3], curve[2].subtract(curve[3])));
|
||||
},
|
||||
|
||||
generateBezier: function(first, last, uPrime, tan1, tan2) {
|
||||
var epsilon = 1e-12,
|
||||
pt1 = this.points[first],
|
||||
pt2 = this.points[last],
|
||||
abs = Math.abs,
|
||||
points = this.points,
|
||||
pt1 = points[first],
|
||||
pt2 = points[last],
|
||||
C = [[0, 0], [0, 0]],
|
||||
X = [0, 0];
|
||||
|
||||
|
@ -10067,7 +10059,7 @@ var PathFitter = Base.extend({
|
|||
b3 = u * u * u,
|
||||
a1 = tan1.normalize(b1),
|
||||
a2 = tan2.normalize(b2),
|
||||
tmp = this.points[first + i]
|
||||
tmp = points[first + i]
|
||||
.subtract(pt1.multiply(b0 + b1))
|
||||
.subtract(pt2.multiply(b2 + b3));
|
||||
C[0][0] += a1.dot(a1);
|
||||
|
@ -10080,7 +10072,7 @@ var PathFitter = Base.extend({
|
|||
|
||||
var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],
|
||||
alpha1, alpha2;
|
||||
if (Math.abs(detC0C1) > epsilon) {
|
||||
if (abs(detC0C1) > epsilon) {
|
||||
var detC0X = C[0][0] * X[1] - C[1][0] * X[0],
|
||||
detXC1 = X[0] * C[1][1] - X[1] * C[0][1];
|
||||
alpha1 = detXC1 / detC0C1;
|
||||
|
@ -10088,9 +10080,9 @@ var PathFitter = Base.extend({
|
|||
} else {
|
||||
var c0 = C[0][0] + C[0][1],
|
||||
c1 = C[1][0] + C[1][1];
|
||||
if (Math.abs(c0) > epsilon) {
|
||||
if (abs(c0) > epsilon) {
|
||||
alpha1 = alpha2 = X[0] / c0;
|
||||
} else if (Math.abs(c1) > epsilon) {
|
||||
} else if (abs(c1) > epsilon) {
|
||||
alpha1 = alpha2 = X[1] / c1;
|
||||
} else {
|
||||
alpha1 = alpha2 = 0;
|
||||
|
@ -10113,8 +10105,10 @@ var PathFitter = Base.extend({
|
|||
}
|
||||
}
|
||||
|
||||
return [pt1, pt1.add(handle1 || tan1.normalize(alpha1)),
|
||||
pt2.add(handle2 || tan2.normalize(alpha2)), pt2];
|
||||
return [pt1,
|
||||
pt1.add(handle1 || tan1.normalize(alpha1)),
|
||||
pt2.add(handle2 || tan2.normalize(alpha2)),
|
||||
pt2];
|
||||
},
|
||||
|
||||
reparameterize: function(first, last, u, curve) {
|
||||
|
|
8
dist/paper-core.min.js
vendored
8
dist/paper-core.min.js
vendored
File diff suppressed because one or more lines are too long
480
dist/paper-full.js
vendored
480
dist/paper-full.js
vendored
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Date: Tue Feb 9 10:07:28 2016 +0100
|
||||
* Date: Tue Feb 9 14:13:30 2016 +0100
|
||||
*
|
||||
***
|
||||
*
|
||||
|
@ -7764,39 +7764,6 @@ var Path = PathItem.extend({
|
|||
this.setSelected(true);
|
||||
},
|
||||
|
||||
flatten: function(maxDistance) {
|
||||
var iterator = new PathIterator(this, 64, 0.1),
|
||||
pos = 0,
|
||||
step = iterator.length / Math.ceil(iterator.length / maxDistance),
|
||||
end = iterator.length + (this._closed ? -step : step) / 2;
|
||||
var segments = [];
|
||||
while (pos <= end) {
|
||||
segments.push(new Segment(iterator.getPointAt(pos)));
|
||||
pos += step;
|
||||
}
|
||||
this.setSegments(segments);
|
||||
},
|
||||
|
||||
reduce: function(options) {
|
||||
var curves = this.getCurves(),
|
||||
simplify = options && options.simplify,
|
||||
tolerance = simplify ? 2e-7 : 0;
|
||||
for (var i = curves.length - 1; i >= 0; i--) {
|
||||
var curve = curves[i];
|
||||
if (!curve.hasHandles() && (curve.getLength() < tolerance
|
||||
|| simplify && curve.isCollinear(curve.getNext())))
|
||||
curve.remove();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
simplify: function(tolerance) {
|
||||
if (this._segments.length > 2) {
|
||||
var fitter = new PathFitter(this, tolerance || 2.5);
|
||||
this.setSegments(fitter.fit());
|
||||
}
|
||||
},
|
||||
|
||||
splitAt: function(location) {
|
||||
var index = location && location.index,
|
||||
time = location && location.time,
|
||||
|
@ -7836,21 +7803,6 @@ var Path = PathItem.extend({
|
|||
return location ? this.splitAt(location) : null;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
this._segments.reverse();
|
||||
for (var i = 0, l = this._segments.length; i < l; i++) {
|
||||
var segment = this._segments[i];
|
||||
var handleIn = segment._handleIn;
|
||||
segment._handleIn = segment._handleOut;
|
||||
segment._handleOut = handleIn;
|
||||
segment._index = i;
|
||||
}
|
||||
this._curves = null;
|
||||
if (this._clockwise !== undefined)
|
||||
this._clockwise = !this._clockwise;
|
||||
this._changed(9);
|
||||
},
|
||||
|
||||
join: function(path) {
|
||||
if (path) {
|
||||
var segments = path._segments,
|
||||
|
@ -7890,6 +7842,159 @@ var Path = PathItem.extend({
|
|||
return this;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
this._segments.reverse();
|
||||
for (var i = 0, l = this._segments.length; i < l; i++) {
|
||||
var segment = this._segments[i];
|
||||
var handleIn = segment._handleIn;
|
||||
segment._handleIn = segment._handleOut;
|
||||
segment._handleOut = handleIn;
|
||||
segment._index = i;
|
||||
}
|
||||
this._curves = null;
|
||||
if (this._clockwise !== undefined)
|
||||
this._clockwise = !this._clockwise;
|
||||
this._changed(9);
|
||||
},
|
||||
|
||||
flatten: function(maxDistance) {
|
||||
var iterator = new PathIterator(this, 64, 0.1),
|
||||
pos = 0,
|
||||
step = iterator.length / Math.ceil(iterator.length / maxDistance),
|
||||
end = iterator.length + (this._closed ? -step : step) / 2;
|
||||
var segments = [];
|
||||
while (pos <= end) {
|
||||
segments.push(new Segment(iterator.getPointAt(pos)));
|
||||
pos += step;
|
||||
}
|
||||
this.setSegments(segments);
|
||||
},
|
||||
|
||||
reduce: function(options) {
|
||||
var curves = this.getCurves(),
|
||||
simplify = options && options.simplify,
|
||||
tolerance = simplify ? 2e-7 : 0;
|
||||
for (var i = curves.length - 1; i >= 0; i--) {
|
||||
var curve = curves[i];
|
||||
if (!curve.hasHandles() && (curve.getLength() < tolerance
|
||||
|| simplify && curve.isCollinear(curve.getNext())))
|
||||
curve.remove();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
simplify: function(tolerance) {
|
||||
var segments = new PathFitter(this).fit(tolerance || 2.5);
|
||||
if (segments)
|
||||
this.setSegments(segments);
|
||||
return !!segments;
|
||||
},
|
||||
|
||||
smooth: function(options) {
|
||||
function getIndex(value, _default) {
|
||||
var index = value && value.index;
|
||||
if (index != null) {
|
||||
var path = value.path;
|
||||
if (path && path !== that)
|
||||
throw new Error(value._class + ' ' + index + ' of ' + path
|
||||
+ ' is not part of ' + that);
|
||||
if (_default && value instanceof Curve)
|
||||
index++;
|
||||
} else {
|
||||
index = typeof value === 'number' ? value : _default;
|
||||
}
|
||||
return Math.min(index < 0 && closed
|
||||
? index % length
|
||||
: index < 0 ? index + length : index, length - 1);
|
||||
}
|
||||
|
||||
var that = this,
|
||||
opts = options || {},
|
||||
type = opts.type || 'asymmetric',
|
||||
segments = this._segments,
|
||||
length = segments.length,
|
||||
closed = this._closed,
|
||||
loop = closed && opts.from === undefined && opts.to === undefined,
|
||||
from = getIndex(opts.from, 0),
|
||||
to = getIndex(opts.to, length - 1);
|
||||
if (from > to) {
|
||||
if (closed) {
|
||||
from -= length;
|
||||
} else {
|
||||
var tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
}
|
||||
if (/^(?:asymmetric|continuous)$/.test(type)) {
|
||||
var asymmetric = type === 'asymmetric',
|
||||
min = Math.min,
|
||||
amount = to - from + 1,
|
||||
n = amount - 1,
|
||||
padding = loop ? min(amount, 4) : 1,
|
||||
paddingLeft = padding,
|
||||
paddingRight = padding,
|
||||
knots = [];
|
||||
if (!closed) {
|
||||
paddingLeft = min(1, from);
|
||||
paddingRight = min(1, length - to - 1);
|
||||
}
|
||||
n += paddingLeft + paddingRight;
|
||||
if (n <= 1)
|
||||
return;
|
||||
for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
|
||||
knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
|
||||
}
|
||||
|
||||
var x = knots[0]._x + 2 * knots[1]._x,
|
||||
y = knots[0]._y + 2 * knots[1]._y,
|
||||
f = 2,
|
||||
n_1 = n - 1,
|
||||
rx = [x],
|
||||
ry = [y],
|
||||
rf = [f],
|
||||
px = [],
|
||||
py = [];
|
||||
for (var i = 1; i < n; i++) {
|
||||
var internal = i < n_1,
|
||||
a = internal ? 1 : asymmetric ? 1 : 2,
|
||||
b = internal ? 4 : asymmetric ? 2 : 7,
|
||||
u = internal ? 4 : asymmetric ? 3 : 8,
|
||||
v = internal ? 2 : asymmetric ? 0 : 1,
|
||||
m = a / f;
|
||||
f = rf[i] = b - m;
|
||||
x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
|
||||
y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
|
||||
}
|
||||
|
||||
px[n_1] = rx[n_1] / rf[n_1];
|
||||
py[n_1] = ry[n_1] / rf[n_1];
|
||||
for (var i = n - 2; i >= 0; i--) {
|
||||
px[i] = (rx[i] - px[i + 1]) / rf[i];
|
||||
py[i] = (ry[i] - py[i + 1]) / rf[i];
|
||||
}
|
||||
px[n] = (3 * knots[n]._x - px[n_1]) / 2;
|
||||
py[n] = (3 * knots[n]._y - py[n_1]) / 2;
|
||||
|
||||
for (var i = paddingLeft, max = n - paddingRight, j = from;
|
||||
i <= max; i++, j++) {
|
||||
var segment = segments[j < 0 ? j + length : j],
|
||||
pt = segment._point,
|
||||
hx = px[i] - pt._x,
|
||||
hy = py[i] - pt._y;
|
||||
if (loop || i < max)
|
||||
segment.setHandleOut(hx, hy);
|
||||
if (loop || i > paddingLeft)
|
||||
segment.setHandleIn(-hx, -hy);
|
||||
}
|
||||
} else {
|
||||
for (var i = from; i <= to; i++) {
|
||||
segments[i < 0 ? i + length : i].smooth(opts,
|
||||
!loop && i === from, !loop && i === to);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
toShape: function(insert) {
|
||||
if (!this._closed)
|
||||
return null;
|
||||
|
@ -8172,111 +8277,6 @@ var Path = PathItem.extend({
|
|||
|
||||
getNearestPoint: function() {
|
||||
return this.getNearestLocation.apply(this, arguments).getPoint();
|
||||
},
|
||||
|
||||
smooth: function(options) {
|
||||
function getIndex(value, _default) {
|
||||
var index = value && value.index;
|
||||
if (index != null) {
|
||||
var path = value.path;
|
||||
if (path && path !== that)
|
||||
throw new Error(value._class + ' ' + index + ' of ' + path
|
||||
+ ' is not part of ' + that);
|
||||
if (_default && value instanceof Curve)
|
||||
index++;
|
||||
} else {
|
||||
index = typeof value === 'number' ? value : _default;
|
||||
}
|
||||
return Math.min(index < 0 && closed
|
||||
? index % length
|
||||
: index < 0 ? index + length : index, length - 1);
|
||||
}
|
||||
|
||||
var that = this,
|
||||
opts = options || {},
|
||||
type = opts.type || 'asymmetric',
|
||||
segments = this._segments,
|
||||
length = segments.length,
|
||||
closed = this._closed,
|
||||
loop = closed && opts.from === undefined && opts.to === undefined,
|
||||
from = getIndex(opts.from, 0),
|
||||
to = getIndex(opts.to, length - 1);
|
||||
if (from > to) {
|
||||
if (closed) {
|
||||
from -= length;
|
||||
} else {
|
||||
var tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
}
|
||||
if (/^(?:asymmetric|continuous)$/.test(type)) {
|
||||
var asymmetric = type === 'asymmetric',
|
||||
min = Math.min,
|
||||
amount = to - from + 1,
|
||||
n = amount - 1,
|
||||
padding = loop ? min(amount, 4) : 1,
|
||||
paddingLeft = padding,
|
||||
paddingRight = padding,
|
||||
knots = [];
|
||||
if (!closed) {
|
||||
paddingLeft = min(1, from);
|
||||
paddingRight = min(1, length - to - 1);
|
||||
}
|
||||
n += paddingLeft + paddingRight;
|
||||
if (n <= 1)
|
||||
return;
|
||||
for (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {
|
||||
knots[i] = segments[(j < 0 ? j + length : j) % length]._point;
|
||||
}
|
||||
|
||||
var x = knots[0]._x + 2 * knots[1]._x,
|
||||
y = knots[0]._y + 2 * knots[1]._y,
|
||||
f = 2,
|
||||
n_1 = n - 1,
|
||||
rx = [x],
|
||||
ry = [y],
|
||||
rf = [f],
|
||||
px = [],
|
||||
py = [];
|
||||
for (var i = 1; i < n; i++) {
|
||||
var internal = i < n_1,
|
||||
a = internal ? 1 : asymmetric ? 1 : 2,
|
||||
b = internal ? 4 : asymmetric ? 2 : 7,
|
||||
u = internal ? 4 : asymmetric ? 3 : 8,
|
||||
v = internal ? 2 : asymmetric ? 0 : 1,
|
||||
m = a / f;
|
||||
f = rf[i] = b - m;
|
||||
x = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;
|
||||
y = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;
|
||||
}
|
||||
|
||||
px[n_1] = rx[n_1] / rf[n_1];
|
||||
py[n_1] = ry[n_1] / rf[n_1];
|
||||
for (var i = n - 2; i >= 0; i--) {
|
||||
px[i] = (rx[i] - px[i + 1]) / rf[i];
|
||||
py[i] = (ry[i] - py[i + 1]) / rf[i];
|
||||
}
|
||||
px[n] = (3 * knots[n]._x - px[n_1]) / 2;
|
||||
py[n] = (3 * knots[n]._y - py[n_1]) / 2;
|
||||
|
||||
for (var i = paddingLeft, max = n - paddingRight, j = from;
|
||||
i <= max; i++, j++) {
|
||||
var segment = segments[j < 0 ? j + length : j],
|
||||
pt = segment._point,
|
||||
hx = px[i] - pt._x,
|
||||
hy = py[i] - pt._y;
|
||||
if (loop || i < max)
|
||||
segment.setHandleOut(hx, hy);
|
||||
if (loop || i > paddingLeft)
|
||||
segment.setHandleIn(-hx, -hy);
|
||||
}
|
||||
} else {
|
||||
for (var i = from; i <= to; i++) {
|
||||
segments[i < 0 ? i + length : i].smooth(opts,
|
||||
!loop && i === from, !loop && i === to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
new function() {
|
||||
|
@ -9040,12 +9040,6 @@ var CompoundPath = PathItem.extend({
|
|||
return items;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
var children = this._children;
|
||||
for (var i = 0, l = children.length; i < l; i++)
|
||||
children[i].reverse();
|
||||
},
|
||||
|
||||
reduce: function reduce(options) {
|
||||
var children = this._children;
|
||||
for (var i = children.length - 1; i >= 0; i--) {
|
||||
|
@ -9063,12 +9057,6 @@ var CompoundPath = PathItem.extend({
|
|||
return reduce.base.call(this);
|
||||
},
|
||||
|
||||
smooth: function(options) {
|
||||
var children = this._children;
|
||||
for (var i = 0, l = children.length; i < l; i++)
|
||||
children[i].smooth(options);
|
||||
},
|
||||
|
||||
isClockwise: function() {
|
||||
var child = this.getFirstChild();
|
||||
return child && child.isClockwise();
|
||||
|
@ -9176,40 +9164,46 @@ new function() {
|
|||
return children[children.length - 1];
|
||||
}
|
||||
|
||||
var fields = {
|
||||
moveTo: function() {
|
||||
var current = getCurrentPath(this),
|
||||
path = current && current.isEmpty() ? current
|
||||
: new Path(Item.NO_INSERT);
|
||||
if (path !== current)
|
||||
this.addChild(path);
|
||||
path.moveTo.apply(path, arguments);
|
||||
},
|
||||
return Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',
|
||||
'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',
|
||||
'arcBy'],
|
||||
function(key) {
|
||||
this[key] = function() {
|
||||
var path = getCurrentPath(this, true);
|
||||
path[key].apply(path, arguments);
|
||||
};
|
||||
}, {
|
||||
moveTo: function() {
|
||||
var current = getCurrentPath(this),
|
||||
path = current && current.isEmpty() ? current
|
||||
: new Path(Item.NO_INSERT);
|
||||
if (path !== current)
|
||||
this.addChild(path);
|
||||
path.moveTo.apply(path, arguments);
|
||||
},
|
||||
|
||||
moveBy: function() {
|
||||
var current = getCurrentPath(this, true),
|
||||
last = current && current.getLastSegment(),
|
||||
point = Point.read(arguments);
|
||||
this.moveTo(last ? point.add(last._point) : point);
|
||||
},
|
||||
moveBy: function() {
|
||||
var current = getCurrentPath(this, true),
|
||||
last = current && current.getLastSegment(),
|
||||
point = Point.read(arguments);
|
||||
this.moveTo(last ? point.add(last._point) : point);
|
||||
},
|
||||
|
||||
closePath: function(join) {
|
||||
getCurrentPath(this, true).closePath(join);
|
||||
}
|
||||
};
|
||||
|
||||
Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo', 'arcTo',
|
||||
'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy', 'arcBy'],
|
||||
function(key) {
|
||||
fields[key] = function() {
|
||||
var path = getCurrentPath(this, true);
|
||||
path[key].apply(path, arguments);
|
||||
};
|
||||
closePath: function(join) {
|
||||
getCurrentPath(this, true).closePath(join);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return fields;
|
||||
});
|
||||
}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {
|
||||
this[key] = function(param) {
|
||||
var children = this._children,
|
||||
res;
|
||||
for (var i = 0, l = children.length; i < l; i++) {
|
||||
res = children[i][key](param) || res;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}, {}));
|
||||
|
||||
PathItem.inject(new function() {
|
||||
var operators = {
|
||||
|
@ -9972,63 +9966,61 @@ var PathIterator = Base.extend({
|
|||
);
|
||||
|
||||
var PathFitter = Base.extend({
|
||||
initialize: function(path, error) {
|
||||
initialize: function(path) {
|
||||
var points = this.points = [],
|
||||
segments = path._segments,
|
||||
prev;
|
||||
for (var i = 0, l = segments.length; i < l; i++) {
|
||||
var point = segments[i].point.clone();
|
||||
closed = path._closed;
|
||||
for (var i = 0, prev, l = segments.length; i < l; i++) {
|
||||
var point = segments[i].point;
|
||||
if (!prev || !prev.equals(point)) {
|
||||
points.push(point);
|
||||
prev = point;
|
||||
points.push(prev = point.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if (path._closed) {
|
||||
this.closed = true;
|
||||
if (closed) {
|
||||
points.unshift(points[points.length - 1]);
|
||||
points.push(points[1]);
|
||||
}
|
||||
|
||||
this.error = error;
|
||||
this.closed = closed;
|
||||
},
|
||||
|
||||
fit: function() {
|
||||
fit: function(error) {
|
||||
var points = this.points,
|
||||
length = points.length,
|
||||
segments = this.segments = length > 0
|
||||
? [new Segment(points[0])] : [];
|
||||
if (length > 1)
|
||||
this.fitCubic(0, length - 1,
|
||||
points[1].subtract(points[0]).normalize(),
|
||||
points[length - 2].subtract(points[length - 1]).normalize());
|
||||
|
||||
if (this.closed) {
|
||||
segments.shift();
|
||||
segments.pop();
|
||||
segments = null;
|
||||
if (length > 0) {
|
||||
segments = [new Segment(points[0])];
|
||||
if (length > 1) {
|
||||
this.fitCubic(segments, error, 0, length - 1,
|
||||
points[1].subtract(points[0]),
|
||||
points[length - 2].subtract(points[length - 1]));
|
||||
if (this.closed) {
|
||||
segments.shift();
|
||||
segments.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return segments;
|
||||
},
|
||||
|
||||
fitCubic: function(first, last, tan1, tan2) {
|
||||
if (last - first == 1) {
|
||||
var pt1 = this.points[first],
|
||||
pt2 = this.points[last],
|
||||
fitCubic: function(segments, error, first, last, tan1, tan2) {
|
||||
var points = this.points;
|
||||
if (last - first === 1) {
|
||||
var pt1 = points[first],
|
||||
pt2 = points[last],
|
||||
dist = pt1.getDistance(pt2) / 3;
|
||||
this.addCurve([pt1, pt1.add(tan1.normalize(dist)),
|
||||
this.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),
|
||||
pt2.add(tan2.normalize(dist)), pt2]);
|
||||
return;
|
||||
}
|
||||
var uPrime = this.chordLengthParameterize(first, last),
|
||||
maxError = Math.max(this.error, this.error * this.error),
|
||||
maxError = Math.max(error, error * error),
|
||||
split,
|
||||
parametersInOrder = true;
|
||||
for (var i = 0; i <= 4; i++) {
|
||||
var curve = this.generateBezier(first, last, uPrime, tan1, tan2);
|
||||
var max = this.findMaxError(first, last, curve, uPrime);
|
||||
if (max.error < this.error && parametersInOrder) {
|
||||
this.addCurve(curve);
|
||||
if (max.error < error && parametersInOrder) {
|
||||
this.addCurve(segments, curve);
|
||||
return;
|
||||
}
|
||||
split = max.index;
|
||||
|
@ -10037,23 +10029,23 @@ var PathFitter = Base.extend({
|
|||
parametersInOrder = this.reparameterize(first, last, uPrime, curve);
|
||||
maxError = max.error;
|
||||
}
|
||||
var tanCenter = this.points[split - 1].subtract(this.points[split + 1])
|
||||
.normalize();
|
||||
this.fitCubic(first, split, tan1, tanCenter);
|
||||
this.fitCubic(split, last, tanCenter.negate(), tan2);
|
||||
var tanCenter = points[split - 1].subtract(points[split + 1]);
|
||||
this.fitCubic(segments, error, first, split, tan1, tanCenter);
|
||||
this.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);
|
||||
},
|
||||
|
||||
addCurve: function(curve) {
|
||||
var prev = this.segments[this.segments.length - 1];
|
||||
addCurve: function(segments, curve) {
|
||||
var prev = segments[segments.length - 1];
|
||||
prev.setHandleOut(curve[1].subtract(curve[0]));
|
||||
this.segments.push(
|
||||
new Segment(curve[3], curve[2].subtract(curve[3])));
|
||||
segments.push(new Segment(curve[3], curve[2].subtract(curve[3])));
|
||||
},
|
||||
|
||||
generateBezier: function(first, last, uPrime, tan1, tan2) {
|
||||
var epsilon = 1e-12,
|
||||
pt1 = this.points[first],
|
||||
pt2 = this.points[last],
|
||||
abs = Math.abs,
|
||||
points = this.points,
|
||||
pt1 = points[first],
|
||||
pt2 = points[last],
|
||||
C = [[0, 0], [0, 0]],
|
||||
X = [0, 0];
|
||||
|
||||
|
@ -10067,7 +10059,7 @@ var PathFitter = Base.extend({
|
|||
b3 = u * u * u,
|
||||
a1 = tan1.normalize(b1),
|
||||
a2 = tan2.normalize(b2),
|
||||
tmp = this.points[first + i]
|
||||
tmp = points[first + i]
|
||||
.subtract(pt1.multiply(b0 + b1))
|
||||
.subtract(pt2.multiply(b2 + b3));
|
||||
C[0][0] += a1.dot(a1);
|
||||
|
@ -10080,7 +10072,7 @@ var PathFitter = Base.extend({
|
|||
|
||||
var detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],
|
||||
alpha1, alpha2;
|
||||
if (Math.abs(detC0C1) > epsilon) {
|
||||
if (abs(detC0C1) > epsilon) {
|
||||
var detC0X = C[0][0] * X[1] - C[1][0] * X[0],
|
||||
detXC1 = X[0] * C[1][1] - X[1] * C[0][1];
|
||||
alpha1 = detXC1 / detC0C1;
|
||||
|
@ -10088,9 +10080,9 @@ var PathFitter = Base.extend({
|
|||
} else {
|
||||
var c0 = C[0][0] + C[0][1],
|
||||
c1 = C[1][0] + C[1][1];
|
||||
if (Math.abs(c0) > epsilon) {
|
||||
if (abs(c0) > epsilon) {
|
||||
alpha1 = alpha2 = X[0] / c0;
|
||||
} else if (Math.abs(c1) > epsilon) {
|
||||
} else if (abs(c1) > epsilon) {
|
||||
alpha1 = alpha2 = X[1] / c1;
|
||||
} else {
|
||||
alpha1 = alpha2 = 0;
|
||||
|
@ -10113,8 +10105,10 @@ var PathFitter = Base.extend({
|
|||
}
|
||||
}
|
||||
|
||||
return [pt1, pt1.add(handle1 || tan1.normalize(alpha1)),
|
||||
pt2.add(handle2 || tan2.normalize(alpha2)), pt2];
|
||||
return [pt1,
|
||||
pt1.add(handle1 || tan1.normalize(alpha1)),
|
||||
pt2.add(handle2 || tan2.normalize(alpha2)),
|
||||
pt2];
|
||||
},
|
||||
|
||||
reparameterize: function(first, last, u, curve) {
|
||||
|
|
10
dist/paper-full.min.js
vendored
10
dist/paper-full.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue