mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-28 17:02:24 -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;
|
||||
|
||||
// // 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, " ") });
|
||||
// // ixs.map(function(a) { markPoint(a.point, " "); });
|
||||
|
||||
|
@ -402,7 +402,7 @@
|
|||
t = t || s.index;
|
||||
if (remove === undefined) { remove = true; }
|
||||
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 cir = new Path.Circle(s.point, 2);
|
||||
cir.style.fillColor = c;
|
||||
|
@ -427,12 +427,12 @@
|
|||
tc = tc || '#ccc';
|
||||
t = t || crv.index;
|
||||
if (remove === undefined) { remove = true; }
|
||||
var p = crv.getPointAt(0.57, true);
|
||||
var t1 = crv.getTangentAt(0.57, true).normalize(-10);
|
||||
var p = crv.getPointAtTime(0.57);
|
||||
var t1 = crv.getTangentAtTime(0.57).normalize(-10);
|
||||
var p2 = p.clone().add(t1);
|
||||
var l = new Path.Line(p, p2).rotate(30, p);
|
||||
var l2 = new Path.Line(p, p2).rotate(-30, p);
|
||||
p = crv.getPointAt(0.43, true);
|
||||
p = crv.getPointAtTime(0.43);
|
||||
var cir = new Path.Circle(p, 8);
|
||||
var text = new PointText(p.subtract([0, -4]));
|
||||
text.justification = 'center';
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
curve.segment2.point = point;
|
||||
var length = curve.length;
|
||||
var step = 10;
|
||||
var iteratively = false;
|
||||
var iteratively = true;
|
||||
var flatten = true;
|
||||
var num = Math.floor(length / step);
|
||||
var prev = 0;
|
||||
|
@ -39,9 +39,9 @@
|
|||
} else {
|
||||
for (var i = 0, pos = 0; i <= num; i++, pos += step) {
|
||||
var t = iteratively
|
||||
? curve.getParameterAt(step, prev)
|
||||
: curve.getParameterAt(pos);
|
||||
var point = curve.getPointAt(t, true);
|
||||
? curve.getTimeAt(step, prev)
|
||||
: curve.getTimeAt(pos);
|
||||
var point = curve.getPointAtTime(t);
|
||||
var circle = new Path.Circle(point, step / 2);
|
||||
circle.strokeColor = 'red';
|
||||
if (remove)
|
||||
|
|
|
@ -27,7 +27,7 @@ paper = new (PaperScope.inject(Base.exports, {
|
|||
// Export jsdom document and window too, for Node.js
|
||||
document: document,
|
||||
window: window,
|
||||
// TODO: Remove in 2017 (deprecated January 2016):
|
||||
// TODO: Remove in 1.0.0? (deprecated January 2016):
|
||||
Symbol: SymbolDefinition,
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* @param {Number} from the curve-time parameter at which the sub-curve
|
||||
|
@ -439,46 +439,44 @@ var Curve = Base.extend(/** @lends Curve# */{
|
|||
|
||||
// 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
|
||||
* 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.
|
||||
*
|
||||
* @name Curve#divide
|
||||
* @function
|
||||
* @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
|
||||
* @param {Number|CurveLocation} location the offset or location 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 #divideAtTime(time)
|
||||
*/
|
||||
// TODO: Rename to divideAt()?
|
||||
divide: function(offset, isParameter, _setHandles) {
|
||||
var parameter = this._getParameter(offset, isParameter),
|
||||
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
||||
divideAt: function(location) {
|
||||
// Accept offsets and CurveLocation objects, as well as objects that act
|
||||
// like them.
|
||||
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,
|
||||
res = null;
|
||||
// Only divide if not at the beginning or end.
|
||||
if (parameter >= tMin && parameter <= tMax) {
|
||||
var parts = Curve.subdivide(this.getValues(), parameter),
|
||||
if (time >= tMin && time <= tMax) {
|
||||
var parts = Curve.subdivide(this.getValues(), time),
|
||||
left = parts[0],
|
||||
right = parts[1],
|
||||
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
|
||||
* will result in two paths.
|
||||
*
|
||||
* @name Curve#split
|
||||
* @function
|
||||
* @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
|
||||
* @param {Number|CurveLocation} location the offset or location on the
|
||||
* curve at which to split
|
||||
* @return {Path} the newly created path after splitting, if any
|
||||
* @see Path#split(index, parameter)
|
||||
* @see Path#splitAt(offset)
|
||||
*/
|
||||
// TODO: Rename to splitAt()?
|
||||
split: function(offset, isParameter) {
|
||||
return this._path
|
||||
? this._path.split(this._segment1._index,
|
||||
this._getParameter(offset, isParameter))
|
||||
: null;
|
||||
splitAt: function(location) {
|
||||
return this._path ? this._path.splitAt(location) : 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);
|
||||
},
|
||||
|
||||
getParameterOf: function(v, point) {
|
||||
getTimeOf: function(v, point) {
|
||||
// Before solving cubics, compare the beginning and end of the curve
|
||||
// with zero epsilon:
|
||||
var p1 = new Point(v[0], v[1]),
|
||||
|
@ -642,7 +666,7 @@ statics: {
|
|||
: null;
|
||||
},
|
||||
|
||||
getNearestParameter: function(v, point) {
|
||||
getNearestTime: function(v, point) {
|
||||
if (Curve.isStraight(v)) {
|
||||
var p1x = v[0], p1y = v[1],
|
||||
p2x = v[6], p2y = v[7],
|
||||
|
@ -656,7 +680,7 @@ statics: {
|
|||
var u = ((point.x - p1x) * vx + (point.y - p1y) * vy) / det;
|
||||
return u < /*#=*/Numerical.EPSILON ? 0
|
||||
: u > /*#=*/(1 - Numerical.EPSILON) ? 1
|
||||
: Curve.getParameterOf(v,
|
||||
: Curve.getTimeOf(v,
|
||||
new Point(p1x + u * vx, p1y + u * vy));
|
||||
}
|
||||
|
||||
|
@ -951,7 +975,7 @@ statics: {
|
|||
* @return {Boolean} {@true if the line is horizontal}
|
||||
*/
|
||||
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;
|
||||
},
|
||||
|
||||
|
@ -961,59 +985,64 @@ statics: {
|
|||
* @return {Boolean} {@true if the line is vertical}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}), /** @lends Curve# */{
|
||||
// Explicitly deactivate the creation of beans, as we have functions here
|
||||
// that look like bean getters but actually read arguments.
|
||||
// See #getParameterOf(), #getLocationOf(), #getNearestLocation(), ...
|
||||
// See #getTimeOf(), #getLocationOf(), #getNearestLocation(), ...
|
||||
beans: false,
|
||||
|
||||
/**
|
||||
* {@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,
|
||||
* 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`
|
||||
* and `1` for negative values of `offset`.
|
||||
*
|
||||
* @param {Number} offset
|
||||
* @param {Number} [start]
|
||||
* @return {Number} the curve time parameter at the specified offset
|
||||
* @param {Number} offset the offset at which to find the curve-time, in
|
||||
* curve length units
|
||||
* @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) {
|
||||
return Curve.getParameterAt(this.getValues(), offset, start);
|
||||
getTimeAt: function(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
|
||||
* curve, `null` otherwise.
|
||||
*
|
||||
* @param {Point} point the point on the curve
|
||||
* @return {Number} the curve time parameter of the specified point
|
||||
* @deprecated, use use {@link #getTimeOf(point)} instead.
|
||||
*/
|
||||
getParameterOf: function(/* point */) {
|
||||
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;
|
||||
},
|
||||
getParameterAt: '#getTimeAt',
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
getLocationOf: function(/* point */) {
|
||||
return this.getLocationAt(this.getParameterOf(Point.read(arguments)),
|
||||
true);
|
||||
return this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1039,6 +1067,23 @@ statics: {
|
|||
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.
|
||||
*
|
||||
|
@ -1050,7 +1095,7 @@ statics: {
|
|||
getNearestLocation: function(/* point */) {
|
||||
var point = Point.read(arguments),
|
||||
values = this.getValues(),
|
||||
t = Curve.getNearestParameter(values, point),
|
||||
t = Curve.getNearestTime(values, point),
|
||||
pt = Curve.getPoint(values, t);
|
||||
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
|
||||
* @function
|
||||
* @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 {Point} the point on the curve at the given offset
|
||||
* @param {Number|CurveLocation} location the offset or location 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
|
||||
* offset.
|
||||
* location.
|
||||
*
|
||||
* @name Curve#getTangentAt
|
||||
* @function
|
||||
* @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 {Point} the normalized tangent of the curve at the given offset
|
||||
* @param {Number|CurveLocation} location the offset or location 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 offset.
|
||||
* Calculates the normal vector of the curve at the given location.
|
||||
*
|
||||
* @name Curve#getNormalAt
|
||||
* @function
|
||||
* @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 {Point} the normal of the curve at the given offset
|
||||
* @param {Number|CurveLocation} location the offset or location 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 offset,
|
||||
* its length reflecting the curve velocity at that location.
|
||||
* Calculates the weighted tangent vector of the curve at the given
|
||||
* location, its length reflecting the curve velocity at that location.
|
||||
*
|
||||
* @name Curve#getWeightedTangentAt
|
||||
* @function
|
||||
* @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 {Point} the weighted tangent of the curve at the given offset
|
||||
* @param {Number|CurveLocation} location the offset or location 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 offset,
|
||||
* Calculates the weighted normal vector of the curve at the given location,
|
||||
* its length reflecting the curve velocity at that location.
|
||||
*
|
||||
* @name Curve#getWeightedNormalAt
|
||||
* @function
|
||||
* @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 {Point} the weighted normal of the curve at the given offset
|
||||
* @param {Number|CurveLocation} location the offset or location on the
|
||||
* curve
|
||||
* @return {Point} the weighted normal of the curve at the given location
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* @function
|
||||
* @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 {Number} the curvature of the curve at the given offset
|
||||
* @param {Number|CurveLocation} location the offset or location on the
|
||||
* curve
|
||||
* @return {Number} the curvature of the curve at the given location
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -1152,11 +1245,18 @@ new function() { // // Scope to inject various curve evaluation methods
|
|||
function(name) {
|
||||
// NOTE: (For easier searching): This loop produces:
|
||||
// getPointAt, getTangentAt, getNormalAt, getWeightedTangentAt,
|
||||
// getWeightedNormalAt, getCurvatureAt
|
||||
this[name + 'At'] = function(offset, isParameter) {
|
||||
// getWeightedNormalAt, getCurvatureAt, getPointAtTime,
|
||||
// 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();
|
||||
return Curve[name](values, isParameter ? offset
|
||||
: Curve.getParameterAt(values, offset, 0));
|
||||
return Curve[name](values, _isTime ? location
|
||||
: Curve.getTimeAt(values, location, 0));
|
||||
};
|
||||
|
||||
this[name + 'AtTime'] = function(time) {
|
||||
return Curve[name](this.getValues(), time);
|
||||
};
|
||||
}, {
|
||||
statics: {
|
||||
|
@ -1306,7 +1406,7 @@ new function() { // Scope for methods that require private functions
|
|||
return Numerical.integrate(ds, a, b, getIterations(a, b));
|
||||
},
|
||||
|
||||
getParameterAt: function(v, offset, start) {
|
||||
getTimeAt: function(v, offset, start) {
|
||||
if (start === undefined)
|
||||
start = offset < 0 ? 1 : 0;
|
||||
if (offset === 0)
|
||||
|
@ -1387,7 +1487,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
|
|||
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
||||
tMax = 1 - tMin;
|
||||
if (t1 == null)
|
||||
t1 = Curve.getParameterOf(v1, p1);
|
||||
t1 = Curve.getTimeOf(v1, p1);
|
||||
// Check t1 and t2 against correct bounds, based on excludeStart/End:
|
||||
// - excludeStart means the start of c1 connects to the end 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) &&
|
||||
t1 <= (excludeEnd ? tMax : 1)) {
|
||||
if (t2 == null)
|
||||
t2 = Curve.getParameterOf(v2, p2);
|
||||
t2 = Curve.getTimeOf(v2, p2);
|
||||
if (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&
|
||||
t2 <= (excludeStart ? tMax : 1)) {
|
||||
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.
|
||||
var tc = roots[i],
|
||||
pc = Curve.getPoint(vc, tc),
|
||||
tl = Curve.getParameterOf(vl, pc);
|
||||
tl = Curve.getTimeOf(vl, pc);
|
||||
if (tl !== null) {
|
||||
var pl = Curve.getPoint(vl, tl),
|
||||
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.
|
||||
for (var i = 0, maxCurvature = 0; i < count; i++) {
|
||||
var curvature = Math.abs(
|
||||
c1.getCurvatureAt(roots[i], true));
|
||||
c1.getCurvatureAtTime(roots[i]));
|
||||
if (curvature > maxCurvature) {
|
||||
maxCurvature = curvature;
|
||||
tSplit = roots[i];
|
||||
|
@ -1894,7 +1994,7 @@ new function() { // Scope for intersection using bezier fat-line clipping
|
|||
for (var i = 0, t1 = 0;
|
||||
i < 2 && pairs.length < 2;
|
||||
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 ? 1 : 7]));
|
||||
if (t2 != null) { // If point is on curve
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
* @name CurveLocation
|
||||
*
|
||||
* @class CurveLocation objects describe a location on {@link Curve} objects, as
|
||||
* defined by the curve-time {@link #parameter}, a value between `0`
|
||||
* (beginning of the curve) and `1` (end of the curve). If the curve is part
|
||||
* of a {@link Path} item, its {@link #index} inside the {@link Path#curves}
|
||||
* defined by the curve-time {@link #time}, a value between `0` (beginning
|
||||
* of the curve) and `1` (end of the curve). If the curve is part of a
|
||||
* {@link Path} item, its {@link #index} inside the {@link Path#curves}
|
||||
* array is also provided.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @param {Curve} curve
|
||||
* @param {Number} parameter
|
||||
* @param {Number} time
|
||||
* @param {Point} [point]
|
||||
*/
|
||||
initialize: function CurveLocation(curve, parameter, point,
|
||||
_overlap, _distance) {
|
||||
initialize: function CurveLocation(curve, time, point, _overlap, _distance) {
|
||||
// Merge intersections very close to the end of a curve with the
|
||||
// beginning of the next curve.
|
||||
if (parameter > /*#=*/(1 - Numerical.CURVETIME_EPSILON)) {
|
||||
if (time > /*#=*/(1 - Numerical.CURVETIME_EPSILON)) {
|
||||
var next = curve.getNext();
|
||||
if (next) {
|
||||
parameter = 0;
|
||||
time = 0;
|
||||
curve = next;
|
||||
}
|
||||
}
|
||||
|
@ -58,8 +57,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
// CurveLocation objects.
|
||||
this._id = UID.get(CurveLocation);
|
||||
this._setCurve(curve);
|
||||
this._parameter = parameter;
|
||||
this._point = point || curve.getPointAt(parameter, true);
|
||||
this._time = time;
|
||||
this._point = point || curve.getPointAtTime(time);
|
||||
this._overlap = _overlap;
|
||||
this._distance = _distance;
|
||||
this._intersection = this._next = this._prev = null;
|
||||
|
@ -84,7 +83,7 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
_setSegment: function(segment) {
|
||||
this._setCurve(segment.getCurve());
|
||||
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()
|
||||
this._point = segment._point.clone();
|
||||
},
|
||||
|
@ -100,15 +99,15 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
var curve = this.getCurve(),
|
||||
segment = this._segment;
|
||||
if (!segment) {
|
||||
var parameter = this.getParameter();
|
||||
if (parameter === 0) {
|
||||
var time = this.getTime();
|
||||
if (time === 0) {
|
||||
segment = curve._segment1;
|
||||
} else if (parameter === 1) {
|
||||
} else if (time === 1) {
|
||||
segment = curve._segment2;
|
||||
} else if (parameter != null) {
|
||||
} else if (time != null) {
|
||||
// Determine the closest segment by comparing curve lengths
|
||||
segment = curve.getPartLength(0, parameter)
|
||||
< curve.getPartLength(parameter, 1)
|
||||
segment = curve.getPartLength(0, time)
|
||||
< curve.getPartLength(time, 1)
|
||||
? curve._segment1
|
||||
: curve._segment2;
|
||||
}
|
||||
|
@ -128,9 +127,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
that = this;
|
||||
if (path && path._version !== this._version) {
|
||||
// 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.
|
||||
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
|
||||
|
@ -139,7 +138,7 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
// still, otherwise assume it's the curve before segment2.
|
||||
function trySegment(segment) {
|
||||
var curve = segment && segment.getCurve();
|
||||
if (curve && (that._parameter = curve.getParameterOf(that._point))
|
||||
if (curve && (that._time = curve.getTimeOf(that._point))
|
||||
!= null) {
|
||||
// Fetch path again as it could be on a new one through split()
|
||||
that._setCurve(curve);
|
||||
|
@ -185,17 +184,24 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
* @bean
|
||||
* @type Number
|
||||
*/
|
||||
getParameter: function() {
|
||||
getTime: function() {
|
||||
var curve = this.getCurve(),
|
||||
parameter = this._parameter;
|
||||
return curve && parameter == null
|
||||
? this._parameter = curve.getParameterOf(this._point)
|
||||
: parameter;
|
||||
time = this._time;
|
||||
return curve && time == null
|
||||
? this._time = curve.getTimeOf(this._point)
|
||||
: time;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @bean
|
||||
* @deprecated use {@link #getTime()} instead.
|
||||
*/
|
||||
getParameter: '#getTime',
|
||||
|
||||
/**
|
||||
* The point which is defined by the {@link #curve} and
|
||||
* {@link #parameter}.
|
||||
* {@link #time}.
|
||||
*
|
||||
* @bean
|
||||
* @type Point
|
||||
|
@ -237,8 +243,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
*/
|
||||
getCurveOffset: function() {
|
||||
var curve = this.getCurve(),
|
||||
parameter = this.getParameter();
|
||||
return parameter != null && curve && curve.getPartLength(0, parameter);
|
||||
time = this.getTime();
|
||||
return time != null && curve && curve.getPartLength(0, time);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -295,8 +301,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
var curve = this.getCurve(),
|
||||
res = null;
|
||||
if (curve) {
|
||||
res = curve.divide(this.getParameter(), true);
|
||||
// Change to the newly inserted segment, also adjusting _parameter.
|
||||
res = curve.divideAtTime(this.getTime());
|
||||
// Change to the newly inserted segment, also adjusting _time.
|
||||
if (res)
|
||||
this._setSegment(res._segment1);
|
||||
}
|
||||
|
@ -305,13 +311,13 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
|
||||
split: function() {
|
||||
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
|
||||
* on a path, by applying the same tolerances as elsewhere when dealing with
|
||||
* curve time parameters.
|
||||
* curve-time parameters.
|
||||
*
|
||||
* @param {CurveLocation} location
|
||||
* @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:
|
||||
diff = abs(
|
||||
((c1.isLast() && c2.isFirst() ? -1 : c1.getIndex())
|
||||
+ this.getParameter()) -
|
||||
+ this.getTime()) -
|
||||
((c2.isLast() && c1.isFirst() ? -1 : c2.getIndex())
|
||||
+ loc.getParameter()));
|
||||
+ loc.getTime()));
|
||||
res = (diff < /*#=*/Numerical.CURVETIME_EPSILON
|
||||
// If diff isn't close enough, compare the actual offsets of
|
||||
// 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();
|
||||
if (index != null)
|
||||
parts.push('index: ' + index);
|
||||
var parameter = this.getParameter();
|
||||
if (parameter != null)
|
||||
parts.push('parameter: ' + f.number(parameter));
|
||||
var time = this.getTime();
|
||||
if (time != null)
|
||||
parts.push('time: ' + f.number(time));
|
||||
if (this._distance != null)
|
||||
parts.push('distance: ' + f.number(this._distance));
|
||||
return '{ ' + parts.join(', ') + ' }';
|
||||
|
@ -409,8 +415,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
var inter = this._intersection;
|
||||
if (!inter)
|
||||
return false;
|
||||
var t1 = this.getParameter(),
|
||||
t2 = inter.getParameter(),
|
||||
var t1 = this.getTime(),
|
||||
t2 = inter.getTime(),
|
||||
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
||||
tMax = 1 - tMin,
|
||||
// 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.
|
||||
// The incomings tangents v1 & v3 are inverted, so that all angles
|
||||
// are pointing outwards in the right direction from the intersection.
|
||||
var v2 = c2.getTangentAt(t1Inside ? t1 : tMin, true),
|
||||
v1 = (t1Inside ? v2 : c1.getTangentAt(tMax, true)).negate(),
|
||||
v4 = c4.getTangentAt(t2Inside ? t2 : tMin, true),
|
||||
v3 = (t2Inside ? v4 : c3.getTangentAt(tMax, true)).negate(),
|
||||
var v2 = c2.getTangentAtTime(t1Inside ? t1 : tMin),
|
||||
v1 = (t1Inside ? v2 : c1.getTangentAtTime(tMax)).negate(),
|
||||
v4 = c4.getTangentAtTime(t2Inside ? t2 : tMin),
|
||||
v3 = (t2Inside ? v4 : c3.getTangentAtTime(tMax)).negate(),
|
||||
// NOTE: For shorter API calls we work with angles in degrees here:
|
||||
a1 = v1.getAngle(),
|
||||
a2 = v2.getAngle(),
|
||||
|
@ -519,9 +525,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
// getWeightedNormalAt, getCurvatureAt
|
||||
var get = name + 'At';
|
||||
this[name] = function() {
|
||||
var parameter = this.getParameter(),
|
||||
curve = this.getCurve();
|
||||
return parameter != null && curve && curve[get](parameter, true);
|
||||
var curve = this.getCurve(),
|
||||
time = this.getTime();
|
||||
return time != null && curve && curve[get](time, true);
|
||||
};
|
||||
}, {
|
||||
// Do not override the existing #getPoint():
|
||||
|
@ -530,7 +536,7 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
new function() { // Scope for statics
|
||||
|
||||
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.
|
||||
var length = locations.length,
|
||||
l = 0,
|
||||
|
@ -575,10 +581,10 @@ new function() { // Scope for statics
|
|||
// NOTE: equals() takes the intersection location into account,
|
||||
// while this calculation of diff doesn't!
|
||||
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.
|
||||
? (loc.getIndex() + loc.getParameter())
|
||||
- (loc2.getIndex() + loc2.getParameter())
|
||||
? (loc.getIndex() + loc.getTime())
|
||||
- (loc2.getIndex() + loc2.getTime())
|
||||
// Sort by path id to group all locs on same path.
|
||||
: path1._id - path2._id;
|
||||
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])
|
||||
|
||||
/**
|
||||
* Splits the path at the given offset. After splitting, the path will be
|
||||
* open. If the path was open already, splitting will result in two paths.
|
||||
* Splits the path at the given offset or 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 {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
|
||||
* @param {Number|CurveLocation} location the offset or location at which to
|
||||
* split the path
|
||||
* @return {Path} the newly created path after splitting, if any
|
||||
*
|
||||
* @example {@paperscript}
|
||||
|
@ -1156,23 +1112,18 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
* angle: 30
|
||||
* };
|
||||
*
|
||||
* var curveLocation = path.getNearestLocation(pointOnCircle);
|
||||
* var location = path.getNearestLocation(pointOnCircle);
|
||||
*
|
||||
* path.split(curveLocation);
|
||||
* path.splitAt(location);
|
||||
* 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
|
||||
* // Draw a V shaped path:
|
||||
* var path = new Path([20, 20], [50, 80], [80, 20]);
|
||||
* path.strokeColor = 'black';
|
||||
*
|
||||
* // Split the path half-way down its second curve:
|
||||
* var path2 = path.split(1, 0.5);
|
||||
* // Split the path half-way:
|
||||
* var path2 = path.splitAt(path2.length / 2);
|
||||
*
|
||||
* // Give the resulting path a red stroke-color
|
||||
* // and move it 20px to the right:
|
||||
|
@ -1186,8 +1137,8 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
* strokeColor: 'black'
|
||||
* });
|
||||
*
|
||||
* // Split the path half-way down its second curve:
|
||||
* path.split(2, 0.5);
|
||||
* // Split the path half-way:
|
||||
* path.splitAt(path.length / 2);
|
||||
*
|
||||
* // Move the first segment, to show where the path
|
||||
* // was split:
|
||||
|
@ -1195,44 +1146,27 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
*
|
||||
* // Select the first segment:
|
||||
* 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) {
|
||||
if (parameter === null)
|
||||
return null;
|
||||
if (arguments.length === 1) {
|
||||
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,
|
||||
splitAt: function(location) {
|
||||
var index = location && location.index,
|
||||
time = location && location.time,
|
||||
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
||||
tMax = 1 - tMin;
|
||||
if (parameter >= tMax) {
|
||||
// t == 1 is the same as t == 0 and index ++
|
||||
if (time >= tMax) {
|
||||
// time == 1 is the same location as time == 0 and index++
|
||||
index++;
|
||||
parameter--;
|
||||
time = 0;
|
||||
}
|
||||
var curves = this.getCurves();
|
||||
if (index >= 0 && index < curves.length) {
|
||||
// Only divide curves if we're not on an existing segment already.
|
||||
if (parameter >= tMin) {
|
||||
// Divide the curve with the index at given parameter.
|
||||
if (time >= tMin) {
|
||||
// Divide the curve with the index at the given curve-time.
|
||||
// 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
|
||||
// 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
|
||||
// the new path through _add(), allowing us to have CurveLocation
|
||||
// keep the connection to the new path through moved curves.
|
||||
|
@ -1261,6 +1195,17 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
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.
|
||||
*/
|
||||
|
@ -1649,8 +1594,8 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
// 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
|
||||
// for round strokes.
|
||||
var parameter = loc.getParameter();
|
||||
if (parameter === 0 || parameter === 1 && numSegments > 1) {
|
||||
var time = loc.getTime();
|
||||
if (time === 0 || time === 1 && numSegments > 1) {
|
||||
if (!checkSegmentStroke(loc.getSegment()))
|
||||
loc = null;
|
||||
} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {
|
||||
|
@ -1693,8 +1638,8 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
// NOTE: (For easier searching): This loop produces:
|
||||
// getPointAt, getTangentAt, getNormalAt, getWeightedTangentAt,
|
||||
// getWeightedNormalAt, getCurvatureAt
|
||||
this[name + 'At'] = function(offset, isParameter) {
|
||||
var loc = this.getLocationAt(offset, isParameter);
|
||||
this[name + 'At'] = function(offset) {
|
||||
var loc = this.getLocationAt(offset);
|
||||
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
|
||||
* 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
|
||||
*/
|
||||
getLocationAt: function(offset, isParameter) {
|
||||
getLocationAt: function(offset) {
|
||||
var curves = this.getCurves(),
|
||||
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++) {
|
||||
var start = length,
|
||||
curve = curves[i];
|
||||
|
@ -1777,7 +1714,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
* @function
|
||||
* @param {Number} offset the offset on the path, where `0` is at
|
||||
* the beginning of the path and {@link Path#length} at the end
|
||||
* @param {Boolean} [isParameter=false]
|
||||
* @return {Point} the point at the given offset
|
||||
*
|
||||
* @example {@paperscript height=150}
|
||||
|
@ -1840,7 +1776,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
* @function
|
||||
* @param {Number} offset the offset on the path, where `0` is at
|
||||
* 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
|
||||
*
|
||||
* @example {@paperscript height=150}
|
||||
|
@ -1907,7 +1842,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
* @function
|
||||
* @param {Number} offset the offset on the path, where `0` is at
|
||||
* 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
|
||||
*
|
||||
* @example {@paperscript height=150}
|
||||
|
@ -1974,7 +1908,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
* @function
|
||||
* @param {Number} offset the offset on the path, where `0` is at
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
@ -1985,7 +1918,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
* @function
|
||||
* @param {Number} offset the offset on the path, where `0` is at
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
@ -1999,7 +1931,6 @@ var Path = PathItem.extend(/** @lends Path# */{
|
|||
* @function
|
||||
* @param {Number} offset the offset on the path, where `0` is at
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
@ -2878,9 +2809,9 @@ statics: {
|
|||
// Handles both 'bevel' and 'miter' joins, as they share a lot of code.
|
||||
var curve2 = segment.getCurve(),
|
||||
curve1 = curve2.getPrevious(),
|
||||
point = curve2.getPointAt(0, true),
|
||||
normal1 = curve1.getNormalAt(1, true),
|
||||
normal2 = curve2.getNormalAt(0, true),
|
||||
point = curve2.getPointAtTime(0),
|
||||
normal1 = curve1.getNormalAtTime(1),
|
||||
normal2 = curve2.getNormalAtTime(0),
|
||||
step = normal1.getDirectedAngle(normal2) < 0 ? -radius : radius;
|
||||
normal1.setLength(step);
|
||||
normal2.setLength(step);
|
||||
|
@ -2923,11 +2854,12 @@ statics: {
|
|||
}
|
||||
// For square caps, we need to step away from point in the direction of
|
||||
// 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
|
||||
// direction to move the point.
|
||||
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.subtract(normal));
|
||||
},
|
||||
|
|
|
@ -248,26 +248,26 @@ PathItem.inject(new function() {
|
|||
results.unshift(loc);
|
||||
}
|
||||
var curve = loc._curve,
|
||||
t = loc._parameter,
|
||||
origT = t,
|
||||
time = loc._time,
|
||||
origTime = time,
|
||||
segment;
|
||||
if (curve !== prevCurve) {
|
||||
// This is a new curve, update noHandles setting.
|
||||
noHandles = !curve.hasHandles();
|
||||
} else if (prevT > 0) {
|
||||
} else if (prevTime > 0) {
|
||||
// Scale parameter when we are splitting same curve multiple
|
||||
// times, but avoid dividing by zero.
|
||||
t /= prevT;
|
||||
time /= prevTime;
|
||||
}
|
||||
if (t < tMin) {
|
||||
if (time < tMin) {
|
||||
segment = curve._segment1;
|
||||
} else if (t > tMax) {
|
||||
} else if (time > tMax) {
|
||||
segment = curve._segment2;
|
||||
} else {
|
||||
// Split the curve at t, passing true for _setHandles to always
|
||||
// set the handles on the sub-curves even if the original curve
|
||||
// had no handles.
|
||||
var newCurve = curve.divide(t, true, true);
|
||||
// Split the curve at time, passing true for _setHandles to
|
||||
// always set the handles on the sub-curves even if the original
|
||||
// curve had no handles.
|
||||
var newCurve = curve.divideAtTime(time, true);
|
||||
// Keep track of curves without handles, so they can be cleared
|
||||
// again at the end.
|
||||
if (noHandles)
|
||||
|
@ -294,7 +294,7 @@ PathItem.inject(new function() {
|
|||
segment._intersection = dest;
|
||||
}
|
||||
prevCurve = curve;
|
||||
prevT = origT;
|
||||
prevTime = origTime;
|
||||
}
|
||||
// Clear segment handles if they were part of a curve with no handles,
|
||||
// once we are done with the entire curve.
|
||||
|
@ -445,9 +445,9 @@ PathItem.inject(new function() {
|
|||
var curve = entry.curve,
|
||||
path = curve._path,
|
||||
parent = path._parent,
|
||||
t = curve.getParameterAt(length),
|
||||
pt = curve.getPointAt(t, true),
|
||||
hor = Math.abs(curve.getTangentAt(t, true).y)
|
||||
t = curve.getTimeAt(length),
|
||||
pt = curve.getPointAtTime(t),
|
||||
hor = Math.abs(curve.getTangentAtTime(t).y)
|
||||
< /*#=*/Numerical.TRIGONOMETRIC_EPSILON;
|
||||
if (parent instanceof CompoundPath)
|
||||
path = parent;
|
||||
|
|
|
@ -91,11 +91,11 @@ var PathIterator = Base.extend({
|
|||
this.parts = parts;
|
||||
this.length = length;
|
||||
// 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;
|
||||
},
|
||||
|
||||
getParameterAt: function(offset) {
|
||||
getTimeAt: function(offset) {
|
||||
// Make sure we're not beyond the requested offset already. Search the
|
||||
// start position backwards from where to then process the loop below.
|
||||
var i, j = this.index;
|
||||
|
@ -135,8 +135,8 @@ var PathIterator = Base.extend({
|
|||
},
|
||||
|
||||
drawPart: function(ctx, from, to) {
|
||||
from = this.getParameterAt(from);
|
||||
to = this.getParameterAt(to);
|
||||
from = this.getTimeAt(from);
|
||||
to = this.getTimeAt(to);
|
||||
for (var i = from.index; i <= to.index; i++) {
|
||||
var curve = Curve.getPart(this.curves[i],
|
||||
i == from.index ? from.value : 0,
|
||||
|
@ -149,7 +149,7 @@ var PathIterator = Base.extend({
|
|||
}, Base.each(Curve._evaluateMethods,
|
||||
function(name) {
|
||||
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);
|
||||
};
|
||||
}, {})
|
||||
|
|
|
@ -12,31 +12,7 @@
|
|||
|
||||
QUnit.module('Curve');
|
||||
|
||||
test('Curve#getParameterOf()', 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() {
|
||||
test('Curve#getPointAtTime()', function() {
|
||||
var curve = new Path.Circle({
|
||||
center: [100, 100],
|
||||
radius: 100
|
||||
|
@ -52,15 +28,18 @@ test('Curve#getPointAt()', function() {
|
|||
|
||||
for (var i = 0; i < points.length; 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],
|
||||
'curve.getPointAt(' + entry[0] + ', true);');
|
||||
'Legacy: curve.getPointAt(' + entry[0] + ', true);');
|
||||
}
|
||||
|
||||
equals(curve.getPointAt(curve.length + 1), null,
|
||||
'Should return null when offset is out of range.');
|
||||
});
|
||||
|
||||
test('Curve#getTangentAt()', function() {
|
||||
test('Curve#getTangentAtTime()', function() {
|
||||
var curve = new Path.Circle({
|
||||
center: [100, 100],
|
||||
radius: 100
|
||||
|
@ -76,14 +55,19 @@ test('Curve#getTangentAt()', function() {
|
|||
|
||||
for (var i = 0; i < tangents.length; 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(),
|
||||
'curve.getTangentAt(' + entry[0] + ', true);');
|
||||
'Legacy: curve.getTangentAt(' + entry[0] + ', true);');
|
||||
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({
|
||||
center: [100, 100],
|
||||
radius: 100
|
||||
|
@ -99,14 +83,19 @@ test('Curve#getNormalAt()', function() {
|
|||
|
||||
for (var i = 0; i < normals.length; 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(),
|
||||
'curve.getNormalAt(' + entry[0] + ', true);');
|
||||
'Legacy: curve.getNormalAt(' + entry[0] + ', true);');
|
||||
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({
|
||||
center: [100, 100],
|
||||
radius: 100
|
||||
|
@ -122,12 +111,15 @@ test('Curve#getCurvatureAt()', function() {
|
|||
|
||||
for (var i = 0; i < curvatures.length; 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],
|
||||
'curve.getCurvatureAt(' + entry[0] + ', true);');
|
||||
'Legacy: curve.getCurvatureAt(' + entry[0] + ', true);');
|
||||
}
|
||||
});
|
||||
|
||||
test('Curve#getCurvatureAt()', function() {
|
||||
test('Curve#getCurvatureAtTime()', function() {
|
||||
var curve = new Path.Line({
|
||||
from: [100, 100],
|
||||
to: [200, 200],
|
||||
|
@ -143,12 +135,15 @@ test('Curve#getCurvatureAt()', function() {
|
|||
|
||||
for (var i = 0; i < curvatures.length; 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],
|
||||
'curve.getCurvatureAt(' + entry[0] + ', true);');
|
||||
'Legacy: curve.getCurvatureAt(' + entry[0] + ', true);');
|
||||
}
|
||||
});
|
||||
|
||||
test('Curve#getParameterAt()', function() {
|
||||
test('Curve#getTimeAt()', function() {
|
||||
var curve = new Path([
|
||||
[[0, 0], [0, 0], [100, 0]],
|
||||
[[200, 200]],
|
||||
|
@ -157,14 +152,16 @@ test('Curve#getParameterAt()', function() {
|
|||
for (var f = 0; f <= 1; f += 0.1) {
|
||||
var o1 = curve.length * f;
|
||||
var o2 = -curve.length * (1 - f);
|
||||
var t1 = curve.getParameterAt(o1);
|
||||
var t2 = curve.getParameterAt(o2);
|
||||
equals(t1, t2, 'Curve parameter at offset ' + o1
|
||||
+ ' should be the same value as at offset' + o2,
|
||||
var message = 'Curve-time parameter at offset ' + o1
|
||||
+ ' should be the same value as at offset' + o2;
|
||||
equals(curve.getTimeAt(o1), curve.getTimeAt(o2), message,
|
||||
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.');
|
||||
});
|
||||
|
||||
|
@ -176,7 +173,6 @@ test('Curve#getLocationAt()', function() {
|
|||
|
||||
equals(curve.getLocationAt(curve.length + 1), null,
|
||||
'Should return null when offset is out of range.');
|
||||
// 'Should return null when point is not on the curve.');
|
||||
});
|
||||
|
||||
test('Curve#isStraight()', function() {
|
||||
|
@ -223,3 +219,31 @@ test('Curve#isLinear()', function() {
|
|||
return new Curve([100, 100], null, null, [200, 200]).isLinear();
|
||||
}, 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();
|
||||
|
||||
for (var i = 0; i < curves.length; i++) {
|
||||
testPoint(path, curves[i].getPointAt(0, true), true);
|
||||
testPoint(path, curves[i].getPointAt(0.5, true), true);
|
||||
testPoint(path, curves[i].getPointAtTime(0), true);
|
||||
testPoint(path, curves[i].getPointAtTime(0.5), true);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -181,8 +181,8 @@ test('Path#contains() (Rotated Rectangle Contours)', function() {
|
|||
path.rotate(45);
|
||||
|
||||
for (var i = 0; i < curves.length; i++) {
|
||||
testPoint(path, curves[i].getPointAt(0, true), true);
|
||||
testPoint(path, curves[i].getPointAt(0.5, true), true);
|
||||
testPoint(path, curves[i].getPointAtTime(0), true);
|
||||
testPoint(path, curves[i].getPointAtTime(0.5), true);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ function testIntersection(intersections, results) {
|
|||
var name = 'intersections[' + i + ']';
|
||||
equals(inter.point, new Point(values.point), name + '.point');
|
||||
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()');
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ test('#565', function() {
|
|||
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
||||
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||
testIntersection(curve1.getIntersections(curve2), [
|
||||
{ point: { x: 354.13635, y: 220.81369 }, index: 0, parameter: 0.46725, crossing: true },
|
||||
{ point: { x: 390.24772, y: 224.27351 }, index: 0, parameter: 0.71605, 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, time: 0.71605, crossing: true }
|
||||
]);
|
||||
|
||||
// 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 path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||
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 path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||
testIntersection(curve1.getIntersections(curve2), [
|
||||
{ point: { x: 547.96568, y: 396.66339 }, index: 0, parameter: 0.07024, crossing: true },
|
||||
{ point: { x: 504.79973, y: 383.37886 }, index: 0, parameter: 0.48077, 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, 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));
|
||||
|
@ -60,7 +60,7 @@ test('#568', function() {
|
|||
var path1 = new Path([curve1.segment1, curve1.segment2]);
|
||||
var path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||
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 ints = 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 path2 = new Path([curve2.segment1, curve2.segment2]);
|
||||
testIntersection(curve1.getIntersections(curve2), [
|
||||
{ point: { x: 352.39945, y: 330.44135 }, index: 0, parameter: 0.41159, crossing: true },
|
||||
{ point: { x: 420.12359, y: 275.83519 }, index: 0, parameter: 1, crossing: false }
|
||||
{ point: { x: 352.39945, y: 330.44135 }, index: 0, time: 0.41159, crossing: true },
|
||||
{ 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 path2 = new Path.Rectangle(new Point(110, 110), [100, 100]);
|
||||
testIntersection(path1.getIntersections(path2), [
|
||||
{ point: { x: 190, y: 110 }, index: 2, parameter: 0, crossing: true },
|
||||
{ point: { x: 110, y: 190 }, index: 3, parameter: 0, crossing: true }
|
||||
{ point: { x: 190, y: 110 }, index: 2, time: 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;
|
||||
equals(length, 172.10112809179614, 'path.length');
|
||||
|
||||
var param = path.curves[0].getParameterAt(length / 4);
|
||||
equals(param, 0.2255849553116685, 'path.curves[0].getParameterAt(length / 4)');
|
||||
var t = path.curves[0].getTimeAt(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();
|
||||
path.moveTo(100, 100);
|
||||
path.lineTo(500, 500);
|
||||
var curve = path.curves[0];
|
||||
var length = curve.length;
|
||||
var t = curve.getParameterAt(length / 3);
|
||||
var t = curve.getTimeAt(length / 3);
|
||||
equals(t, 0.3869631475722452);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue