Merge branch 'master' into bool-new

* master:
  Share code that handles bounds in roots between solveQuadratic() and solveCubic()
  Inline EPSILON and TOLERANCE for better performance in Numerical.
  Clean up code a bit.
  Filter out insert property in Item#set()
  Typo Paelette -> Palette
  Rename Item#anchor -> Item#pivot
  Minor documentation fixes.
This commit is contained in:
hkrish 2013-12-24 00:02:15 +01:00
commit f23303e371
6 changed files with 85 additions and 79 deletions

View file

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="UTF-8">
<title>Paelette</title>
<title>Palette</title>
<link rel="stylesheet" href="../css/style.css">
<script type="text/javascript" src="../../dist/paper.js"></script>
<script type="text/paperscript" canvas="canvas">
@ -70,4 +70,4 @@
<body>
<canvas id="canvas" width="640" height="100"></canvas>
</body>
</html>
</html>

View file

@ -31,7 +31,7 @@
strokeWidth: 30,
strokeJoin: 'round',
strokeCap: 'butt',
anchor: leftPath.position,
pivot: leftPath.position,
position: view.center
});
@ -59,7 +59,7 @@
}
leftPath.smooth();
rightPath.smooth();
group.anchor = [leftPath.position.x, 0];
group.pivot = [leftPath.position.x, 0];
group.position = view.center;
}

View file

@ -53,7 +53,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
_serializeFields: {
name: null,
matrix: new Matrix(),
anchor: null,
pivot: null,
locked: false,
visible: true,
blendMode: 'normal',
@ -279,7 +279,7 @@ var Item = Base.extend(Callback, /** @lends Item# */{
*/
set: function(props) {
if (props)
this._set(props);
this._set(props, { insert: true });
return this;
},
@ -772,11 +772,11 @@ var Item = Base.extend(Callback, /** @lends Item# */{
// modified, it would hold new values already and only then cause the
// calling of #setPosition.
if (!position) {
// If an anchor point is provided, use it to determine position
// If an pivot point is provided, use it to determine position
// based on the matrix. Otherwise use the center of the bounds.
var anchor = this._anchor;
position = this._position = anchor
? this._matrix._transformPoint(anchor)
var pivot = this._pivot;
position = this._position = pivot
? this._matrix._transformPoint(pivot)
: this.getBounds().getCenter(true);
}
return new ctor(position.x, position.y, this, 'setPosition');
@ -790,11 +790,11 @@ var Item = Base.extend(Callback, /** @lends Item# */{
},
/**
* The item's anchor point specified in the item coordinate system, defining
* the reference point for {@link #position}, as well as the pivot point for
* all transformations. By default, it is set to {@code null}, meaning the
* {@link Rectangle#center} of the item's {@link #bounds} rectangle is used
* as the anchor.
* The item's pivot point specified in the item coordinate system, defining
* the point around which all transformations are hinging. This is also the
* reference point for {@link #position}. By default, it is set to
* {@code null}, meaning the {@link Rectangle#center} of the item's
* {@link #bounds} rectangle is used as pivot.
*
* @type Point
* @bean
@ -802,22 +802,22 @@ var Item = Base.extend(Callback, /** @lends Item# */{
*
* @example {@paperscript}
*/
getAnchor: function(/* dontLink */) {
var anchor = this._anchor;
if (anchor) {
getPivot: function(/* dontLink */) {
var pivot = this._pivot;
if (pivot) {
var ctor = arguments[0] ? Point : LinkedPoint;
anchor = new ctor(anchor.x, anchor.y, this, 'setAnchor');
pivot = new ctor(pivot.x, pivot.y, this, 'setAnchor');
}
return anchor;
return pivot;
},
setAnchor: function(/* point */) {
this._anchor = Point.read(arguments);
setPivot: function(/* point */) {
this._pivot = Point.read(arguments);
// No need for _changed() since the only thing this affects is _position
delete this._position;
},
_anchor: null,
_pivot: null,
// TODO: Keep these around for a bit since it was introduced on the mailing
// list, then remove in a while.
@ -2781,15 +2781,15 @@ var Item = Base.extend(Callback, /** @lends Item# */{
var matrix = this._matrix;
if (this._applyMatrix(matrix, true)) {
// When the matrix could be applied, we also need to transform
// color styles (only gradients so far) and anchor point:
var anchor = this._anchor,
// color styles (only gradients so far) and pivot point:
var pivot = this._pivot,
style = this._style,
// pass true for dontMerge so we don't recursively transform
// styles on groups' children.
fillColor = style.getFillColor(true),
strokeColor = style.getStrokeColor(true);
if (anchor)
anchor.transform(matrix);
if (pivot)
pivot.transform(matrix);
if (fillColor)
fillColor.transform(matrix);
if (strokeColor)

View file

@ -69,11 +69,12 @@ var PathItem = Item.extend(/** @lends PathItem# */{
curves2 = path.getCurves(),
matrix1 = this._matrix.orNullIfIdentity(),
matrix2 = path._matrix.orNullIfIdentity(),
length1 = curves1.length,
length2 = curves2.length,
values2 = [];
for (var i = 0; i < length2; i++)
values2[i] = curves2[i].getValues(matrix2);
for (var i = 0, l = curves1.length; i < l; i++) {
for (var i = 0; i < length1; i++) {
var curve1 = curves1[i],
values1 = curve1.getValues(matrix1);
for (var j = 0; j < length2; j++)

View file

@ -365,8 +365,8 @@ var Color = Base.extend(new function() {
* {@code destination: Point} the destination point of the gradient
* {@code stops: Array of GradientStop} the gradient stops describing
* the gradient, as an alternative to providing a gradient object<br>
* {@code radial: Boolean} controls whether the gradient is radial, as
* an alternative to providing a gradient object<br>
* {@code radial: Boolean} controls whether the gradient is radial,
* as an alternative to providing a gradient object<br>
*
* @name Color#initialize
* @param {Object} object an object describing the components and
@ -454,13 +454,18 @@ var Color = Base.extend(new function() {
* // Create a circle shaped path at the center of the view
* // with a radius of 80:
* var path = new Path.Circle({
* center: view.center,
* radius: 80
* center: view.center,
* radius: 80
* });
*
* // The stops array: yellow mixes with red between 0 and 15%,
* // 15% to 30% is pure red, red mixes with black between 30% to 100%:
* var stops = [['yellow', 0], ['red', 0.15], ['red', 0.3], ['black', 0.9]];
* var stops = [
* ['yellow', 0],
* ['red', 0.15],
* ['red', 0.3],
* ['black', 0.9]
* ];
*
* // Create a radial gradient using the color stops array:
* var gradient = new Gradient(stops, true);
@ -971,14 +976,16 @@ var Color = Base.extend(new function() {
* }
*/
/**
* The saturation of the color as a value between {@code 0} and {@code 1}.
* The saturation of the color as a value between {@code 0} and
* {@code 1}.
*
* @name Color#saturation
* @property
* @type Number
*/
/**
* The brightness of the color as a value between {@code 0} and {@code 1}.
* The brightness of the color as a value between {@code 0} and
* {@code 1}.
*
* @name Color#brightness
* @property
@ -988,8 +995,9 @@ var Color = Base.extend(new function() {
/**
* {@grouptitle HSL Components}
*
* The lightness of the color as a value between {@code 0} and {@code 1}.
* All other components are shared with HSB.
* The lightness of the color as a value between {@code 0} and
* {@code 1}.
* Note that all other components are shared with HSB.
*
* @name Color#lightness
* @property
@ -1043,8 +1051,8 @@ var Color = Base.extend(new function() {
* @type Point
*
* @example {@paperscript height=300}
* // Move the destination point of the gradient, by moving your mouse over
* // the view below:
* // Move the destination point of the gradient, by moving your mouse
* // over the view below:
*
* // Create a circle shaped path at the center of the view,
* // using 40% of the height of the view as its radius
@ -1167,7 +1175,8 @@ var Color = Base.extend(new function() {
* @function
* @operator
* @param {Number} number the number to add
* @return {Color} the addition of the color and the value as a new color
* @return {Color} the addition of the color and the value as a new
* color
*
* @example
* var color = new Color(0.5, 1, 1);

View file

@ -56,12 +56,29 @@ var Numerical = new function() {
sqrt = Math.sqrt,
pow = Math.pow,
cos = Math.cos,
PI = Math.PI;
PI = Math.PI,
TOLERANCE = 10e-6,
EPSILON = 10e-12;
// Sets up min and max values for roots and returns a add() function that
// handles bounds checks and itself retuns the amount of added roots.
function setupRoots(roots, min, max) {
var unbound = min === undefined,
minE = min - EPSILON,
maxE = max + EPSILON,
count = 0;
// Returns a function that adds roots with checks
return function(root) {
if (unbound || root > minE && root < maxE)
roots[count++] = root < min ? min : root > max ? max : root;
return count;
};
}
return {
TOLERANCE: 10e-6,
TOLERANCE: TOLERANCE,
// Precision when comparing against 0
EPSILON: 10e-12,
EPSILON: EPSILON,
// Kappa, see: http://www.whizkidtech.redprince.net/bezier/circle/kappa/
KAPPA: 4 * (sqrt(2) - 1) / 3,
@ -70,7 +87,7 @@ var Numerical = new function() {
* Numerical.EPSILON.
*/
isZero: function(val) {
return abs(val) <= Numerical.EPSILON;
return abs(val) <= EPSILON;
},
/**
@ -127,36 +144,26 @@ var Numerical = new function() {
* a*x^2 + b*x + c = 0
*/
solveQuadratic: function(a, b, c, roots, min, max) {
var epsilon = Numerical.EPSILON,
unbound = min === undefined,
minE = min - epsilon,
maxE = max + epsilon,
count = 0;
function add(root) {
if (unbound || root > minE && root < maxE)
roots[count++] = root < min ? min : root > max ? max : root;
return count;
}
var add = setupRoots(roots, min, max);
// Code ported over and adapted from Uintah library (MIT license).
// If a is 0, equation is actually linear, return 0 or 1 easy roots.
if (abs(a) < epsilon) {
if (abs(b) >= epsilon)
if (abs(a) < EPSILON) {
if (abs(b) >= EPSILON)
return add(-c / b);
// If all the coefficients are 0, we have infinite solutions!
return abs(c) < epsilon ? -1 : 0; // Infinite or 0 solutions
return abs(c) < EPSILON ? -1 : 0; // Infinite or 0 solutions
}
// Convert to normal form: x^2 + px + q = 0
var p = b / (2 * a);
var q = c / a;
var p2 = p * p;
if (p2 < q - epsilon)
if (p2 < q - EPSILON)
return 0;
var s = p2 > q ? sqrt(p2 - q) : 0;
add (s - p);
var s = p2 > q ? sqrt(p2 - q) : 0,
count = add(s - p);
if (s > 0)
add(-s - p);
count = add(-s - p);
return count;
},
@ -167,29 +174,18 @@ var Numerical = new function() {
* a*x^3 + b*x^2 + c*x + d = 0
*/
solveCubic: function(a, b, c, d, roots, min, max) {
var epsilon = Numerical.EPSILON;
// If a is 0, equation is actually quadratic.
if (abs(a) < epsilon)
if (abs(a) < EPSILON)
return Numerical.solveQuadratic(b, c, d, roots, min, max);
var unbound = min === undefined,
minE = min - epsilon,
maxE = max + epsilon,
count = 0;
function add(root) {
if (unbound || root > minE && root < maxE)
roots[count++] = root < min ? min : root > max ? max : root;
return count;
}
// Code ported over and adapted from Uintah library (MIT license).
// Normalize to form: x^3 + b x^2 + c x + d = 0:
b /= a;
c /= a;
d /= a;
// Compute discriminants
var bb = b * b,
var add = setupRoots(roots, min, max),
// Compute discriminants
bb = b * b,
p = (bb - 3 * c) / 9,
q = (2 * bb * b - 9 * b * c + 27 * d) / 54,
// Use Cardano's formula
@ -197,8 +193,8 @@ var Numerical = new function() {
D = q * q - ppp;
// Substitute x = y - b/3 to eliminate quadric term: x^3 +px + q = 0
b /= 3;
if (abs(D) < epsilon) {
if (abs(q) < epsilon) // One triple solution.
if (abs(D) < EPSILON) {
if (abs(q) < EPSILON) // One triple solution.
return add(-b);
// One single and one double solution.
var sqp = sqrt(p),