mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-29 09:22:22 -05:00
Rename curve-time in API from 'parameter' to 'time'
And create separate versions of methods that receive curve-time arguments instead of offsets. Curve#getNormalAt(time, true) -> #getNormalAtTime(true) Curve#divide() -> #divideAt(offset) / #divideAtTime(time) Curve#split() -> #splitAt(offset) / #splitAtTime(time) Curve#getParameterAt(offset) -> #getTimeAt(offset) Curve#getParameterOf(point) -> getTimeOf(point) Curve#getPointAt(time, true) -> #getPointAtTime(time) Curve#getTangentAt(time, true) -> #getTangenttTime(time) Curve#getNormalAt(time, true) -> #getNormalAtTime(time) Curve#getCurvatureAt(time, true) -> #getCurvatureAtTime(time) CurveLocation#parameter -> #time Path#split(offset/location) -> #splitAt(offset/location) Closes #563
This commit is contained in:
parent
45595b2b1d
commit
340a1e2a5f
12 changed files with 447 additions and 385 deletions
|
@ -257,7 +257,7 @@
|
||||||
// pathB.style = pathStyleBoolean;
|
// pathB.style = pathStyleBoolean;
|
||||||
|
|
||||||
// // var ixs = pathA.getIntersections(pathB);
|
// // var ixs = pathA.getIntersections(pathB);
|
||||||
// // ixs.map(function(a) { console.log("(" + a.path.id + " , " + a.curve.index + " , "+ a.parameter +")");
|
// // ixs.map(function(a) { console.log("(" + a.path.id + " , " + a.curve.index + " , "+ a.time +")");
|
||||||
// // markPoint(a.point, " ") });
|
// // markPoint(a.point, " ") });
|
||||||
// // ixs.map(function(a) { markPoint(a.point, " "); });
|
// // ixs.map(function(a) { markPoint(a.point, " "); });
|
||||||
|
|
||||||
|
@ -402,7 +402,7 @@
|
||||||
t = t || s.index;
|
t = t || s.index;
|
||||||
if (remove === undefined) { remove = true; }
|
if (remove === undefined) { remove = true; }
|
||||||
var crv = s.curve;
|
var crv = s.curve;
|
||||||
var t1 = crv.getNormalAt(0, true).normalize(10);
|
var t1 = crv.getNormalAtTime(0).normalize(10);
|
||||||
var p = s.point.clone().add(t1);
|
var p = s.point.clone().add(t1);
|
||||||
var cir = new Path.Circle(s.point, 2);
|
var cir = new Path.Circle(s.point, 2);
|
||||||
cir.style.fillColor = c;
|
cir.style.fillColor = c;
|
||||||
|
@ -427,12 +427,12 @@
|
||||||
tc = tc || '#ccc';
|
tc = tc || '#ccc';
|
||||||
t = t || crv.index;
|
t = t || crv.index;
|
||||||
if (remove === undefined) { remove = true; }
|
if (remove === undefined) { remove = true; }
|
||||||
var p = crv.getPointAt(0.57, true);
|
var p = crv.getPointAtTime(0.57);
|
||||||
var t1 = crv.getTangentAt(0.57, true).normalize(-10);
|
var t1 = crv.getTangentAtTime(0.57).normalize(-10);
|
||||||
var p2 = p.clone().add(t1);
|
var p2 = p.clone().add(t1);
|
||||||
var l = new Path.Line(p, p2).rotate(30, p);
|
var l = new Path.Line(p, p2).rotate(30, p);
|
||||||
var l2 = new Path.Line(p, p2).rotate(-30, p);
|
var l2 = new Path.Line(p, p2).rotate(-30, p);
|
||||||
p = crv.getPointAt(0.43, true);
|
p = crv.getPointAtTime(0.43);
|
||||||
var cir = new Path.Circle(p, 8);
|
var cir = new Path.Circle(p, 8);
|
||||||
var text = new PointText(p.subtract([0, -4]));
|
var text = new PointText(p.subtract([0, -4]));
|
||||||
text.justification = 'center';
|
text.justification = 'center';
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
curve.segment2.point = point;
|
curve.segment2.point = point;
|
||||||
var length = curve.length;
|
var length = curve.length;
|
||||||
var step = 10;
|
var step = 10;
|
||||||
var iteratively = false;
|
var iteratively = true;
|
||||||
var flatten = true;
|
var flatten = true;
|
||||||
var num = Math.floor(length / step);
|
var num = Math.floor(length / step);
|
||||||
var prev = 0;
|
var prev = 0;
|
||||||
|
@ -39,9 +39,9 @@
|
||||||
} else {
|
} else {
|
||||||
for (var i = 0, pos = 0; i <= num; i++, pos += step) {
|
for (var i = 0, pos = 0; i <= num; i++, pos += step) {
|
||||||
var t = iteratively
|
var t = iteratively
|
||||||
? curve.getParameterAt(step, prev)
|
? curve.getTimeAt(step, prev)
|
||||||
: curve.getParameterAt(pos);
|
: curve.getTimeAt(pos);
|
||||||
var point = curve.getPointAt(t, true);
|
var point = curve.getPointAtTime(t);
|
||||||
var circle = new Path.Circle(point, step / 2);
|
var circle = new Path.Circle(point, step / 2);
|
||||||
circle.strokeColor = 'red';
|
circle.strokeColor = 'red';
|
||||||
if (remove)
|
if (remove)
|
||||||
|
|
|
@ -27,7 +27,7 @@ paper = new (PaperScope.inject(Base.exports, {
|
||||||
// Export jsdom document and window too, for Node.js
|
// Export jsdom document and window too, for Node.js
|
||||||
document: document,
|
document: document,
|
||||||
window: window,
|
window: window,
|
||||||
// TODO: Remove in 2017 (deprecated January 2016):
|
// TODO: Remove in 1.0.0? (deprecated January 2016):
|
||||||
Symbol: SymbolDefinition,
|
Symbol: SymbolDefinition,
|
||||||
PlacedSymbol: SymbolItem
|
PlacedSymbol: SymbolItem
|
||||||
}))();
|
}))();
|
||||||
|
|
|
@ -403,7 +403,7 @@ var Curve = Base.extend(/** @lends Curve# */{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new curve as a sub-curve from this curve, its range defined by
|
* Creates a new curve as a sub-curve from this curve, its range defined by
|
||||||
* the given parameters. If `from` is larger than `to`, then
|
* the given curve-time parameters. If `from` is larger than `to`, then
|
||||||
* the resulting curve will have its direction reversed.
|
* the resulting curve will have its direction reversed.
|
||||||
*
|
*
|
||||||
* @param {Number} from the curve-time parameter at which the sub-curve
|
* @param {Number} from the curve-time parameter at which the sub-curve
|
||||||
|
@ -439,46 +439,44 @@ var Curve = Base.extend(/** @lends Curve# */{
|
||||||
|
|
||||||
// TODO: adjustThroughPoint
|
// TODO: adjustThroughPoint
|
||||||
|
|
||||||
/**
|
|
||||||
* Private method that handles all types of offset / isParameter pairs and
|
|
||||||
* converts it to a curve parameter.
|
|
||||||
*/
|
|
||||||
_getParameter: function(offset, isParameter) {
|
|
||||||
return isParameter
|
|
||||||
? offset
|
|
||||||
// Accept CurveLocation objects, and objects that act like
|
|
||||||
// them:
|
|
||||||
: offset && offset.curve === this
|
|
||||||
? offset.parameter
|
|
||||||
: offset === undefined && isParameter === undefined
|
|
||||||
? 0.5 // default is in the middle
|
|
||||||
: this.getParameterAt(offset, 0);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divides the curve into two curves at the given offset. The curve itself
|
* Divides the curve into two curves at the given offset. The curve itself
|
||||||
* is modified and becomes the first part, the second part is returned as a
|
* is modified and becomes the first part, the second part is returned as a
|
||||||
* new curve. If the modified curve belongs to a path item, the second part
|
* new curve. If the modified curve belongs to a path item, the second part
|
||||||
* is also added to the path.
|
* is also added to the path.
|
||||||
*
|
*
|
||||||
* @name Curve#divide
|
* @param {Number|CurveLocation} location the offset or location on the
|
||||||
* @function
|
* curve at which to divide
|
||||||
* @param {Number} [offset=0.5] the offset on the curve at which to split,
|
|
||||||
* or the curve time parameter if `isParameter` is `true`
|
|
||||||
* @param {Boolean} [isParameter=false] pass `true` if `offset` is a curve
|
|
||||||
* time parameter
|
|
||||||
* @return {Curve} the second part of the divided curve, if the offset is
|
* @return {Curve} the second part of the divided curve, if the offset is
|
||||||
* within the valid range, {code null} otherwise.
|
* within the valid range, {code null} otherwise.
|
||||||
|
* @see #divideAtTime(time)
|
||||||
*/
|
*/
|
||||||
// TODO: Rename to divideAt()?
|
divideAt: function(location) {
|
||||||
divide: function(offset, isParameter, _setHandles) {
|
// Accept offsets and CurveLocation objects, as well as objects that act
|
||||||
var parameter = this._getParameter(offset, isParameter),
|
// like them.
|
||||||
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
return this.divideAtTime(location && location.curve === this
|
||||||
|
? location.time : location);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Divides the curve into two curves at the given curve-time parameter. The
|
||||||
|
* curve itself is modified and becomes the first part, the second part is
|
||||||
|
* returned as a new curve. If the modified curve belongs to a path item,
|
||||||
|
* the second part is also added to the path.
|
||||||
|
*
|
||||||
|
* @param {Number} time the curve-time parameter on the curve at which to
|
||||||
|
* divide
|
||||||
|
* @return {Curve} the second part of the divided curve, if the offset is
|
||||||
|
* within the valid range, {code null} otherwise.
|
||||||
|
* @see #divideAt(offset)
|
||||||
|
*/
|
||||||
|
divideAtTime: function(time, _setHandles) {
|
||||||
|
// Only divide if not at the beginning or end.
|
||||||
|
var tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
||||||
tMax = 1 - tMin,
|
tMax = 1 - tMin,
|
||||||
res = null;
|
res = null;
|
||||||
// Only divide if not at the beginning or end.
|
if (time >= tMin && time <= tMax) {
|
||||||
if (parameter >= tMin && parameter <= tMax) {
|
var parts = Curve.subdivide(this.getValues(), time),
|
||||||
var parts = Curve.subdivide(this.getValues(), parameter),
|
|
||||||
left = parts[0],
|
left = parts[0],
|
||||||
right = parts[1],
|
right = parts[1],
|
||||||
setHandles = _setHandles || this.hasHandles(),
|
setHandles = _setHandles || this.hasHandles(),
|
||||||
|
@ -519,21 +517,47 @@ var Curve = Base.extend(/** @lends Curve# */{
|
||||||
* splitting, the path will be open. If the path was open already, splitting
|
* splitting, the path will be open. If the path was open already, splitting
|
||||||
* will result in two paths.
|
* will result in two paths.
|
||||||
*
|
*
|
||||||
* @name Curve#split
|
* @param {Number|CurveLocation} location the offset or location on the
|
||||||
* @function
|
* curve at which to split
|
||||||
* @param {Number} [offset=0.5] the offset on the curve at which to split,
|
|
||||||
* or the curve time parameter if `isParameter` is `true`
|
|
||||||
* @param {Boolean} [isParameter=false] pass `true` if `offset` is a curve
|
|
||||||
* time parameter
|
|
||||||
* @return {Path} the newly created path after splitting, if any
|
* @return {Path} the newly created path after splitting, if any
|
||||||
* @see Path#split(index, parameter)
|
* @see Path#splitAt(offset)
|
||||||
*/
|
*/
|
||||||
// TODO: Rename to splitAt()?
|
splitAt: function(location) {
|
||||||
split: function(offset, isParameter) {
|
return this._path ? this._path.splitAt(location) : null;
|
||||||
return this._path
|
},
|
||||||
? this._path.split(this._segment1._index,
|
|
||||||
this._getParameter(offset, isParameter))
|
/**
|
||||||
: null;
|
* Splits the path this curve belongs to at the given offset. After
|
||||||
|
* splitting, the path will be open. If the path was open already, splitting
|
||||||
|
* will result in two paths.
|
||||||
|
*
|
||||||
|
* @param {Number} time the curve-time parameter on the curve at which to
|
||||||
|
* split
|
||||||
|
* @return {Path} the newly created path after splitting, if any
|
||||||
|
* @see Path#splitAt(offset)
|
||||||
|
*/
|
||||||
|
splitAtTime: function(t) {
|
||||||
|
return this.splitAt(this.getLocationAtTime(t));
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: Remove in 1.0.0? (deprecated January 2016):
|
||||||
|
/**
|
||||||
|
* @deprecated, use use {@link #divideAt(offset)} or
|
||||||
|
* {@link #divideAtTime(time)} instead.
|
||||||
|
*/
|
||||||
|
divide: function(offset, isTime) {
|
||||||
|
return this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset
|
||||||
|
: this.getTimeAt(offset));
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: Remove in 1.0.0? (deprecated January 2016):
|
||||||
|
/**
|
||||||
|
* @deprecated, use use {@link #splitAt(offset)} or
|
||||||
|
* {@link #splitAtTime(time)} instead.
|
||||||
|
*/
|
||||||
|
split: function(offset, isTime) {
|
||||||
|
return this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset
|
||||||
|
: this.getTimeAt(offset));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -610,7 +634,7 @@ statics: {
|
||||||
return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
|
return Numerical.solveCubic(a, b, c, p1 - val, roots, min, max);
|
||||||
},
|
},
|
||||||
|
|
||||||
getParameterOf: function(v, point) {
|
getTimeOf: function(v, point) {
|
||||||
// Before solving cubics, compare the beginning and end of the curve
|
// Before solving cubics, compare the beginning and end of the curve
|
||||||
// with zero epsilon:
|
// with zero epsilon:
|
||||||
var p1 = new Point(v[0], v[1]),
|
var p1 = new Point(v[0], v[1]),
|
||||||
|
@ -642,7 +666,7 @@ statics: {
|
||||||
: null;
|
: null;
|
||||||
},
|
},
|
||||||
|
|
||||||
getNearestParameter: function(v, point) {
|
getNearestTime: function(v, point) {
|
||||||
if (Curve.isStraight(v)) {
|
if (Curve.isStraight(v)) {
|
||||||
var p1x = v[0], p1y = v[1],
|
var p1x = v[0], p1y = v[1],
|
||||||
p2x = v[6], p2y = v[7],
|
p2x = v[6], p2y = v[7],
|
||||||
|
@ -656,7 +680,7 @@ statics: {
|
||||||
var u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;
|
var u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;
|
||||||
return u < /*#=*/Numerical.EPSILON ? 0
|
return u < /*#=*/Numerical.EPSILON ? 0
|
||||||
: u > /*#=*/(1 - Numerical.EPSILON) ? 1
|
: u > /*#=*/(1 - Numerical.EPSILON) ? 1
|
||||||
: Curve.getParameterOf(v,
|
: Curve.getTimeOf(v,
|
||||||
new Point(p1x + u * vx, p1y + u * vy));
|
new Point(p1x + u * vx, p1y + u * vy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,7 +975,7 @@ statics: {
|
||||||
* @return {Boolean} {@true if the line is horizontal}
|
* @return {Boolean} {@true if the line is horizontal}
|
||||||
*/
|
*/
|
||||||
isHorizontal: function() {
|
isHorizontal: function() {
|
||||||
return this.isStraight() && Math.abs(this.getTangentAt(0.5, true).y)
|
return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y)
|
||||||
< /*#=*/Numerical.TRIGONOMETRIC_EPSILON;
|
< /*#=*/Numerical.TRIGONOMETRIC_EPSILON;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -961,59 +985,64 @@ statics: {
|
||||||
* @return {Boolean} {@true if the line is vertical}
|
* @return {Boolean} {@true if the line is vertical}
|
||||||
*/
|
*/
|
||||||
isVertical: function() {
|
isVertical: function() {
|
||||||
return this.isStraight() && Math.abs(this.getTangentAt(0.5, true).x)
|
return this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x)
|
||||||
< /*#=*/Numerical.TRIGONOMETRIC_EPSILON;
|
< /*#=*/Numerical.TRIGONOMETRIC_EPSILON;
|
||||||
}
|
}
|
||||||
}), /** @lends Curve# */{
|
}), /** @lends Curve# */{
|
||||||
// Explicitly deactivate the creation of beans, as we have functions here
|
// Explicitly deactivate the creation of beans, as we have functions here
|
||||||
// that look like bean getters but actually read arguments.
|
// that look like bean getters but actually read arguments.
|
||||||
// See #getParameterOf(), #getLocationOf(), #getNearestLocation(), ...
|
// See #getTimeOf(), #getLocationOf(), #getNearestLocation(), ...
|
||||||
beans: false,
|
beans: false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@grouptitle Positions on Curves}
|
* {@grouptitle Positions on Curves}
|
||||||
*
|
*
|
||||||
* Calculates the curve time parameter of the specified offset on the path,
|
* Calculates the curve location at the specified offset on the curve.
|
||||||
|
*
|
||||||
|
* @param {Number} offset the offset on the curve
|
||||||
|
* @return {CurveLocation} the curve location at the specified the offset
|
||||||
|
*/
|
||||||
|
getLocationAt: function(offset, _isTime) {
|
||||||
|
// TODO: Remove _isTime handling in 1.0.0? (deprecated Jan 2016):
|
||||||
|
return this.getLocationAtTime(
|
||||||
|
_isTime ? offset : this.getTimeAt(offset));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the curve location at the specified curve-time parameter on
|
||||||
|
* the curve.
|
||||||
|
*
|
||||||
|
* @param {Number} time the curve-time parameter on the curve
|
||||||
|
* @return {CurveLocation} the curve location at the specified the location
|
||||||
|
*/
|
||||||
|
getLocationAtTime: function(t) {
|
||||||
|
return t != null && t >= 0 && t <= 1
|
||||||
|
? new CurveLocation(this, t)
|
||||||
|
: null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the curve-time parameter of the specified offset on the path,
|
||||||
* relative to the provided start parameter. If offset is a negative value,
|
* relative to the provided start parameter. If offset is a negative value,
|
||||||
* the parameter is searched to the left of the start parameter. If no start
|
* the parameter is searched to the left of the start parameter. If no start
|
||||||
* parameter is provided, a default of `0` for positive values of `offset`
|
* parameter is provided, a default of `0` for positive values of `offset`
|
||||||
* and `1` for negative values of `offset`.
|
* and `1` for negative values of `offset`.
|
||||||
*
|
*
|
||||||
* @param {Number} offset
|
* @param {Number} offset the offset at which to find the curve-time, in
|
||||||
* @param {Number} [start]
|
* curve length units
|
||||||
* @return {Number} the curve time parameter at the specified offset
|
* @param {Number} [start] the curve-time in relation to which the offset is
|
||||||
|
* determined
|
||||||
|
* @return {Number} the curve-time parameter at the specified location
|
||||||
*/
|
*/
|
||||||
getParameterAt: function(offset, start) {
|
getTimeAt: function(offset, start) {
|
||||||
return Curve.getParameterAt(this.getValues(), offset, start);
|
return Curve.getTimeAt(this.getValues(), offset, start);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// TODO: Remove in 1.0.0? (deprecated January 2016):
|
||||||
/**
|
/**
|
||||||
* Returns the curve time parameter of the specified point if it lies on the
|
* @deprecated, use use {@link #getTimeOf(point)} instead.
|
||||||
* curve, `null` otherwise.
|
|
||||||
*
|
|
||||||
* @param {Point} point the point on the curve
|
|
||||||
* @return {Number} the curve time parameter of the specified point
|
|
||||||
*/
|
*/
|
||||||
getParameterOf: function(/* point */) {
|
getParameterAt: '#getTimeAt',
|
||||||
return Curve.getParameterOf(this.getValues(), Point.read(arguments));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the curve location at the specified offset or curve time
|
|
||||||
* parameter.
|
|
||||||
*
|
|
||||||
* @param {Number} offset the offset on the curve, or the curve time
|
|
||||||
* parameter if `isParameter` is `true`
|
|
||||||
* @param {Boolean} [isParameter=false] pass `true` if `offset` is a curve
|
|
||||||
* time parameter
|
|
||||||
* @return {CurveLocation} the curve location at the specified the offset
|
|
||||||
*/
|
|
||||||
getLocationAt: function(offset, isParameter) {
|
|
||||||
var t = isParameter ? offset : this.getParameterAt(offset);
|
|
||||||
return t != null && t >= 0 && t <= 1
|
|
||||||
? new CurveLocation(this, t)
|
|
||||||
: null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the curve location of the specified point if it lies on the
|
* Returns the curve location of the specified point if it lies on the
|
||||||
|
@ -1023,8 +1052,7 @@ statics: {
|
||||||
* @return {CurveLocation} the curve location of the specified point
|
* @return {CurveLocation} the curve location of the specified point
|
||||||
*/
|
*/
|
||||||
getLocationOf: function(/* point */) {
|
getLocationOf: function(/* point */) {
|
||||||
return this.getLocationAt(this.getParameterOf(Point.read(arguments)),
|
return this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));
|
||||||
true);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1039,6 +1067,23 @@ statics: {
|
||||||
return loc ? loc.getOffset() : null;
|
return loc ? loc.getOffset() : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the curve-time parameter of the specified point if it lies on the
|
||||||
|
* curve, `null` otherwise.
|
||||||
|
*
|
||||||
|
* @param {Point} point the point on the curve
|
||||||
|
* @return {Number} the curve-time parameter of the specified point
|
||||||
|
*/
|
||||||
|
getTimeOf: function(/* point */) {
|
||||||
|
return Curve.getTimeOf(this.getValues(), Point.read(arguments));
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: Remove in 1.0.0? (deprecated January 2016):
|
||||||
|
/**
|
||||||
|
* @deprecated, use use {@link #getTimeOf(point)} instead.
|
||||||
|
*/
|
||||||
|
getParameterOf: '#getTimeOf',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the nearest location on the curve to the specified point.
|
* Returns the nearest location on the curve to the specified point.
|
||||||
*
|
*
|
||||||
|
@ -1050,7 +1095,7 @@ statics: {
|
||||||
getNearestLocation: function(/* point */) {
|
getNearestLocation: function(/* point */) {
|
||||||
var point = Point.read(arguments),
|
var point = Point.read(arguments),
|
||||||
values = this.getValues(),
|
values = this.getValues(),
|
||||||
t = Curve.getNearestParameter(values, point),
|
t = Curve.getNearestTime(values, point),
|
||||||
pt = Curve.getPoint(values, t);
|
pt = Curve.getPoint(values, t);
|
||||||
return new CurveLocation(this, t, pt, null, point.getDistance(pt));
|
return new CurveLocation(this, t, pt, null, point.getDistance(pt));
|
||||||
},
|
},
|
||||||
|
@ -1068,81 +1113,129 @@ statics: {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the point on the curve at the given offset.
|
* Calculates the point on the curve at the given location.
|
||||||
*
|
*
|
||||||
* @name Curve#getPointAt
|
* @name Curve#getPointAt
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the curve, or the curve time
|
* @param {Number|CurveLocation} location the offset or location on the
|
||||||
* parameter if `isParameter` is `true`
|
* curve
|
||||||
* @param {Boolean} [isParameter=false] pass `true` if `offset` is a curve
|
* @return {Point} the point on the curve at the given location
|
||||||
* time parameter
|
|
||||||
* @return {Point} the point on the curve at the given offset
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the normalized tangent vector of the curve at the given
|
* Calculates the normalized tangent vector of the curve at the given
|
||||||
* offset.
|
* location.
|
||||||
*
|
*
|
||||||
* @name Curve#getTangentAt
|
* @name Curve#getTangentAt
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the curve, or the curve time
|
* @param {Number|CurveLocation} location the offset or location on the
|
||||||
* parameter if `isParameter` is `true`
|
* curve
|
||||||
* @param {Boolean} [isParameter=false] pass `true` if `offset` is a curve
|
* @return {Point} the normalized tangent of the curve at the given location
|
||||||
* time parameter
|
|
||||||
* @return {Point} the normalized tangent of the curve at the given offset
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the normal vector of the curve at the given offset.
|
* Calculates the normal vector of the curve at the given location.
|
||||||
*
|
*
|
||||||
* @name Curve#getNormalAt
|
* @name Curve#getNormalAt
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the curve, or the curve time
|
* @param {Number|CurveLocation} location the offset or location on the
|
||||||
* parameter if `isParameter` is `true`
|
* curve
|
||||||
* @param {Boolean} [isParameter=false] pass `true` if `offset` is a curve
|
* @return {Point} the normal of the curve at the given location
|
||||||
* time parameter
|
|
||||||
* @return {Point} the normal of the curve at the given offset
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the weighted tangent vector of the curve at the given offset,
|
* Calculates the weighted tangent vector of the curve at the given
|
||||||
* its length reflecting the curve velocity at that location.
|
* location, its length reflecting the curve velocity at that location.
|
||||||
*
|
*
|
||||||
* @name Curve#getWeightedTangentAt
|
* @name Curve#getWeightedTangentAt
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the curve, or the curve time
|
* @param {Number|CurveLocation} location the offset or location on the
|
||||||
* parameter if `isParameter` is `true`
|
* curve
|
||||||
* @param {Boolean} [isParameter=false] pass `true` if `offset` is a curve
|
* @return {Point} the weighted tangent of the curve at the given location
|
||||||
* time parameter
|
|
||||||
* @return {Point} the weighted tangent of the curve at the given offset
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the weighted normal vector of the curve at the given offset,
|
* Calculates the weighted normal vector of the curve at the given location,
|
||||||
* its length reflecting the curve velocity at that location.
|
* its length reflecting the curve velocity at that location.
|
||||||
*
|
*
|
||||||
* @name Curve#getWeightedNormalAt
|
* @name Curve#getWeightedNormalAt
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the curve, or the curve time
|
* @param {Number|CurveLocation} location the offset or location on the
|
||||||
* parameter if `isParameter` is `true`
|
* curve
|
||||||
* @param {Boolean} [isParameter=false] pass `true` if `offset` is a curve
|
* @return {Point} the weighted normal of the curve at the given location
|
||||||
* time parameter
|
|
||||||
* @return {Point} the weighted normal of the curve at the given offset
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the curvature of the curve at the given offset. Curvatures
|
* Calculates the curvature of the curve at the given location. Curvatures
|
||||||
* indicate how sharply a curve changes direction. A straight line has zero
|
* indicate how sharply a curve changes direction. A straight line has zero
|
||||||
* curvature, where as a circle has a constant curvature. The curve's radius
|
* curvature, where as a circle has a constant curvature. The curve's radius
|
||||||
* at the given offset is the reciprocal value of its curvature.
|
* at the given location is the reciprocal value of its curvature.
|
||||||
*
|
*
|
||||||
* @name Curve#getCurvatureAt
|
* @name Curve#getCurvatureAt
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the curve, or the curve time
|
* @param {Number|CurveLocation} location the offset or location on the
|
||||||
* parameter if `isParameter` is `true`
|
* curve
|
||||||
* @param {Boolean} [isParameter=false] pass `true` if `offset` is a curve
|
* @return {Number} the curvature of the curve at the given location
|
||||||
* time parameter
|
*/
|
||||||
* @return {Number} the curvature of the curve at the given offset
|
|
||||||
|
/**
|
||||||
|
* Calculates the point on the curve at the given location.
|
||||||
|
*
|
||||||
|
* @name Curve#getPointAtTime
|
||||||
|
* @function
|
||||||
|
* @param {Number} time the curve-time parameter on the curve
|
||||||
|
* @return {Point} the point on the curve at the given location
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the normalized tangent vector of the curve at the given
|
||||||
|
* location.
|
||||||
|
*
|
||||||
|
* @name Curve#getTangentAtTime
|
||||||
|
* @function
|
||||||
|
* @param {Number} time the curve-time parameter on the curve
|
||||||
|
* @return {Point} the normalized tangent of the curve at the given location
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the normal vector of the curve at the given location.
|
||||||
|
*
|
||||||
|
* @name Curve#getNormalAtTime
|
||||||
|
* @function
|
||||||
|
* @param {Number} time the curve-time parameter on the curve
|
||||||
|
* @return {Point} the normal of the curve at the given location
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the weighted tangent vector of the curve at the given
|
||||||
|
* location, its length reflecting the curve velocity at that location.
|
||||||
|
*
|
||||||
|
* @name Curve#getWeightedTangentAtTime
|
||||||
|
* @function
|
||||||
|
* @param {Number} time the curve-time parameter on the curve
|
||||||
|
* @return {Point} the weighted tangent of the curve at the given location
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the weighted normal vector of the curve at the given location,
|
||||||
|
* its length reflecting the curve velocity at that location.
|
||||||
|
*
|
||||||
|
* @name Curve#getWeightedNormalAtTime
|
||||||
|
* @function
|
||||||
|
* @param {Number} time the curve-time parameter on the curve
|
||||||
|
* @return {Point} the weighted normal of the curve at the given location
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the curvature of the curve at the given location. Curvatures
|
||||||
|
* indicate how sharply a curve changes direction. A straight line has zero
|
||||||
|
* curvature, where as a circle has a constant curvature. The curve's radius
|
||||||
|
* at the given location is the reciprocal value of its curvature.
|
||||||
|
*
|
||||||
|
* @name Curve#getCurvatureAtTime
|
||||||
|
* @function
|
||||||
|
* @param {Number} time the curve-time parameter on the curve
|
||||||
|
* @return {Number} the curvature of the curve at the given location
|
||||||
*/
|
*/
|
||||||
},
|
},
|
||||||
new function() { // // Scope to inject various curve evaluation methods
|
new function() { // // Scope to inject various curve evaluation methods
|
||||||
|
@ -1152,11 +1245,18 @@ new function() { // // Scope to inject various curve evaluation methods
|
||||||
function(name) {
|
function(name) {
|
||||||
// NOTE: (For easier searching): This loop produces:
|
// NOTE: (For easier searching): This loop produces:
|
||||||
// getPointAt, getTangentAt, getNormalAt, getWeightedTangentAt,
|
// getPointAt, getTangentAt, getNormalAt, getWeightedTangentAt,
|
||||||
// getWeightedNormalAt, getCurvatureAt
|
// getWeightedNormalAt, getCurvatureAt, getPointAtTime,
|
||||||
this[name + 'At'] = function(offset, isParameter) {
|
// getTangentAtTime, getNormalAtTime, getWeightedTangentAtTime,
|
||||||
|
// getWeightedNormalAtTime, getCurvatureAtTime
|
||||||
|
// TODO: Remove _isTime handling in 1.0.0? (deprecated Jan 2016):
|
||||||
|
this[name + 'At'] = function(location, _isTime) {
|
||||||
var values = this.getValues();
|
var values = this.getValues();
|
||||||
return Curve[name](values, isParameter ? offset
|
return Curve[name](values, _isTime ? location
|
||||||
: Curve.getParameterAt(values, offset, 0));
|
: Curve.getTimeAt(values, location, 0));
|
||||||
|
};
|
||||||
|
|
||||||
|
this[name + 'AtTime'] = function(time) {
|
||||||
|
return Curve[name](this.getValues(), time);
|
||||||
};
|
};
|
||||||
}, {
|
}, {
|
||||||
statics: {
|
statics: {
|
||||||
|
@ -1306,7 +1406,7 @@ new function() { // Scope for methods that require private functions
|
||||||
return Numerical.integrate(ds, a, b, getIterations(a, b));
|
return Numerical.integrate(ds, a, b, getIterations(a, b));
|
||||||
},
|
},
|
||||||
|
|
||||||
getParameterAt: function(v, offset, start) {
|
getTimeAt: function(v, offset, start) {
|
||||||
if (start === undefined)
|
if (start === undefined)
|
||||||
start = offset < 0 ? 1 : 0;
|
start = offset < 0 ? 1 : 0;
|
||||||
if (offset === 0)
|
if (offset === 0)
|
||||||
|
@ -1387,7 +1487,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
|
||||||
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
||||||
tMax = 1 - tMin;
|
tMax = 1 - tMin;
|
||||||
if (t1 == null)
|
if (t1 == null)
|
||||||
t1 = Curve.getParameterOf(v1, p1);
|
t1 = Curve.getTimeOf(v1, p1);
|
||||||
// Check t1 and t2 against correct bounds, based on excludeStart/End:
|
// Check t1 and t2 against correct bounds, based on excludeStart/End:
|
||||||
// - excludeStart means the start of c1 connects to the end of c2
|
// - excludeStart means the start of c1 connects to the end of c2
|
||||||
// - endConneted means the end of c1 connects to the start of c2
|
// - endConneted means the end of c1 connects to the start of c2
|
||||||
|
@ -1398,7 +1498,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
|
||||||
if (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&
|
if (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&
|
||||||
t1 <= (excludeEnd ? tMax : 1)) {
|
t1 <= (excludeEnd ? tMax : 1)) {
|
||||||
if (t2 == null)
|
if (t2 == null)
|
||||||
t2 = Curve.getParameterOf(v2, p2);
|
t2 = Curve.getTimeOf(v2, p2);
|
||||||
if (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&
|
if (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&
|
||||||
t2 <= (excludeStart ? tMax : 1)) {
|
t2 <= (excludeStart ? tMax : 1)) {
|
||||||
var renormalize = param.renormalize;
|
var renormalize = param.renormalize;
|
||||||
|
@ -1643,7 +1743,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
|
||||||
// the real curve and with that the location on the line.
|
// the real curve and with that the location on the line.
|
||||||
var tc = roots[i],
|
var tc = roots[i],
|
||||||
pc = Curve.getPoint(vc, tc),
|
pc = Curve.getPoint(vc, tc),
|
||||||
tl = Curve.getParameterOf(vl, pc);
|
tl = Curve.getTimeOf(vl, pc);
|
||||||
if (tl !== null) {
|
if (tl !== null) {
|
||||||
var pl = Curve.getPoint(vl, tl),
|
var pl = Curve.getPoint(vl, tl),
|
||||||
t1 = flip ? tl : tc,
|
t1 = flip ? tl : tc,
|
||||||
|
@ -1809,7 +1909,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
|
||||||
// the loop in case of a self intersection.
|
// the loop in case of a self intersection.
|
||||||
for (var i = 0, maxCurvature = 0; i < count; i++) {
|
for (var i = 0, maxCurvature = 0; i < count; i++) {
|
||||||
var curvature = Math.abs(
|
var curvature = Math.abs(
|
||||||
c1.getCurvatureAt(roots[i], true));
|
c1.getCurvatureAtTime(roots[i]));
|
||||||
if (curvature > maxCurvature) {
|
if (curvature > maxCurvature) {
|
||||||
maxCurvature = curvature;
|
maxCurvature = curvature;
|
||||||
tSplit = roots[i];
|
tSplit = roots[i];
|
||||||
|
@ -1894,7 +1994,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
|
||||||
for (var i = 0, t1 = 0;
|
for (var i = 0, t1 = 0;
|
||||||
i < 2 && pairs.length < 2;
|
i < 2 && pairs.length < 2;
|
||||||
i += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {
|
i += t1 === 0 ? 0 : 1, t1 = t1 ^ 1) {
|
||||||
var t2 = Curve.getParameterOf(v[i ^ 1], new Point(
|
var t2 = Curve.getTimeOf(v[i ^ 1], new Point(
|
||||||
v[i][t1 === 0 ? 0 : 6],
|
v[i][t1 === 0 ? 0 : 6],
|
||||||
v[i][t1 === 0 ? 1 : 7]));
|
v[i][t1 === 0 ? 1 : 7]));
|
||||||
if (t2 != null) { // If point is on curve
|
if (t2 != null) { // If point is on curve
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
* @name CurveLocation
|
* @name CurveLocation
|
||||||
*
|
*
|
||||||
* @class CurveLocation objects describe a location on {@link Curve} objects, as
|
* @class CurveLocation objects describe a location on {@link Curve} objects, as
|
||||||
* defined by the curve-time {@link #parameter}, a value between `0`
|
* defined by the curve-time {@link #time}, a value between `0` (beginning
|
||||||
* (beginning of the curve) and `1` (end of the curve). If the curve is part
|
* of the curve) and `1` (end of the curve). If the curve is part of a
|
||||||
* of a {@link Path} item, its {@link #index} inside the {@link Path#curves}
|
* {@link Path} item, its {@link #index} inside the {@link Path#curves}
|
||||||
* array is also provided.
|
* array is also provided.
|
||||||
*
|
*
|
||||||
* The class is in use in many places, such as
|
* The class is in use in many places, such as
|
||||||
|
@ -38,17 +38,16 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
* Creates a new CurveLocation object.
|
* Creates a new CurveLocation object.
|
||||||
*
|
*
|
||||||
* @param {Curve} curve
|
* @param {Curve} curve
|
||||||
* @param {Number} parameter
|
* @param {Number} time
|
||||||
* @param {Point} [point]
|
* @param {Point} [point]
|
||||||
*/
|
*/
|
||||||
initialize: function CurveLocation(curve, parameter, point,
|
initialize: function CurveLocation(curve, time, point, _overlap, _distance) {
|
||||||
_overlap, _distance) {
|
|
||||||
// Merge intersections very close to the end of a curve with the
|
// Merge intersections very close to the end of a curve with the
|
||||||
// beginning of the next curve.
|
// beginning of the next curve.
|
||||||
if (parameter > /*#=*/(1 - Numerical.CURVETIME_EPSILON)) {
|
if (time > /*#=*/(1 - Numerical.CURVETIME_EPSILON)) {
|
||||||
var next = curve.getNext();
|
var next = curve.getNext();
|
||||||
if (next) {
|
if (next) {
|
||||||
parameter = 0;
|
time = 0;
|
||||||
curve = next;
|
curve = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,8 +57,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
// CurveLocation objects.
|
// CurveLocation objects.
|
||||||
this._id = UID.get(CurveLocation);
|
this._id = UID.get(CurveLocation);
|
||||||
this._setCurve(curve);
|
this._setCurve(curve);
|
||||||
this._parameter = parameter;
|
this._time = time;
|
||||||
this._point = point || curve.getPointAt(parameter, true);
|
this._point = point || curve.getPointAtTime(time);
|
||||||
this._overlap = _overlap;
|
this._overlap = _overlap;
|
||||||
this._distance = _distance;
|
this._distance = _distance;
|
||||||
this._intersection = this._next = this._prev = null;
|
this._intersection = this._next = this._prev = null;
|
||||||
|
@ -84,7 +83,7 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
_setSegment: function(segment) {
|
_setSegment: function(segment) {
|
||||||
this._setCurve(segment.getCurve());
|
this._setCurve(segment.getCurve());
|
||||||
this._segment = segment;
|
this._segment = segment;
|
||||||
this._parameter = segment === this._segment1 ? 0 : 1;
|
this._time = segment === this._segment1 ? 0 : 1;
|
||||||
// To avoid issues with imprecision in getCurve() / trySegment()
|
// To avoid issues with imprecision in getCurve() / trySegment()
|
||||||
this._point = segment._point.clone();
|
this._point = segment._point.clone();
|
||||||
},
|
},
|
||||||
|
@ -100,15 +99,15 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
var curve = this.getCurve(),
|
var curve = this.getCurve(),
|
||||||
segment = this._segment;
|
segment = this._segment;
|
||||||
if (!segment) {
|
if (!segment) {
|
||||||
var parameter = this.getParameter();
|
var time = this.getTime();
|
||||||
if (parameter === 0) {
|
if (time === 0) {
|
||||||
segment = curve._segment1;
|
segment = curve._segment1;
|
||||||
} else if (parameter === 1) {
|
} else if (time === 1) {
|
||||||
segment = curve._segment2;
|
segment = curve._segment2;
|
||||||
} else if (parameter != null) {
|
} else if (time != null) {
|
||||||
// Determine the closest segment by comparing curve lengths
|
// Determine the closest segment by comparing curve lengths
|
||||||
segment = curve.getPartLength(0, parameter)
|
segment = curve.getPartLength(0, time)
|
||||||
< curve.getPartLength(parameter, 1)
|
< curve.getPartLength(time, 1)
|
||||||
? curve._segment1
|
? curve._segment1
|
||||||
: curve._segment2;
|
: curve._segment2;
|
||||||
}
|
}
|
||||||
|
@ -128,9 +127,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
that = this;
|
that = this;
|
||||||
if (path && path._version !== this._version) {
|
if (path && path._version !== this._version) {
|
||||||
// If the path's segments have changed in the meantime, clear the
|
// If the path's segments have changed in the meantime, clear the
|
||||||
// internal _parameter value and force refetching of the correct
|
// internal _time value and force re-fetching of the correct
|
||||||
// curve again here.
|
// curve again here.
|
||||||
this._parameter = this._curve = this._offset = null;
|
this._time = this._curve = this._offset = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If path is out of sync, access current curve objects through segment1
|
// If path is out of sync, access current curve objects through segment1
|
||||||
|
@ -139,7 +138,7 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
// still, otherwise assume it's the curve before segment2.
|
// still, otherwise assume it's the curve before segment2.
|
||||||
function trySegment(segment) {
|
function trySegment(segment) {
|
||||||
var curve = segment && segment.getCurve();
|
var curve = segment && segment.getCurve();
|
||||||
if (curve && (that._parameter = curve.getParameterOf(that._point))
|
if (curve && (that._time = curve.getTimeOf(that._point))
|
||||||
!= null) {
|
!= null) {
|
||||||
// Fetch path again as it could be on a new one through split()
|
// Fetch path again as it could be on a new one through split()
|
||||||
that._setCurve(curve);
|
that._setCurve(curve);
|
||||||
|
@ -185,17 +184,24 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
* @bean
|
* @bean
|
||||||
* @type Number
|
* @type Number
|
||||||
*/
|
*/
|
||||||
getParameter: function() {
|
getTime: function() {
|
||||||
var curve = this.getCurve(),
|
var curve = this.getCurve(),
|
||||||
parameter = this._parameter;
|
time = this._time;
|
||||||
return curve && parameter == null
|
return curve && time == null
|
||||||
? this._parameter = curve.getParameterOf(this._point)
|
? this._time = curve.getTimeOf(this._point)
|
||||||
: parameter;
|
: time;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @bean
|
||||||
|
* @deprecated use {@link #getTime()} instead.
|
||||||
|
*/
|
||||||
|
getParameter: '#getTime',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The point which is defined by the {@link #curve} and
|
* The point which is defined by the {@link #curve} and
|
||||||
* {@link #parameter}.
|
* {@link #time}.
|
||||||
*
|
*
|
||||||
* @bean
|
* @bean
|
||||||
* @type Point
|
* @type Point
|
||||||
|
@ -237,8 +243,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
*/
|
*/
|
||||||
getCurveOffset: function() {
|
getCurveOffset: function() {
|
||||||
var curve = this.getCurve(),
|
var curve = this.getCurve(),
|
||||||
parameter = this.getParameter();
|
time = this.getTime();
|
||||||
return parameter != null && curve && curve.getPartLength(0, parameter);
|
return time != null && curve && curve.getPartLength(0, time);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -295,8 +301,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
var curve = this.getCurve(),
|
var curve = this.getCurve(),
|
||||||
res = null;
|
res = null;
|
||||||
if (curve) {
|
if (curve) {
|
||||||
res = curve.divide(this.getParameter(), true);
|
res = curve.divideAtTime(this.getTime());
|
||||||
// Change to the newly inserted segment, also adjusting _parameter.
|
// Change to the newly inserted segment, also adjusting _time.
|
||||||
if (res)
|
if (res)
|
||||||
this._setSegment(res._segment1);
|
this._setSegment(res._segment1);
|
||||||
}
|
}
|
||||||
|
@ -305,13 +311,13 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
|
|
||||||
split: function() {
|
split: function() {
|
||||||
var curve = this.getCurve();
|
var curve = this.getCurve();
|
||||||
return curve ? curve.split(this.getParameter(), true) : null;
|
return curve ? curve.splitAtTime(this.getTime()) : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether tow CurveLocation objects are describing the same location
|
* Checks whether tow CurveLocation objects are describing the same location
|
||||||
* on a path, by applying the same tolerances as elsewhere when dealing with
|
* on a path, by applying the same tolerances as elsewhere when dealing with
|
||||||
* curve time parameters.
|
* curve-time parameters.
|
||||||
*
|
*
|
||||||
* @param {CurveLocation} location
|
* @param {CurveLocation} location
|
||||||
* @return {Boolean} {@true if the locations are equal}
|
* @return {Boolean} {@true if the locations are equal}
|
||||||
|
@ -332,9 +338,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
// We need to wrap diff around the path's beginning / end:
|
// We need to wrap diff around the path's beginning / end:
|
||||||
diff = abs(
|
diff = abs(
|
||||||
((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())
|
((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())
|
||||||
+ this.getParameter()) -
|
+ this.getTime()) -
|
||||||
((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())
|
((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())
|
||||||
+ loc.getParameter()));
|
+ loc.getTime()));
|
||||||
res = (diff < /*#=*/Numerical.CURVETIME_EPSILON
|
res = (diff < /*#=*/Numerical.CURVETIME_EPSILON
|
||||||
// If diff isn't close enough, compare the actual offsets of
|
// If diff isn't close enough, compare the actual offsets of
|
||||||
// both locations to determine if they're in the same spot,
|
// both locations to determine if they're in the same spot,
|
||||||
|
@ -363,9 +369,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
var index = this.getIndex();
|
var index = this.getIndex();
|
||||||
if (index != null)
|
if (index != null)
|
||||||
parts.push('index: ' + index);
|
parts.push('index: ' + index);
|
||||||
var parameter = this.getParameter();
|
var time = this.getTime();
|
||||||
if (parameter != null)
|
if (time != null)
|
||||||
parts.push('parameter: ' + f.number(parameter));
|
parts.push('time: ' + f.number(time));
|
||||||
if (this._distance != null)
|
if (this._distance != null)
|
||||||
parts.push('distance: ' + f.number(this._distance));
|
parts.push('distance: ' + f.number(this._distance));
|
||||||
return '{ ' + parts.join(', ') + ' }';
|
return '{ ' + parts.join(', ') + ' }';
|
||||||
|
@ -409,8 +415,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
var inter = this._intersection;
|
var inter = this._intersection;
|
||||||
if (!inter)
|
if (!inter)
|
||||||
return false;
|
return false;
|
||||||
var t1 = this.getParameter(),
|
var t1 = this.getTime(),
|
||||||
t2 = inter.getParameter(),
|
t2 = inter.getTime(),
|
||||||
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
||||||
tMax = 1 - tMin,
|
tMax = 1 - tMin,
|
||||||
// t*Inside specifies if the found intersection is inside the curve.
|
// t*Inside specifies if the found intersection is inside the curve.
|
||||||
|
@ -480,10 +486,10 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
// and the code will doe the right thing.
|
// and the code will doe the right thing.
|
||||||
// The incomings tangents v1 & v3 are inverted, so that all angles
|
// The incomings tangents v1 & v3 are inverted, so that all angles
|
||||||
// are pointing outwards in the right direction from the intersection.
|
// are pointing outwards in the right direction from the intersection.
|
||||||
var v2 = c2.getTangentAt(t1Inside ? t1 : tMin, true),
|
var v2 = c2.getTangentAtTime(t1Inside ? t1 : tMin),
|
||||||
v1 = (t1Inside ? v2 : c1.getTangentAt(tMax, true)).negate(),
|
v1 = (t1Inside ? v2 : c1.getTangentAtTime(tMax)).negate(),
|
||||||
v4 = c4.getTangentAt(t2Inside ? t2 : tMin, true),
|
v4 = c4.getTangentAtTime(t2Inside ? t2 : tMin),
|
||||||
v3 = (t2Inside ? v4 : c3.getTangentAt(tMax, true)).negate(),
|
v3 = (t2Inside ? v4 : c3.getTangentAtTime(tMax)).negate(),
|
||||||
// NOTE: For shorter API calls we work with angles in degrees here:
|
// NOTE: For shorter API calls we work with angles in degrees here:
|
||||||
a1 = v1.getAngle(),
|
a1 = v1.getAngle(),
|
||||||
a2 = v2.getAngle(),
|
a2 = v2.getAngle(),
|
||||||
|
@ -519,9 +525,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
// getWeightedNormalAt, getCurvatureAt
|
// getWeightedNormalAt, getCurvatureAt
|
||||||
var get = name + 'At';
|
var get = name + 'At';
|
||||||
this[name] = function() {
|
this[name] = function() {
|
||||||
var parameter = this.getParameter(),
|
var curve = this.getCurve(),
|
||||||
curve = this.getCurve();
|
time = this.getTime();
|
||||||
return parameter != null && curve && curve[get](parameter, true);
|
return time != null && curve && curve[get](time, true);
|
||||||
};
|
};
|
||||||
}, {
|
}, {
|
||||||
// Do not override the existing #getPoint():
|
// Do not override the existing #getPoint():
|
||||||
|
@ -530,7 +536,7 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
new function() { // Scope for statics
|
new function() { // Scope for statics
|
||||||
|
|
||||||
function insert(locations, loc, merge) {
|
function insert(locations, loc, merge) {
|
||||||
// Insert-sort by path-id, curve, parameter so we can easily merge
|
// Insert-sort by path-id, curve, time so we can easily merge
|
||||||
// duplicates with calls to equals() after.
|
// duplicates with calls to equals() after.
|
||||||
var length = locations.length,
|
var length = locations.length,
|
||||||
l = 0,
|
l = 0,
|
||||||
|
@ -575,10 +581,10 @@ new function() { // Scope for statics
|
||||||
// NOTE: equals() takes the intersection location into account,
|
// NOTE: equals() takes the intersection location into account,
|
||||||
// while this calculation of diff doesn't!
|
// while this calculation of diff doesn't!
|
||||||
diff = path1 === path2
|
diff = path1 === path2
|
||||||
//Sort by both index and parameter. The two values added
|
//Sort by both index and time. The two values added
|
||||||
// together provides a convenient sorting index.
|
// together provides a convenient sorting index.
|
||||||
? (loc.getIndex() + loc.getParameter())
|
? (loc.getIndex() + loc.getTime())
|
||||||
- (loc2.getIndex() + loc2.getParameter())
|
- (loc2.getIndex() + loc2.getTime())
|
||||||
// Sort by path id to group all locs on same path.
|
// Sort by path id to group all locs on same path.
|
||||||
: path1._id - path2._id;
|
: path1._id - path2._id;
|
||||||
if (diff < 0) {
|
if (diff < 0) {
|
||||||
|
|
156
src/path/Path.js
156
src/path/Path.js
|
@ -1092,56 +1092,12 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
// TODO: reduceSegments([flatness])
|
// TODO: reduceSegments([flatness])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits the path at the given offset. After splitting, the path will be
|
* Splits the path at the given offset or location. After splitting, the
|
||||||
* open. If the path was open already, splitting will result in two paths.
|
* path will be open. If the path was open already, splitting will result in
|
||||||
|
* two paths.
|
||||||
*
|
*
|
||||||
* @name Path#split
|
* @param {Number|CurveLocation} location the offset or location at which to
|
||||||
* @function
|
* split the path
|
||||||
* @param {Number} offset the offset at which to split the path
|
|
||||||
* as a number between 0 and {@link Path#length}
|
|
||||||
* @return {Path} the newly created path after splitting, if any
|
|
||||||
*
|
|
||||||
* @example {@paperscript} // Splitting an open path
|
|
||||||
* var path = new Path();
|
|
||||||
* path.strokeColor = 'black';
|
|
||||||
* path.add(20, 20);
|
|
||||||
*
|
|
||||||
* // Add an arc through {x: 90, y: 80} to {x: 160, y: 20}
|
|
||||||
* path.arcTo([90, 80], [160, 20]);
|
|
||||||
*
|
|
||||||
* // Split the path at 30% of its length:
|
|
||||||
* var path2 = path.split(path.length * 0.3);
|
|
||||||
* path2.strokeColor = 'red';
|
|
||||||
*
|
|
||||||
* // Move the newly created path 40px to the right:
|
|
||||||
* path2.position.x += 40;
|
|
||||||
*
|
|
||||||
* @example {@paperscript} // Splitting a closed path
|
|
||||||
* var path = new Path.Rectangle({
|
|
||||||
* from: [20, 20],
|
|
||||||
* to: [80, 80],
|
|
||||||
* strokeColor: 'black'
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* // Split the path at 60% of its length:
|
|
||||||
* path.split(path.length * 0.6);
|
|
||||||
*
|
|
||||||
* // Move the first segment, to show where the path
|
|
||||||
* // was split:
|
|
||||||
* path.firstSegment.point.x += 20;
|
|
||||||
*
|
|
||||||
* // Select the first segment:
|
|
||||||
* path.firstSegment.selected = true;
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Splits the path at the given curve location. After splitting, the path
|
|
||||||
* will be open. If the path was open already, splitting will result in two
|
|
||||||
* paths.
|
|
||||||
*
|
|
||||||
* @name Path#split
|
|
||||||
* @function
|
|
||||||
* @param {CurveLocation} location the curve location at which to split
|
|
||||||
* the path
|
|
||||||
* @return {Path} the newly created path after splitting, if any
|
* @return {Path} the newly created path after splitting, if any
|
||||||
*
|
*
|
||||||
* @example {@paperscript}
|
* @example {@paperscript}
|
||||||
|
@ -1156,23 +1112,18 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
* angle: 30
|
* angle: 30
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
* var curveLocation = path.getNearestLocation(pointOnCircle);
|
* var location = path.getNearestLocation(pointOnCircle);
|
||||||
*
|
*
|
||||||
* path.split(curveLocation);
|
* path.splitAt(location);
|
||||||
* path.lastSegment.selected = true;
|
* path.lastSegment.selected = true;
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Splits the path at the given curve index and parameter. After splitting,
|
|
||||||
* the path will be open. If the path was open already, splitting will
|
|
||||||
* result in two paths.
|
|
||||||
*
|
*
|
||||||
* @example {@paperscript} // Splitting an open path
|
* @example {@paperscript} // Splitting an open path
|
||||||
* // Draw a V shaped path:
|
* // Draw a V shaped path:
|
||||||
* var path = new Path([20, 20], [50, 80], [80, 20]);
|
* var path = new Path([20, 20], [50, 80], [80, 20]);
|
||||||
* path.strokeColor = 'black';
|
* path.strokeColor = 'black';
|
||||||
*
|
*
|
||||||
* // Split the path half-way down its second curve:
|
* // Split the path half-way:
|
||||||
* var path2 = path.split(1, 0.5);
|
* var path2 = path.splitAt(path2.length / 2);
|
||||||
*
|
*
|
||||||
* // Give the resulting path a red stroke-color
|
* // Give the resulting path a red stroke-color
|
||||||
* // and move it 20px to the right:
|
* // and move it 20px to the right:
|
||||||
|
@ -1186,8 +1137,8 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
* strokeColor: 'black'
|
* strokeColor: 'black'
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* // Split the path half-way down its second curve:
|
* // Split the path half-way:
|
||||||
* path.split(2, 0.5);
|
* path.splitAt(path.length / 2);
|
||||||
*
|
*
|
||||||
* // Move the first segment, to show where the path
|
* // Move the first segment, to show where the path
|
||||||
* // was split:
|
* // was split:
|
||||||
|
@ -1195,44 +1146,27 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
*
|
*
|
||||||
* // Select the first segment:
|
* // Select the first segment:
|
||||||
* path.firstSegment.selected = true;
|
* path.firstSegment.selected = true;
|
||||||
*
|
|
||||||
* @param {Number} index the index of the curve in the {@link Path#curves}
|
|
||||||
* array at which to split
|
|
||||||
* @param {Number} parameter the curve-time parameter at which the curve
|
|
||||||
* will be split
|
|
||||||
* @return {Path} the newly created path after splitting, if any
|
|
||||||
*/
|
*/
|
||||||
split: function(index, parameter) {
|
splitAt: function(location) {
|
||||||
if (parameter === null)
|
var index = location && location.index,
|
||||||
return null;
|
time = location && location.time,
|
||||||
if (arguments.length === 1) {
|
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
||||||
var arg = index;
|
|
||||||
// split(offset), convert offset to location
|
|
||||||
if (typeof arg === 'number')
|
|
||||||
arg = this.getLocationAt(arg);
|
|
||||||
if (!arg)
|
|
||||||
return null;
|
|
||||||
// split(location)
|
|
||||||
index = arg.index;
|
|
||||||
parameter = arg.parameter;
|
|
||||||
}
|
|
||||||
var tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
|
||||||
tMax = 1 - tMin;
|
tMax = 1 - tMin;
|
||||||
if (parameter >= tMax) {
|
if (time >= tMax) {
|
||||||
// t == 1 is the same as t == 0 and index ++
|
// time == 1 is the same location as time == 0 and index++
|
||||||
index++;
|
index++;
|
||||||
parameter--;
|
time = 0;
|
||||||
}
|
}
|
||||||
var curves = this.getCurves();
|
var curves = this.getCurves();
|
||||||
if (index >= 0 && index < curves.length) {
|
if (index >= 0 && index < curves.length) {
|
||||||
// Only divide curves if we're not on an existing segment already.
|
// Only divide curves if we're not on an existing segment already.
|
||||||
if (parameter >= tMin) {
|
if (time >= tMin) {
|
||||||
// Divide the curve with the index at given parameter.
|
// Divide the curve with the index at the given curve-time.
|
||||||
// Increase because dividing adds more segments to the path.
|
// Increase because dividing adds more segments to the path.
|
||||||
curves[index++].divide(parameter, true);
|
curves[index++].divideAtTime(time);
|
||||||
}
|
}
|
||||||
// Create the new path with the segments to the right of given
|
// Create the new path with the segments to the right of given
|
||||||
// parameter, which are removed from the current path. Pass true
|
// curve-time, which are removed from the current path. Pass true
|
||||||
// for includeCurves, since we want to preserve and move them to
|
// for includeCurves, since we want to preserve and move them to
|
||||||
// the new path through _add(), allowing us to have CurveLocation
|
// the new path through _add(), allowing us to have CurveLocation
|
||||||
// keep the connection to the new path through moved curves.
|
// keep the connection to the new path through moved curves.
|
||||||
|
@ -1261,6 +1195,17 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated, use use {@link #splitAt(offset)} instead.
|
||||||
|
*/
|
||||||
|
split: function(index, time) {
|
||||||
|
var curve,
|
||||||
|
location = time === undefined ? index
|
||||||
|
: (curve = this.getCurves()[index])
|
||||||
|
&& curve.getLocationAtTime(time);
|
||||||
|
return location ? this.splitAt(location) : null;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverses the orientation of the path, by reversing all its segments.
|
* Reverses the orientation of the path, by reversing all its segments.
|
||||||
*/
|
*/
|
||||||
|
@ -1649,8 +1594,8 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
// Now see if we're on a segment, and if so, check for its
|
// Now see if we're on a segment, and if so, check for its
|
||||||
// stroke join / cap first. If not, do a normal radius check
|
// stroke join / cap first. If not, do a normal radius check
|
||||||
// for round strokes.
|
// for round strokes.
|
||||||
var parameter = loc.getParameter();
|
var time = loc.getTime();
|
||||||
if (parameter === 0 || parameter === 1 && numSegments > 1) {
|
if (time === 0 || time === 1 && numSegments > 1) {
|
||||||
if (!checkSegmentStroke(loc.getSegment()))
|
if (!checkSegmentStroke(loc.getSegment()))
|
||||||
loc = null;
|
loc = null;
|
||||||
} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {
|
} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {
|
||||||
|
@ -1693,8 +1638,8 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
// NOTE: (For easier searching): This loop produces:
|
// NOTE: (For easier searching): This loop produces:
|
||||||
// getPointAt, getTangentAt, getNormalAt, getWeightedTangentAt,
|
// getPointAt, getTangentAt, getNormalAt, getWeightedTangentAt,
|
||||||
// getWeightedNormalAt, getCurvatureAt
|
// getWeightedNormalAt, getCurvatureAt
|
||||||
this[name + 'At'] = function(offset, isParameter) {
|
this[name + 'At'] = function(offset) {
|
||||||
var loc = this.getLocationAt(offset, isParameter);
|
var loc = this.getLocationAt(offset);
|
||||||
return loc && loc[name]();
|
return loc && loc[name]();
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -1741,19 +1686,11 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
*
|
*
|
||||||
* @param {Number} offset the offset on the path, where `0` is at
|
* @param {Number} offset the offset on the path, where `0` is at
|
||||||
* the beginning of the path and {@link Path#length} at the end
|
* the beginning of the path and {@link Path#length} at the end
|
||||||
* @param {Boolean} [isParameter=false]
|
|
||||||
* @return {CurveLocation} the curve location at the specified offset
|
* @return {CurveLocation} the curve location at the specified offset
|
||||||
*/
|
*/
|
||||||
getLocationAt: function(offset, isParameter) {
|
getLocationAt: function(offset) {
|
||||||
var curves = this.getCurves(),
|
var curves = this.getCurves(),
|
||||||
length = 0;
|
length = 0;
|
||||||
if (isParameter) {
|
|
||||||
// offset consists of curve index and curve parameter, before and
|
|
||||||
// after the fractional digit.
|
|
||||||
var index = ~~offset, // = Math.floor()
|
|
||||||
curve = curves[index];
|
|
||||||
return curve ? curve.getLocationAt(offset - index, true) : null;
|
|
||||||
}
|
|
||||||
for (var i = 0, l = curves.length; i < l; i++) {
|
for (var i = 0, l = curves.length; i < l; i++) {
|
||||||
var start = length,
|
var start = length,
|
||||||
curve = curves[i];
|
curve = curves[i];
|
||||||
|
@ -1777,7 +1714,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the path, where `0` is at
|
* @param {Number} offset the offset on the path, where `0` is at
|
||||||
* the beginning of the path and {@link Path#length} at the end
|
* the beginning of the path and {@link Path#length} at the end
|
||||||
* @param {Boolean} [isParameter=false]
|
|
||||||
* @return {Point} the point at the given offset
|
* @return {Point} the point at the given offset
|
||||||
*
|
*
|
||||||
* @example {@paperscript height=150}
|
* @example {@paperscript height=150}
|
||||||
|
@ -1840,7 +1776,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the path, where `0` is at
|
* @param {Number} offset the offset on the path, where `0` is at
|
||||||
* the beginning of the path and {@link Path#length} at the end
|
* the beginning of the path and {@link Path#length} at the end
|
||||||
* @param {Boolean} [isParameter=false]
|
|
||||||
* @return {Point} the normalized tangent vector at the given offset
|
* @return {Point} the normalized tangent vector at the given offset
|
||||||
*
|
*
|
||||||
* @example {@paperscript height=150}
|
* @example {@paperscript height=150}
|
||||||
|
@ -1907,7 +1842,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the path, where `0` is at
|
* @param {Number} offset the offset on the path, where `0` is at
|
||||||
* the beginning of the path and {@link Path#length} at the end
|
* the beginning of the path and {@link Path#length} at the end
|
||||||
* @param {Boolean} [isParameter=false]
|
|
||||||
* @return {Point} the normal vector at the given offset
|
* @return {Point} the normal vector at the given offset
|
||||||
*
|
*
|
||||||
* @example {@paperscript height=150}
|
* @example {@paperscript height=150}
|
||||||
|
@ -1974,7 +1908,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the path, where `0` is at
|
* @param {Number} offset the offset on the path, where `0` is at
|
||||||
* the beginning of the path and {@link Path#length} at the end
|
* the beginning of the path and {@link Path#length} at the end
|
||||||
* @param {Boolean} [isParameter=false]
|
|
||||||
* @return {Point} the weighted tangent vector at the given offset
|
* @return {Point} the weighted tangent vector at the given offset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1985,7 +1918,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the path, where `0` is at
|
* @param {Number} offset the offset on the path, where `0` is at
|
||||||
* the beginning of the path and {@link Path#length} at the end
|
* the beginning of the path and {@link Path#length} at the end
|
||||||
* @param {Boolean} [isParameter=false]
|
|
||||||
* @return {Point} the weighted normal vector at the given offset
|
* @return {Point} the weighted normal vector at the given offset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1999,7 +1931,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} offset the offset on the path, where `0` is at
|
* @param {Number} offset the offset on the path, where `0` is at
|
||||||
* the beginning of the path and {@link Path#length} at the end
|
* the beginning of the path and {@link Path#length} at the end
|
||||||
* @param {Boolean} [isParameter=false]
|
|
||||||
* @return {Number} the normal vector at the given offset
|
* @return {Number} the normal vector at the given offset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -2878,9 +2809,9 @@ statics: {
|
||||||
// Handles both 'bevel' and 'miter' joins, as they share a lot of code.
|
// Handles both 'bevel' and 'miter' joins, as they share a lot of code.
|
||||||
var curve2 = segment.getCurve(),
|
var curve2 = segment.getCurve(),
|
||||||
curve1 = curve2.getPrevious(),
|
curve1 = curve2.getPrevious(),
|
||||||
point = curve2.getPointAt(0, true),
|
point = curve2.getPointAtTime(0),
|
||||||
normal1 = curve1.getNormalAt(1, true),
|
normal1 = curve1.getNormalAtTime(1),
|
||||||
normal2 = curve2.getNormalAt(0, true),
|
normal2 = curve2.getNormalAtTime(0),
|
||||||
step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
|
step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
|
||||||
normal1.setLength(step);
|
normal1.setLength(step);
|
||||||
normal2.setLength(step);
|
normal2.setLength(step);
|
||||||
|
@ -2923,11 +2854,12 @@ statics: {
|
||||||
}
|
}
|
||||||
// For square caps, we need to step away from point in the direction of
|
// For square caps, we need to step away from point in the direction of
|
||||||
// the tangent, which is the rotated normal.
|
// the tangent, which is the rotated normal.
|
||||||
// Checking loc.getParameter() for 0 is to see whether this is the first
|
// Checking loc.getTime() for 0 is to see whether this is the first
|
||||||
// or the last segment of the open path, in order to determine in which
|
// or the last segment of the open path, in order to determine in which
|
||||||
// direction to move the point.
|
// direction to move the point.
|
||||||
if (cap === 'square')
|
if (cap === 'square')
|
||||||
point = point.add(normal.rotate(loc.getParameter() === 0 ? -90 : 90));
|
point = point.add(normal.rotate(
|
||||||
|
loc.getTime() === 0 ? -90 : 90));
|
||||||
addPoint(point.add(normal));
|
addPoint(point.add(normal));
|
||||||
addPoint(point.subtract(normal));
|
addPoint(point.subtract(normal));
|
||||||
},
|
},
|
||||||
|
|
|
@ -248,26 +248,26 @@ PathItem.inject(new function() {
|
||||||
results.unshift(loc);
|
results.unshift(loc);
|
||||||
}
|
}
|
||||||
var curve = loc._curve,
|
var curve = loc._curve,
|
||||||
t = loc._parameter,
|
time = loc._time,
|
||||||
origT = t,
|
origTime = time,
|
||||||
segment;
|
segment;
|
||||||
if (curve !== prevCurve) {
|
if (curve !== prevCurve) {
|
||||||
// This is a new curve, update noHandles setting.
|
// This is a new curve, update noHandles setting.
|
||||||
noHandles = !curve.hasHandles();
|
noHandles = !curve.hasHandles();
|
||||||
} else if (prevT > 0) {
|
} else if (prevTime > 0) {
|
||||||
// Scale parameter when we are splitting same curve multiple
|
// Scale parameter when we are splitting same curve multiple
|
||||||
// times, but avoid dividing by zero.
|
// times, but avoid dividing by zero.
|
||||||
t /= prevT;
|
time /= prevTime;
|
||||||
}
|
}
|
||||||
if (t < tMin) {
|
if (time < tMin) {
|
||||||
segment = curve._segment1;
|
segment = curve._segment1;
|
||||||
} else if (t > tMax) {
|
} else if (time > tMax) {
|
||||||
segment = curve._segment2;
|
segment = curve._segment2;
|
||||||
} else {
|
} else {
|
||||||
// Split the curve at t, passing true for _setHandles to always
|
// Split the curve at time, passing true for _setHandles to
|
||||||
// set the handles on the sub-curves even if the original curve
|
// always set the handles on the sub-curves even if the original
|
||||||
// had no handles.
|
// curve had no handles.
|
||||||
var newCurve = curve.divide(t, true, true);
|
var newCurve = curve.divideAtTime(time, true);
|
||||||
// Keep track of curves without handles, so they can be cleared
|
// Keep track of curves without handles, so they can be cleared
|
||||||
// again at the end.
|
// again at the end.
|
||||||
if (noHandles)
|
if (noHandles)
|
||||||
|
@ -294,7 +294,7 @@ PathItem.inject(new function() {
|
||||||
segment._intersection = dest;
|
segment._intersection = dest;
|
||||||
}
|
}
|
||||||
prevCurve = curve;
|
prevCurve = curve;
|
||||||
prevT = origT;
|
prevTime = origTime;
|
||||||
}
|
}
|
||||||
// Clear segment handles if they were part of a curve with no handles,
|
// Clear segment handles if they were part of a curve with no handles,
|
||||||
// once we are done with the entire curve.
|
// once we are done with the entire curve.
|
||||||
|
@ -445,9 +445,9 @@ PathItem.inject(new function() {
|
||||||
var curve = entry.curve,
|
var curve = entry.curve,
|
||||||
path = curve._path,
|
path = curve._path,
|
||||||
parent = path._parent,
|
parent = path._parent,
|
||||||
t = curve.getParameterAt(length),
|
t = curve.getTimeAt(length),
|
||||||
pt = curve.getPointAt(t, true),
|
pt = curve.getPointAtTime(t),
|
||||||
hor = Math.abs(curve.getTangentAt(t, true).y)
|
hor = Math.abs(curve.getTangentAtTime(t).y)
|
||||||
< /*#=*/Numerical.TRIGONOMETRIC_EPSILON;
|
< /*#=*/Numerical.TRIGONOMETRIC_EPSILON;
|
||||||
if (parent instanceof CompoundPath)
|
if (parent instanceof CompoundPath)
|
||||||
path = parent;
|
path = parent;
|
||||||
|
|
|
@ -91,11 +91,11 @@ var PathIterator = Base.extend({
|
||||||
this.parts = parts;
|
this.parts = parts;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
// Keep a current index from the part where we last where in
|
// Keep a current index from the part where we last where in
|
||||||
// getParameterAt(), to optimise for iterator-like usage of iterator.
|
// getTimeAt(), to optimise for iterator-like usage of iterator.
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
getParameterAt: function(offset) {
|
getTimeAt: function(offset) {
|
||||||
// Make sure we're not beyond the requested offset already. Search the
|
// Make sure we're not beyond the requested offset already. Search the
|
||||||
// start position backwards from where to then process the loop below.
|
// start position backwards from where to then process the loop below.
|
||||||
var i, j = this.index;
|
var i, j = this.index;
|
||||||
|
@ -135,8 +135,8 @@ var PathIterator = Base.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
drawPart: function(ctx, from, to) {
|
drawPart: function(ctx, from, to) {
|
||||||
from = this.getParameterAt(from);
|
from = this.getTimeAt(from);
|
||||||
to = this.getParameterAt(to);
|
to = this.getTimeAt(to);
|
||||||
for (var i = from.index; i <= to.index; i++) {
|
for (var i = from.index; i <= to.index; i++) {
|
||||||
var curve = Curve.getPart(this.curves[i],
|
var curve = Curve.getPart(this.curves[i],
|
||||||
i == from.index ? from.value : 0,
|
i == from.index ? from.value : 0,
|
||||||
|
@ -149,7 +149,7 @@ var PathIterator = Base.extend({
|
||||||
}, Base.each(Curve._evaluateMethods,
|
}, Base.each(Curve._evaluateMethods,
|
||||||
function(name) {
|
function(name) {
|
||||||
this[name + 'At'] = function(offset, weighted) {
|
this[name + 'At'] = function(offset, weighted) {
|
||||||
var param = this.getParameterAt(offset);
|
var param = this.getTimeAt(offset);
|
||||||
return Curve[name](this.curves[param.index], param.value, weighted);
|
return Curve[name](this.curves[param.index], param.value, weighted);
|
||||||
};
|
};
|
||||||
}, {})
|
}, {})
|
||||||
|
|
|
@ -12,31 +12,7 @@
|
||||||
|
|
||||||
QUnit.module('Curve');
|
QUnit.module('Curve');
|
||||||
|
|
||||||
test('Curve#getParameterOf()', function() {
|
test('Curve#getPointAtTime()', function() {
|
||||||
// For issue #708:
|
|
||||||
var path = new Path.Rectangle({
|
|
||||||
center: new Point(300, 100),
|
|
||||||
size: new Point(100, 100),
|
|
||||||
strokeColor: 'black'
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var pos = 0; pos < path.length; pos += 10) {
|
|
||||||
var point1 = path.getPointAt(pos),
|
|
||||||
point2 = null;
|
|
||||||
for (var i = 0; i < path.curves.length; i++) {
|
|
||||||
var curve = path.curves[i];
|
|
||||||
var parameter = curve.getParameterOf(point1);
|
|
||||||
if (parameter) {
|
|
||||||
point2 = curve.getLocationAt(parameter, true).point;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
equals(point1, point2, 'curve.getLocationAt(curve.getParameterOf('
|
|
||||||
+ point1 + ')).point;');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Curve#getPointAt()', function() {
|
|
||||||
var curve = new Path.Circle({
|
var curve = new Path.Circle({
|
||||||
center: [100, 100],
|
center: [100, 100],
|
||||||
radius: 100
|
radius: 100
|
||||||
|
@ -52,15 +28,18 @@ test('Curve#getPointAt()', function() {
|
||||||
|
|
||||||
for (var i = 0; i < points.length; i++) {
|
for (var i = 0; i < points.length; i++) {
|
||||||
var entry = points[i];
|
var entry = points[i];
|
||||||
|
equals(curve.getPointAtTime(entry[0]), entry[1],
|
||||||
|
'curve.getPointAtTime(' + entry[0] + ');');
|
||||||
|
// Legacy version:
|
||||||
equals(curve.getPointAt(entry[0], true), entry[1],
|
equals(curve.getPointAt(entry[0], true), entry[1],
|
||||||
'curve.getPointAt(' + entry[0] + ', true);');
|
'Legacy: curve.getPointAt(' + entry[0] + ', true);');
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(curve.getPointAt(curve.length + 1), null,
|
equals(curve.getPointAt(curve.length + 1), null,
|
||||||
'Should return null when offset is out of range.');
|
'Should return null when offset is out of range.');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Curve#getTangentAt()', function() {
|
test('Curve#getTangentAtTime()', function() {
|
||||||
var curve = new Path.Circle({
|
var curve = new Path.Circle({
|
||||||
center: [100, 100],
|
center: [100, 100],
|
||||||
radius: 100
|
radius: 100
|
||||||
|
@ -76,14 +55,19 @@ test('Curve#getTangentAt()', function() {
|
||||||
|
|
||||||
for (var i = 0; i < tangents.length; i++) {
|
for (var i = 0; i < tangents.length; i++) {
|
||||||
var entry = tangents[i];
|
var entry = tangents[i];
|
||||||
|
equals(curve.getTangentAtTime(entry[0]), entry[1].normalize(),
|
||||||
|
'curve.getTangentAtTime(' + entry[0] + ');');
|
||||||
|
equals(curve.getWeightedTangentAtTime(entry[0]), entry[1],
|
||||||
|
'curve.getWeightedTangentAtTime(' + entry[0] + ');');
|
||||||
|
// Legacy version:
|
||||||
equals(curve.getTangentAt(entry[0], true), entry[1].normalize(),
|
equals(curve.getTangentAt(entry[0], true), entry[1].normalize(),
|
||||||
'curve.getTangentAt(' + entry[0] + ', true);');
|
'Legacy: curve.getTangentAt(' + entry[0] + ', true);');
|
||||||
equals(curve.getWeightedTangentAt(entry[0], true), entry[1],
|
equals(curve.getWeightedTangentAt(entry[0], true), entry[1],
|
||||||
'curve.getWeightedTangentAt(' + entry[0] + ', true);');
|
'Legacy: curve.getWeightedTangentAt(' + entry[0] + ', true);');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Curve#getNormalAt()', function() {
|
test('Curve#getNormalAtTime()', function() {
|
||||||
var curve = new Path.Circle({
|
var curve = new Path.Circle({
|
||||||
center: [100, 100],
|
center: [100, 100],
|
||||||
radius: 100
|
radius: 100
|
||||||
|
@ -99,14 +83,19 @@ test('Curve#getNormalAt()', function() {
|
||||||
|
|
||||||
for (var i = 0; i < normals.length; i++) {
|
for (var i = 0; i < normals.length; i++) {
|
||||||
var entry = normals[i];
|
var entry = normals[i];
|
||||||
|
equals(curve.getNormalAtTime(entry[0]), entry[1].normalize(),
|
||||||
|
'curve.getNormalAtTime(' + entry[0] + ');');
|
||||||
|
equals(curve.getWeightedNormalAtTime(entry[0]), entry[1],
|
||||||
|
'curve.getWeightedNormalAtTime(' + entry[0] + ');');
|
||||||
|
// Legacy version:
|
||||||
equals(curve.getNormalAt(entry[0], true), entry[1].normalize(),
|
equals(curve.getNormalAt(entry[0], true), entry[1].normalize(),
|
||||||
'curve.getNormalAt(' + entry[0] + ', true);');
|
'Legacy: curve.getNormalAt(' + entry[0] + ', true);');
|
||||||
equals(curve.getWeightedNormalAt(entry[0], true), entry[1],
|
equals(curve.getWeightedNormalAt(entry[0], true), entry[1],
|
||||||
'curve.getWeightedNormalAt(' + entry[0] + ', true);');
|
'Legacy: curve.getWeightedNormalAt(' + entry[0] + ', true);');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Curve#getCurvatureAt()', function() {
|
test('Curve#getCurvatureAtTime()', function() {
|
||||||
var curve = new Path.Circle({
|
var curve = new Path.Circle({
|
||||||
center: [100, 100],
|
center: [100, 100],
|
||||||
radius: 100
|
radius: 100
|
||||||
|
@ -122,12 +111,15 @@ test('Curve#getCurvatureAt()', function() {
|
||||||
|
|
||||||
for (var i = 0; i < curvatures.length; i++) {
|
for (var i = 0; i < curvatures.length; i++) {
|
||||||
var entry = curvatures[i];
|
var entry = curvatures[i];
|
||||||
|
equals(curve.getCurvatureAtTime(entry[0]), entry[1],
|
||||||
|
'curve.getCurvatureAtTime(' + entry[0] + ');');
|
||||||
|
// Legacy version:
|
||||||
equals(curve.getCurvatureAt(entry[0], true), entry[1],
|
equals(curve.getCurvatureAt(entry[0], true), entry[1],
|
||||||
'curve.getCurvatureAt(' + entry[0] + ', true);');
|
'Legacy: curve.getCurvatureAt(' + entry[0] + ', true);');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Curve#getCurvatureAt()', function() {
|
test('Curve#getCurvatureAtTime()', function() {
|
||||||
var curve = new Path.Line({
|
var curve = new Path.Line({
|
||||||
from: [100, 100],
|
from: [100, 100],
|
||||||
to: [200, 200],
|
to: [200, 200],
|
||||||
|
@ -143,12 +135,15 @@ test('Curve#getCurvatureAt()', function() {
|
||||||
|
|
||||||
for (var i = 0; i < curvatures.length; i++) {
|
for (var i = 0; i < curvatures.length; i++) {
|
||||||
var entry = curvatures[i];
|
var entry = curvatures[i];
|
||||||
|
equals(curve.getCurvatureAtTime(entry[0]), entry[1],
|
||||||
|
'curve.getCurvatureAtTime(' + entry[0] + ');');
|
||||||
|
// Legacy version:
|
||||||
equals(curve.getCurvatureAt(entry[0], true), entry[1],
|
equals(curve.getCurvatureAt(entry[0], true), entry[1],
|
||||||
'curve.getCurvatureAt(' + entry[0] + ', true);');
|
'Legacy: curve.getCurvatureAt(' + entry[0] + ', true);');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Curve#getParameterAt()', function() {
|
test('Curve#getTimeAt()', function() {
|
||||||
var curve = new Path([
|
var curve = new Path([
|
||||||
[[0, 0], [0, 0], [100, 0]],
|
[[0, 0], [0, 0], [100, 0]],
|
||||||
[[200, 200]],
|
[[200, 200]],
|
||||||
|
@ -157,14 +152,16 @@ test('Curve#getParameterAt()', function() {
|
||||||
for (var f = 0; f <= 1; f += 0.1) {
|
for (var f = 0; f <= 1; f += 0.1) {
|
||||||
var o1 = curve.length * f;
|
var o1 = curve.length * f;
|
||||||
var o2 = -curve.length * (1 - f);
|
var o2 = -curve.length * (1 - f);
|
||||||
var t1 = curve.getParameterAt(o1);
|
var message = 'Curve-time parameter at offset ' + o1
|
||||||
var t2 = curve.getParameterAt(o2);
|
+ ' should be the same value as at offset' + o2;
|
||||||
equals(t1, t2, 'Curve parameter at offset ' + o1
|
equals(curve.getTimeAt(o1), curve.getTimeAt(o2), message,
|
||||||
+ ' should be the same value as at offset' + o2,
|
|
||||||
Numerical.CURVETIME_EPSILON);
|
Numerical.CURVETIME_EPSILON);
|
||||||
|
// Legacy version:
|
||||||
|
equals(curve.getParameterAt(o1), curve.getParameterAt(o2),
|
||||||
|
'Legacy: ' + message, Numerical.CURVETIME_EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(curve.getParameterAt(curve.length + 1), null,
|
equals(curve.getTimeAt(curve.length + 1), null,
|
||||||
'Should return null when offset is out of range.');
|
'Should return null when offset is out of range.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -176,7 +173,6 @@ test('Curve#getLocationAt()', function() {
|
||||||
|
|
||||||
equals(curve.getLocationAt(curve.length + 1), null,
|
equals(curve.getLocationAt(curve.length + 1), null,
|
||||||
'Should return null when offset is out of range.');
|
'Should return null when offset is out of range.');
|
||||||
// 'Should return null when point is not on the curve.');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Curve#isStraight()', function() {
|
test('Curve#isStraight()', function() {
|
||||||
|
@ -223,3 +219,31 @@ test('Curve#isLinear()', function() {
|
||||||
return new Curve([100, 100], null, null, [200, 200]).isLinear();
|
return new Curve([100, 100], null, null, [200, 200]).isLinear();
|
||||||
}, false);
|
}, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Curve#getTimeOf()', function() {
|
||||||
|
// For issue #708:
|
||||||
|
var path = new Path.Rectangle({
|
||||||
|
center: new Point(300, 100),
|
||||||
|
size: new Point(100, 100),
|
||||||
|
strokeColor: 'black'
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var pos = 0; pos < path.length; pos += 10) {
|
||||||
|
var point1 = path.getPointAt(pos),
|
||||||
|
point2 = null;
|
||||||
|
for (var i = 0; i < path.curves.length; i++) {
|
||||||
|
var curve = path.curves[i];
|
||||||
|
var time = curve.getTimeOf(point1);
|
||||||
|
if (time) {
|
||||||
|
// Legacy-check-hack:
|
||||||
|
equals(curve.getParameterOf(point1), time,
|
||||||
|
'Legacy: curve.getParameterOf() should return the same'
|
||||||
|
+ ' as curve.getTimeOf()');
|
||||||
|
point2 = curve.getLocationAtTime(time).point;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
equals(point1, point2, 'curve.getLocationAt(curve.getTimeOf('
|
||||||
|
+ point1 + ')).point;');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
@ -168,8 +168,8 @@ test('Path#contains() (Rectangle Contours)', function() {
|
||||||
curves = path.getCurves();
|
curves = path.getCurves();
|
||||||
|
|
||||||
for (var i = 0; i < curves.length; i++) {
|
for (var i = 0; i < curves.length; i++) {
|
||||||
testPoint(path, curves[i].getPointAt(0, true), true);
|
testPoint(path, curves[i].getPointAtTime(0), true);
|
||||||
testPoint(path, curves[i].getPointAt(0.5, true), true);
|
testPoint(path, curves[i].getPointAtTime(0.5), true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -181,8 +181,8 @@ test('Path#contains() (Rotated Rectangle Contours)', function() {
|
||||||
path.rotate(45);
|
path.rotate(45);
|
||||||
|
|
||||||
for (var i = 0; i < curves.length; i++) {
|
for (var i = 0; i < curves.length; i++) {
|
||||||
testPoint(path, curves[i].getPointAt(0, true), true);
|
testPoint(path, curves[i].getPointAtTime(0), true);
|
||||||
testPoint(path, curves[i].getPointAt(0.5, true), true);
|
testPoint(path, curves[i].getPointAtTime(0.5), true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ function testIntersection(intersections, results) {
|
||||||
var name = 'intersections[' + i + ']';
|
var name = 'intersections[' + i + ']';
|
||||||
equals(inter.point, new Point(values.point), name + '.point');
|
equals(inter.point, new Point(values.point), name + '.point');
|
||||||
equals(inter.index, values.index, name + '.index');
|
equals(inter.index, values.index, name + '.index');
|
||||||
equals(inter.parameter, values.parameter || 0, name + '.parameter');
|
equals(inter.time, values.time || 0, name + '.time');
|
||||||
equals(inter.isCrossing(), values.crossing || false, name + '.isCrossing()');
|
equals(inter.isCrossing(), values.crossing || false, name + '.isCrossing()');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@ test('#565', function() {
|
||||||
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
||||||
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||||
testIntersection(curve1.getIntersections(curve2), [
|
testIntersection(curve1.getIntersections(curve2), [
|
||||||
{ point: { x: 354.13635, y: 220.81369 }, index: 0, parameter: 0.46725, crossing: true },
|
{ point: { x: 354.13635, y: 220.81369 }, index: 0, time: 0.46725, crossing: true },
|
||||||
{ point: { x: 390.24772, y: 224.27351 }, index: 0, parameter: 0.71605, crossing: true }
|
{ point: { x: 390.24772, y: 224.27351 }, index: 0, time: 0.71605, crossing: true }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Alternative pair of curves that has the same issue
|
// Alternative pair of curves that has the same issue
|
||||||
|
@ -41,7 +41,7 @@ test('#565', function() {
|
||||||
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
||||||
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||||
testIntersection(curve1.getIntersections(curve2), [
|
testIntersection(curve1.getIntersections(curve2), [
|
||||||
{ point: { x: 335.62744, y: 338.15939 }, index: 0, parameter: 0.26516, crossing: true }
|
{ point: { x: 335.62744, y: 338.15939 }, index: 0, time: 0.26516, crossing: true }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ test('#568', function() {
|
||||||
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
||||||
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||||
testIntersection(curve1.getIntersections(curve2), [
|
testIntersection(curve1.getIntersections(curve2), [
|
||||||
{ point: { x: 547.96568, y: 396.66339 }, index: 0, parameter: 0.07024, crossing: true },
|
{ point: { x: 547.96568, y: 396.66339 }, index: 0, time: 0.07024, crossing: true },
|
||||||
{ point: { x: 504.79973, y: 383.37886 }, index: 0, parameter: 0.48077, crossing: true }
|
{ point: { x: 504.79973, y: 383.37886 }, index: 0, time: 0.48077, crossing: true }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var curve1 = new Curve(new Point(0, 0), new Point(20, 40) , new Point (-30, -50), new Point(50, 50));
|
var curve1 = new Curve(new Point(0, 0), new Point(20, 40) , new Point (-30, -50), new Point(50, 50));
|
||||||
|
@ -60,7 +60,7 @@ test('#568', function() {
|
||||||
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
||||||
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||||
testIntersection(curve1.getIntersections(curve2), [
|
testIntersection(curve1.getIntersections(curve2), [
|
||||||
{ point: { x: 50, y: 50 }, index: 0, parameter: 1, crossing: false }
|
{ point: { x: 50, y: 50 }, index: 0, time: 1, crossing: false }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ test('#570', function() {
|
||||||
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||||
var ints = curve1.getIntersections(curve2);
|
var ints = curve1.getIntersections(curve2);
|
||||||
testIntersection(curve1.getIntersections(curve2), [
|
testIntersection(curve1.getIntersections(curve2), [
|
||||||
{ point: { x: 311.16035, y: 406.29853 }, index: 0, parameter: 1, crossing: false }
|
{ point: { x: 311.16035, y: 406.29853 }, index: 0, time: 1, crossing: false }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@ test('#571', function() {
|
||||||
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
||||||
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||||
testIntersection(curve1.getIntersections(curve2), [
|
testIntersection(curve1.getIntersections(curve2), [
|
||||||
{ point: { x: 352.39945, y: 330.44135 }, index: 0, parameter: 0.41159, crossing: true },
|
{ point: { x: 352.39945, y: 330.44135 }, index: 0, time: 0.41159, crossing: true },
|
||||||
{ point: { x: 420.12359, y: 275.83519 }, index: 0, parameter: 1, crossing: false }
|
{ point: { x: 420.12359, y: 275.83519 }, index: 0, time: 1, crossing: false }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ test('circle and square (existing segments overlaps on curves)', function() {
|
||||||
var path1 = new Path.Circle(new Point(110, 110), 80);
|
var path1 = new Path.Circle(new Point(110, 110), 80);
|
||||||
var path2 = new Path.Rectangle(new Point(110, 110), [100, 100]);
|
var path2 = new Path.Rectangle(new Point(110, 110), [100, 100]);
|
||||||
testIntersection(path1.getIntersections(path2), [
|
testIntersection(path1.getIntersections(path2), [
|
||||||
{ point: { x: 190, y: 110 }, index: 2, parameter: 0, crossing: true },
|
{ point: { x: 190, y: 110 }, index: 2, time: 0, crossing: true },
|
||||||
{ point: { x: 110, y: 190 }, index: 3, parameter: 0, crossing: true }
|
{ point: { x: 110, y: 190 }, index: 3, time: 0, crossing: true }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,16 +21,16 @@ test('path.length', function() {
|
||||||
var length = path.length;
|
var length = path.length;
|
||||||
equals(length, 172.10112809179614, 'path.length');
|
equals(length, 172.10112809179614, 'path.length');
|
||||||
|
|
||||||
var param = path.curves[0].getParameterAt(length / 4);
|
var t = path.curves[0].getTimeAt(length / 4);
|
||||||
equals(param, 0.2255849553116685, 'path.curves[0].getParameterAt(length / 4)');
|
equals(t, 0.2255849553116685, 'path.curves[0].getTimeAt(length / 4)');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('curve.getParameter with straight curve', function() {
|
test('curve.getTimeAt() with straight curve', function() {
|
||||||
var path = new Path();
|
var path = new Path();
|
||||||
path.moveTo(100, 100);
|
path.moveTo(100, 100);
|
||||||
path.lineTo(500, 500);
|
path.lineTo(500, 500);
|
||||||
var curve = path.curves[0];
|
var curve = path.curves[0];
|
||||||
var length = curve.length;
|
var length = curve.length;
|
||||||
var t = curve.getParameterAt(length / 3);
|
var t = curve.getTimeAt(length / 3);
|
||||||
equals(t, 0.3869631475722452);
|
equals(t, 0.3869631475722452);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue