2011-03-04 08:34:31 -05:00
|
|
|
var Curve = this.Curve = Base.extend({
|
2011-03-06 07:29:17 -05:00
|
|
|
beans: true,
|
|
|
|
|
2011-03-06 07:24:15 -05:00
|
|
|
initialize: function(arg0, arg1, arg2, arg3) {
|
|
|
|
if (arguments.length == 0) {
|
|
|
|
this._segment1 = new Segment();
|
|
|
|
this._segment2 = new Segment();
|
|
|
|
} else if (arguments.length == 1) {
|
|
|
|
// TODO: If beans are not activated, this won't copy from
|
|
|
|
// an existing segment. OK?
|
|
|
|
this._segment1 = new Segment(arg0.segment1);
|
|
|
|
this._segment2 = new Segment(arg0.segment2);
|
|
|
|
} else if (arguments.length == 2) {
|
|
|
|
if (arg0 instanceof Path) {
|
|
|
|
this._path = arg0;
|
|
|
|
this._index1 = arg1;
|
|
|
|
this._updateSegments();
|
|
|
|
} else {
|
|
|
|
this._segment1 = new Segment(arg0);
|
|
|
|
this._segment2 = new Segment(arg1);
|
|
|
|
}
|
|
|
|
} else if (arguments.length == 4) {
|
|
|
|
this._segment1 = new Segment(arg0, null, arg1);
|
|
|
|
this._segment2 = new Segment(arg3, arg2, null);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_updateSegments: function() {
|
|
|
|
if (this._path) {
|
|
|
|
this._index2 = this._index1 + 1;
|
|
|
|
// A closing curve?
|
|
|
|
var segments = this._path._segments;
|
|
|
|
if (this._index2 >= segments.length)
|
|
|
|
this._index2 = 0;
|
|
|
|
this._segment1 = segments[this._index1];
|
|
|
|
this._segment2 = segments[this._index2];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
getPath: function() {
|
|
|
|
return this._path;
|
|
|
|
},
|
|
|
|
|
|
|
|
getIndex: function() {
|
|
|
|
return this._index1;
|
|
|
|
},
|
|
|
|
|
|
|
|
_setIndex: function(index) {
|
2011-03-06 07:25:08 -05:00
|
|
|
this._index1 = index;
|
|
|
|
this._updateSegments();
|
2011-03-06 07:24:15 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The first anchor point of the curve.
|
|
|
|
*/
|
|
|
|
getPoint1: function() {
|
|
|
|
return this._segment1._point;
|
|
|
|
},
|
|
|
|
|
|
|
|
setPoint1: function() {
|
|
|
|
var point = Point.read(arguments);
|
|
|
|
this._segment1._point.set(point.x, point.y);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The second anchor point of the curve.
|
|
|
|
*/
|
|
|
|
getPoint2: function() {
|
|
|
|
return this._segment2._point;
|
|
|
|
},
|
|
|
|
|
|
|
|
setPoint2: function() {
|
|
|
|
var point = Point.read(arguments);
|
|
|
|
this._segment2._point.set(point.x, point.y);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The handle point that describes the tangent in the first anchor point.
|
|
|
|
*/
|
|
|
|
getHandle1: function() {
|
|
|
|
return this._segment1._handleOut;
|
|
|
|
},
|
|
|
|
|
|
|
|
setHandle1: function() {
|
|
|
|
var point = Point.read(arguments);
|
|
|
|
this._segment1._handleOut.set(point.x, point.y);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The handle point that describes the tangent in the second anchor point.
|
|
|
|
*/
|
|
|
|
getHandle2: function() {
|
|
|
|
return this._segment2._handleIn;
|
|
|
|
},
|
|
|
|
|
|
|
|
setHandle2: function() {
|
|
|
|
var point = Point.read(arguments);
|
|
|
|
this._segment2._handleIn.set(point.x, point.y);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The first segment of the curve.
|
|
|
|
*/
|
|
|
|
getSegment1: function() {
|
|
|
|
return this._segment1;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The second segment of the curve.
|
|
|
|
*/
|
|
|
|
getSegment2: function() {
|
|
|
|
return this._segment2;
|
2011-03-06 07:29:17 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
// Calculates arclength of a cubic using adaptive simpson integration.
|
|
|
|
getLength: function(goal) {
|
|
|
|
var seg0 = this._segment1,
|
|
|
|
seg1 = this._segment2,
|
|
|
|
z0 = seg0._point,
|
|
|
|
z1 = seg1._point,
|
|
|
|
c0 = z0.add(seg0._handleOut),
|
|
|
|
c1 = z1.add(seg1._handleIn);
|
|
|
|
// TODO: Check for straight lines and handle separately.
|
|
|
|
|
|
|
|
// Calculate the coefficients of a Bezier derivative, divided by 3.
|
|
|
|
var ax = 3 * (c0.x - c1.x) - z0.x + z1.x,
|
|
|
|
bx = 2 * (z0.x + c1.x) - 4 * c0.x,
|
|
|
|
cx = c0.x - z0.x,
|
|
|
|
|
|
|
|
ay = 3 * (c0.y - c1.y) - z0.y + z1.y,
|
|
|
|
by = 2 * (z0.y + c1.y) - 4 * c0.y,
|
|
|
|
cy = c0.y - z0.y;
|
|
|
|
|
|
|
|
function ds(t) {
|
|
|
|
// Calculate quadratic equations of derivatives for x and y
|
|
|
|
var dx = (ax * t + bx) * t + cx,
|
|
|
|
dy = (ay * t + by) * t + cy;
|
|
|
|
return Math.sqrt(dx * dx + dy * dy);
|
|
|
|
}
|
|
|
|
|
|
|
|
var integral = MathUtils.simpson(ds, 0.0, 1.0, MathUtils.EPSILON, 1.0);
|
|
|
|
if (integral == null)
|
|
|
|
throw new Error('Nesting capacity exceeded in Path#getLenght()');
|
|
|
|
// Multiply by 3 again, as derivative was divided by 3
|
|
|
|
var length = 3 * integral;
|
|
|
|
if (goal == undefined || goal < 0 || goal >= length)
|
|
|
|
return length;
|
|
|
|
var result = MathUtils.unsimpson(goal, ds, 0, goal / integral,
|
|
|
|
100 * MathUtils.EPSILON, integral, Math.sqrt(MathUtils.EPSILON), 1);
|
|
|
|
if (!result)
|
|
|
|
throw new Error('Nesting capacity exceeded in computing arctime');
|
|
|
|
return -result.b;
|
2011-03-02 11:22:26 -05:00
|
|
|
}
|
|
|
|
});
|